chore: upgrade deps & code style
This commit is contained in:
parent
9a05f858db
commit
74df8be4f2
|
@ -0,0 +1,5 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
||||
chrome 79
|
|
@ -12,4 +12,9 @@ dist
|
|||
.husky
|
||||
.local
|
||||
/bin
|
||||
/src/mock
|
||||
Dockerfile
|
||||
commitlint.config.js
|
||||
|
||||
components.d.ts
|
||||
auto-imports.d.ts
|
||||
|
|
98
.eslintrc.js
98
.eslintrc.js
|
@ -1,6 +1,4 @@
|
|||
// @ts-check
|
||||
const { defineConfig } = require('eslint-define-config');
|
||||
module.exports = defineConfig({
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
|
@ -15,28 +13,50 @@ module.exports = defineConfig({
|
|||
jsxPragma: 'React',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
tsx: true,
|
||||
},
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'prettier', 'import'],
|
||||
extends: [
|
||||
'plugin:vue/vue3-recommended',
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'prettier',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx', '*.vue'],
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
// js/ts
|
||||
// 'no-console': ['warn', { allow: ['error'] }],
|
||||
'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'],
|
||||
camelcase: ['error', { properties: 'never' }],
|
||||
|
||||
'no-var': 'error',
|
||||
'no-empty': ['error', { allowEmptyCatch: true }],
|
||||
'no-void': 'error',
|
||||
'prefer-const': ['warn', { destructuring: 'all', ignoreReadBeforeAssign: true }],
|
||||
'prefer-template': 'error',
|
||||
'object-shorthand': ['error', 'always', { ignoreConstructors: false, avoidQuotes: true }],
|
||||
'block-scoped-var': 'error',
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
||||
// '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
|
@ -51,29 +71,43 @@ module.exports = defineConfig({
|
|||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
// vue
|
||||
'vue/no-v-html': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-explicit-emits': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
|
||||
// prettier
|
||||
'prettier/prettier': 'error',
|
||||
|
||||
// import
|
||||
'import/first': 'error',
|
||||
'import/no-duplicates': 'error',
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'never',
|
||||
component: 'always',
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: 'vue',
|
||||
group: 'external',
|
||||
position: 'before',
|
||||
},
|
||||
svg: 'always',
|
||||
math: 'always',
|
||||
{
|
||||
pattern: '@vue/**',
|
||||
group: 'external',
|
||||
position: 'before',
|
||||
},
|
||||
{
|
||||
pattern: 'ant-design-vue',
|
||||
group: 'internal',
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
pathGroupsExcludedImportTypes: ['type'],
|
||||
},
|
||||
});
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
* text=auto eol=lf
|
||||
*.ts linguist-detectable=false
|
||||
*.css linguist-detectable=false
|
||||
*.scss linguist-detectable=false
|
||||
*.js linguist-detectable=true
|
||||
*.vue linguist-detectable=true
|
|
@ -6,30 +6,48 @@ env:
|
|||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
repo-sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# 设置服务器时区为东八区
|
||||
- name: Set time zone
|
||||
run: sudo timedatectl set-timezone 'Asia/Shanghai'
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
# Full git history is needed to get a proper list of changed files within `super-linter`
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js v14.x
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14.x'
|
||||
node-version: '16'
|
||||
registry-url: https://registry.npmjs.com/
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Install
|
||||
run: pnpm install
|
||||
- name: Cache ~/.pnpm-store
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-pnpm-store
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: ${{ runner.os }}-preview-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-preview-${{ env.cache-name }}-
|
||||
${{ runner.os }}-preview-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm i --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
FORCE_COLOR: 2
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
|
@ -60,6 +78,6 @@ jobs:
|
|||
# 注意替换为你的 Gitee 仓库,仓库名严格区分大小写,请准确填写,否则会出错
|
||||
gitee-repo: buqiyuan/vite-vue3-lowcode
|
||||
# 是否强制使用 HTTPS
|
||||
https: false
|
||||
https: true
|
||||
# 要部署的分支,默认是 master,若是其他分支,则需要指定(指定的分支必须存在)
|
||||
branch: gh-pages
|
||||
|
|
|
@ -51,3 +51,7 @@ testem.log
|
|||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# auto generate file
|
||||
components.d.ts
|
||||
auto-imports.d.ts
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# shamefully-hoist=true
|
||||
# strict-peer-dependencies=false
|
||||
|
||||
registry = https://registry.npmmirror.com
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"johnsoncodehk.volar",
|
||||
"vue.volar",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"stylelint.vscode-stylelint",
|
||||
"esbenp.prettier-vscode",
|
||||
|
|
|
@ -1,11 +1,32 @@
|
|||
{
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
"volar.tsPlugin": true,
|
||||
"volar.tsPluginStatus": false,
|
||||
"npm.packageManager": "pnpm",
|
||||
"editor.tabSize": 2,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"files.eol": "\n",
|
||||
"eslint.probe": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"html",
|
||||
"vue",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc"
|
||||
],
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"html",
|
||||
"vue",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc"
|
||||
],
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.log": true,
|
||||
|
@ -55,9 +76,9 @@
|
|||
"**/yarn.lock": true
|
||||
},
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "yarn",
|
||||
"stylelint.packageManager": "pnpm",
|
||||
"path-intellisense.mappings": {
|
||||
"/@/": "${workspaceRoot}/src"
|
||||
"@/": "${workspaceRoot}/src"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
@ -83,28 +104,24 @@
|
|||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": false
|
||||
"source.fixAll.stylelint": true
|
||||
}
|
||||
},
|
||||
"i18n-ally.localesPaths": [
|
||||
"src/locales/lang"
|
||||
],
|
||||
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||
"i18n-ally.enabledParsers": [
|
||||
"ts"
|
||||
],
|
||||
"i18n-ally.enabledParsers": ["ts"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": [
|
||||
"vue",
|
||||
"react"
|
||||
],
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"]
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
// Generated by 'unplugin-auto-import'
|
||||
// We suggest you to commit this file into source control
|
||||
export {};
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope'];
|
||||
const computed: typeof import('vue')['computed'];
|
||||
const createApp: typeof import('vue')['createApp'];
|
||||
const customRef: typeof import('vue')['customRef'];
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'];
|
||||
const defineComponent: typeof import('vue')['defineComponent'];
|
||||
const effectScope: typeof import('vue')['effectScope'];
|
||||
const EffectScope: typeof import('vue')['EffectScope'];
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance'];
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope'];
|
||||
const h: typeof import('vue')['h'];
|
||||
const inject: typeof import('vue')['inject'];
|
||||
const isProxy: typeof import('vue')['isProxy'];
|
||||
const isReactive: typeof import('vue')['isReactive'];
|
||||
const isReadonly: typeof import('vue')['isReadonly'];
|
||||
const isRef: typeof import('vue')['isRef'];
|
||||
const markRaw: typeof import('vue')['markRaw'];
|
||||
|
@ -50,5 +52,6 @@ declare global {
|
|||
const useSlots: typeof import('vue')['useSlots'];
|
||||
const watch: typeof import('vue')['watch'];
|
||||
const watchEffect: typeof import('vue')['watchEffect'];
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect'];
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect'];
|
||||
}
|
||||
export {};
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// generated by unplugin-vue-components
|
||||
// We suggest you to commit this file into source control
|
||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core';
|
||||
|
||||
declare module 'vue' {
|
||||
export {};
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
ElAside: typeof import('element-plus/es')['ElAside'];
|
||||
ElButton: typeof import('element-plus/es')['ElButton'];
|
||||
|
@ -26,8 +29,11 @@ declare module 'vue' {
|
|||
ElTag: typeof import('element-plus/es')['ElTag'];
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip'];
|
||||
ElTree: typeof import('element-plus/es')['ElTree'];
|
||||
InfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'];
|
||||
RouterLink: typeof import('vue-router')['RouterLink'];
|
||||
RouterView: typeof import('vue-router')['RouterView'];
|
||||
}
|
||||
|
||||
export interface ComponentCustomProperties {
|
||||
vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'];
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
|
120
package.json
120
package.json
|
@ -7,7 +7,7 @@
|
|||
"bootstrap": "pnpm install",
|
||||
"serve": "npm run dev",
|
||||
"dev": "cross-env --max_old_space_size=4096 vite",
|
||||
"build": "cross-env vite build",
|
||||
"build": "rimraf dist && cross-env NODE_ENV=production vite build",
|
||||
"build:no-cache": "pnpm clean:cache && npm run build",
|
||||
"build-tsc": "vue-tsc --noEmit && vite build",
|
||||
"preview": "npm run build && vite preview",
|
||||
|
@ -15,77 +15,89 @@
|
|||
"log": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
|
||||
"clean:lib": "rimraf node_modules",
|
||||
"format": "prettier --write .",
|
||||
"lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx,.md,.json --max-warnings 0 && pretty-quick --check --branch main",
|
||||
"lint:fix": "eslint --fix . --ext .vue,.js,.ts,.jsx,.tsx,.md,.json && pretty-quick --branch main",
|
||||
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
||||
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"lint:lint-staged": "lint-staged",
|
||||
"deploy": "npm run build && npx gh-pages -d dist",
|
||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||
"test:br": "npx http-server dist --cors --brotli -c-1",
|
||||
"prepare": "husky install",
|
||||
"postversion": "git push && git push origin --tags",
|
||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||
"prepare": "husky install"
|
||||
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
|
||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||
"test:br": "npx http-server dist --cors --brotli -c-1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^0.2.4",
|
||||
"@element-plus/icons-vue": "^2.0.6",
|
||||
"@vant/touch-emulator": "^1.3.2",
|
||||
"@vueuse/core": "^7.5.3",
|
||||
"@vueuse/integrations": "^7.5.3",
|
||||
"@vueuse/core": "^8.7.5",
|
||||
"@vueuse/integrations": "^8.7.5",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^0.24.0",
|
||||
"dayjs": "^1.10.7",
|
||||
"dexie": "^3.2.0",
|
||||
"element-plus": "1.3.0-beta.5",
|
||||
"axios": "^0.27.2",
|
||||
"dayjs": "^1.11.3",
|
||||
"dexie": "^3.2.2",
|
||||
"element-plus": "2.2.8",
|
||||
"lodash-es": "^4.17.21",
|
||||
"monaco-editor": "^0.31.1",
|
||||
"nanoid": "^3.1.32",
|
||||
"monaco-editor": "^0.33.0",
|
||||
"nanoid": "^4.0.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^1.0.0-1",
|
||||
"pinia": "^2.0.9",
|
||||
"pinia": "^2.0.14",
|
||||
"qrcode": "^1.5.0",
|
||||
"qs": "^6.10.3",
|
||||
"vant": "3.4.1",
|
||||
"vue": "3.2.26",
|
||||
"vue-router": "^4.0.12",
|
||||
"qs": "^6.11.0",
|
||||
"vant": "3.5.2",
|
||||
"vue": "3.2.37",
|
||||
"vue-router": "^4.0.16",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.0.2",
|
||||
"@commitlint/config-conventional": "^16.0.0",
|
||||
"@types/lodash-es": "^4.17.5",
|
||||
"@types/node": "^17.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
||||
"@typescript-eslint/parser": "^5.9.1",
|
||||
"@vitejs/plugin-legacy": "^1.6.4",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.3",
|
||||
"@vue/compiler-sfc": "3.2.26",
|
||||
"@commitlint/cli": "^17.0.3",
|
||||
"@commitlint/config-conventional": "^17.0.3",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.3",
|
||||
"@typescript-eslint/parser": "^5.30.3",
|
||||
"@vitejs/plugin-legacy": "^1.8.2",
|
||||
"@vitejs/plugin-vue": "^2.3.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"commitizen": "^4.2.4",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.7.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-define-config": "^1.2.2",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.3.0",
|
||||
"husky": "^7.0.4",
|
||||
"lint-staged": "^12.1.7",
|
||||
"postcss-html": "^1.3.0",
|
||||
"prettier": "^2.5.1",
|
||||
"sass": "1.48.0",
|
||||
"stylelint": "^14.2.0",
|
||||
"eslint": "^8.19.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-define-config": "^1.5.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.1.1",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^13.0.3",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-html": "^1.4.1",
|
||||
"postcss-scss": "^4.0.4",
|
||||
"prettier": "^2.7.1",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "1.53.0",
|
||||
"stylelint": "^14.9.1",
|
||||
"stylelint-config-html": "^1.0.0",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^6.0.0",
|
||||
"stylelint-config-standard": "^24.0.0",
|
||||
"stylelint-config-recommended": "^8.0.0",
|
||||
"stylelint-config-standard": "^26.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"stylelint-scss": "^4.1.0",
|
||||
"typescript": "^4.5.4",
|
||||
"unplugin-auto-import": "^0.5.11",
|
||||
"unplugin-vue-components": "^0.17.11",
|
||||
"vite": "2.7.12",
|
||||
"vite-plugin-windicss": "^1.6.2",
|
||||
"vue-eslint-parser": "^8.0.1",
|
||||
"windicss": "^3.4.2"
|
||||
"stylelint-scss": "^4.2.0",
|
||||
"typescript": "^4.7.4",
|
||||
"unplugin-auto-import": "^0.9.2",
|
||||
"unplugin-vue-components": "^0.21.0",
|
||||
"unplugin-vue-define-options": "^0.6.1",
|
||||
"vite": "2.9.13",
|
||||
"vite-plugin-checker": "^0.4.7",
|
||||
"vite-plugin-windicss": "^1.8.6",
|
||||
"vue-eslint-parser": "^9.0.3",
|
||||
"vue-tsc": "^0.38.2",
|
||||
"windicss": "^3.5.6"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -104,17 +116,14 @@
|
|||
},
|
||||
"homepage": "https://github.com/buqiyuan/vite-vue3-lowcode#readme",
|
||||
"engines": {
|
||||
"node": "^12 || >=14"
|
||||
"node": ">=14"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
|
||||
"prettier --write--parser json"
|
||||
],
|
||||
"package.json": [
|
||||
"*.json": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.vue": [
|
||||
|
@ -129,5 +138,6 @@
|
|||
"*.md": [
|
||||
"prettier --write"
|
||||
]
|
||||
}
|
||||
},
|
||||
"packageManager": "^pnpm@6.32.4"
|
||||
}
|
||||
|
|
3190
pnpm-lock.yaml
3190
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -7,46 +7,46 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { CacheEnum } from '@/enums'
|
||||
import { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils'
|
||||
import { defineComponent, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { CacheEnum } from '@/enums';
|
||||
import { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
setup() {
|
||||
const keepAliveRef = ref()
|
||||
const route = useRoute()
|
||||
const keepAliveRef = ref();
|
||||
const route = useRoute();
|
||||
const jsonData: VisualEditorModelValue = JSON.parse(
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string
|
||||
)
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string,
|
||||
);
|
||||
|
||||
// 不需要缓存的页面
|
||||
const notNeedcachePages = Object.keys(jsonData.pages).filter(
|
||||
(key) => !jsonData.pages[key].config.keepAlive
|
||||
)
|
||||
console.log('notNeedcachePages:', notNeedcachePages)
|
||||
(key) => !jsonData.pages[key].config.keepAlive,
|
||||
);
|
||||
console.log('notNeedcachePages:', notNeedcachePages);
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
(path) => {
|
||||
if (notNeedcachePages.includes(path)) {
|
||||
// 获取keep-alive缓存
|
||||
const routeCaches = keepAliveRef.value?.$?.__v_cache
|
||||
console.log('keep-alive cache', path, routeCaches)
|
||||
const routeCaches = keepAliveRef.value?.$?.__v_cache;
|
||||
console.log('keep-alive cache', path, routeCaches);
|
||||
// 从keep-alive的缓存中删除不需要缓存的路由
|
||||
routeCaches.delete(path)
|
||||
routeCaches.delete(path);
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
return { keepAliveRef }
|
||||
}
|
||||
})
|
||||
return { keepAliveRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body::-webkit-scrollbar {
|
||||
body::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
import router from './router'
|
||||
import router from './router';
|
||||
|
||||
import { setupVant } from '@/plugins/vant'
|
||||
import { setupVant } from '@/plugins/vant';
|
||||
|
||||
import 'animate.css'
|
||||
import 'animate.css';
|
||||
|
||||
const app = createApp(App)
|
||||
const app = createApp(App);
|
||||
|
||||
// 安装vant插件
|
||||
setupVant(app)
|
||||
setupVant(app);
|
||||
|
||||
app.config.globalProperties.$$refs = {}
|
||||
app.config.globalProperties.$$refs = {};
|
||||
|
||||
// if (import.meta.env.DEV) {
|
||||
window.$$refs = app.config.globalProperties.$$refs
|
||||
window.$$refs = app.config.globalProperties.$$refs;
|
||||
// }
|
||||
|
||||
app.use(router).mount('#app')
|
||||
app.use(router).mount('#app');
|
||||
|
|
|
@ -6,30 +6,30 @@
|
|||
* @Description: 路由表
|
||||
* @FilePath: \vite-vue3-lowcode\preview\router.ts
|
||||
*/
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils'
|
||||
import { CacheEnum } from '@/enums'
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
||||
import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils';
|
||||
import { CacheEnum } from '@/enums';
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('./views/preview.vue')
|
||||
}
|
||||
]
|
||||
component: () => import('./views/preview.vue'),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
})
|
||||
routes,
|
||||
});
|
||||
|
||||
// 获取本地缓存的页面数据
|
||||
const jsonData: VisualEditorModelValue = JSON.parse(
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string
|
||||
)
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string,
|
||||
);
|
||||
|
||||
router.beforeEach((to) => {
|
||||
document.title = jsonData?.pages?.[to.path]?.title ?? document.title
|
||||
return true
|
||||
})
|
||||
document.title = jsonData?.pages?.[to.path]?.title ?? document.title;
|
||||
return true;
|
||||
});
|
||||
|
||||
export default router
|
||||
export default router;
|
||||
|
|
|
@ -5,7 +5,7 @@ export enum ResultEnum {
|
|||
SUCCESS = 0,
|
||||
ERROR = -1,
|
||||
TIMEOUT = 10042,
|
||||
TYPE = 'success'
|
||||
TYPE = 'success',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ export enum RequestEnum {
|
|||
POST = 'POST',
|
||||
PATCH = 'PATCH',
|
||||
PUT = 'PUT',
|
||||
DELETE = 'DELETE'
|
||||
DELETE = 'DELETE',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,5 +30,5 @@ export enum ContentTypeEnum {
|
|||
// form-data 一般配合qs
|
||||
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
// form-data 上传
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8'
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8',
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import axios, { AxiosRequestConfig } from 'axios';
|
|||
import qs from 'qs';
|
||||
// import store from '@/store'
|
||||
import { Toast } from 'vant';
|
||||
import router from '@/router';
|
||||
import { ContentTypeEnum } from './httpEnum';
|
||||
import router from '@/router';
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
|
@ -85,7 +85,7 @@ service.interceptors.response.use(
|
|||
if (error.message?.includes('timeout')) {
|
||||
Toast('请求超时!');
|
||||
}
|
||||
console.log('err' + error); // for debug
|
||||
console.log(`err${error}`); // for debug
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\preview\views\comp-render.tsx
|
||||
*/
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
||||
import { visualConfig } from '@/visual.config'
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CompRender',
|
||||
props: {
|
||||
element: {
|
||||
type: Object as PropType<VisualEditorBlockData>,
|
||||
default: () => ({})
|
||||
}
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
return visualConfig.componentMap[props.element.componentKey].render({
|
||||
|
@ -24,7 +24,7 @@ export default defineComponent({
|
|||
props: props.element.props || {},
|
||||
model: {},
|
||||
block: props.element,
|
||||
custom: {}
|
||||
})
|
||||
}
|
||||
})
|
||||
custom: {},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,59 +13,59 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs, onMounted } from 'vue'
|
||||
import { Toast } from 'vant'
|
||||
import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils'
|
||||
import SlotItem from './slot-item.vue'
|
||||
import router from '../router'
|
||||
import { CacheEnum } from '@/enums'
|
||||
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import router from '../router';
|
||||
import SlotItem from './slot-item.vue';
|
||||
import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils';
|
||||
import { CacheEnum } from '@/enums';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'Preview',
|
||||
components: {
|
||||
SlotItem
|
||||
SlotItem,
|
||||
},
|
||||
setup() {
|
||||
const jsonData: VisualEditorModelValue = JSON.parse(
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string
|
||||
)
|
||||
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string,
|
||||
);
|
||||
|
||||
if (!jsonData || !Object.keys(jsonData.pages)) {
|
||||
Toast.fail('当前没有可以预览的页面!')
|
||||
Toast.fail('当前没有可以预览的页面!');
|
||||
}
|
||||
|
||||
const route = router.currentRoute
|
||||
const route = router.currentRoute;
|
||||
|
||||
const currentPage = jsonData.pages[route.value.path]
|
||||
console.log('currentPage:', currentPage)
|
||||
const currentPage = jsonData.pages[route.value.path];
|
||||
console.log('currentPage:', currentPage);
|
||||
|
||||
const state = reactive({
|
||||
blocks: currentPage?.blocks
|
||||
})
|
||||
blocks: currentPage?.blocks,
|
||||
});
|
||||
|
||||
// 如果当前页面路由匹配不到,则重定向到首页
|
||||
if (!state.blocks) {
|
||||
router.replace('/')
|
||||
router.replace('/');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (currentPage?.config) {
|
||||
const { bgImage, bgColor } = currentPage.config
|
||||
const { bgImage, bgColor } = currentPage.config;
|
||||
const bodyStyleStr = `
|
||||
body {
|
||||
background-color: ${bgColor};
|
||||
background-image: url(${bgImage});
|
||||
}
|
||||
`
|
||||
document.styleSheets[0].insertRule(bodyStyleStr)
|
||||
`;
|
||||
document.styleSheets[0].insertRule(bodyStyleStr);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
actions: jsonData.actions,
|
||||
models: jsonData.models
|
||||
}
|
||||
}
|
||||
})
|
||||
models: jsonData.models,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -19,82 +19,84 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, PropType } from 'vue'
|
||||
import CompRender from './comp-render'
|
||||
import { useAnimate } from '@/hooks/useAnimate'
|
||||
import type {
|
||||
import { defineComponent, onMounted, PropType } from 'vue';
|
||||
import request from '../utils/http/request';
|
||||
import { ContentTypeEnum } from '../utils/http/httpEnum';
|
||||
import CompRender from './comp-render';
|
||||
import type {
|
||||
VisualEditorBlockData,
|
||||
VisualEditorActions,
|
||||
VisualEditorModel,
|
||||
FetchApiItem
|
||||
} from '@/visual-editor/visual-editor.utils'
|
||||
import request from '../utils/http/request'
|
||||
import { ContentTypeEnum } from '../utils/http/httpEnum'
|
||||
FetchApiItem,
|
||||
} from '@/visual-editor/visual-editor.utils';
|
||||
import { useAnimate } from '@/hooks/useAnimate';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'SlotItem',
|
||||
components: { CompRender },
|
||||
props: {
|
||||
element: {
|
||||
type: [Object] as PropType<VisualEditorBlockData>,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
actions: {
|
||||
type: Object as PropType<VisualEditorActions>,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
models: {
|
||||
type: Object as PropType<VisualEditorModel[]>,
|
||||
default: () => ({})
|
||||
}
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
// TODO 生成组件事件
|
||||
const events = props.element.actions.reduce((prev, curr) => {
|
||||
prev[curr.event] = async () => {
|
||||
for (const handle of curr.handle) {
|
||||
const [scopeType, actionType, handleKey] = handle.link
|
||||
const [scopeType, actionType, handleKey] = handle.link;
|
||||
if (scopeType === 'global') {
|
||||
const apis: FetchApiItem[] = props.actions[actionType].apis
|
||||
const { data, options } = apis.find((item) => item.key == handleKey)!
|
||||
const pramsObj = {}
|
||||
const apis: FetchApiItem[] = props.actions[actionType].apis;
|
||||
// const { data, options } = apis.find((item) => item.key == handleKey)!;
|
||||
const { options } = apis.find((item) => item.key == handleKey)!;
|
||||
// const pramsObj = {};
|
||||
await request({
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': ContentTypeEnum[options.contentType]
|
||||
'Content-Type': ContentTypeEnum[options.contentType],
|
||||
},
|
||||
data: {
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
}
|
||||
})
|
||||
password: '123456',
|
||||
},
|
||||
});
|
||||
} else if (scopeType === 'component') {
|
||||
console.log('scopeType', scopeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return prev
|
||||
}, {})
|
||||
};
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
onMounted(() => {
|
||||
const animations = props.element.animations
|
||||
const animations = props.element.animations;
|
||||
if (animations?.length) {
|
||||
let animateEl =
|
||||
(window.$$refs[props.element._vid]?.$el as HTMLElement) ??
|
||||
(window.$$refs[props.element._vid] as HTMLElement)
|
||||
(window.$$refs[props.element._vid] as HTMLElement);
|
||||
|
||||
animateEl = animateEl?.closest('.__slot-item')?.firstChild as HTMLElement
|
||||
animateEl = animateEl?.closest('.__slot-item')?.firstChild as HTMLElement;
|
||||
|
||||
if (animateEl) {
|
||||
useAnimate(animateEl, animations)
|
||||
useAnimate(animateEl, animations);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
events
|
||||
}
|
||||
}
|
||||
})
|
||||
events,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
22
src/App.vue
22
src/App.vue
|
@ -7,21 +7,21 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide } from 'vue'
|
||||
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
|
||||
import { initVisualData, injectKey, localKey } from '@/visual-editor/hooks/useVisualData'
|
||||
import { provide } from 'vue';
|
||||
import zhCn from 'element-plus/lib/locale/lang/zh-cn';
|
||||
import { initVisualData, injectKey, localKey } from '@/visual-editor/hooks/useVisualData';
|
||||
|
||||
const visualData = initVisualData()
|
||||
// 注入可视化编辑器所有配置
|
||||
provide(injectKey, visualData)
|
||||
const visualData = initVisualData();
|
||||
// 注入可视化编辑器所有配置
|
||||
provide(injectKey, visualData);
|
||||
|
||||
const { jsonData } = visualData
|
||||
const { jsonData } = visualData;
|
||||
|
||||
window.addEventListener('beforeunload', () => {
|
||||
sessionStorage.setItem(localKey, JSON.stringify(jsonData))
|
||||
})
|
||||
window.addEventListener('beforeunload', () => {
|
||||
sessionStorage.setItem(localKey, JSON.stringify(jsonData));
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'style/common';
|
||||
@import 'style/common';
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface NavItem {
|
||||
path: string
|
||||
name: string
|
||||
isActive: boolean
|
||||
path: string;
|
||||
name: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ export enum ResultEnum {
|
|||
SUCCESS = 0,
|
||||
ERROR = -1,
|
||||
TIMEOUT = 10042,
|
||||
TYPE = 'success'
|
||||
TYPE = 'success',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ export enum RequestEnum {
|
|||
POST = 'POST',
|
||||
PATCH = 'PATCH',
|
||||
PUT = 'PUT',
|
||||
DELETE = 'DELETE'
|
||||
DELETE = 'DELETE',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,5 +30,5 @@ export enum ContentTypeEnum {
|
|||
// form-data 一般配合qs
|
||||
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
// form-data 上传
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8'
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8',
|
||||
}
|
||||
|
|
|
@ -10,5 +10,5 @@
|
|||
* @description 本地缓存枚举
|
||||
*/
|
||||
export enum CacheEnum {
|
||||
PAGE_DATA_KEY = 'PAGE_DATA_KEY'
|
||||
PAGE_DATA_KEY = 'PAGE_DATA_KEY',
|
||||
}
|
||||
|
|
|
@ -7,55 +7,55 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\hooks\useAnimate.ts
|
||||
*/
|
||||
|
||||
import type { Animation } from '@/visual-editor/visual-editor.utils'
|
||||
import type { Animation } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
export const useAnimate = async (
|
||||
animateEl: HTMLElement,
|
||||
animations: Animation | Animation[],
|
||||
prefixCls = 'animate__'
|
||||
prefixCls = 'animate__',
|
||||
) => {
|
||||
animations = Array.isArray(animations) ? animations : [animations]
|
||||
animations = Array.isArray(animations) ? animations : [animations];
|
||||
|
||||
const play = (animate: Animation) =>
|
||||
new Promise((resolve) => {
|
||||
if (animateEl) {
|
||||
const animationName = `${prefixCls}${animate.value}`
|
||||
const animationName = `${prefixCls}${animate.value}`;
|
||||
|
||||
// 过滤可能残留的animate.css动画类名
|
||||
animateEl.classList.value = animateEl.classList.value
|
||||
.split(' ')
|
||||
.filter((item) => !item.includes(prefixCls))
|
||||
.join(' ')
|
||||
.join(' ');
|
||||
|
||||
// 设置动画属性
|
||||
const setAnimate = () => {
|
||||
animateEl.style.setProperty('--animate-duration', `${animate.duration}s`)
|
||||
animateEl.style.setProperty('animation-delay', `${animate.delay}s`)
|
||||
animateEl.style.setProperty('--animate-duration', `${animate.duration}s`);
|
||||
animateEl.style.setProperty('animation-delay', `${animate.delay}s`);
|
||||
animateEl.style.setProperty(
|
||||
'animation-iteration-count',
|
||||
`${animate.infinite ? 'infinite' : animate.count}`
|
||||
)
|
||||
animateEl?.classList.add(`${prefixCls}animated`, animationName)
|
||||
}
|
||||
`${animate.infinite ? 'infinite' : animate.count}`,
|
||||
);
|
||||
animateEl?.classList.add(`${prefixCls}animated`, animationName);
|
||||
};
|
||||
|
||||
// 动画结束时,删除类名
|
||||
const handleAnimationEnd = (event?: AnimationEvent) => {
|
||||
event?.stopPropagation()
|
||||
animateEl.classList.remove(`${prefixCls}animated`, animationName)
|
||||
animateEl.removeEventListener('animationend', handleAnimationEnd)
|
||||
resolve('animation end')
|
||||
}
|
||||
event?.stopPropagation();
|
||||
animateEl.classList.remove(`${prefixCls}animated`, animationName);
|
||||
animateEl.removeEventListener('animationend', handleAnimationEnd);
|
||||
resolve('animation end');
|
||||
};
|
||||
|
||||
setAnimate()
|
||||
setAnimate();
|
||||
|
||||
animateEl?.addEventListener('animationend', handleAnimationEnd, { once: true })
|
||||
animateEl?.addEventListener('animationend', handleAnimationEnd, { once: true });
|
||||
// animateEl?.addEventListener('animationcancel', handleAnimationEnd, { once: true })
|
||||
} else {
|
||||
resolve('动画执行失败!执行动画元素不存在!')
|
||||
resolve('动画执行失败!执行动画元素不存在!');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
for (const item of animations) {
|
||||
await play(item)
|
||||
await play(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,23 +5,23 @@
|
|||
* @description:useGlobalProperties
|
||||
* @update: 2021/5/3 21:13
|
||||
*/
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import { RouteLocationNormalizedLoaded, Router } from 'vue-router'
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import { RouteLocationNormalizedLoaded, Router } from 'vue-router';
|
||||
|
||||
interface GlobalProperties {
|
||||
$$refs: any
|
||||
$route: RouteLocationNormalizedLoaded
|
||||
$router: Router
|
||||
$$refs: any;
|
||||
$route: RouteLocationNormalizedLoaded;
|
||||
$router: Router;
|
||||
}
|
||||
|
||||
export const useGlobalProperties = () => {
|
||||
const globalProperties = getCurrentInstance()!.appContext.config
|
||||
.globalProperties as GlobalProperties
|
||||
.globalProperties as GlobalProperties;
|
||||
|
||||
const registerRef = (el, _vid: string) => el && (globalProperties.$$refs[_vid] = el)
|
||||
const registerRef = (el, _vid: string) => el && (globalProperties.$$refs[_vid] = el);
|
||||
|
||||
return {
|
||||
globalProperties,
|
||||
registerRef
|
||||
}
|
||||
}
|
||||
registerRef,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Button } from 'vant'
|
||||
import { Button } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'button',
|
||||
|
@ -13,21 +13,21 @@ export default {
|
|||
label: '按钮',
|
||||
preview: () => <Button type={'primary'}>按钮</Button>,
|
||||
render: ({ props, block, styles }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
<Button ref={(el) => registerRef(el, block._vid)} {...props}></Button>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
resize: {
|
||||
height: true,
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
events: [
|
||||
{ label: '点击按钮,且按钮状态不为加载或禁用时触发', value: 'click' },
|
||||
{ label: '开始触摸按钮时触发', value: 'touchstart' }
|
||||
{ label: '开始触摸按钮时触发', value: 'touchstart' },
|
||||
],
|
||||
props: {
|
||||
text: createEditorInputProp({ label: '按钮文字', defaultValue: '按钮' }),
|
||||
|
@ -36,48 +36,48 @@ export default {
|
|||
options: [
|
||||
{
|
||||
label: '主要按钮',
|
||||
value: 'primary'
|
||||
value: 'primary',
|
||||
},
|
||||
{
|
||||
label: '成功按钮',
|
||||
value: 'success'
|
||||
value: 'success',
|
||||
},
|
||||
{
|
||||
label: '默认按钮',
|
||||
value: 'default'
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
label: '警告按钮',
|
||||
value: 'warning'
|
||||
value: 'warning',
|
||||
},
|
||||
{
|
||||
label: '危险按钮',
|
||||
value: 'danger'
|
||||
}
|
||||
value: 'danger',
|
||||
},
|
||||
],
|
||||
defaultValue: 'default'
|
||||
defaultValue: 'default',
|
||||
}),
|
||||
size: createEditorSelectProp({
|
||||
label: '按钮尺寸',
|
||||
options: [
|
||||
{
|
||||
label: '大型',
|
||||
value: 'large'
|
||||
value: 'large',
|
||||
},
|
||||
{
|
||||
label: '普通',
|
||||
value: 'normal'
|
||||
value: 'normal',
|
||||
},
|
||||
{
|
||||
label: '小型',
|
||||
value: 'small'
|
||||
value: 'small',
|
||||
},
|
||||
{
|
||||
label: '迷你',
|
||||
value: 'mini'
|
||||
}
|
||||
value: 'mini',
|
||||
},
|
||||
],
|
||||
defaultValue: 'normal'
|
||||
defaultValue: 'normal',
|
||||
}),
|
||||
'native-type': createEditorSelectProp({
|
||||
label: '原生button的type属性',
|
||||
|
@ -85,14 +85,14 @@ export default {
|
|||
{ label: '普通button', value: 'button' },
|
||||
{
|
||||
label: '表单提交按钮',
|
||||
value: 'submit'
|
||||
value: 'submit',
|
||||
},
|
||||
{
|
||||
label: '表单重置按钮',
|
||||
value: 'reset'
|
||||
}
|
||||
value: 'reset',
|
||||
},
|
||||
],
|
||||
defaultValue: 'button'
|
||||
defaultValue: 'button',
|
||||
}),
|
||||
to: createEditorInputProp({ label: '路由跳转' }),
|
||||
url: createEditorInputProp({ label: '跳转链接' }),
|
||||
|
@ -103,7 +103,7 @@ export default {
|
|||
block: createEditorSwitchProp({ label: '是否为块级元素', defaultValue: false }),
|
||||
color: createEditorInputProp({
|
||||
label: '按钮颜色',
|
||||
tips: '按钮颜色,支持传入 linear-gradient 渐变色'
|
||||
tips: '按钮颜色,支持传入 linear-gradient 渐变色',
|
||||
}),
|
||||
disabled: createEditorSwitchProp({ label: '是否禁用按钮' }),
|
||||
hairline: createEditorSwitchProp({ label: '是否使用 0.5px 边框' }),
|
||||
|
@ -113,17 +113,17 @@ export default {
|
|||
options: [
|
||||
{
|
||||
label: '左侧',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '右侧',
|
||||
value: 'right'
|
||||
}
|
||||
]
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
}),
|
||||
'icon-prefix': createEditorInputProp({
|
||||
label: '图标类名前缀',
|
||||
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性'
|
||||
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性',
|
||||
}),
|
||||
loading: createEditorSwitchProp({ label: '是否显示为加载状态' }),
|
||||
'loading-size': createEditorInputProp({ label: '加载图标大小' }),
|
||||
|
@ -132,9 +132,9 @@ export default {
|
|||
label: '加载图标类型',
|
||||
options: [
|
||||
{ label: 'circular', value: 'circular' },
|
||||
{ label: 'spinner', value: 'spinner' }
|
||||
{ label: 'spinner', value: 'spinner' },
|
||||
],
|
||||
defaultValue: 'circular'
|
||||
})
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
defaultValue: 'circular',
|
||||
}),
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
* @Description: 表单项类型 - 复选框
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\checkbox\index.tsx
|
||||
*/
|
||||
import { computed } from 'vue'
|
||||
import { Field, Checkbox, CheckboxGroup } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { computed } from 'vue';
|
||||
import { Field, Checkbox, CheckboxGroup } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorCrossSortableProp,
|
||||
createEditorModelBindProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorModelBindProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'checkbox',
|
||||
|
@ -33,14 +33,16 @@ export default {
|
|||
</CheckboxGroup>
|
||||
),
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
const checkList = computed({
|
||||
get() {
|
||||
return typeof props.modelValue === 'string' ? props.modelValue.split(',') : props.modelValue
|
||||
return typeof props.modelValue === 'string'
|
||||
? props.modelValue.split(',')
|
||||
: props.modelValue;
|
||||
},
|
||||
set: (val) => (props.modelValue = val)
|
||||
})
|
||||
set: (val) => (props.modelValue = val),
|
||||
});
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -61,16 +63,16 @@ export default {
|
|||
</Checkbox>
|
||||
))}
|
||||
</CheckboxGroup>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputProp({
|
||||
label: '默认值',
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
}),
|
||||
name: createEditorModelBindProp({ label: '字段绑定', defaultValue: '' }),
|
||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '复选框' }),
|
||||
|
@ -81,33 +83,33 @@ export default {
|
|||
defaultValue: [
|
||||
{ label: '胡萝卜', value: 'carrot' },
|
||||
{ label: '白菜', value: 'cabbage' },
|
||||
{ label: '猪', value: 'pig' }
|
||||
]
|
||||
{ label: '猪', value: 'pig' },
|
||||
],
|
||||
}),
|
||||
direction: createEditorSelectProp({
|
||||
label: '排列方向',
|
||||
options: [
|
||||
{
|
||||
label: '水平',
|
||||
value: 'horizontal'
|
||||
value: 'horizontal',
|
||||
},
|
||||
{
|
||||
label: '垂直',
|
||||
value: 'vertical'
|
||||
}
|
||||
value: 'vertical',
|
||||
},
|
||||
],
|
||||
defaultValue: 'horizontal'
|
||||
defaultValue: 'horizontal',
|
||||
}),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
},
|
||||
events: [
|
||||
{ label: '当绑定值变化时触发的事件', value: 'change' },
|
||||
{ label: '点击复选框时触发', value: 'click' }
|
||||
{ label: '点击复选框时触发', value: 'click' },
|
||||
],
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import { Field, Popup, DatetimePicker } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { useAttrs, reactive } from 'vue';
|
||||
import { Field, Popup, DatetimePicker } from 'vant';
|
||||
import dayjs from 'dayjs';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputNumberProp,
|
||||
createEditorInputProp,
|
||||
createEditorModelBindProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import { useAttrs, reactive } from 'vue'
|
||||
import { isDate } from '@/visual-editor/utils/is'
|
||||
import dayjs from 'dayjs'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import { isDate } from '@/visual-editor/utils/is';
|
||||
|
||||
const dateType = {
|
||||
'month-day': 'MM-DD',
|
||||
'year-month': 'YYYY-MM',
|
||||
date: 'YYYY-MM-DD',
|
||||
datehour: 'YYYY-MM-DD HH',
|
||||
datetime: 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
datetime: 'YYYY-MM-DD HH:mm:ss',
|
||||
};
|
||||
|
||||
export default {
|
||||
key: 'datetimePicker',
|
||||
|
@ -27,23 +27,25 @@ export default {
|
|||
label: '表单项类型 - 时间选择器',
|
||||
preview: () => <Field name="datetimePicker" label="时间选择器" placeholder={'点击选择'}></Field>,
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
const attrs = useAttrs()
|
||||
const attrs = useAttrs();
|
||||
|
||||
const state = reactive({
|
||||
showPicker: false,
|
||||
text: '',
|
||||
currentDate: new Date()
|
||||
})
|
||||
currentDate: new Date(),
|
||||
});
|
||||
|
||||
const onConfirm = (value) => {
|
||||
const date = isDate(value) ? dayjs(value).format(props.format || dateType[props.type]) : value
|
||||
props.modelValue = date
|
||||
state.text = date
|
||||
state.showPicker = false
|
||||
console.log(props)
|
||||
}
|
||||
const date = isDate(value)
|
||||
? dayjs(value).format(props.format || dateType[props.type])
|
||||
: value;
|
||||
props.modelValue = date;
|
||||
state.text = date;
|
||||
state.showPicker = false;
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -60,7 +62,7 @@ export default {
|
|||
<span class={'placeholder'}>{props.placeholder}</span>
|
||||
) : (
|
||||
state.text
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Popup v-model={[state.showPicker, 'show']} position={'bottom'} teleport="body">
|
||||
|
@ -74,7 +76,7 @@ export default {
|
|||
/>
|
||||
</Popup>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputProp({ label: '默认值' }),
|
||||
|
@ -86,60 +88,60 @@ export default {
|
|||
options: [
|
||||
{
|
||||
label: 'date',
|
||||
value: 'date'
|
||||
value: 'date',
|
||||
},
|
||||
{
|
||||
label: 'datetime',
|
||||
value: 'datetime'
|
||||
value: 'datetime',
|
||||
},
|
||||
{
|
||||
label: 'year-month',
|
||||
value: 'year-month'
|
||||
value: 'year-month',
|
||||
},
|
||||
{
|
||||
label: 'month-day',
|
||||
value: 'month-day'
|
||||
value: 'month-day',
|
||||
},
|
||||
{
|
||||
label: 'datehour',
|
||||
value: 'datehour'
|
||||
}
|
||||
value: 'datehour',
|
||||
},
|
||||
],
|
||||
defaultValue: 'datetime'
|
||||
defaultValue: 'datetime',
|
||||
}),
|
||||
format: createEditorInputProp({
|
||||
label: '自定义日期格式化值',
|
||||
tips: 'YYYY-MM-DD HH:mm:ss',
|
||||
defaultValue: ''
|
||||
defaultValue: '',
|
||||
}),
|
||||
cancelButtonText: createEditorInputProp({ label: '取消按钮文字' }),
|
||||
columnsOrder: createEditorInputProp({
|
||||
label: '自定义列排序数组',
|
||||
tips: '可选值为:year、month、day、hour、minute,传多个值以英文逗号隔开'
|
||||
tips: '可选值为:year、month、day、hour、minute,传多个值以英文逗号隔开',
|
||||
}),
|
||||
confirmButtonText: createEditorInputProp({ label: '确认按钮文字' }),
|
||||
filter: createEditorInputProp({ label: '选项过滤函数' }),
|
||||
formatter: createEditorInputProp({ label: '选项格式化函数' }),
|
||||
itemHeight: createEditorInputProp({
|
||||
label: '选项高度',
|
||||
tips: '支持 px vw vh rem 单位,默认 px'
|
||||
tips: '支持 px vw vh rem 单位,默认 px',
|
||||
}),
|
||||
loading: createEditorSwitchProp({ label: '是否显示加载状态' }),
|
||||
showToolbar: createEditorSwitchProp({ label: '是否显示顶部栏' }),
|
||||
swipeDuration: createEditorInputProp({ label: '快速滑动时惯性滚动的时长,单位ms' }),
|
||||
visibleItemCount: createEditorInputNumberProp({ label: '可见的选项个数', defaultValue: 6 }),
|
||||
placeholder: createEditorInputProp({ label: '占位符', defaultValue: '请选择' }),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
},
|
||||
events: [
|
||||
{ label: '当值变化时触发的事件', value: 'change' },
|
||||
{ label: '点击完成按钮时触发的事件', value: 'confirm' },
|
||||
{ label: '点击取消按钮时触发的事件', value: 'cancel' }
|
||||
{ label: '点击取消按钮时触发的事件', value: 'cancel' },
|
||||
],
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* @Description: 分割线
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\divider\index.tsx
|
||||
*/
|
||||
import { Divider } from 'vant'
|
||||
import { computed } from 'vue';
|
||||
import { Divider } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import {
|
||||
createEditorColorProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { computed } from 'vue'
|
||||
createEditorSelectProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'divider',
|
||||
|
@ -23,23 +23,23 @@ export default {
|
|||
label: '分割线',
|
||||
preview: () => <Divider style="width:190px">文本</Divider>,
|
||||
render: ({ props, block, styles }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
const style = computed(() => ({
|
||||
width: '100%',
|
||||
color: props['text-color'],
|
||||
borderColor: props['divider-color']
|
||||
}))
|
||||
borderColor: props['divider-color'],
|
||||
}));
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
<Divider ref={(el) => registerRef(el, block._vid)} {...props} style={style.value}>
|
||||
{{
|
||||
default: () => props.text
|
||||
default: () => props.text,
|
||||
}}
|
||||
</Divider>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
text: createEditorInputProp({ label: '展示文本', defaultValue: '文本' }),
|
||||
|
@ -48,12 +48,12 @@ export default {
|
|||
options: [
|
||||
{ label: '左边', value: 'left' },
|
||||
{ label: '中间', value: 'center' },
|
||||
{ label: '右边', value: 'right' }
|
||||
{ label: '右边', value: 'right' },
|
||||
],
|
||||
defaultValue: 'center'
|
||||
defaultValue: 'center',
|
||||
}),
|
||||
dashed: createEditorSwitchProp({ label: '是否为虚线' }),
|
||||
'text-color': createEditorColorProp({ label: '文本颜色' }),
|
||||
'divider-color': createEditorColorProp({ label: '分割线颜色' })
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
'divider-color': createEditorColorProp({ label: '分割线颜色' }),
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\image\index.tsx
|
||||
*/
|
||||
import { Image } from 'vant';
|
||||
import { Picture } from '@element-plus/icons-vue';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import { Picture } from '@element-plus/icons-vue';
|
||||
|
||||
export default {
|
||||
key: 'image',
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const modules = import.meta.globEager('./*/index.tsx')
|
||||
const modules = import.meta.globEager('./*/index.tsx');
|
||||
|
||||
const components = {}
|
||||
const components = {};
|
||||
|
||||
Object.keys(modules).forEach((key: string) => {
|
||||
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1')
|
||||
components[name] = modules[key]?.default || modules[key]
|
||||
})
|
||||
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1');
|
||||
components[name] = modules[key]?.default || modules[key];
|
||||
});
|
||||
|
||||
console.log(components, 'base-widgets')
|
||||
export default components
|
||||
console.log(components, 'base-widgets');
|
||||
export default components;
|
||||
|
|
|
@ -2,8 +2,8 @@ import {
|
|||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorModelBindProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorModelBindProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -15,7 +15,7 @@ import {
|
|||
export const createFieldProps = () => ({
|
||||
modelValue: createEditorInputProp({
|
||||
label: '默认值',
|
||||
defaultValue: ''
|
||||
defaultValue: '',
|
||||
}),
|
||||
name: createEditorModelBindProp({ label: '字段绑定', defaultValue: '' }),
|
||||
label: createEditorInputProp({ label: '输入框左侧文本', defaultValue: '输入框' }),
|
||||
|
@ -27,9 +27,9 @@ export const createFieldProps = () => ({
|
|||
{ label: '文本域', value: 'textarea' },
|
||||
{ label: '密码', value: 'password' },
|
||||
{ label: '电话', value: 'tel' },
|
||||
{ label: '小数点', value: 'digit' }
|
||||
{ label: '小数点', value: 'digit' },
|
||||
],
|
||||
defaultValue: 'text'
|
||||
defaultValue: 'text',
|
||||
}),
|
||||
placeholder: createEditorInputProp({ label: '占位提示文字', defaultValue: '请输入' }),
|
||||
colon: createEditorSwitchProp({ label: '是否在 label 后面添加冒号' }),
|
||||
|
@ -41,18 +41,18 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
|
@ -62,80 +62,80 @@ export const createFieldProps = () => ({
|
|||
'arrow-direction': createEditorInputProp({
|
||||
label: '箭头方向',
|
||||
defaultValue: '',
|
||||
tips: '箭头方向,可选值为 left up down'
|
||||
tips: '箭头方向,可选值为 left up down',
|
||||
}),
|
||||
autosize: createEditorSwitchProp({
|
||||
label: '自适应内容高度',
|
||||
defaultValue: false,
|
||||
tips: '是否自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为px'
|
||||
tips: '是否自适应内容高度,只对 textarea 有效,可传入对象,如 { maxHeight: 100, minHeight: 50 },单位为px',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
center: createEditorSwitchProp({ label: '内容垂直居中' }),
|
||||
'clear-icon': createEditorInputProp({
|
||||
label: '清除图标',
|
||||
tips: '清除图标名称或图片链接'
|
||||
tips: '清除图标名称或图片链接',
|
||||
}),
|
||||
'clear-trigger': createEditorSelectProp({
|
||||
label: '清除图标显示时机',
|
||||
options: [
|
||||
{ label: '输入框不为空时展示', value: 'always' },
|
||||
{ label: '输入框聚焦且不为空时展示', value: 'focus' }
|
||||
{ label: '输入框聚焦且不为空时展示', value: 'focus' },
|
||||
],
|
||||
defaultValue: 'always',
|
||||
tips: '显示清除图标的时机,always 表示输入框不为空时展示,focus 表示输入框聚焦且不为空时展示'
|
||||
tips: '显示清除图标的时机,always 表示输入框不为空时展示,focus 表示输入框聚焦且不为空时展示',
|
||||
}),
|
||||
clearable: createEditorSwitchProp({
|
||||
label: '是否启用清除图标',
|
||||
defaultValue: false,
|
||||
tips: '是否启用清除图标,点击清除图标后会清空输入框'
|
||||
tips: '是否启用清除图标,点击清除图标后会清空输入框',
|
||||
}),
|
||||
clickable: createEditorSwitchProp({ label: '是否开启点击反馈' }),
|
||||
'format-trigger': createEditorInputProp({ label: '格式化函数触发的时机' }),
|
||||
formatter: createEditorInputProp({ label: '输入内容格式化函数' }),
|
||||
'icon-prefix': createEditorInputProp({
|
||||
label: '图标类名前缀',
|
||||
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性'
|
||||
tips: '图标类名前缀,同 Icon 组件的 class-prefix 属性',
|
||||
}),
|
||||
'input-align': createEditorSelectProp({
|
||||
label: '输入框对齐方式',
|
||||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
'label-align': createEditorSelectProp({
|
||||
label: '左侧文本对齐方式',
|
||||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
'label-width': createEditorInputProp({ label: '左侧文本宽度' }),
|
||||
maxlength: createEditorInputProp({ label: '输入的最大字符数', defaultValue: 500 }),
|
||||
'show-word-limit': createEditorSwitchProp({
|
||||
label: '是否显示字数统计',
|
||||
tips: '需要设置 maxlength 属性'
|
||||
})
|
||||
})
|
||||
tips: '需要设置 maxlength 属性',
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
* @Description: 表单项类型 - 输入框
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\input\index.tsx
|
||||
*/
|
||||
import { Field } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { Field } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'input',
|
||||
|
@ -19,11 +19,11 @@ export default {
|
|||
<Field name="用户名" label="用户名" labelWidth={50} colon placeholder="请输入用户名" />
|
||||
),
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
let rules = []
|
||||
let rules = [];
|
||||
try {
|
||||
rules = JSON.parse(props.rules)
|
||||
rules = JSON.parse(props.rules);
|
||||
} catch (e) {}
|
||||
|
||||
return () => (
|
||||
|
@ -36,7 +36,7 @@ export default {
|
|||
rules={rules}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
events: [
|
||||
{ label: '输入框内容变化时触发', value: 'update:model-value' },
|
||||
|
@ -46,13 +46,13 @@ export default {
|
|||
{ label: '点击组件时触发', value: 'click' },
|
||||
{ label: '点击输入区域时触发', value: 'click-input' },
|
||||
{ label: '点击左侧图标时触发', value: 'click-left-icon' },
|
||||
{ label: '点击右侧图标时触发', value: 'click-right-icon' }
|
||||
{ label: '点击右侧图标时触发', value: 'click-right-icon' },
|
||||
],
|
||||
props: createFieldProps(),
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
* @Description: 导航栏
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\nav-bar\index.tsx
|
||||
*/
|
||||
import { NavBar } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createEditorInputProp, createEditorSwitchProp } from '@/visual-editor/visual-editor.props'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { onBeforeUnmount, onMounted } from 'vue'
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
import { NavBar } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { createEditorInputProp, createEditorSwitchProp } from '@/visual-editor/visual-editor.props';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'nav-bar',
|
||||
|
@ -20,42 +20,42 @@ export default {
|
|||
<NavBar title="标题" left-text="返回" right-text="按钮" left-arrow style={{ width: '100%' }} />
|
||||
),
|
||||
render: ({ props, block }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
onMounted(() => {
|
||||
const compEl = window.$$refs[block._vid]?.$el
|
||||
const draggableEl = compEl?.closest('div[data-draggable]')
|
||||
const navbarEl = draggableEl?.querySelector('.van-nav-bar--fixed') as HTMLDivElement
|
||||
const compEl = window.$$refs[block._vid]?.$el;
|
||||
const draggableEl = compEl?.closest('div[data-draggable]');
|
||||
const navbarEl = draggableEl?.querySelector('.van-nav-bar--fixed') as HTMLDivElement;
|
||||
const dragArea = document.querySelector(
|
||||
'.simulator-editor-content > .dragArea '
|
||||
) as HTMLDivElement
|
||||
'.simulator-editor-content > .dragArea ',
|
||||
) as HTMLDivElement;
|
||||
if (draggableEl && navbarEl && dragArea) {
|
||||
navbarEl.style.position = 'unset'
|
||||
draggableEl.style.position = 'fixed'
|
||||
draggableEl.style.top = '0'
|
||||
draggableEl.style.left = '0'
|
||||
draggableEl.style.width = '100%'
|
||||
dragArea.style.paddingTop = '50px'
|
||||
navbarEl.style.position = 'unset';
|
||||
draggableEl.style.position = 'fixed';
|
||||
draggableEl.style.top = '0';
|
||||
draggableEl.style.left = '0';
|
||||
draggableEl.style.width = '100%';
|
||||
dragArea.style.paddingTop = '50px';
|
||||
} else {
|
||||
document.body.style.paddingTop = '46px'
|
||||
const slotEl = compEl?.closest('__slot-item')
|
||||
document.body.style.paddingTop = '46px';
|
||||
const slotEl = compEl?.closest('__slot-item');
|
||||
if (slotEl) {
|
||||
slotEl.style.position = 'fixed'
|
||||
slotEl.style.bottom = '0'
|
||||
slotEl.style.position = 'fixed';
|
||||
slotEl.style.bottom = '0';
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
const dragArea = document.querySelector(
|
||||
'.simulator-editor-content > .dragArea '
|
||||
) as HTMLDivElement
|
||||
'.simulator-editor-content > .dragArea ',
|
||||
) as HTMLDivElement;
|
||||
if (dragArea) {
|
||||
dragArea.style.paddingTop = ''
|
||||
dragArea.style.paddingTop = '';
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return () => <NavBar ref={(el) => registerRef(el, block._vid)} {...props} />
|
||||
return () => <NavBar ref={(el) => registerRef(el, block._vid)} {...props} />;
|
||||
},
|
||||
props: {
|
||||
title: createEditorInputProp({ label: '标题', defaultValue: '标题' }),
|
||||
|
@ -69,15 +69,15 @@ export default {
|
|||
border: createEditorSwitchProp({ label: '是否显示下边框', defaultValue: false }),
|
||||
leftText: createEditorInputProp({ label: '左侧文案', defaultValue: '返回' }),
|
||||
rightText: createEditorInputProp({ label: '右侧文案', defaultValue: '按钮' }),
|
||||
leftArrow: createEditorSwitchProp({ label: '是否显示左侧箭头', defaultValue: true })
|
||||
leftArrow: createEditorSwitchProp({ label: '是否显示左侧箭头', defaultValue: true }),
|
||||
},
|
||||
events: [
|
||||
{ label: '点击左侧按钮时触发', value: 'click-left' },
|
||||
{ label: '点击右侧按钮时触发', value: 'click-right' }
|
||||
{ label: '点击右侧按钮时触发', value: 'click-right' },
|
||||
],
|
||||
showStyleConfig: false,
|
||||
draggable: false,
|
||||
resize: {
|
||||
width: true
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
width: true,
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export const createFieldProps = () => ({
|
||||
background: createEditorInputProp({ label: '滚动条背景' }),
|
||||
|
@ -22,23 +22,23 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '默认',
|
||||
value: ''
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: '可关闭',
|
||||
value: 'closeable'
|
||||
value: 'closeable',
|
||||
},
|
||||
{
|
||||
label: '链接',
|
||||
value: 'link'
|
||||
}
|
||||
]
|
||||
value: 'link',
|
||||
},
|
||||
],
|
||||
}),
|
||||
scrollable: createEditorSwitchProp({ label: '是否开启滚动播放,内容长度溢出时默认开启' }),
|
||||
speed: createEditorInputProp({ label: '滚动速率 (px/s)' }),
|
||||
text: createEditorInputProp({
|
||||
label: '通知文本内容',
|
||||
defaultValue: '在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。'
|
||||
defaultValue: '在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。',
|
||||
}),
|
||||
wrapable: createEditorSwitchProp({ label: '是否开启文本换行,只在禁用滚动时生效' })
|
||||
})
|
||||
wrapable: createEditorSwitchProp({ label: '是否开启文本换行,只在禁用滚动时生效' }),
|
||||
});
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\notice-bar\index.tsx
|
||||
*/
|
||||
import { NoticeBar } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { NoticeBar } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'NoticeBar',
|
||||
|
@ -23,24 +23,24 @@ export default {
|
|||
/>
|
||||
),
|
||||
render: ({ block, props, styles }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
<NoticeBar ref={(el) => registerRef(el, block._vid)} style={{ width: '100%' }} {...props} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
events: [
|
||||
{ label: '点击通知栏时触发', value: 'click' },
|
||||
{ label: '关闭通知栏时触发', value: 'close' },
|
||||
{ label: '每当滚动栏重新开始滚动时触发', value: 'replay' }
|
||||
{ label: '每当滚动栏重新开始滚动时触发', value: 'replay' },
|
||||
],
|
||||
props: createFieldProps(),
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* @Description: 表单项类型 - 选择器
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\picker\index.tsx
|
||||
*/
|
||||
import { Field, Popup, Picker } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { reactive, useAttrs } from 'vue';
|
||||
import { Field, Popup, Picker } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorCrossSortableProp,
|
||||
createEditorInputProp,
|
||||
createEditorModelBindProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import { reactive, useAttrs } from 'vue'
|
||||
createEditorModelBindProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'picker',
|
||||
|
@ -23,31 +23,31 @@ export default {
|
|||
label: '表单项类型 - 选择器',
|
||||
preview: () => <Field name="picker" label="选择器" placeholder={'点击选择'}></Field>,
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
const attrs = useAttrs()
|
||||
const attrs = useAttrs();
|
||||
|
||||
const state = reactive({
|
||||
showPicker: false,
|
||||
text: '',
|
||||
defaultIndex: 0
|
||||
})
|
||||
defaultIndex: 0,
|
||||
});
|
||||
const customFieldName = {
|
||||
text: 'label',
|
||||
value: 'value'
|
||||
}
|
||||
value: 'value',
|
||||
};
|
||||
|
||||
const onConfirm = (value) => {
|
||||
props.modelValue = value.value
|
||||
state.text = value[props.valueKey || 'text']
|
||||
state.showPicker = false
|
||||
console.log(props)
|
||||
}
|
||||
props.modelValue = value.value;
|
||||
state.text = value[props.valueKey || 'text'];
|
||||
state.showPicker = false;
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
return () => {
|
||||
if (props.modelValue) {
|
||||
state.defaultIndex = props.columns?.findIndex((item) => item.value == props.modelValue)
|
||||
state.text = props.columns[state.defaultIndex]?.label
|
||||
state.defaultIndex = props.columns?.findIndex((item) => item.value == props.modelValue);
|
||||
state.text = props.columns[state.defaultIndex]?.label;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -66,7 +66,7 @@ export default {
|
|||
<span class={'placeholder'}>{props.placeholder}</span>
|
||||
) : (
|
||||
state.text
|
||||
)
|
||||
),
|
||||
}}
|
||||
</Field>
|
||||
<Popup v-model={[state.showPicker, 'show']} position={'bottom'}>
|
||||
|
@ -81,8 +81,8 @@ export default {
|
|||
/>
|
||||
</Popup>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputProp({ label: '默认值' }),
|
||||
|
@ -94,21 +94,21 @@ export default {
|
|||
multiple: false,
|
||||
defaultValue: [
|
||||
{ label: '杭州', value: 'hangzhou' },
|
||||
{ label: '上海', value: 'shanghai' }
|
||||
]
|
||||
{ label: '上海', value: 'shanghai' },
|
||||
],
|
||||
}),
|
||||
placeholder: createEditorInputProp({ label: '占位符', defaultValue: '请选择' }),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
},
|
||||
events: [
|
||||
{ label: '点击完成按钮时触发', value: 'confirm' },
|
||||
{ label: '点击取消按钮时触发', value: 'cancel' },
|
||||
{ label: '选项改变时触发', value: 'change' }
|
||||
{ label: '选项改变时触发', value: 'change' },
|
||||
],
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
* @Description: 进度条
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\process\index.tsx
|
||||
*/
|
||||
import { Progress } from 'vant'
|
||||
import { Progress } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import {
|
||||
createEditorColorProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorInputProp,
|
||||
createEditorInputNumberProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
createEditorInputNumberProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'process',
|
||||
|
@ -21,13 +21,13 @@ export default {
|
|||
label: '进度条',
|
||||
preview: () => <Progress style="width:190px" percentage={50} />,
|
||||
render: ({ props, styles }) => {
|
||||
const RenderProgress = () => <Progress {...props} pivotText={props.pivotText || undefined} />
|
||||
const RenderProgress = () => <Progress {...props} pivotText={props.pivotText || undefined} />;
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
<RenderProgress />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
percentage: createEditorInputNumberProp({ label: '进度百分比', defaultValue: 50 }),
|
||||
|
@ -38,6 +38,6 @@ export default {
|
|||
pivotText: createEditorInputProp({ label: '进度文字内容' }),
|
||||
pivotColor: createEditorColorProp({ label: '进度文字背景色', defaultValue: '#1989fa' }),
|
||||
textColor: createEditorColorProp({ label: '进度文字颜色', defaultValue: '#ffffff' }),
|
||||
showPivot: createEditorSwitchProp({ label: '是否显示进度文字', defaultValue: true })
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
showPivot: createEditorSwitchProp({ label: '是否显示进度文字', defaultValue: true }),
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* @Description: 表单项类型 - 单选框
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\radio\index.tsx
|
||||
*/
|
||||
import { Field, Radio, RadioGroup } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { Field, Radio, RadioGroup } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorCrossSortableProp,
|
||||
createEditorInputProp,
|
||||
createEditorModelBindProp,
|
||||
createEditorSelectProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSelectProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'radio',
|
||||
|
@ -28,7 +28,7 @@ export default {
|
|||
</RadioGroup>
|
||||
),
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -49,11 +49,11 @@ export default {
|
|||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputProp({ label: '默认值', defaultValue: '' }),
|
||||
|
@ -66,30 +66,30 @@ export default {
|
|||
defaultValue: [
|
||||
{ label: '胡萝卜', value: 'carrot' },
|
||||
{ label: '白菜', value: 'cabbage' },
|
||||
{ label: '猪', value: 'pig' }
|
||||
]
|
||||
{ label: '猪', value: 'pig' },
|
||||
],
|
||||
}),
|
||||
direction: createEditorSelectProp({
|
||||
label: '排列方向',
|
||||
options: [
|
||||
{
|
||||
label: '水平',
|
||||
value: 'horizontal'
|
||||
value: 'horizontal',
|
||||
},
|
||||
{
|
||||
label: '垂直',
|
||||
value: 'vertical'
|
||||
}
|
||||
value: 'vertical',
|
||||
},
|
||||
],
|
||||
defaultValue: 'horizontal'
|
||||
defaultValue: 'horizontal',
|
||||
}),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
},
|
||||
events: [{ label: '点击单选框时触发', value: 'click' }],
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\rate\index.tsx
|
||||
*/
|
||||
import { Field, Rate } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputNumberProp,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\slider\index.tsx
|
||||
*/
|
||||
import { Field, Slider } from 'vant';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { omit } from 'lodash-es';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputNumberProp,
|
||||
|
@ -16,7 +17,6 @@ import {
|
|||
createEditorModelBindProp,
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import { omit } from 'lodash-es';
|
||||
|
||||
export default {
|
||||
key: 'slider',
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
* @Description: '表单项类型 - 步进器
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\stepper\index.tsx
|
||||
*/
|
||||
import { Field, Stepper } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { watchEffect } from 'vue';
|
||||
import { Field, Stepper } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputNumberProp,
|
||||
createEditorInputProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorSelectProp,
|
||||
createEditorModelBindProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import { watchEffect } from 'vue'
|
||||
createEditorModelBindProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'stepper',
|
||||
|
@ -32,11 +32,11 @@ export default {
|
|||
></Field>
|
||||
),
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
watchEffect(() => {
|
||||
props.name = Array.isArray(props.name) ? [...props.name].pop() : props.name
|
||||
})
|
||||
props.name = Array.isArray(props.name) ? [...props.name].pop() : props.name;
|
||||
});
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -50,11 +50,11 @@ export default {
|
|||
v-model={props.modelValue}
|
||||
{...props}
|
||||
></Stepper>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputNumberProp({ label: '默认值', defaultValue: 0 }),
|
||||
|
@ -66,12 +66,12 @@ export default {
|
|||
allowEmpty: createEditorSwitchProp({ label: '是否允许输入的值为空', defaultValue: false }),
|
||||
buttonSize: createEditorInputProp({
|
||||
label: '按钮大小以及输入框高度,默认单位为 px',
|
||||
defaultValue: '28px'
|
||||
defaultValue: '28px',
|
||||
}),
|
||||
decimalLength: createEditorInputProp({ label: '固定显示的小数位数', defaultValue: '' }),
|
||||
defaultValue: createEditorInputProp({
|
||||
label: '初始值,当 v-model 为空时生效',
|
||||
defaultValue: '1'
|
||||
defaultValue: '1',
|
||||
}),
|
||||
disableInput: createEditorSwitchProp({ label: '是否禁用输入框', defaultValue: false }),
|
||||
disableMinus: createEditorSwitchProp({ label: '是否禁用减少按钮', defaultValue: false }),
|
||||
|
@ -90,17 +90,17 @@ export default {
|
|||
options: [
|
||||
{
|
||||
label: '默认',
|
||||
value: ''
|
||||
value: '',
|
||||
},
|
||||
{ label: '圆角风格', value: 'round' }
|
||||
{ label: '圆角风格', value: 'round' },
|
||||
],
|
||||
defaultValue: ''
|
||||
})
|
||||
defaultValue: '',
|
||||
}),
|
||||
},
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -9,14 +9,17 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorCrossSortableProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorCrossSortableProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export const createFieldProps = () => ({
|
||||
images: createEditorCrossSortableProp({
|
||||
label: '图片列表',
|
||||
labelPosition: 'top',
|
||||
defaultValue: ['https://img.yzcdn.cn/vant/apple-1.jpg', 'https://img.yzcdn.cn/vant/apple-2.jpg']
|
||||
defaultValue: [
|
||||
'https://img.yzcdn.cn/vant/apple-1.jpg',
|
||||
'https://img.yzcdn.cn/vant/apple-2.jpg',
|
||||
],
|
||||
}),
|
||||
// width: createEditorInputProp({ label: '滑块宽度,单位为 px', defaultValue: 'auto' }),
|
||||
height: createEditorInputProp({ label: '滑块高度,单位为 px', defaultValue: '200' }),
|
||||
|
@ -29,5 +32,5 @@ export const createFieldProps = () => ({
|
|||
showIndicators: createEditorSwitchProp({ label: '是否显示指示器', defaultValue: true }),
|
||||
stopPropagation: createEditorSwitchProp({ label: '是否阻止滑动事件冒泡', defaultValue: true }),
|
||||
touchable: createEditorSwitchProp({ label: '是否可以通过手势滑动', defaultValue: true }),
|
||||
vertical: createEditorSwitchProp({ label: '是否为纵向滚动', defaultValue: false })
|
||||
})
|
||||
vertical: createEditorSwitchProp({ label: '是否为纵向滚动', defaultValue: false }),
|
||||
});
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* @Description: 轮播图组件
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\swipe\index.tsx
|
||||
*/
|
||||
import { Swipe, SwipeItem } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { Swipe, SwipeItem } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
const swipeItemStyle = `color: #fff;
|
||||
font-size: 20px;
|
||||
line-height: 150px;
|
||||
text-align: center;
|
||||
background-color: #39a9ed;`
|
||||
background-color: #39a9ed;`;
|
||||
|
||||
export default {
|
||||
key: 'swipe',
|
||||
|
@ -30,7 +30,7 @@ export default {
|
|||
</Swipe>
|
||||
),
|
||||
render: ({ block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div>
|
||||
|
@ -48,15 +48,15 @@ export default {
|
|||
))}
|
||||
</Swipe>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: createFieldProps(),
|
||||
events: [{ label: '每一页轮播结束后触发', value: 'change' }],
|
||||
showStyleConfig: false,
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorSwitchProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
/**
|
||||
* @name: createFieldProps
|
||||
|
@ -19,21 +19,21 @@ export const createFieldProps = () => ({
|
|||
options: [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '居中',
|
||||
value: 'center'
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
}
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
defaultValue: 'left'
|
||||
defaultValue: 'left',
|
||||
}),
|
||||
border: createEditorSwitchProp({ label: '是否显示内边框', defaultValue: true }),
|
||||
readonly: createEditorSwitchProp({ label: '是否为只读状态' }),
|
||||
required: createEditorSwitchProp({ label: '是否显示表单必填星号' }),
|
||||
rules: createEditorInputProp({ label: '表单校验规则' })
|
||||
})
|
||||
rules: createEditorInputProp({ label: '表单校验规则' }),
|
||||
});
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
* @Description: 表单项类型 - 开关
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\switch\index.tsx
|
||||
*/
|
||||
import { Field, Switch } from 'vant'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { createFieldProps } from './createFieldProps'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { Field, Switch } from 'vant';
|
||||
import { createFieldProps } from './createFieldProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorInputProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorColorProp,
|
||||
createEditorModelBindProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorModelBindProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'switch',
|
||||
|
@ -25,7 +25,7 @@ export default {
|
|||
<Field name="switch" label="开关" v-slots={{ input: () => <Switch size={20} /> }} />
|
||||
),
|
||||
render: ({ styles, block, props }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -40,11 +40,11 @@ export default {
|
|||
{...props}
|
||||
v-model={props.modelValue}
|
||||
/>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
modelValue: createEditorInputProp({ label: '默认值', defaultValue: 'false' }),
|
||||
|
@ -57,16 +57,16 @@ export default {
|
|||
disabled: createEditorSwitchProp({ label: '是否为禁用状态' }),
|
||||
loading: createEditorSwitchProp({ label: '是否为加载状态' }),
|
||||
size: createEditorInputProp({ label: '开关尺寸', defaultValue: '20px' }),
|
||||
...createFieldProps()
|
||||
...createFieldProps(),
|
||||
},
|
||||
events: [
|
||||
{ label: '开关状态切换时触发', value: 'change' },
|
||||
{ label: '点击时触发', value: 'click' }
|
||||
{ label: '点击时触发', value: 'click' },
|
||||
],
|
||||
resize: {
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
model: {
|
||||
default: '绑定字段'
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
default: '绑定字段',
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
* @Description: 导航栏
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\tabbar\index.tsx
|
||||
*/
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
import { Tabbar, TabbarItem } from 'vant';
|
||||
import { getTabbarItem } from './tabbar-item';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import {
|
||||
createEditorCrossSortableProp,
|
||||
|
@ -15,10 +17,8 @@ import {
|
|||
createEditorColorProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import { getTabbarItem } from './tabbar-item';
|
||||
import { createNewBlock } from '@/visual-editor/visual-editor.utils';
|
||||
import { BASE_URL } from '@/visual-editor/utils';
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
|
||||
const defaultTabbarItems = [
|
||||
{
|
||||
|
|
|
@ -50,5 +50,5 @@ export const fontArr = [
|
|||
{ label: '方正姚体', value: 'FZYaoti' },
|
||||
{ label: '思源黑体', value: 'Source Han Sans CN' },
|
||||
{ label: '思源宋体', value: 'Source Han Serif SC' },
|
||||
{ label: '文泉驿微米黑', value: 'WenQuanYi Micro Hei' }
|
||||
]
|
||||
{ label: '文泉驿微米黑', value: 'WenQuanYi Micro Hei' },
|
||||
];
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
* @Description: 文本
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\text\index.tsx
|
||||
*/
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { fontArr } from './fontArr';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import {
|
||||
createEditorColorProp,
|
||||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorInputNumberProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { fontArr } from './fontArr'
|
||||
createEditorInputNumberProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export default {
|
||||
key: 'text',
|
||||
|
@ -22,7 +22,7 @@ export default {
|
|||
label: '文本',
|
||||
preview: () => <span>预览文本</span>,
|
||||
render: ({ props, block, styles }) => {
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
return () => (
|
||||
<div
|
||||
|
@ -31,12 +31,12 @@ export default {
|
|||
color: props.color,
|
||||
fontSize: `${parseFloat(props.size)}px`,
|
||||
fontFamily: props.font,
|
||||
...styles
|
||||
...styles,
|
||||
}}
|
||||
>
|
||||
{props.text || '默认文本'}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
props: {
|
||||
text: createEditorInputProp({ label: '显示文本' }),
|
||||
|
@ -44,7 +44,7 @@ export default {
|
|||
color: createEditorColorProp({ label: '字体颜色' }),
|
||||
size: createEditorInputNumberProp({
|
||||
label: '字体大小',
|
||||
defaultValue: 16
|
||||
})
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
defaultValue: 16,
|
||||
}),
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -11,24 +11,24 @@ import {
|
|||
createEditorInputProp,
|
||||
createEditorSelectProp,
|
||||
createEditorSwitchProp,
|
||||
createEditorTableProp
|
||||
} from '@/visual-editor/visual-editor.props'
|
||||
createEditorTableProp,
|
||||
} from '@/visual-editor/visual-editor.props';
|
||||
|
||||
// 对齐方式
|
||||
const alignOptions = [
|
||||
{
|
||||
label: '左对齐',
|
||||
value: 'left'
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: '右对齐',
|
||||
value: 'right'
|
||||
value: 'right',
|
||||
},
|
||||
{
|
||||
label: '居中对齐',
|
||||
value: 'center'
|
||||
}
|
||||
]
|
||||
value: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
export const compProps = {
|
||||
'slots.default.children': createEditorTableProp({
|
||||
|
@ -37,37 +37,37 @@ export const compProps = {
|
|||
options: [
|
||||
{ label: '显示值', field: 'label' },
|
||||
{ label: '绑定值', field: 'value' },
|
||||
{ label: '备注', field: 'comments' }
|
||||
{ label: '备注', field: 'comments' },
|
||||
],
|
||||
showKey: 'label'
|
||||
showKey: 'label',
|
||||
},
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
}),
|
||||
colon: createEditorSwitchProp({ label: '是否在 label 后面添加冒号' }),
|
||||
disabled: createEditorSwitchProp({ label: '是否禁用表单中的所有输入框' }),
|
||||
errorMessageAlign: createEditorSelectProp({
|
||||
label: '错误提示文案对齐方式',
|
||||
defaultValue: 'left',
|
||||
options: alignOptions
|
||||
options: alignOptions,
|
||||
}),
|
||||
inputAlign: createEditorSelectProp({
|
||||
label: '输入框对齐方式',
|
||||
defaultValue: 'left',
|
||||
options: alignOptions
|
||||
options: alignOptions,
|
||||
}),
|
||||
labelAlign: createEditorSelectProp({
|
||||
label: '表单项 label 对齐方式',
|
||||
defaultValue: 'left',
|
||||
options: alignOptions
|
||||
options: alignOptions,
|
||||
}),
|
||||
labelWidth: createEditorInputProp({ label: '表单项 label 宽度,默认单位为px' }),
|
||||
readonly: createEditorSwitchProp({ label: '是否将表单中的所有输入框设置为只读状态' }),
|
||||
scrollToError: createEditorSwitchProp({
|
||||
label: '在提交表单且校验不通过时滚动至错误的表单项'
|
||||
label: '在提交表单且校验不通过时滚动至错误的表单项',
|
||||
}),
|
||||
showError: createEditorSwitchProp({ label: '是否在校验不通过时标红输入框' }),
|
||||
showErrorMessage: createEditorSwitchProp({
|
||||
label: '是否在校验不通过时在输入框下方展示错误提示'
|
||||
label: '是否在校验不通过时在输入框下方展示错误提示',
|
||||
}),
|
||||
submitOnEnter: createEditorSwitchProp({ label: '是否在按下回车键时提交表单' }),
|
||||
validateFirst: createEditorSwitchProp({ label: '是否在某一项校验不通过时停止校验' }),
|
||||
|
@ -76,17 +76,17 @@ export const compProps = {
|
|||
options: [
|
||||
{
|
||||
label: 'onChange',
|
||||
value: 'onChange'
|
||||
value: 'onChange',
|
||||
},
|
||||
{
|
||||
label: 'onSubmit',
|
||||
value: 'onSubmit'
|
||||
value: 'onSubmit',
|
||||
},
|
||||
{
|
||||
label: 'onBlur',
|
||||
value: 'onBlur'
|
||||
}
|
||||
value: 'onBlur',
|
||||
},
|
||||
],
|
||||
defaultValue: 'onBlur'
|
||||
})
|
||||
}
|
||||
defaultValue: 'onBlur',
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\packages\container-component\form\index.tsx
|
||||
*/
|
||||
import { Form, Field, Button } from 'vant'
|
||||
import { renderSlot, useSlots } from 'vue'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { compProps } from './compProps'
|
||||
import { renderSlot, useSlots } from 'vue';
|
||||
import { Form, Field, Button } from 'vant';
|
||||
import { compProps } from './compProps';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
export default {
|
||||
key: 'form',
|
||||
|
@ -27,13 +27,13 @@ export default {
|
|||
</div>
|
||||
</Form>
|
||||
),
|
||||
render: function ({ props, styles, block }) {
|
||||
const slots = useSlots()
|
||||
const { registerRef } = useGlobalProperties()
|
||||
render({ props, styles, block }) {
|
||||
const slots = useSlots();
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
const onSubmit = (values) => {
|
||||
console.log('onSubmit:', values)
|
||||
}
|
||||
console.log('onSubmit:', values);
|
||||
};
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -46,15 +46,15 @@ export default {
|
|||
{renderSlot(slots, 'default')}
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
resize: {
|
||||
height: true,
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
events: [
|
||||
{ label: '提交表单且验证通过后触发', value: 'submit' },
|
||||
{ label: '提交表单且验证不通过后触发', value: 'failed' }
|
||||
{ label: '提交表单且验证不通过后触发', value: 'failed' },
|
||||
],
|
||||
props: compProps
|
||||
} as VisualEditorComponent
|
||||
props: compProps,
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const modules = import.meta.globEager('./*/index.tsx')
|
||||
const modules = import.meta.globEager('./*/index.tsx');
|
||||
|
||||
const components = {}
|
||||
const components = {};
|
||||
|
||||
Object.keys(modules).forEach((key: string) => {
|
||||
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1')
|
||||
components[name] = modules[key]?.default || modules[key]
|
||||
})
|
||||
const name = key.replace(/\.\/(.*)\/index\.(tsx|vue)/, '$1');
|
||||
components[name] = modules[key]?.default || modules[key];
|
||||
});
|
||||
|
||||
console.log(components, 'container-component')
|
||||
export default components
|
||||
console.log(components, 'container-component');
|
||||
export default components;
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import { Col, Row } from 'vant'
|
||||
import { renderSlot, useSlots } from 'vue'
|
||||
import { createEditorInputProp, createEditorSelectProp } from '@/visual-editor/visual-editor.props'
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils'
|
||||
import styleModule from './index.module.scss'
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties'
|
||||
import { watchEffect } from 'vue'
|
||||
import { renderSlot, useSlots, watchEffect } from 'vue';
|
||||
import { Col, Row } from 'vant';
|
||||
import styleModule from './index.module.scss';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { createEditorInputProp, createEditorSelectProp } from '@/visual-editor/visual-editor.props';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
|
||||
interface SlotItem {
|
||||
value: string
|
||||
[prop: string]: any
|
||||
value: string;
|
||||
[prop: string]: any;
|
||||
}
|
||||
|
||||
const slotsTemp = {} as any
|
||||
const slotsTemp = {} as any;
|
||||
|
||||
const createSlots = (str: string): SlotItem =>
|
||||
str.split(':').reduce(
|
||||
|
@ -19,12 +18,12 @@ const createSlots = (str: string): SlotItem =>
|
|||
prev[`slot${index}`] = {
|
||||
key: `slot${index}`,
|
||||
span: curr,
|
||||
children: []
|
||||
}
|
||||
return prev
|
||||
children: [],
|
||||
};
|
||||
return prev;
|
||||
},
|
||||
{ value: str }
|
||||
)
|
||||
{ value: str },
|
||||
);
|
||||
|
||||
export default {
|
||||
key: 'layout',
|
||||
|
@ -38,20 +37,20 @@ export default {
|
|||
</Row>
|
||||
),
|
||||
render: ({ props, styles, block, custom }) => {
|
||||
const slots = useSlots()
|
||||
const { registerRef } = useGlobalProperties()
|
||||
const slots = useSlots();
|
||||
const { registerRef } = useGlobalProperties();
|
||||
|
||||
slotsTemp[block._vid] ??= {}
|
||||
slotsTemp[block._vid] ??= {};
|
||||
|
||||
watchEffect(() => {
|
||||
if (Object.keys(props.slots || {}).length) {
|
||||
Object.keys(props.slots).forEach((key) => {
|
||||
if (slotsTemp[block._vid][key]?.children) {
|
||||
props.slots[key].children = slotsTemp[block._vid][key].children
|
||||
props.slots[key].children = slotsTemp[block._vid][key].children;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return () => (
|
||||
<div style={styles}>
|
||||
|
@ -64,20 +63,20 @@ export default {
|
|||
{Object.values(Object.keys(props.slots).length ? props.slots : createSlots('12:12'))
|
||||
?.filter((item) => typeof item !== 'string')
|
||||
.map((spanItem: SlotItem, spanIndex) => {
|
||||
slotsTemp[block._vid][`slot${spanIndex}`] = spanItem
|
||||
slotsTemp[block._vid][`slot${spanIndex}`] = spanItem;
|
||||
return (
|
||||
<>
|
||||
<Col span={spanItem.span}>{renderSlot(slots, `slot${spanIndex}`)}</Col>
|
||||
</>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
},
|
||||
resize: {
|
||||
height: true,
|
||||
width: true
|
||||
width: true,
|
||||
},
|
||||
props: {
|
||||
gutter: createEditorInputProp({ label: '列间隔' }),
|
||||
|
@ -90,9 +89,9 @@ export default {
|
|||
{ label: '18:6', value: createSlots('18:6') },
|
||||
{ label: '8:8:8', value: createSlots('8:8:8') },
|
||||
{ label: '6:12:6', value: createSlots('6:12:6') },
|
||||
{ label: '6:6:6:6', value: createSlots('6:6:6:6') }
|
||||
{ label: '6:6:6:6', value: createSlots('6:6:6:6') },
|
||||
],
|
||||
defaultValue: createSlots('12:12')
|
||||
defaultValue: createSlots('12:12'),
|
||||
}),
|
||||
justify: createEditorSelectProp({
|
||||
label: '主轴对齐方式',
|
||||
|
@ -101,16 +100,16 @@ export default {
|
|||
{ label: '居中排列', value: 'center' },
|
||||
{ label: '均匀对齐', value: 'space-around' },
|
||||
{ label: '两端对齐', value: 'space-between' },
|
||||
{ label: '右对齐', value: 'end' }
|
||||
]
|
||||
{ label: '右对齐', value: 'end' },
|
||||
],
|
||||
}),
|
||||
align: createEditorSelectProp({
|
||||
label: '交叉轴对齐方式',
|
||||
options: [
|
||||
{ label: '顶部对齐', value: 'top' },
|
||||
{ label: '垂直居中', value: 'center' },
|
||||
{ label: '底部对齐', value: 'bottom' }
|
||||
]
|
||||
})
|
||||
}
|
||||
} as VisualEditorComponent
|
||||
{ label: '底部对齐', value: 'bottom' },
|
||||
],
|
||||
}),
|
||||
},
|
||||
} as VisualEditorComponent;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import type { App } from 'vue'
|
||||
import '@vant/touch-emulator'
|
||||
import 'vant/lib/index.css'
|
||||
|
||||
import { Lazyload } from 'vant'
|
||||
import { Lazyload } from 'vant';
|
||||
import type { App } from 'vue';
|
||||
import '@vant/touch-emulator';
|
||||
import 'vant/lib/index.css';
|
||||
|
||||
export const setupVant = (app: App) => {
|
||||
app.use(Lazyload)
|
||||
}
|
||||
app.use(Lazyload);
|
||||
};
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import NProgress from 'nprogress' // progress bar
|
||||
import 'nprogress/css/nprogress.css' // 进度条样式
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
||||
import NProgress from 'nprogress'; // progress bar
|
||||
import 'nprogress/css/nprogress.css'; // 进度条样式
|
||||
|
||||
NProgress.configure({ showSpinner: false }) // NProgress Configuration
|
||||
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/visual-editor/index.vue')
|
||||
}
|
||||
]
|
||||
component: () => import('@/visual-editor/index.vue'),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
})
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach(() => {
|
||||
NProgress.start() // start progress bar
|
||||
return true
|
||||
})
|
||||
NProgress.start(); // start progress bar
|
||||
return true;
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
NProgress.done() // finish progress bar
|
||||
})
|
||||
NProgress.done(); // finish progress bar
|
||||
});
|
||||
|
||||
export default router
|
||||
export default router;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { App } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import type { App } from 'vue';
|
||||
|
||||
const store = createPinia();
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
*/
|
||||
import { defineComponent } from 'vue';
|
||||
import { ElInput, ElIcon } from 'element-plus';
|
||||
import type { PropType } from 'vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import styles from './index.module.scss';
|
||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||
import styles from './index.module.scss';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
export const FormatInputNumber = defineComponent({
|
||||
props: {
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* @description:MonacoEditor
|
||||
* @update: 2021/4/30 0:01
|
||||
*/
|
||||
import { Monaco } from './monaco'
|
||||
import { defineComponent, onMounted, PropType, shallowRef, ref, onBeforeUnmount, watch } from 'vue'
|
||||
import styles from './MonacoEditor.module.scss'
|
||||
let subscription: Monaco.IDisposable | undefined
|
||||
let preventTriggerChangeEvent = false
|
||||
import { defineComponent, onMounted, PropType, shallowRef, ref, onBeforeUnmount, watch } from 'vue';
|
||||
import { Monaco } from './monaco';
|
||||
import styles from './MonacoEditor.module.scss';
|
||||
let subscription: Monaco.IDisposable | undefined;
|
||||
let preventTriggerChangeEvent = false;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MonacoEditor',
|
||||
|
@ -17,45 +17,45 @@ export default defineComponent({
|
|||
code: {
|
||||
// 代码
|
||||
type: String as PropType<string>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
layout: {
|
||||
// 布局
|
||||
type: Object as PropType<Monaco.editor.IDimension>,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
options: {
|
||||
type: Object as PropType<Monaco.editor.IStandaloneEditorConstructionOptions>,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
vid: [String, Number],
|
||||
onChange: {
|
||||
type: Function as PropType<
|
||||
(value: string, event: Monaco.editor.IModelContentChangedEvent) => void
|
||||
>
|
||||
>,
|
||||
},
|
||||
title: {
|
||||
type: String as PropType<string>,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
// 需要一个shallowRef: 只监听value,不关心实际对象
|
||||
const editorRef = shallowRef<Monaco.editor.IStandaloneCodeEditor | null>(null)
|
||||
const editorRef = shallowRef<Monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||
|
||||
// 需要生成编辑器的Dom
|
||||
const containerDomRef = ref(null)
|
||||
const containerDomRef = ref(null);
|
||||
|
||||
// 格式化代码
|
||||
const formatCode = () => {
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
editorRef.value!.getAction('editor.action.formatDocument').run()
|
||||
editorRef.value!.getAction('editor.action.formatDocument').run();
|
||||
},
|
||||
{ timeout: 800 }
|
||||
)
|
||||
}
|
||||
{ timeout: 800 },
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 组件初始化时创建一个MonacoEditor的实例
|
||||
|
@ -66,44 +66,44 @@ export default defineComponent({
|
|||
formatOnPaste: true, // 当粘贴的时候自动进行一次格式化代码
|
||||
tabSize: 2, // tab缩进长度
|
||||
minimap: {
|
||||
enabled: false // 不需要小的缩略图
|
||||
enabled: false, // 不需要小的缩略图
|
||||
},
|
||||
fontFamily: '微软雅黑', //字体
|
||||
// automaticLayout: true, //编辑器自适应布局,可能会影响性能
|
||||
overviewRulerBorder: false,
|
||||
scrollBeyondLastLine: false, //滚动配置,溢出才滚动
|
||||
...props.options
|
||||
})
|
||||
...props.options,
|
||||
});
|
||||
|
||||
// 如果代码有变化,会在这里监听到,当受到外部数据改变时,不需要触发change事件
|
||||
subscription = editorRef.value.onDidChangeModelContent((event) => {
|
||||
if (!preventTriggerChangeEvent) {
|
||||
// getValue: 获取编辑器中的所有文本
|
||||
props.onChange?.(editorRef.value!.getValue(), event)
|
||||
props.onChange?.(editorRef.value!.getValue(), event);
|
||||
}
|
||||
})
|
||||
formatCode()
|
||||
editorRef.value.layout(props.layout)
|
||||
})
|
||||
});
|
||||
formatCode();
|
||||
editorRef.value.layout(props.layout);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 组件销毁时卸载编辑器
|
||||
if (subscription) {
|
||||
subscription.dispose()
|
||||
subscription.dispose();
|
||||
}
|
||||
})
|
||||
});
|
||||
// 更新编辑器
|
||||
const refreshEditor = () => {
|
||||
if (editorRef.value) {
|
||||
const editor = editorRef.value
|
||||
const editor = editorRef.value;
|
||||
// 获取编辑器的textModel文本
|
||||
const model = editor.getModel()
|
||||
const model = editor.getModel();
|
||||
|
||||
// 如果代码发生变化 这里需要更新一版
|
||||
if (model && props.code !== model.getValue()) {
|
||||
// 这是进行一次常规化的操作 文档原文:Push an "undo stop" in the undo-redo stack.
|
||||
editor.pushUndoStop()
|
||||
preventTriggerChangeEvent = true
|
||||
editor.pushUndoStop();
|
||||
preventTriggerChangeEvent = true;
|
||||
/**
|
||||
* @function 开始编辑编辑器, 文档原文:Push edit operations, basically editing the model. This is the preferred way of editing the model. The edit operations will land on the undo stack.
|
||||
* @param 编辑操作之前的光标状态。调用撤销或重做时,将返回此光标状态
|
||||
|
@ -115,20 +115,20 @@ export default defineComponent({
|
|||
[
|
||||
{
|
||||
range: model.getFullModelRange(),
|
||||
text: props.code
|
||||
}
|
||||
text: props.code,
|
||||
},
|
||||
],
|
||||
() => null
|
||||
)
|
||||
() => null,
|
||||
);
|
||||
}
|
||||
|
||||
editor.pushUndoStop()
|
||||
preventTriggerChangeEvent = false
|
||||
formatCode()
|
||||
}
|
||||
editor.pushUndoStop();
|
||||
preventTriggerChangeEvent = false;
|
||||
formatCode();
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => props.vid, refreshEditor, { immediate: true })
|
||||
watch(() => props.vid, refreshEditor, { immediate: true });
|
||||
|
||||
return () => {
|
||||
return (
|
||||
|
@ -140,7 +140,7 @@ export default defineComponent({
|
|||
)}
|
||||
<div class={styles.code} ref={containerDomRef}></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
// https://github.com/vitejs/vite/discussions/1791#discussioncomment-321046
|
||||
|
||||
import * as Monaco from 'monaco-editor'
|
||||
import * as Monaco from 'monaco-editor';
|
||||
// import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
|
||||
// import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
||||
// import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
||||
|
||||
const global: any = globalThis || window
|
||||
const global: any = globalThis || window;
|
||||
|
||||
global.MonacoEnvironment = {
|
||||
getWorker(_: string, label: string) {
|
||||
if (label === 'json') return new jsonWorker()
|
||||
if (label === 'css' || label === 'scss' || label === 'less') return new cssWorker()
|
||||
if (label === 'json') return new jsonWorker();
|
||||
if (label === 'css' || label === 'scss' || label === 'less') return new cssWorker();
|
||||
// if (label === 'html' || label === 'handlebars' || label === 'razor') return new htmlWorker()
|
||||
// if (label === 'typescript' || label === 'javascript') return new tsWorker()
|
||||
// return new editorWorker()
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const languages = Monaco.languages.getLanguages()
|
||||
const languages = Monaco.languages.getLanguages();
|
||||
|
||||
export { Monaco, languages }
|
||||
export { Monaco, languages };
|
||||
|
|
|
@ -68,11 +68,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { VideoPlay } from '@element-plus/icons-vue';
|
||||
import Preview from './preview.vue';
|
||||
import { useTools } from './useTools';
|
||||
import { useVisualData, localKey } from '@/visual-editor/hooks/useVisualData';
|
||||
import { BASE_URL } from '@/visual-editor/utils';
|
||||
import { useTools } from './useTools';
|
||||
import { VideoPlay } from '@element-plus/icons-vue';
|
||||
|
||||
const isShowH5Preview = ref(false);
|
||||
|
||||
|
|
|
@ -11,40 +11,40 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs } from 'vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { BASE_URL } from '@/visual-editor/utils'
|
||||
/**
|
||||
import { defineComponent, reactive, toRefs } from 'vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { BASE_URL } from '@/visual-editor/utils';
|
||||
/**
|
||||
* @name: preview
|
||||
* @author: 卜启缘
|
||||
* @date: 2021/4/29 23:09
|
||||
* @description:preview
|
||||
* @update: 2021/4/29 23:09
|
||||
*/
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'Preview',
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:visible'],
|
||||
setup(props, { emit }) {
|
||||
const state = reactive({
|
||||
dialogVisible: useVModel(props, 'visible', emit),
|
||||
previewUrl: `${BASE_URL}preview/${location.hash}`
|
||||
})
|
||||
previewUrl: `${BASE_URL}preview/${location.hash}`,
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state)
|
||||
}
|
||||
}
|
||||
})
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.h5-preview {
|
||||
.h5-preview {
|
||||
overflow: hidden;
|
||||
|
||||
.el-dialog__body {
|
||||
|
@ -64,5 +64,5 @@ export default defineComponent({
|
|||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,11 +7,8 @@
|
|||
*/
|
||||
import { reactive } from 'vue';
|
||||
import { ElMessage, ElRadio, ElRadioGroup } from 'element-plus';
|
||||
import { useQRCode } from '@vueuse/integrations';
|
||||
import { useQRCode } from '@vueuse/integrations/useQRCode';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { useVisualData, localKey } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor';
|
||||
import {
|
||||
DocumentCopy,
|
||||
Cellphone,
|
||||
|
@ -23,6 +20,9 @@ import {
|
|||
Download,
|
||||
Upload,
|
||||
} from '@element-plus/icons-vue';
|
||||
import { useVisualData, localKey } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor';
|
||||
import 'element-plus/es/components/message/style/css';
|
||||
|
||||
export const useTools = () => {
|
||||
|
@ -95,7 +95,7 @@ export const useTools = () => {
|
|||
title: '真机预览',
|
||||
icon: Cellphone,
|
||||
onClick: () => {
|
||||
const qrcode = useQRCode(location.origin + '/preview');
|
||||
const qrcode = useQRCode(`${location.origin}/preview`);
|
||||
useModal({
|
||||
title: '预览二维码(暂不可用)',
|
||||
props: {
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
*/
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
import styles from './index.module.scss';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
import { createNewBlock } from '@/visual-editor/visual-editor.utils';
|
||||
import DraggableTransitionGroup from '@/visual-editor/components/simulator-editor/draggable-transition-group.vue';
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BaseWidgets',
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
*/
|
||||
import { defineComponent } from 'vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
import Draggable from 'vuedraggable';
|
||||
import styles from './index.module.scss';
|
||||
import { createNewBlock } from '@/visual-editor/visual-editor.utils';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { Suitcase } from '@element-plus/icons-vue';
|
||||
import styles from './index.module.scss';
|
||||
import type { VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
import { createNewBlock } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ContainerComponent',
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
<div class="model-item-title">
|
||||
<span class="truncate w-160px">{{ item.name }}</span>
|
||||
<div class="model-actions">
|
||||
<el-icon size="24" color="#2196f3" @click.stop="editApiItem(item)">
|
||||
<ElIcon :size="24" color="#2196f3" @click.stop="editApiItem(item)">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
</ElIcon>
|
||||
<el-popconfirm
|
||||
confirm-button-text="确定"
|
||||
cancel-button-text="取消"
|
||||
|
@ -34,7 +34,7 @@
|
|||
@confirm="deleteFetchApi(item.key)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-icon size="24" color="#f44336"><Delete /></el-icon>
|
||||
<ElIcon :size="24" color="#f44336"><Delete /></ElIcon>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
|
@ -59,15 +59,16 @@
|
|||
ElButton,
|
||||
ElMessage,
|
||||
ElCascader,
|
||||
ElIcon,
|
||||
} from 'element-plus';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { Delete, Edit } from '@element-plus/icons-vue';
|
||||
import { useImportSwaggerJsonModal } from './utils';
|
||||
import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { generateNanoid } from '@/visual-editor/utils/';
|
||||
import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum';
|
||||
import { useImportSwaggerJsonModal } from './utils';
|
||||
import { Delete, Edit } from '@element-plus/icons-vue';
|
||||
|
||||
interface IState {
|
||||
activeNames: string[];
|
||||
|
@ -246,6 +247,7 @@
|
|||
|
||||
.model-actions {
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
padding: 6px;
|
||||
margin: 0 2px;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div class="model-item-title">
|
||||
<span class="truncate w-160px">{{ item.name }}</span>
|
||||
<div class="model-actions">
|
||||
<el-icon size="24" color="#2196f3" @click.stop="editModel(item)">
|
||||
<el-icon :size="24" color="#2196f3" @click.stop="editModel(item)">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-popconfirm
|
||||
|
@ -32,7 +32,7 @@
|
|||
@confirm="deleteModel(item.key)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-icon size="24" color="#f44336"><Delete /></el-icon>
|
||||
<el-icon :size="24" color="#f44336"><Delete /></el-icon>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
|
@ -59,14 +59,15 @@
|
|||
ElCard,
|
||||
ElButton,
|
||||
ElMessage,
|
||||
ElIcon,
|
||||
} from 'element-plus';
|
||||
import { useVisualData, fieldTypes } from '@/visual-editor/hooks/useVisualData';
|
||||
import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { generateNanoid } from '@/visual-editor/utils/';
|
||||
import { useImportSwaggerJsonModal } from './utils';
|
||||
import { Delete, Edit } from '@element-plus/icons-vue';
|
||||
import { useImportSwaggerJsonModal } from './utils';
|
||||
import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { useVisualData, fieldTypes } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { generateNanoid } from '@/visual-editor/utils/';
|
||||
|
||||
interface IState {
|
||||
activeNames: string[];
|
||||
|
@ -261,6 +262,7 @@
|
|||
|
||||
.model-actions {
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
padding: 6px;
|
||||
margin: 0 2px;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<!--
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-24 18:36:03
|
||||
* @LastEditTime: 2021-07-07 14:12:15
|
||||
* @LastEditTime: 2022-07-02 23:13:00
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 数据源管理
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\index.vue
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/left-aside/components/data-source/index.vue
|
||||
-->
|
||||
<template>
|
||||
<el-tabs type="border-card" stretch class="data-source">
|
||||
|
@ -17,18 +17,16 @@
|
|||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx" name="基本组件">
|
||||
import { DataBoard } from '@element-plus/icons-vue';
|
||||
import DataModel from './data-model.vue';
|
||||
import DataFetch from './data-fetch.vue';
|
||||
|
||||
export default {
|
||||
defineOptions({
|
||||
label: '数据源',
|
||||
order: 2,
|
||||
icon: DataBoard,
|
||||
};
|
||||
</script>
|
||||
<script setup lang="tsx" name="基本组件">
|
||||
import DataModel from './data-model.vue';
|
||||
import DataFetch from './data-fetch.vue';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-27 13:15:19
|
||||
* @LastEditTime: 2021-06-27 15:22:51
|
||||
* @LastEditTime: 2022-07-02 23:12:37
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\utils.tsx
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/left-aside/components/data-source/utils.tsx
|
||||
*/
|
||||
import { ElMessage } from 'element-plus';
|
||||
import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { generateNanoid } from '@/visual-editor/utils';
|
||||
import type { FetchApiItem } from '@/visual-editor/visual-editor.utils';
|
||||
import { RequestEnum } from '@/enums/httpEnum';
|
||||
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
/**
|
||||
* @description 导入丝袜哥, eg: 简单的解析代码,需要根据自己需要完善
|
||||
|
@ -51,7 +50,7 @@ export const importSwaggerJson = (swagger: any) => {
|
|||
key: generateNanoid(),
|
||||
name: apiUrlObj.summary,
|
||||
options: {
|
||||
url: url, // 请求的url
|
||||
url, // 请求的url
|
||||
method: method.toLocaleUpperCase() as RequestEnum, // 请求的方法
|
||||
contentType: apiUrlObj.produces[0] || apiUrlObj.consumes[0], // 请求的内容类型
|
||||
},
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
const modules = import.meta.globEager('./*/index.(tsx|vue)')
|
||||
const modules = import.meta.globEager('./*/index.(tsx|vue)');
|
||||
|
||||
const components = {}
|
||||
const components = {};
|
||||
|
||||
console.log(modules, '起航')
|
||||
console.log(modules, '起航');
|
||||
|
||||
for (const path in modules) {
|
||||
const comp = modules[path].default
|
||||
components[comp.name || path.split('/')[1]] = comp
|
||||
const comp = modules[path].default;
|
||||
components[comp.name || path.split('/')[1]] = comp;
|
||||
}
|
||||
console.log('left-aside components:', components)
|
||||
console.log('left-aside components:', components);
|
||||
|
||||
export default components
|
||||
export default components;
|
||||
|
|
|
@ -40,23 +40,21 @@
|
|||
</el-tree>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
export default {
|
||||
<script lang="tsx" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { ElMessage, ElForm, ElFormItem, ElInput } from 'element-plus';
|
||||
import { Tickets, Plus, MoreFilled, Edit, Delete, Link } from '@element-plus/icons-vue';
|
||||
import type { VisualEditorPage } from '@/visual-editor/visual-editor.utils';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { useVisualData, createNewPage } from '@/visual-editor/hooks/useVisualData';
|
||||
|
||||
defineOptions({
|
||||
name: 'PageTree',
|
||||
label: '页面',
|
||||
order: 1,
|
||||
icon: Tickets,
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useVisualData, createNewPage } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { ElMessage, ElForm, ElFormItem, ElInput } from 'element-plus';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import type { VisualEditorPage } from '@/visual-editor/visual-editor.utils';
|
||||
import { Tickets, Plus, MoreFilled, Edit, Delete, Link } from '@element-plus/icons-vue';
|
||||
});
|
||||
|
||||
const rules = {
|
||||
title: [{ required: true, message: '请输入页面标题', trigger: 'blur' }],
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<!--
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-24 00:35:17
|
||||
* @LastEditTime: 2021-07-07 14:02:29
|
||||
* @LastEditTime: 2022-07-02 18:26:09
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 左侧边栏
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\index.vue
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/left-aside/index.vue
|
||||
-->
|
||||
<template>
|
||||
<el-tabs v-model="activeName" tab-position="left" class="left-aside">
|
||||
|
@ -22,12 +22,6 @@
|
|||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'LeftAside',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* @description 左侧边栏
|
||||
|
@ -35,6 +29,10 @@
|
|||
import { ref } from 'vue';
|
||||
import components from './components';
|
||||
|
||||
defineOptions({
|
||||
name: 'LeftAside',
|
||||
});
|
||||
|
||||
const tabs = Object.keys(components)
|
||||
.map((name) => {
|
||||
const { label, icon, order } = components[name];
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
*/
|
||||
import { defineComponent, reactive, ref, watchEffect } from 'vue';
|
||||
import { ElTabs, ElTabPane, ElRow, ElCol, ElButton, ElSwitch, ElAlert, ElIcon } from 'element-plus';
|
||||
import { onClickOutside } from '@vueuse/core';
|
||||
import { Plus, CaretRight } from '@element-plus/icons-vue';
|
||||
import { animationTabs } from './animateConfig';
|
||||
import styles from './animate.module.scss';
|
||||
import { onClickOutside } from '@vueuse/core';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import type { Animation } from '@/visual-editor/visual-editor.utils';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useAnimate } from '@/hooks/useAnimate';
|
||||
import { Plus, CaretRight } from '@element-plus/icons-vue';
|
||||
import 'element-plus/es/components/alert/style/css';
|
||||
|
||||
export const Animate = defineComponent({
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import type { Animation } from '@/visual-editor/visual-editor.utils'
|
||||
import type { Animation } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
export interface animationBoxTs {
|
||||
label: string
|
||||
value: Animation[]
|
||||
label: string;
|
||||
value: Animation[];
|
||||
}
|
||||
// 动画类型
|
||||
export interface animationTabsTs {
|
||||
in: animationBoxTs
|
||||
out: animationBoxTs
|
||||
other: animationBoxTs
|
||||
in: animationBoxTs;
|
||||
out: animationBoxTs;
|
||||
other: animationBoxTs;
|
||||
}
|
||||
|
||||
export const animationTabs: animationTabsTs = {
|
||||
in: {
|
||||
label: '进入',
|
||||
value: []
|
||||
value: [],
|
||||
},
|
||||
out: {
|
||||
label: '退出',
|
||||
value: []
|
||||
value: [],
|
||||
},
|
||||
other: {
|
||||
label: '其他',
|
||||
value: []
|
||||
}
|
||||
}
|
||||
value: [],
|
||||
},
|
||||
};
|
||||
|
||||
const opt = [
|
||||
{
|
||||
|
@ -33,41 +33,41 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '弹跳',
|
||||
value: 'bounce'
|
||||
value: 'bounce',
|
||||
},
|
||||
{
|
||||
label: '闪烁',
|
||||
value: 'flash'
|
||||
value: 'flash',
|
||||
},
|
||||
{
|
||||
label: '跳动',
|
||||
value: 'pulse'
|
||||
value: 'pulse',
|
||||
},
|
||||
{
|
||||
label: '抖动',
|
||||
value: 'headShake'
|
||||
value: 'headShake',
|
||||
},
|
||||
{
|
||||
label: '摇摆',
|
||||
value: 'swing'
|
||||
value: 'swing',
|
||||
},
|
||||
{
|
||||
label: '橡皮圈',
|
||||
value: 'rubberBand'
|
||||
value: 'rubberBand',
|
||||
},
|
||||
{
|
||||
label: '果冻',
|
||||
value: 'jello'
|
||||
value: 'jello',
|
||||
},
|
||||
{
|
||||
label: '晃动',
|
||||
value: 'tada'
|
||||
value: 'tada',
|
||||
},
|
||||
{
|
||||
label: '抖动',
|
||||
value: 'wobble'
|
||||
}
|
||||
]
|
||||
value: 'wobble',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -76,25 +76,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '弹跳进入',
|
||||
value: 'bounceIn'
|
||||
value: 'bounceIn',
|
||||
},
|
||||
{
|
||||
label: '向下弹跳进入',
|
||||
value: 'bounceInDown'
|
||||
value: 'bounceInDown',
|
||||
},
|
||||
{
|
||||
label: '向右弹跳进入',
|
||||
value: 'bounceInLeft'
|
||||
value: 'bounceInLeft',
|
||||
},
|
||||
{
|
||||
label: '向左弹跳进入',
|
||||
value: 'bounceInRight'
|
||||
value: 'bounceInRight',
|
||||
},
|
||||
{
|
||||
label: '向上弹跳进入',
|
||||
value: 'bounceInUp'
|
||||
}
|
||||
]
|
||||
value: 'bounceInUp',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -103,25 +103,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '弹跳退出',
|
||||
value: 'bounceOut'
|
||||
value: 'bounceOut',
|
||||
},
|
||||
{
|
||||
label: '向下弹跳退出',
|
||||
value: 'bounceOutDown'
|
||||
value: 'bounceOutDown',
|
||||
},
|
||||
{
|
||||
label: '向左弹跳退出',
|
||||
value: 'bounceOutLeft'
|
||||
value: 'bounceOutLeft',
|
||||
},
|
||||
{
|
||||
label: '向右弹跳退出',
|
||||
value: 'bounceOutRight'
|
||||
value: 'bounceOutRight',
|
||||
},
|
||||
{
|
||||
label: '向上弹跳退出',
|
||||
value: 'bounceOutUp'
|
||||
}
|
||||
]
|
||||
value: 'bounceOutUp',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -130,41 +130,41 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '渐显进入',
|
||||
value: 'fadeIn'
|
||||
value: 'fadeIn',
|
||||
},
|
||||
{
|
||||
label: '向下渐显进入',
|
||||
value: 'fadeInDown'
|
||||
value: 'fadeInDown',
|
||||
},
|
||||
{
|
||||
label: '由屏幕外向下渐显进入',
|
||||
value: 'fadeInDownBig'
|
||||
value: 'fadeInDownBig',
|
||||
},
|
||||
{
|
||||
label: '向右显进入',
|
||||
value: 'fadeInLeft'
|
||||
value: 'fadeInLeft',
|
||||
},
|
||||
{
|
||||
label: '由屏幕外向右渐显进入',
|
||||
value: 'fadeInLeftBig'
|
||||
value: 'fadeInLeftBig',
|
||||
},
|
||||
{
|
||||
label: '向左渐显进入',
|
||||
value: 'fadeInRight'
|
||||
value: 'fadeInRight',
|
||||
},
|
||||
{
|
||||
label: '由屏幕外向左渐显进入',
|
||||
value: 'fadeInRightBig'
|
||||
value: 'fadeInRightBig',
|
||||
},
|
||||
{
|
||||
label: '向上渐显进入',
|
||||
value: 'fadeInUp'
|
||||
value: 'fadeInUp',
|
||||
},
|
||||
{
|
||||
label: '由屏幕外向上渐显进入',
|
||||
value: 'fadeInUpBig'
|
||||
}
|
||||
]
|
||||
value: 'fadeInUpBig',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -173,41 +173,41 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '渐隐退出',
|
||||
value: 'fadeOut'
|
||||
value: 'fadeOut',
|
||||
},
|
||||
{
|
||||
label: '向下渐隐退出',
|
||||
value: 'fadeOutDown'
|
||||
value: 'fadeOutDown',
|
||||
},
|
||||
{
|
||||
label: '向下渐隐退出屏幕外',
|
||||
value: 'fadeOutDownBig'
|
||||
value: 'fadeOutDownBig',
|
||||
},
|
||||
{
|
||||
label: '向左渐隐退出',
|
||||
value: 'fadeOutLeft'
|
||||
value: 'fadeOutLeft',
|
||||
},
|
||||
{
|
||||
label: '向左渐隐退出屏幕外',
|
||||
value: 'fadeOutLeftBig'
|
||||
value: 'fadeOutLeftBig',
|
||||
},
|
||||
{
|
||||
label: '向右渐隐退出',
|
||||
value: 'fadeOutRight'
|
||||
value: 'fadeOutRight',
|
||||
},
|
||||
{
|
||||
label: '向右渐隐退出屏幕外',
|
||||
value: 'fadeOutRightBig'
|
||||
value: 'fadeOutRightBig',
|
||||
},
|
||||
{
|
||||
label: '向上渐隐退出',
|
||||
value: 'fadeOutUp'
|
||||
value: 'fadeOutUp',
|
||||
},
|
||||
{
|
||||
label: '向上渐隐退出屏幕外',
|
||||
value: 'fadeOutUpBig'
|
||||
}
|
||||
]
|
||||
value: 'fadeOutUpBig',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -216,25 +216,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '翻动',
|
||||
value: 'flip'
|
||||
value: 'flip',
|
||||
},
|
||||
{
|
||||
label: '纵向翻动',
|
||||
value: 'flipInX'
|
||||
value: 'flipInX',
|
||||
},
|
||||
{
|
||||
label: '横向翻动',
|
||||
value: 'flipInY'
|
||||
value: 'flipInY',
|
||||
},
|
||||
{
|
||||
label: '立体纵向翻动',
|
||||
value: 'flipOutX'
|
||||
value: 'flipOutX',
|
||||
},
|
||||
{
|
||||
label: '立体横向翻动',
|
||||
value: 'flipOutY'
|
||||
}
|
||||
]
|
||||
value: 'flipOutY',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -243,21 +243,21 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '向左加速进入',
|
||||
value: 'lightSpeedInRight'
|
||||
value: 'lightSpeedInRight',
|
||||
},
|
||||
{
|
||||
label: '向右加速进入',
|
||||
value: 'lightSpeedInLeft'
|
||||
value: 'lightSpeedInLeft',
|
||||
},
|
||||
{
|
||||
label: '向右加速退出',
|
||||
value: 'lightSpeedOutRight'
|
||||
value: 'lightSpeedOutRight',
|
||||
},
|
||||
{
|
||||
label: '向左加速退出',
|
||||
value: 'lightSpeedOutLeft'
|
||||
}
|
||||
]
|
||||
value: 'lightSpeedOutLeft',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -266,25 +266,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '旋转渐显',
|
||||
value: 'rotateIn'
|
||||
value: 'rotateIn',
|
||||
},
|
||||
{
|
||||
label: '左下角旋转渐显',
|
||||
value: 'rotateInDownLeft'
|
||||
value: 'rotateInDownLeft',
|
||||
},
|
||||
{
|
||||
label: '右下角旋转渐显',
|
||||
value: 'rotateInDownRight'
|
||||
value: 'rotateInDownRight',
|
||||
},
|
||||
{
|
||||
label: '左上角旋转渐显',
|
||||
value: 'rotateInUpLeft'
|
||||
value: 'rotateInUpLeft',
|
||||
},
|
||||
{
|
||||
label: '右上角旋转渐显',
|
||||
value: 'rotateInUpRight'
|
||||
}
|
||||
]
|
||||
value: 'rotateInUpRight',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -293,25 +293,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '旋转渐隐',
|
||||
value: 'rotateOut'
|
||||
value: 'rotateOut',
|
||||
},
|
||||
{
|
||||
label: '左下角旋转渐隐',
|
||||
value: 'rotateOutDownLeft'
|
||||
value: 'rotateOutDownLeft',
|
||||
},
|
||||
{
|
||||
label: '左下角旋转渐隐',
|
||||
value: 'rotateOutDownRight'
|
||||
value: 'rotateOutDownRight',
|
||||
},
|
||||
{
|
||||
label: '左上角旋转渐隐',
|
||||
value: 'rotateOutUpLeft'
|
||||
value: 'rotateOutUpLeft',
|
||||
},
|
||||
{
|
||||
label: '右上角旋转渐隐',
|
||||
value: 'rotateOutUpRight'
|
||||
}
|
||||
]
|
||||
value: 'rotateOutUpRight',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -320,21 +320,21 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '向上平移进入',
|
||||
value: 'slideInUp'
|
||||
value: 'slideInUp',
|
||||
},
|
||||
{
|
||||
label: '向下平移进入',
|
||||
value: 'slideInDown'
|
||||
value: 'slideInDown',
|
||||
},
|
||||
{
|
||||
label: '向右平移进入',
|
||||
value: 'slideInLeft'
|
||||
value: 'slideInLeft',
|
||||
},
|
||||
{
|
||||
label: '向左平移进入',
|
||||
value: 'slideInRight'
|
||||
}
|
||||
]
|
||||
value: 'slideInRight',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '平移退出',
|
||||
|
@ -342,21 +342,21 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '向上平移退出',
|
||||
value: 'slideOutUp'
|
||||
value: 'slideOutUp',
|
||||
},
|
||||
{
|
||||
label: '向下平移退出',
|
||||
value: 'slideOutDown'
|
||||
value: 'slideOutDown',
|
||||
},
|
||||
{
|
||||
label: '向左平移退出',
|
||||
value: 'slideOutLeft'
|
||||
value: 'slideOutLeft',
|
||||
},
|
||||
{
|
||||
label: '向右平移退出',
|
||||
value: 'slideOutRight'
|
||||
}
|
||||
]
|
||||
value: 'slideOutRight',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -365,25 +365,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '放大进入',
|
||||
value: 'zoomIn'
|
||||
value: 'zoomIn',
|
||||
},
|
||||
{
|
||||
label: '向下放大进入',
|
||||
value: 'zoomInDown'
|
||||
value: 'zoomInDown',
|
||||
},
|
||||
{
|
||||
label: '向右放大进入',
|
||||
value: 'zoomInLeft'
|
||||
value: 'zoomInLeft',
|
||||
},
|
||||
{
|
||||
label: '向左放大进入',
|
||||
value: 'zoomInRight'
|
||||
value: 'zoomInRight',
|
||||
},
|
||||
{
|
||||
label: '向上放大进入',
|
||||
value: 'zoomInUp'
|
||||
}
|
||||
]
|
||||
value: 'zoomInUp',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -392,25 +392,25 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '缩小退出',
|
||||
value: 'zoomOut'
|
||||
value: 'zoomOut',
|
||||
},
|
||||
{
|
||||
label: '向下缩小退出',
|
||||
value: 'zoomOutDown'
|
||||
value: 'zoomOutDown',
|
||||
},
|
||||
{
|
||||
label: '向左缩小退出',
|
||||
value: 'zoomOutLeft'
|
||||
value: 'zoomOutLeft',
|
||||
},
|
||||
{
|
||||
label: '向右缩小退出',
|
||||
value: 'zoomOutRight'
|
||||
value: 'zoomOutRight',
|
||||
},
|
||||
{
|
||||
label: '向上缩小退出',
|
||||
value: 'zoomOutUp'
|
||||
}
|
||||
]
|
||||
value: 'zoomOutUp',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -419,51 +419,51 @@ const opt = [
|
|||
children: [
|
||||
{
|
||||
label: '悬挂',
|
||||
value: 'hinge'
|
||||
value: 'hinge',
|
||||
},
|
||||
{
|
||||
label: '滚动进入',
|
||||
value: 'rollIn'
|
||||
value: 'rollIn',
|
||||
},
|
||||
{
|
||||
label: '滚动退出',
|
||||
value: 'rollOut'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
value: 'rollOut',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @return {Object} { animationValue: animatonLabel }
|
||||
*/
|
||||
const inReg = /进|渐显/
|
||||
const outReg = /退|渐隐/
|
||||
const inReg = /进|渐显/;
|
||||
const outReg = /退|渐隐/;
|
||||
const defaultOption = {
|
||||
delay: 0,
|
||||
count: 1,
|
||||
duration: 1,
|
||||
infinite: false
|
||||
}
|
||||
infinite: false,
|
||||
};
|
||||
for (let index = 0; index < opt.length; index++) {
|
||||
const items = opt[index].children
|
||||
const items = opt[index].children;
|
||||
items.forEach((item) => {
|
||||
if (inReg.test(item.label)) {
|
||||
animationTabs.in.value.push({
|
||||
...item,
|
||||
...defaultOption
|
||||
})
|
||||
...defaultOption,
|
||||
});
|
||||
} else if (outReg.test(item.label)) {
|
||||
animationTabs.out.value.push({
|
||||
...item,
|
||||
...defaultOption
|
||||
})
|
||||
...defaultOption,
|
||||
});
|
||||
} else {
|
||||
animationTabs.other.value.push({
|
||||
...item,
|
||||
...defaultOption
|
||||
})
|
||||
...defaultOption,
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export default animationTabs
|
||||
export default animationTabs;
|
||||
|
|
|
@ -21,12 +21,12 @@ import {
|
|||
ElIcon,
|
||||
} from 'element-plus';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { isObject } from '@/visual-editor/utils/is';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { PropConfig } from '../prop-config';
|
||||
import { VisualEditorBlockData, VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { Rank, CirclePlus, Remove } from '@element-plus/icons-vue';
|
||||
import { PropConfig } from '../prop-config';
|
||||
import { isObject } from '@/visual-editor/utils/is';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { VisualEditorBlockData, VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
interface OptionItem extends LabelValue {
|
||||
component?: VisualEditorComponent;
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\attr-editor\components\index.ts
|
||||
*/
|
||||
|
||||
export { CrossSortableOptionsEditor } from './cross-sortable-options-editor/cross-sortable-options-editor'
|
||||
export { TablePropEditor } from './table-prop-editor/table-prop-editor'
|
||||
export { CrossSortableOptionsEditor } from './cross-sortable-options-editor/cross-sortable-options-editor';
|
||||
export { TablePropEditor } from './table-prop-editor/table-prop-editor';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-07-11 17:53:54
|
||||
* @LastEditTime: 2021-07-11 18:36:17
|
||||
* @LastEditTime: 2022-07-02 22:58:55
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 组件属性配置
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\attr-editor\components\prop-config\index.tsx
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/right-attribute-panel/components/attr-editor/components/prop-config/index.tsx
|
||||
*/
|
||||
|
||||
import { computed, defineComponent, PropType } from 'vue';
|
||||
|
@ -19,14 +19,15 @@ import {
|
|||
ElFormItem,
|
||||
ElTooltip,
|
||||
ElIcon,
|
||||
ExpandTrigger,
|
||||
} from 'element-plus';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { Warning } from '@element-plus/icons-vue';
|
||||
import { TablePropEditor, CrossSortableOptionsEditor } from '../../components';
|
||||
import { useDotProp } from '@/visual-editor/hooks/useDotProp';
|
||||
import { VisualEditorProps, VisualEditorPropsType } from '@/visual-editor/visual-editor.props';
|
||||
import { TablePropEditor, CrossSortableOptionsEditor } from '../../components';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { VisualEditorBlockData, VisualEditorComponent } from '@/visual-editor/visual-editor.utils';
|
||||
import { Warning } from '@element-plus/icons-vue';
|
||||
|
||||
export const PropConfig = defineComponent({
|
||||
props: {
|
||||
|
@ -92,11 +93,11 @@ export const PropConfig = defineComponent({
|
|||
children: 'entitys',
|
||||
label: 'name',
|
||||
value: 'key',
|
||||
expandTrigger: 'hover',
|
||||
expandTrigger: ExpandTrigger.HOVER,
|
||||
}}
|
||||
placeholder="请选择绑定的请求数据"
|
||||
v-model={propObj[prop]}
|
||||
options={models.value}
|
||||
options={[...models.value]}
|
||||
></ElCascader>
|
||||
),
|
||||
}[propConfig.type]();
|
||||
|
@ -126,9 +127,11 @@ export const PropConfig = defineComponent({
|
|||
popper-class="max-w-200px"
|
||||
content={propConfig.tips}
|
||||
>
|
||||
<div>
|
||||
<ElIcon>
|
||||
<Warning />
|
||||
</ElIcon>
|
||||
</div>
|
||||
</ElTooltip>
|
||||
)}
|
||||
{propConfig.label}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { VisualEditorProps } from '@/visual-editor/visual-editor.props';
|
||||
import { defineComponent, getCurrentInstance, onMounted, PropType, reactive, createApp } from 'vue';
|
||||
import { defer } from '@/visual-editor/utils/defer';
|
||||
import { ElButton, ElDialog, ElTable, ElTableColumn, ElInput } from 'element-plus';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { defer } from '@/visual-editor/utils/defer';
|
||||
import { VisualEditorProps } from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export interface TablePropEditorServiceOption {
|
||||
data: any[];
|
||||
|
@ -66,7 +66,7 @@ const ServiceComponent = defineComponent({
|
|||
|
||||
return () => (
|
||||
<>
|
||||
<ElDialog v-model={state.showFlag}>
|
||||
<ElDialog modelValue={state.showFlag}>
|
||||
{{
|
||||
default: () => (
|
||||
<div>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import { defineComponent, PropType, SetupContext } from 'vue'
|
||||
import { VisualEditorProps } from '@/visual-editor/visual-editor.props'
|
||||
import { ElButton, ElTag } from 'element-plus'
|
||||
import { $$tablePropEditor } from './table-prop-edit.service'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { defineComponent, PropType, SetupContext } from 'vue';
|
||||
import { ElButton, ElTag } from 'element-plus';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { $$tablePropEditor } from './table-prop-edit.service';
|
||||
import { VisualEditorProps } from '@/visual-editor/visual-editor.props';
|
||||
|
||||
export const TablePropEditor = defineComponent({
|
||||
props: {
|
||||
modelValue: { type: Array as PropType<any[]> },
|
||||
propConfig: { type: Object as PropType<VisualEditorProps>, required: true }
|
||||
propConfig: { type: Object as PropType<VisualEditorProps>, required: true },
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }: SetupContext) {
|
||||
const model = useVModel(props, 'modelValue', emit)
|
||||
const model = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const onClick = async () => {
|
||||
const data = await $$tablePropEditor({
|
||||
config: props.propConfig,
|
||||
data: props.modelValue || []
|
||||
})
|
||||
model.value = data
|
||||
}
|
||||
data: props.modelValue || [],
|
||||
});
|
||||
model.value = data;
|
||||
};
|
||||
|
||||
return () => (
|
||||
<div>
|
||||
|
@ -30,6 +30,6 @@ export const TablePropEditor = defineComponent({
|
|||
<ElTag {...({ onClick } as any)}>{item[props.propConfig.table!.showKey]}</ElTag>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
*/
|
||||
import { defineComponent, computed, watch } from 'vue';
|
||||
import { ElForm, ElFormItem, ElPopover, ElRadioGroup, ElRadioButton, ElIcon } from 'element-plus';
|
||||
import { Warning } from '@element-plus/icons-vue';
|
||||
import { PropConfig } from './components/prop-config';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { FormatInputNumber } from '@/visual-editor/components/common/format-input-number';
|
||||
import { PropConfig } from './components/prop-config';
|
||||
import { Warning } from '@element-plus/icons-vue';
|
||||
|
||||
export const AttrEditor = defineComponent({
|
||||
setup() {
|
||||
|
@ -75,8 +75,8 @@ export const AttrEditor = defineComponent({
|
|||
</ElFormItem>
|
||||
</>,
|
||||
);
|
||||
if (!!component) {
|
||||
if (!!component.props) {
|
||||
if (component) {
|
||||
if (component.props) {
|
||||
content.push(<PropConfig component={component} block={currentBlock.value} />);
|
||||
{
|
||||
currentBlock.value.showStyleConfig &&
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-06-24 11:01:45
|
||||
* @LastEditTime: 2021-07-08 09:53:27
|
||||
* @LastEditTime: 2022-07-02 18:29:25
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 事件-动作
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\event-action\index.tsx
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/right-attribute-panel/components/event-action/index.tsx
|
||||
*/
|
||||
import { computed, ref, defineComponent, reactive } from 'vue';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import {
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
|
@ -21,10 +20,11 @@ import {
|
|||
ElCollapseItem,
|
||||
ElPopconfirm,
|
||||
} from 'element-plus';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import type { Action } from '@/visual-editor/visual-editor.utils';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { generateNanoid } from '@/visual-editor/utils/';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
interface IState {
|
||||
activeNames: string[];
|
||||
|
@ -92,7 +92,6 @@ export const EventAction = defineComponent({
|
|||
.filter((item) => item.actions?.length)
|
||||
.map((item) => {
|
||||
item.value = item._vid;
|
||||
item.label = item.label;
|
||||
item.children = (item.actions || []).map((item: any) => {
|
||||
item.label = item.name;
|
||||
item.value = item.key;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* @Author: 卜启缘
|
||||
* @Date: 2021-07-05 10:51:09
|
||||
* @LastEditTime: 2021-07-08 23:20:17
|
||||
* @LastEditTime: 2022-07-02 22:46:59
|
||||
* @LastEditors: 卜启缘
|
||||
* @Description: 表单规则
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\form-rule\index.tsx
|
||||
* @FilePath: /vite-vue3-lowcode/src/visual-editor/components/right-attribute-panel/components/form-rule/index.tsx
|
||||
*/
|
||||
import { defineComponent } from 'vue';
|
||||
import { ElCard, ElTooltip } from 'element-plus';
|
||||
|
@ -29,7 +29,7 @@ export const FormRule = defineComponent({
|
|||
default: () => <div>暂无规则</div>,
|
||||
}}
|
||||
</ElCard>
|
||||
<ElCard shadow={'always'} bodyStyle={{ padding: 1 ? '0' : '20px' }} class={'mb-20px'}>
|
||||
<ElCard shadow={'always'} bodyStyle={{ padding: '0' }} class={'mb-20px'}>
|
||||
{{
|
||||
header: () => (
|
||||
<div class="flex justify-between">
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\index.ts
|
||||
*/
|
||||
|
||||
export { AttrEditor } from './attr-editor'
|
||||
export { Animate } from './animate/Animate'
|
||||
export { PageSetting } from './page-setting/pageSetting'
|
||||
export { EventAction } from './event-action/'
|
||||
export { FormRule } from './form-rule/'
|
||||
export { AttrEditor } from './attr-editor';
|
||||
export { Animate } from './animate/Animate';
|
||||
export { PageSetting } from './page-setting/pageSetting';
|
||||
export { EventAction } from './event-action/';
|
||||
export { FormRule } from './form-rule/';
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
*/
|
||||
import { defineComponent } from 'vue';
|
||||
import { ElForm, ElFormItem, ElInput, ElUpload, ElColorPicker, ElSwitch } from 'element-plus';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import styles from './styles.module.scss';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
|
||||
export const PageSetting = defineComponent({
|
||||
setup() {
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
*/
|
||||
|
||||
import { defineComponent, reactive, watch } from 'vue';
|
||||
import styles from './index.module.scss';
|
||||
import { ElTabPane, ElTabs } from 'element-plus';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { AttrEditor, Animate, PageSetting, EventAction, FormRule } from './components';
|
||||
import { DArrowLeft, DArrowRight } from '@element-plus/icons-vue';
|
||||
import styles from './index.module.scss';
|
||||
import { AttrEditor, Animate, PageSetting, EventAction, FormRule } from './components';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RightAttributePanel',
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
* @Description:
|
||||
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\simulator-editor\comp-render.tsx
|
||||
*/
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
||||
import { visualConfig } from '@/visual.config'
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
|
||||
import { visualConfig } from '@/visual.config';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CompRender',
|
||||
props: {
|
||||
element: {
|
||||
type: Object as PropType<VisualEditorBlockData>,
|
||||
default: () => ({})
|
||||
}
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
return visualConfig.componentMap[props.element.componentKey].render({
|
||||
|
@ -24,7 +24,7 @@ export default defineComponent({
|
|||
props: props.element.props || {},
|
||||
model: {},
|
||||
block: props.element,
|
||||
custom: {}
|
||||
})
|
||||
}
|
||||
})
|
||||
custom: {},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
v-model="list"
|
||||
class="dragArea list-group"
|
||||
:class="{ isDrag }"
|
||||
tag="transition-group"
|
||||
:component-data="{
|
||||
tag: 'div',
|
||||
tag: 'ul',
|
||||
type: 'transition-group',
|
||||
name: !isDrag ? 'flip-list' : null
|
||||
name: !isDrag ? 'flip-list' : null,
|
||||
}"
|
||||
:group="group"
|
||||
v-bind="{ ...dragOptions, ...$attrs }"
|
||||
|
@ -24,78 +23,78 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
/**
|
||||
/**
|
||||
* @name: draggable-transition-group
|
||||
* @author:卜启缘
|
||||
* @date: 2021/5/1 23:15
|
||||
* @description:draggable-transition-group
|
||||
* @update: 2021/5/1 23:15
|
||||
*/
|
||||
import { computed, defineComponent, reactive, toRefs, SetupContext } from 'vue'
|
||||
import draggable from 'vuedraggable'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { computed, defineComponent, reactive, toRefs, SetupContext } from 'vue';
|
||||
import draggable from 'vuedraggable';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'DraggableTransitionGroup',
|
||||
components: { draggable },
|
||||
props: {
|
||||
moduleValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
default: () => [],
|
||||
},
|
||||
drag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
itemKey: {
|
||||
type: String,
|
||||
default: '_vid'
|
||||
default: '_vid',
|
||||
},
|
||||
group: {
|
||||
type: Object,
|
||||
default: () => ({ name: 'components' })
|
||||
default: () => ({ name: 'components' }),
|
||||
},
|
||||
fallbackClass: String
|
||||
fallbackClass: String,
|
||||
},
|
||||
emits: ['update:moduleValue', 'update:drag'],
|
||||
setup(props, { emit }: SetupContext) {
|
||||
const state = reactive({
|
||||
list: useVModel(props, 'moduleValue', emit),
|
||||
isDrag: useVModel(props, 'drag', emit)
|
||||
})
|
||||
isDrag: useVModel(props, 'drag', emit),
|
||||
});
|
||||
|
||||
const dragOptions = computed(() => ({
|
||||
animation: 200,
|
||||
disabled: false,
|
||||
scroll: true,
|
||||
ghostClass: 'ghost'
|
||||
}))
|
||||
ghostClass: 'ghost',
|
||||
}));
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
dragOptions
|
||||
}
|
||||
}
|
||||
})
|
||||
dragOptions,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './func.scss';
|
||||
@import './func.scss';
|
||||
|
||||
.flip-list-move {
|
||||
.flip-list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
.no-move {
|
||||
.no-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
}
|
||||
|
||||
.ghost {
|
||||
.ghost {
|
||||
background: #c8ebfb;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group {
|
||||
.list-group {
|
||||
height: 100%;
|
||||
min-height: 40px;
|
||||
|
||||
|
@ -106,5 +105,5 @@ export default defineComponent({
|
|||
&.isDrag:not(.no-child) :deep(.list-group-item.has-slot) {
|
||||
@include showContainerBorder;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -55,13 +55,13 @@
|
|||
|
||||
<script lang="tsx">
|
||||
import { defineComponent, reactive, watchEffect, toRefs } from 'vue';
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import DraggableTransitionGroup from './draggable-transition-group.vue';
|
||||
import { $$dropdown, DropdownOption } from '@/visual-editor/utils/dropdown-service';
|
||||
import CompRender from './comp-render';
|
||||
import SlotItem from './slot-item.vue';
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
|
||||
import { $$dropdown, DropdownOption } from '@/visual-editor/utils/dropdown-service';
|
||||
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useGlobalProperties } from '@/hooks/useGlobalProperties';
|
||||
import { useVisualData } from '@/visual-editor/hooks/useVisualData';
|
||||
import { useModal } from '@/visual-editor/hooks/useModal';
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
:data-label="innerElement.label"
|
||||
:class="{
|
||||
focus: innerElement.focus,
|
||||
focusWithChild: innerElement.focusWithChild
|
||||
focusWithChild: innerElement.focusWithChild,
|
||||
}"
|
||||
@contextmenu.stop.prevent="onContextmenuBlock($event, innerElement, slotChildren)"
|
||||
@mousedown.stop="selectComp(innerElement)"
|
||||
|
@ -21,7 +21,7 @@
|
|||
<comp-render
|
||||
:element="innerElement"
|
||||
:style="{
|
||||
pointerEvents: Object.keys(innerElement.props?.slots || {}).length ? 'auto' : 'none'
|
||||
pointerEvents: Object.keys(innerElement.props?.slots || {}).length ? 'auto' : 'none',
|
||||
}"
|
||||
>
|
||||
<template v-for="(value, key) in innerElement.props?.slots" :key="key" #[key]>
|
||||
|
@ -40,7 +40,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
/**
|
||||
/**
|
||||
* @name: slot-item
|
||||
* @author:卜启缘
|
||||
* @date: 2021/5/2 22:36
|
||||
|
@ -48,64 +48,64 @@
|
|||
* @update: 2021/5/2 22:36
|
||||
*/
|
||||
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import DraggableTransitionGroup from './draggable-transition-group.vue'
|
||||
import CompRender from './comp-render'
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils'
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import DraggableTransitionGroup from './draggable-transition-group.vue';
|
||||
import CompRender from './comp-render';
|
||||
import type { VisualEditorBlockData } from '@/visual-editor/visual-editor.utils';
|
||||
|
||||
export default defineComponent({
|
||||
export default defineComponent({
|
||||
name: 'SlotItem',
|
||||
components: { CompRender, DraggableTransitionGroup },
|
||||
props: {
|
||||
slotKey: {
|
||||
type: String as PropType<string>,
|
||||
default: ''
|
||||
type: String as PropType<string | number>,
|
||||
default: '',
|
||||
},
|
||||
drag: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
children: {
|
||||
type: Array as PropType<VisualEditorBlockData[]>,
|
||||
default: () => []
|
||||
default: () => [],
|
||||
},
|
||||
selectComp: {
|
||||
type: Function as PropType<(comp: VisualEditorBlockData) => void>,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
onContextmenuBlock: {
|
||||
type: Function as PropType<
|
||||
(
|
||||
e: MouseEvent,
|
||||
block: VisualEditorBlockData,
|
||||
parentBlocks?: VisualEditorBlockData[]
|
||||
parentBlocks?: VisualEditorBlockData[],
|
||||
) => void
|
||||
>,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ['update:children', 'on-selected', 'update:drag'],
|
||||
setup(props, { emit }) {
|
||||
// 初始化时设置上次选中的组件
|
||||
props.children.some((item) => item.focus && !void props.selectComp(item))
|
||||
props.children.some((item) => item.focus && props.selectComp(item));
|
||||
|
||||
return {
|
||||
isDrag: useVModel(props, 'drag', emit),
|
||||
slotChildren: useVModel(props, 'children', emit)
|
||||
}
|
||||
}
|
||||
})
|
||||
slotChildren: useVModel(props, 'children', emit),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './func.scss';
|
||||
@import './func.scss';
|
||||
|
||||
.inner-draggable {
|
||||
.inner-draggable {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.inner-draggable.slot::after {
|
||||
.inner-draggable.slot::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -123,9 +123,9 @@ export default defineComponent({
|
|||
outline-offset: -1px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
.list-group-item {
|
||||
position: relative;
|
||||
padding: 3px;
|
||||
cursor: move;
|
||||
|
@ -148,5 +148,5 @@ export default defineComponent({
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
* @update: 2021/5/2 19:54
|
||||
*/
|
||||
export const useDotProp = (originObj, propName) => {
|
||||
const props: string[] = propName.split('.')
|
||||
const isDotProp = props.length > 1
|
||||
const prop = props.pop()!
|
||||
const propObj = props.reduce((prev, curr) => (prev[curr] ??= {}), originObj)
|
||||
const props: string[] = propName.split('.');
|
||||
const isDotProp = props.length > 1;
|
||||
const prop = props.pop()!;
|
||||
const propObj = props.reduce((prev, curr) => (prev[curr] ??= {}), originObj);
|
||||
return {
|
||||
prop,
|
||||
propObj,
|
||||
isDotProp
|
||||
}
|
||||
}
|
||||
isDotProp,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,58 +12,58 @@ import {
|
|||
PropType,
|
||||
getCurrentInstance,
|
||||
ComponentInternalInstance,
|
||||
isVNode
|
||||
} from 'vue'
|
||||
import { ElButton, ElDialog } from 'element-plus'
|
||||
import { isFunction } from '@/visual-editor/utils/is'
|
||||
isVNode,
|
||||
} from 'vue';
|
||||
import { ElButton, ElDialog } from 'element-plus';
|
||||
import { isFunction } from '@/visual-editor/utils/is';
|
||||
|
||||
interface ModalOptions {
|
||||
title?: string
|
||||
footer?: null | (() => JSX.Element)
|
||||
content: ComponentInternalInstance | (() => JSX.Element)
|
||||
onConfirm?: () => void
|
||||
onCancel?: () => void
|
||||
title?: string;
|
||||
footer?: null | (() => JSX.Element);
|
||||
content: ComponentInternalInstance | (() => JSX.Element);
|
||||
onConfirm?: () => void;
|
||||
onCancel?: () => void;
|
||||
props?: {
|
||||
[propName: string]: any
|
||||
}
|
||||
[propName: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
const Modal = defineComponent({
|
||||
props: {
|
||||
options: {
|
||||
type: Object as PropType<ModalOptions>,
|
||||
default: () => ({})
|
||||
}
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance()!
|
||||
const instance = getCurrentInstance()!;
|
||||
|
||||
const state = reactive({
|
||||
options: props.options,
|
||||
visible: true
|
||||
})
|
||||
visible: true,
|
||||
});
|
||||
|
||||
const methods = {
|
||||
service: (options: ModalOptions) => {
|
||||
state.options = options
|
||||
methods.show()
|
||||
state.options = options;
|
||||
methods.show();
|
||||
},
|
||||
show: () => (state.visible = true),
|
||||
hide: () => (state.visible = false)
|
||||
}
|
||||
hide: () => (state.visible = false),
|
||||
};
|
||||
|
||||
const handler = {
|
||||
onConfirm: async () => {
|
||||
await state.options.onConfirm?.()
|
||||
methods.hide()
|
||||
await state.options.onConfirm?.();
|
||||
methods.hide();
|
||||
},
|
||||
onCancel: () => {
|
||||
state.options.onCancel?.()
|
||||
methods.hide()
|
||||
}
|
||||
}
|
||||
state.options.onCancel?.();
|
||||
methods.hide();
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(instance.proxy, methods)
|
||||
Object.assign(instance.proxy!, methods);
|
||||
|
||||
return () => (
|
||||
<ElDialog
|
||||
|
@ -88,24 +88,24 @@ const Modal = defineComponent({
|
|||
确定
|
||||
</ElButton>
|
||||
</div>
|
||||
)
|
||||
),
|
||||
}}
|
||||
</ElDialog>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const useModal = (() => {
|
||||
let instance: any
|
||||
let instance: any;
|
||||
return (options: ModalOptions) => {
|
||||
if (instance) {
|
||||
instance.service(options)
|
||||
return instance
|
||||
instance.service(options);
|
||||
return instance;
|
||||
}
|
||||
const div = document.createElement('div')
|
||||
document.body.appendChild(div)
|
||||
const app = createApp(Modal, { options })
|
||||
instance = app.mount(div)
|
||||
return instance
|
||||
}
|
||||
})()
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
const app = createApp(Modal, { options });
|
||||
instance = app.mount(div);
|
||||
return instance;
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
import { ref, watch, defineComponent } from 'vue'
|
||||
import { ref, watch, defineComponent } from 'vue';
|
||||
|
||||
export function useModel<T>(getter: () => T, emitter: (val: T) => void) {
|
||||
const state = ref(getter()) as { value: T }
|
||||
const state = ref(getter()) as { value: T };
|
||||
|
||||
watch(getter, (val) => {
|
||||
if (val !== state.value) {
|
||||
state.value = val
|
||||
state.value = val;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
get value() {
|
||||
return state.value
|
||||
return state.value;
|
||||
},
|
||||
set value(val: T) {
|
||||
if (state.value !== val) {
|
||||
state.value = val
|
||||
emitter(val)
|
||||
}
|
||||
}
|
||||
state.value = val;
|
||||
emitter(val);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const TestUseModel = defineComponent({
|
||||
props: {
|
||||
modelValue: { type: String }
|
||||
modelValue: { type: String },
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, ctx) {
|
||||
const model = useModel(
|
||||
() => props.modelValue,
|
||||
(val) => ctx.emit('update:modelValue', val)
|
||||
)
|
||||
(val) => ctx.emit('update:modelValue', val),
|
||||
);
|
||||
return () => (
|
||||
<div>
|
||||
自定义的输入框
|
||||
<input type="text" v-model={model.value} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue