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