Commit dad95e78 authored by liang's avatar liang

init

parents
Pipeline #350 failed with stages
> 1%
last 2 versions
not dead
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
NODE_ENV = 'development'
VUE_APP_BASE_API = 'mockServer'
VUE_APP_BASE_API = 'http://192.168.31.140:11999/'
VUE_CLI_BABEL_TRANSPILE_MODULES = true
NODE_ENV = 'production'
VUE_APP_BASE_API = '/disease-api/'
NODE_ENV = test
VUE_APP_BASE_API = 'http://192.168.1.104'
src/assets
src/icons
public
dist
node_modules
module.exports = {
root: true,
env: {
node: true,
},
extends: ["plugin:vue/recommended", "@vue/prettier"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"vue/no-v-html": "off",
},
parserOptions: {
parser: "babel-eslint",
},
overrides: [
{
files: [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)",
],
env: {
jest: true,
},
},
],
}
*.html text eol=lf
*.css text eol=lf
*.js text eol=lf
*.scss text eol=lf
*.vue text eol=lf
*.hbs text eol=lf
*.sh text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.js linguist-language=Vue
\ No newline at end of file
.DS_Store
node_modules
dist
.env.local
.env.*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
public/video
*.zip
*.7z
module.exports = {
extends: ["stylelint-config-standard", "stylelint-config-recess-order"],
rules: {
"at-rule-no-unknown": [
true,
{
ignoreAtRules: [
"mixin",
"extend",
"content",
"include",
"for",
"function",
"return",
],
},
],
"selector-pseudo-element-no-unknown": [
true,
{
ignorePseudoElements: ["v-deep"],
},
],
"selector-pseudo-class-no-unknown": [
true,
{
ignorePseudoClasses: ["export"],
},
],
indentation: 2,
"no-descending-specificity": null,
"declaration-colon-newline-after": null,
},
ignoreFiles: ["**/*.js", "dist/*.*"],
};
{
"prettier.configPath": "",
"editor.formatOnSave": true
}
# 联盟早期胃癌筛查 2.0
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn run serve
```
### Compiles and minifies for production
```
yarn run build
```
module.exports = {
presets: [
"@vue/cli-plugin-babel/preset",
],
"plugins": [
[
"import",
{
"libraryName": "vxe-table",
"style": true // 样式是否也按需加载
}
]
]
}
[1027/094332.838:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
[1027/113129.762:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
[1027/131658.414:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
#!/usr/bin/env bash
set -e
npm run build:test
cd dist
touch .nojekyll
git init
git add -A
git commit -m 'deploy'
git push -f "https://${access_token}@gitee.com/chu1204505056/vue-admin-beautiful-template.git" master:gh-pages
start "https://gitee.com/chu1204505056/vue-admin-beautiful-template/pages"
cd -
cd -
rimraf dist
exec /bin/bash
###/changeLog/getList###mockServer
POST http://localhost:80/mock-server/changeLog/getList
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/colorfulIcon/list###
POST http://localhost:80/mock-server/colorfulIcon/list
Content-Type: application/x-www-form-urlencoded
###mockServer
###/menu/navigate###
POST http://localhost:80/mock-server/menu/navigate
Content-Type: application/x-www-form-urlenmockServer
###
###/icon/list###
POST http://localhost:80/mock-server/icon/mockServer
Content-Type: application/x-www-form-urlencoded
###
###/face/list###mockServer
POST http://localhost:80/mock-server/face/list
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/table/list###
POST http://localhost:80/mock-server/table/list
Content-Type: application/x-www-form-urlencoded
###mockServer
###/remixicon/getList###
POST http://localhost:80/mock-server/remixicon/getList
Content-Type: application/x-www-form-urlenmockServer
###
###/publicKey###
POST http://localhost:80/mock-server/pumockServer
Content-Type: application/x-www-form-urlencoded
###
###/tree/list###mockServer
POST http://localhost:80/mock-server/tree/list
Content-Type: application/x-www-form-urlencoded
###
mockServer
###/upload###
POST http://localhost:80/mock-server/upload
Content-Type: application/x-www-form-urlencoded
###mockServer
###/login###
POST http://localhost:80/mock-server/login
Content-Type: application/x-www-form-urlenmockServer
###
###/waterfall/list###
POST http://localhost:80/mock-server/waterfall/list
Content-Type: application/x-www-form-urlencoded
###
###/logout###
POST http://localhost:80/mock-server/logout
Content-Type: application/x-www-form-urlencoded
###
###/user/info###
POST http://localhost:80/mock-server/user/info
Content-Type: application/x-www-form-urlencoded
###
const data = [
{
path: "/",
component: "Layout",
redirect: "index",
children: [
{
path: "index",
name: "Index",
component: "index/index",
meta: {
title: "首页",
icon: "home",
affix: true,
},
},
],
},
];
export default [
{
url: "/menu/navigate",
type: "post",
response: (config) => {
return { code: 200, msg: "success", data: data };
},
},
];
import { handleRandomImage } from "../utils";
const accessTokens = {
admin: "admin-accessToken",
editor: "editor-accessToken",
test: "test-accessToken",
};
export default [
{
url: "/publicKey",
type: "post",
response: (config) => {
return {
code: 1,
msg: "success",
data: {
mockServer: true,
},
};
},
},
{
url: "/login",
type: "post",
response: (config) => {
const { userName } = config.body;
const accessToken = accessTokens[userName];
if (!accessToken) {
return {
code: 500,
msg: "帐户或密码不正确。",
};
}
return {
code: 1,
msg: "success2222",
data: { accessToken },
};
},
},
{
url: "/user/info",
type: "post",
response: (config) => {
const { accessToken } = config.body;
let permissions = ["admin"];
let userName = "admin";
if ("admin-accessToken" === accessToken) {
permissions = ["admin"];
userName = "admin";
}
if ("editor-accessToken" === accessToken) {
permissions = ["editor"];
userName = "editor";
}
if ("test-accessToken" === accessToken) {
permissions = ["admin", "editor", "test"];
userName = "test";
}
return {
code: 1,
msg: "success",
data: {
permissions,
userName,
avatar: handleRandomImage(50, 50),
},
};
},
},
{
url: "/logout",
type: "post",
response: () => {
return {
code: 1,
msg: "success",
};
},
},
];
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
import { handleMockArray } from "./utils";
import chalk from "chalk";
import dotenv from "dotenv";
import fs from "fs";
import { devPort, httpRequestFile } from "../src/config/settings";
const mocks = [];
const mockArray = handleMockArray();
if (httpRequestFile) {
fs.writeFile("./http/mock.http", "", {}, function (err) {
if (err) throw err;
});
}
mockArray.forEach(async (item) => {
const obj = require(item).default;
const envConfig = dotenv.parse(fs.readFileSync(".env.development"));
const mockUrl = envConfig["VUE_APP_BASE_API"];
await mocks.push(...obj);
if (httpRequestFile) {
obj.forEach((item) => {
fs.appendFile(
"./http/mock.http",
`\r\n###${item.url}###\r\POST http://localhost:${devPort}/${mockUrl}${item.url}\r\nContent-Type: application/x-www-form-urlencoded\r\n###\r\n`,
(error) => {
if (error)
return chalk.red(`\n > 追加HTTP Request失败${error.message}`);
}
);
});
}
});
export default mocks;
const chokidar = require("chokidar");
const bodyParser = require("body-parser");
const chalk = require("chalk");
const path = require("path");
const Mock = require("mockjs");
const mockDir = path.join(process.cwd(), "mock");
/**
*
* @param app
* @returns {{mockStartIndex: number, mockRoutesLength: number}}
*/
function registerRoutes(app) {
let mockLastIndex;
const { default: mocks } = require("./index.js");
const mocksForServer = mocks.map((route) => {
return responseFake(route.url, route.type, route.response);
});
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response);
mockLastIndex = app._router.stack.length;
}
const mockRoutesLength = Object.keys(mocksForServer).length;
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength,
};
}
/**
*
* @param url
* @param type
* @param respond
* @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
*/
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || "get",
response(req, res) {
if (JSON.stringify(req.body) !== "{}") {
console.log(chalk.green(`> 请求地址:${req.path}`));
console.log(chalk.green(`> 请求参数:${JSON.stringify(req.body)}\n`));
} else {
console.log(chalk.green(`> 请求地址:${req.path}\n`));
}
res.json(
Mock.mock(respond instanceof Function ? respond(req, res) : respond)
);
},
};
};
/**
*
* @param app
*/
module.exports = (app) => {
require("@babel/register");
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
const mockRoutes = registerRoutes(app);
let mockRoutesLength = mockRoutes.mockRoutesLength;
let mockStartIndex = mockRoutes.mockStartIndex;
chokidar
.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true,
})
.on("all", (event, path) => {
if (event === "change" || event === "add") {
try {
app._router.stack.splice(mockStartIndex, mockRoutesLength);
Object.keys(require.cache).forEach((item) => {
if (item.includes(mockDir)) {
delete require.cache[require.resolve(item)];
}
});
const mockRoutes = registerRoutes(app);
mockRoutesLength = mockRoutes.mockRoutesLength;
mockStartIndex = mockRoutes.mockStartIndex;
//console.log(chalk.blue(`> Mock服务热更新成功:${path}`));
} catch (error) {
console.log(chalk.red(error));
}
}
});
};
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
import Mock from "mockjs";
import { paramObj } from "../src/utils";
const mocks = [];
const files = require.context("./controller", false, /\.js$/);
files.keys().forEach((key) => {
const obj = files(key).default;
mocks.push(...obj);
});
export function mockXHR() {
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send;
Mock.XHR.prototype.send = function () {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false;
if (this.responseType) {
this.custom.xhr.responseType = this.responseType;
}
}
this.proxy_send(...arguments);
};
function XHR2ExpressReqWrap(respond) {
return function (options) {
let result = null;
if (respond instanceof Function) {
const { body, type, url } = options;
result = respond({
method: type,
body: JSON.parse(body),
query: paramObj(url),
});
} else {
result = respond;
}
return Mock.mock(result);
};
}
for (const i of mocks) {
Mock.mock(
new RegExp(i.url),
i.type || "get",
XHR2ExpressReqWrap(i.response)
);
}
}
import { Random } from "mockjs";
import { join } from "path";
import fs from "fs";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 随机生成图片url。
* @param width
* @param height
* @returns {string}
*/
export function handleRandomImage(width = 50, height = 50) {
return `https://picsum.photos/${width}/${height}?random=${Random.guid()}`;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
* @returns {[]}
*/
export function handleMockArray() {
const mockArray = [];
const getFiles = (jsonPath) => {
const jsonFiles = [];
const findJsonFile = (path) => {
const files = fs.readdirSync(path);
files.forEach((item) => {
const fPath = join(path, item);
const stat = fs.statSync(fPath);
if (stat.isDirectory() === true) findJsonFile(item);
if (stat.isFile() === true) jsonFiles.push(item);
});
};
findJsonFile(jsonPath);
jsonFiles.forEach((item) => mockArray.push(`./controller/${item}`));
};
getFiles("mock/controller");
return mockArray;
}
This diff is collapsed.
{
"name": "vue-admin-beautiful-template",
"version": "1.0.0",
"private": true,
"author": "chuzhixin",
"participants": [],
"homepage": "https://chu1204505056.gitee.io/vue-admin-beautiful",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:test": "vue-cli-service build --mode test",
"globle": "npm install -g cnpm --registry=https://registry.npm.taobao.org&&cnpm i rimraf npm-check-updates nrm -g&&rimraf node_modules&&cnpm i",
"lint": "vue-cli-service lint --fix",
"lint:style": "stylelint **/*.{vue,css,scss} --fix",
"inspect": "vue-cli-service inspect",
"template": "plop",
"clear": "rimraf node_modules&&cnpm i",
"update": "nrm use taobao&&ncu -u&&cnpm i",
"svgo": "svgo -f src/remixicon/svg --config=svgo.yml",
"push": "start ./push.sh",
"deploy": "start ./deploy.sh"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.5",
"crypto-js": "^4.0.0",
"dayjs": "^1.8.28",
"echarts": "^5.1.2",
"element-ui": "^2.15.2",
"js-cookie": "^2.2.1",
"jsbarcode": "^3.11.5",
"jsencrypt": "^3.0.0-rc.1",
"lodash": "^4.17.15",
"monaco-editor": "^0.23.0",
"nprogress": "^0.2.0",
"qrcodejs2": "^0.0.2",
"qs": "^6.9.4",
"screenfull": "^5.0.2",
"vue": "^2.6.11",
"vue-count-to": "^1.0.13",
"vue-router": "^3.3.4",
"vue-virtual-scroller": "^1.0.10",
"vuedraggable": "^2.24.3",
"vuex": "^3.4.0",
"vxe-table": "3",
"xe-utils": "3",
"zx-icon": "^1.0.9",
"zx-keel": "^0.9.2",
"zx-layouts": "^0.1.18",
"zx-templates": "^0.0.7"
},
"devDependencies": {
"@babel/register": "^7.10.3",
"@vue/cli-plugin-babel": "^4.4.5",
"@vue/cli-plugin-eslint": "^4.4.5",
"@vue/cli-plugin-router": "^4.4.5",
"@vue/cli-plugin-vuex": "^4.4.5",
"@vue/cli-service": "^4.4.5",
"@vue/eslint-config-prettier": "^6.0.0",
"autoprefixer": "^9.8.2",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.13.3",
"compression-webpack-plugin": "^4.0.0",
"eslint": "^7.3.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-vue": "^6.2.2",
"filemanager-webpack-plugin": "^2.0.5",
"html-webpack-plugin": "^4.3.0",
"husky": "^4.2.5",
"lint-staged": "^10.2.11",
"mockjs": "^1.1.0",
"plop": "^2.7.1",
"prettier": "^2.0.5",
"sass": "^1.26.9",
"sass-loader": "^8.0.2",
"script-ext-html-webpack-plugin": "^2.1.4",
"script-loader": "^0.7.2",
"serve-static": "^1.14.1",
"stylelint": "^13.6.1",
"stylelint-config-recess-order": "^2.0.4",
"stylelint-config-standard": "^20.0.0",
"stylelint-order": "^4.1.0",
"stylelint-scss": "^3.18.0",
"svg-sprite-loader": "^5.0.0",
"svgo": "^1.3.2",
"vue-template-compiler": "^2.6.11",
"webpackbar": "^4.0.0"
},
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
}
}
<template>
<div class="form-config-container">
<el-form
label-position="left"
label-suffix=":"
label-width="130px"
size="small"
>
<el-form-item label="标签对齐方式">
<el-select v-model="data.labelPosition" placeholder="标签对齐方式">
<el-option label="左对齐" value="left"></el-option>
<el-option label="右对齐" value="right"></el-option>
<el-option label="顶部对齐" value="top"></el-option>
</el-select>
</el-form-item>
<el-form-item label="标签宽度">
<el-input-number
v-model="data.labelWidth"
:min="80"
:max="500"
:step="10"
controls-position="right"
placeholder="标签宽度"
style="width: 100%"
></el-input-number>
</el-form-item>
<el-form-item label="项之间的间隔">
<el-input-number
v-model="data.gutter"
:min="0"
:max="60"
:step="5"
controls-position="right"
placeholder="项之间的间隔"
style="width: 100%"
></el-input-number>
</el-form-item>
<el-form-item label="多分组转标签">
<el-switch v-model="data.tabs" active-color="#409EFF"></el-switch>
</el-form-item>
<el-form-item label="显示跳转按钮" v-if="data.tabs">
<el-switch v-model="data.nextTabBtn" active-color="#409EFF"></el-switch>
</el-form-item>
<el-form-item label="跳转按钮的文字" v-if="data.tabs && data.nextTabBtn">
<el-input
v-model="data.nextTabText"
placeholder="跳转按钮的文字"
></el-input>
</el-form-item>
<!-- <el-form-item label="详情模式">
<el-switch v-model="data.detail"></el-switch>
</el-form-item> -->
<!-- <el-form-item label="标签样式"
v-if="data.tabs">
<el-select v-model="data.tabsType">
<el-option label="基础"
value=""></el-option>
<el-option label="卡片"
value="card"></el-option>
<el-option label="卡片2"
value="border-card"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="显示按钮">
<el-switch v-model="data.menuBtn" active-color="#409EFF"></el-switch>
</el-form-item>
<!-- <el-form-item label="按钮位置"
v-if="data.menuBtn">
<el-select v-model="data.menuPostion"
placeholder="按钮位置">
<el-option label="居左"
value="left"></el-option>
<el-option label="居中"
value="center"></el-option>
<el-option label="居右"
value="right"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="显示提交按钮" v-if="data.menuBtn">
<el-switch v-model="data.submitBtn" active-color="#409EFF"></el-switch>
</el-form-item>
<!-- <el-form-item label="提交按钮的大小"
v-if="data.menuBtn && data.submitBtn">
<el-select v-model="data.submitSize"
placeholder="提交按钮的大小">
<el-option label="正常"
value="medium"></el-option>
<el-option label="小"
value="small"></el-option>
<el-option label="超小"
value="mini"></el-option>
</el-select>
</el-form-item> -->
<el-form-item
label="提交按钮的文字"
v-if="data.menuBtn && data.submitBtn"
>
<el-input
v-model="data.submitText"
placeholder="提交按钮的文字"
></el-input>
</el-form-item>
<el-form-item label="显示清空按钮" v-if="data.menuBtn">
<el-switch v-model="data.emptyBtn" active-color="#409EFF"></el-switch>
</el-form-item>
<!-- <el-form-item label="清空按钮的大小"
v-if="data.menuBtn && data.emptyBtn">
<el-select v-model="data.emptySize"
placeholder="提交按钮的大小">
<el-option label="正常"
value="medium"></el-option>
<el-option label="小"
value="small"></el-option>
<el-option label="超小"
value="mini"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="清空按钮的文字" v-if="data.menuBtn && data.emptyBtn">
<el-input
v-model="data.emptyText"
placeholder="清空按钮的文字"
></el-input>
</el-form-item>
<el-form-item label="全局只读">
<el-switch v-model="data.readonly"></el-switch>
</el-form-item>
<el-form-item label="全局禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<!-- <el-form-item label="全局栅格">
<el-input v-model="data.span"
placeholder="全局栅格"></el-input>
</el-form-item> -->
<el-form-item label="字段批量设置">
<el-button
type="warning"
@click="$emit('change', 'importantField', true)"
>设为重要字段</el-button
>
<el-button
type="warning"
@click="$emit('change', 'importantField', false)"
>设为不重要字段</el-button
>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "form-config",
props: ["data"],
}
</script>
This diff is collapsed.
This diff is collapsed.
<template>
<div class="widget-form-container">
<el-form
:label-position="data.labelPosition || 'left'"
:label-width="data.labelWidth ? `${data.labelWidth}px` : '100px'"
:model="form"
ref="widgetForm"
size="small"
>
<el-row :gutter="data.gutter">
<draggable
class="widget-form-list"
:list="data.column"
:group="{ name: 'form' }"
ghost-class="ghost"
:animation="300"
@add="handleWidgetAdd"
@end="$emit('change')"
>
<template v-for="(column, index) in data.column">
<div
class="widget-form-table"
v-if="column.type == 'dynamic'"
:key="index"
:class="{ active: selectWidget.prop == column.prop }"
@click="handleSelectWidget(index)"
>
<widget-form-table
:data="data"
:column="column"
:index="index"
:select.sync="selectWidget"
@change="$emit('change')"
></widget-form-table>
</div>
<div
class="widget-form-group"
v-else-if="column.type == 'group'"
:key="index"
:class="{ active: selectWidget.prop == column.prop }"
@click="handleSelectWidget(index)"
>
<widget-form-group
:data="data"
:column="column"
:index="index"
:select.sync="selectWidget"
@change="$emit('change')"
>
</widget-form-group>
</div>
<el-col
v-else
:key="index"
:md="column.span || 12"
:xs="24"
:offset="column.offset || 0"
>
<!-- :label-width="column.labelWidth ? `${column.labelWidth}px` : ''" -->
<div
:class="{
active: selectWidget.prop == column.prop,
required: column.required,
}"
class="widget-form-item"
@click="handleSelectWidget(index)"
:style="column.styles"
>
<el-form-item
:style="{
width: column.width ? `${(column.width / 24) * 100}%` : '',
}"
:label="
column.label
? `${column.label}${column.labelSuffix || ':'}`
: ''
"
:prop="column.prop"
:label-width="
column.label
? column.labelWidth
? `${column.labelWidth}px`
: ''
: '0px'
"
>
<widget-form-item
:item="column"
:params="column.params"
></widget-form-item>
<el-button
title="删除"
@click.stop="handleWidgetDelete(index)"
class="widget-action-delete"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
<!-- <el-button title="复制"
@click.stop="handleWidgetClone(index)"
class="widget-action-clone"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="primary">
<i class="iconfont icon-copy"></i>
</el-button> -->
</el-form-item>
</div>
</el-col>
</template>
</draggable>
</el-row>
</el-form>
</div>
</template>
<script>
import WidgetFormItem from "./WidgetFormItem"
import WidgetFormTable from "./WidgetFormTable"
import WidgetFormGroup from "./WidgetFormGroup"
import Draggable from "vuedraggable"
export default {
name: "widget-form",
components: { Draggable, WidgetFormItem, WidgetFormTable, WidgetFormGroup },
props: ["data", "select"],
data() {
return {
selectWidget: this.select,
form: {},
}
},
methods: {
handleSelectWidget(index) {
this.selectWidget = this.data.column[index]
},
handleWidgetAdd(evt) {
const newIndex = evt.newIndex
const data = this.deepClone(this.data.column[newIndex])
if (
!data.prop ||
(data.type === "dynamic" && data.prop === "fixed_field")
)
data.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
delete data.icon
delete data.subfield
if (data.type == "dynamic") data.span = 24
if (data.type == "title") {
delete data.label
this.form[data.prop] = data.value
}
data.cType = ""
data.subfield = false
this.$set(this.data.column, newIndex, data)
this.handleSelectWidget(newIndex)
this.$emit("change")
},
handleWidgetDelete(index) {
if (this.data.column.length - 1 === index) {
if (index === 0) this.selectWidget = {}
else this.handleSelectWidget(index - 1)
} else this.handleSelectWidget(index + 1)
this.$nextTick(() => {
this.data.column.splice(index, 1)
this.$emit("change")
})
},
handleWidgetClone(index) {
let cloneData = this.deepClone(this.data.column[index])
cloneData.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
this.data.column.splice(index, 0, cloneData)
this.$nextTick(() => {
this.handleSelectWidget(index + 1)
this.$emit("change")
})
},
},
watch: {
select(val) {
this.selectWidget = val
},
selectWidget: {
handler(val) {
this.$emit("update:select", val)
},
deep: true,
},
},
}
</script>
<template>
<div>
<h4 class="widget-form-group__head" v-show="column.label">
<i
:class="column.icon"
v-show="column.icon"
style="margin-right: 10px"
></i
>{{ column.label }}
</h4>
<draggable
class="widget-form-group__body"
:style="{
paddingLeft: column.labelWidth ? `${column.labelWidth}px` : '',
}"
:list="column.children.column"
:group="{ name: 'form' }"
ghost-class="ghost"
:animation="200"
:key="column.prop"
@add="handleWidgetGroupAdd($event, column)"
@end="$emit('change')"
>
<template v-for="(item, groupIndex) in column.children.column">
<div
class="widget-form-table"
v-if="item.type == 'dynamic'"
:key="groupIndex"
:class="{ active: selectWidget.prop == item.prop }"
@click.stop="handleWidgetTableSelect(item)"
>
<widget-form-table
:data="column.children"
:column="item"
:index="groupIndex"
:select.sync="selectWidget"
@change="$emit('change')"
></widget-form-table>
</div>
<div
class="widget-form-group"
v-else-if="item.type === 'group'"
:key="groupIndex"
:class="{ active: selectWidget.prop == item.prop }"
@click.stop="handleWidgetTableSelect(item)"
>
<widget-form-group
:data="column.children"
:column="item"
:index="groupIndex"
:select.sync="selectWidget"
@change="$emit('change')"
>
</widget-form-group>
</div>
<el-col
v-else
:key="groupIndex"
:md="item.span || 12"
:xs="24"
:offset="item.offset || 0"
>
<div
class="widget-form-group__item"
:class="{
active: selectWidget.prop == item.prop,
required: item.required,
}"
:style="item.styles"
@click.stop="handleWidgetTableSelect(item)"
>
<el-form-item
:label="
item.label ? `${item.label}${item.labelSuffix || ':'}` : ''
"
:prop="item.prop"
:label-width="
item.label
? item.labelWidth
? `${item.labelWidth}px`
: ''
: '0px'
"
:style="{
width: item.width ? `${(item.width / 24) * 100}%` : '',
}"
>
<widget-form-item
:item="item"
:params="column.params"
></widget-form-item>
<el-button
title="删除"
@click.stop="handleWidgetTableDelete(column, groupIndex)"
class="widget-form-group__item--delete"
v-if="selectWidget.prop == item.prop"
circle
plain
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
<!-- <el-button title="复制"
@click.stop="handleWidgetTableClone(column, item)"
class="widget-form-group__item--clone"
v-if="selectWidget.prop == item.prop"
circle
plain
type="primary">
<i class="iconfont icon-copy"></i>
</el-button> -->
</el-form-item>
</div>
</el-col>
</template>
</draggable>
<el-button
title="删除"
@click.stop="handleWidgetDelete(index)"
class="widget-action-delete"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
<el-button
title="清空"
@click.stop="handleWidgetClear(index)"
class="widget-action-clear"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="warning"
>
<i class="iconfont icon-clear"></i>
</el-button>
<!-- <el-button
title="复制"
@click.stop="handleWidgetCloneTable(index)"
class="widget-action-clone"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="primary"
>
<i class="iconfont icon-copy"></i>
</el-button> -->
</div>
</template>
<script>
import WidgetFormItem from "./WidgetFormItem"
import WidgetFormTable from "./WidgetFormTable"
import draggable from "vuedraggable"
export default {
name: "widget-form-group",
props: ["data", "column", "select", "index"],
components: { WidgetFormItem, WidgetFormTable, draggable },
data() {
return {
selectWidget: this.select,
}
},
methods: {
handleSelectWidget(index) {
this.selectWidget = this.data.column[index]
},
handleWidgetClear(index) {
this.data.column[index].children.column = []
this.selectWidget = this.data.column[index]
this.$emit("change")
},
handleWidgetDelete(index) {
if (this.data.column.length - 1 === index) {
if (index === 0) this.selectWidget = {}
else this.handleSelectWidget(index - 1)
} else this.handleSelectWidget(index + 1)
this.$nextTick(() => {
this.data.column.splice(index, 1)
this.$emit("change")
})
},
handleWidgetCloneTable(index) {
let cloneData = this.deepClone(this.data.column[index])
cloneData.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
cloneData.children.column.forEach((t) => {
t.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
})
this.data.column.splice(index, 0, cloneData)
this.$nextTick(() => {
this.handleSelectWidget(index + 1)
this.$emit("change")
})
},
handleWidgetTableSelect(data) {
this.selectWidget = data
},
handleWidgetTableClone(column, item) {
const data = this.deepClone(item)
data.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
this.$set(column.children.column, column.children.column.length, {
...data,
})
this.$nextTick(() => {
this.selectWidget =
column.children.column[column.children.column.length - 1]
this.$emit("change")
})
},
handleWidgetTableDelete(column, index) {
if (column.children.column.length - 1 == index) {
if (index == 0) this.selectWidget = column
else this.selectWidget = column.children.column[index - 1]
} else this.selectWidget = column.children.column[index + 1]
this.$nextTick(() => {
column.children.column.splice(index, 1)
this.$emit("change")
})
},
handleWidgetGroupAdd(evt, column) {
let newIndex = evt.newIndex
const item = evt.item
if (newIndex == 1 && newIndex > column.children.column.length - 1)
newIndex = 0
const data = this.deepClone(column.children.column[newIndex])
if (!data) return
if (
!data.prop ||
(data.type === "dynamic" && data.prop === "fixed_field")
)
data.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
delete data.icon
if (
data.type == "dynamic" ||
data.type === "title" ||
data.type === "dental-tab" ||
data.type === "dental-tab-tj"
)
data.span = 24
if (data.type == "title") {
delete data.label
}
data.cType = ""
data.subfield = false
this.$set(column.children.column, newIndex, { ...data })
this.selectWidget = column.children.column[newIndex]
this.$emit("change")
},
},
watch: {
select(val) {
this.selectWidget = val
},
selectWidget: {
handler(val) {
this.$emit("update:select", val)
},
deep: true,
},
},
}
</script>
<template>
<div>
<span
v-if="item.type == 'title'"
:style="item.styles"
style="margin-left: 5px"
>
{{ item.value }}
</span>
<component
v-else
:is="getComponent(item.type, item.component)"
v-bind="
Object.assign(deepClone(item), params, { size: item.size || 'small' })
"
:multiple="false"
:placeholder="item.placeholder || getPlaceholder(item)"
:dic="item.dicData"
:value="
['time', 'timerange', 'checkbox'].includes(item.type)
? item.dicData
: undefined
"
>
<span v-if="params.html" v-html="params.html"></span>
</component>
</div>
</template>
<script>
export default {
name: "widget-form-item",
props: {
item: {
type: Object,
default: () => {
return {}
},
},
params: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {
form: {},
}
},
methods: {
getComponent(type, component) {
let KEY_COMPONENT_NAME = "avue-"
let result = "input"
if (component) return component
else if (["array", "img", "url"].includes(type)) result = "array"
else if (type === "select") result = "select"
else if (type === "radio") result = "radio"
else if (type === "checkbox") result = "checkbox"
else if (["time", "timerange"].includes(type)) result = "time"
else if (
[
"dates",
"date",
"datetime",
"datetimerange",
"daterange",
"week",
"month",
"year",
].includes(type)
)
result = "date"
else if (type === "cascader") result = "cascader"
else if (type === "number") result = "input-number"
else if (type === "password") result = "input"
else if (type === "switch") result = "switch"
else if (type === "rate") result = "rate"
else if (type === "upload") result = "upload"
else if (type === "slider") result = "slider"
else if (type === "dynamic") result = "dynamic"
else if (type === "icon") result = "input-icon"
else if (type === "color") result = "input-color"
else if (type === "map") result = "input-map"
return KEY_COMPONENT_NAME + result
},
getPlaceholder(item) {
const label = item.label
if (
[
"select",
"checkbox",
"radio",
"tree",
"color",
"dates",
"date",
"datetime",
"datetimerange",
"daterange",
"week",
"month",
"year",
"map",
"icon",
].includes(item.type)
)
return `请选择 ${label}`
else return `请输入 ${label}`
},
},
}
</script>
This diff is collapsed.
<template>
<div>
<h3 style="margin: 10px" v-show="column.label">{{ column.label }}</h3>
<draggable
class="widget-form-table__content"
:list="column.children.column"
:group="{ name: 'form' }"
ghost-class="ghost"
:animation="200"
handle=".widget-form-table__item"
@add="handleWidgetTableAdd($event, column)"
@end="$emit('change')"
>
<template v-if="column.children.column.length > 0">
<template v-if="column.children.type === 'form'">
<el-col
v-for="(item, tableIndex) in column.children.column"
:key="tableIndex"
:md="item.span || 12"
:xs="24"
>
<div
class="widget-form-table__item is-form"
:class="{
active: selectWidget.prop == item.prop,
required: item.required,
}"
@click.stop="handleWidgetTableSelect(item)"
:style="item.styles"
>
<el-form-item
:label="
item.label ? `${item.label}${item.labelSuffix || ':'}` : ''
"
:prop="item.prop"
:label-width="
item.label
? item.labelWidth
? `${item.labelWidth}px`
: ''
: '0px'
"
:style="{
width: item.width ? `${(item.width / 24) * 100}%` : '100%',
}"
>
<widget-form-item
:item="item"
:params="column.params"
></widget-form-item>
<el-button
title="删除"
@click.stop="handleWidgetTableDelete(column, tableIndex)"
class="widget-table-action-delete"
v-if="selectWidget.prop == item.prop"
circle
plain
size="small"
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
</el-form-item>
</div>
</el-col>
</template>
<template v-else>
<div
v-for="(item, tableIndex) in column.children.column"
:key="tableIndex"
class="widget-form-table__item"
:class="{
active: selectWidget.prop == item.prop,
required: item.required,
}"
:style="{
width:
item.type === 'dynamic'
? '100%'
: item.width
? `${item.width}px`
: '32%',
}"
@click.stop="handleWidgetTableSelect(item)"
>
<el-table :data="[item]" border>
<el-table-column
:prop="item.prop"
:label="item.label"
:align="column.children.align"
:header-align="column.children.headerAlign"
>
<widget-form-item
:item="item"
:params="column.params"
></widget-form-item>
<el-button
title="删除"
@click.stop="handleWidgetTableDelete(column, tableIndex)"
class="widget-table-action-delete"
v-if="selectWidget.prop == item.prop"
circle
plain
size="small"
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
<!-- <el-button title="复制"
@click.stop="handleWidgetTableClone(column, item)"
class="widget-table-action-clone"
v-if="selectWidget.prop == item.prop"
circle
plain
size='small'
type="primary">
<i class="iconfont icon-copy"></i>
</el-button> -->
</el-table-column>
</el-table>
</div>
</template>
</template>
<template v-else>
<div>拖拽字段至此</div>
</template>
</draggable>
<el-button
title="删除"
@click.stop="handleWidgetDelete(index)"
class="widget-action-delete"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="danger"
>
<i class="iconfont icon-delete"></i>
</el-button>
<el-button
title="清空"
@click.stop="handleWidgetClear(index)"
class="widget-action-clear"
v-if="selectWidget.prop == column.prop"
circle
plain
size="small"
type="warning"
>
<i class="iconfont icon-clear"></i>
</el-button>
<!-- <el-button title="复制"
@click.stop="handleWidgetCloneTable(index)"
class="widget-action-clone"
v-if="selectWidget.prop == column.prop"
circle
plain
size='small'
type="primary">
<i class="iconfont icon-copy"></i>
</el-button> -->
</div>
</template>
<script>
import WidgetFormItem from "./WidgetFormItem"
import draggable from "vuedraggable"
export default {
name: "widget-form-table",
props: ["data", "column", "select", "index"],
components: { WidgetFormItem, draggable },
data() {
return {
selectWidget: this.select,
}
},
methods: {
handleSelectWidget(index) {
this.selectWidget = this.data.column[index]
},
handleWidgetClear(index) {
this.data.column[index].children.column = []
this.selectWidget = this.data.column[index]
this.$emit("change")
},
handleWidgetDelete(index) {
if (this.data.column.length - 1 === index) {
if (index === 0) this.selectWidget = {}
else this.handleSelectWidget(index - 1)
} else this.handleSelectWidget(index + 1)
this.$nextTick(() => {
this.data.column.splice(index, 1)
this.$emit("change")
})
},
handleWidgetCloneTable(index) {
let cloneData = this.deepClone(this.data.column[index])
cloneData.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
cloneData.children.column.forEach((t) => {
t.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
})
this.data.column.splice(index, 0, cloneData)
this.$nextTick(() => {
this.handleSelectWidget(index + 1)
this.$emit("change")
})
},
handleWidgetTableAdd(evt, column) {
let newIndex = evt.newIndex
const item = evt.item
const { type } = item._underlying_vm_
if (newIndex == 1 && newIndex > column.children.column.length - 1)
newIndex = 0
if (type === "group") {
this.$message.warning("该类型不可拖入")
column.children.column.splice(newIndex, 1)
return
}
const data = this.deepClone(column.children.column[newIndex])
if (!data.prop)
data.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
if (data.type === "dynamic") {
data.prop = "fixed_field"
}
data.cType = column.children.type === "form" ? "form" : "table"
data.subfield = true
delete data.icon
this.$set(column.children.column, newIndex, { ...data })
this.selectWidget = column.children.column[newIndex]
this.$emit("change")
},
handleWidgetTableSelect(data) {
this.selectWidget = data
},
handleWidgetTableClone(column, item) {
const data = this.deepClone(item)
data.prop = Date.now() + "_" + Math.ceil(Math.random() * 99999)
this.$set(column.children.column, column.children.column.length, {
...data,
})
this.$nextTick(() => {
this.selectWidget =
column.children.column[column.children.column.length - 1]
this.$emit("change")
})
},
handleWidgetTableDelete(column, index) {
if (column.children.column.length - 1 == index) {
if (index == 0) this.selectWidget = column
else this.selectWidget = column.children.column[index - 1]
} else this.selectWidget = column.children.column[index + 1]
this.$nextTick(() => {
column.children.column.splice(index, 1)
this.$emit("change")
})
},
},
watch: {
select(val) {
this.selectWidget = val
},
selectWidget: {
handler(val) {
this.$emit("update:select", val)
},
deep: true,
},
"column.children.type": {
handler(type) {
this.column.children.column.map((item) => {
this.$set(item, "cType", type ? "form" : "table")
})
},
immediate: true,
},
},
}
</script>
<template>
<div class="el-form-item--small el-form--label-top" style="padding: 13px">
<strong class="el-form-item__label" style="padding: 0">显隐配置:</strong>
<div class="el-form-item__content">
<draggable
tag="ul"
:list="data.dynamicshSet"
:group="{ name: 'dynamicsh' }"
ghost-class="ghost"
handle=".drag-item"
v-if="data.dynamicshSet && data.dynamicshSet.length > 0"
>
<li v-for="(item, index) in data.dynamicshSet" :key="index">
<i
class="drag-item el-icon-s-operation"
style="font-size: 16px; margin: 0 5px; cursor: move"
></i>
<el-input
:style="{
'margin-right': '5px',
}"
size="mini"
clearable
v-model="item.value"
placeholder="值"
></el-input>
<el-input
size="mini"
clearable
v-model="item.target"
placeholder="字段"
></el-input>
<el-button
@click="handleRemoveFields(index)"
circle
plain
type="danger"
size="mini"
icon="el-icon-minus"
style="padding: 4px; margin-left: 5px"
></el-button>
</li>
</draggable>
<div style="margin-left: 22px">
<el-button type="text" @click="handleAddFields">添加列 </el-button>
</div>
</div>
</div>
</template>
<script>
import Draggable from "vuedraggable"
export default {
props: ["data"],
components: { Draggable },
data() {
return {}
},
methods: {
handleRemoveFields(index) {
this.data.dynamicshSet.splice(index, 1)
},
handleAddFields() {
if (!this.data.dynamicshSet) {
this.$set(this.data, "dynamicshSet", [])
}
this.data.dynamicshSet.push({ value: ``, target: `` })
},
},
}
</script>
<template>
<div>
<el-form-item label="占位内容">
<el-input v-model="data.placeholder"
clearable
placeholder="占位内容"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="尺寸">
<el-radio-group v-model="data.size"
size="mini">
<el-radio-button label="medium">正常</el-radio-button>
<el-radio-button label="small"></el-radio-button>
<el-radio-button label="mini">超小</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'config-array',
props: ['data'],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
}
}
},
methods: {
generateRule() {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `请输入${this.data.label}` }
else this.validator.required = null
this.generateRule()
}
}
}
</script>
<template>
<div>
<el-form-item label="占位内容">
<el-input v-model="data.placeholder"
clearable
placeholder="占位内容"></el-input>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-color",
props: ['data'],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
}
}
},
methods: {
generateRule() {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
else this.validator.required = null
this.generateRule()
}
}
}
</script>
<template>
<div>
<el-form-item label="标题宽度">
<el-input
v-model="data.labelWidth"
clearable
placeholder="标题宽度"
></el-input>
</el-form-item>
<div class="el-form-item el-form-item--small el-form--label-top">
<label class="el-form-item__label" style="padding: 0">自定义属性:</label>
<div class="el-form-item__content">
<!-- <monaco-editor
v-model="params"
height="300"
:keyIndex="data.prop"
:options="options"
></monaco-editor> -->
</div>
</div>
<div class="el-form-item el-form-item--small el-form--label-top">
<label class="el-form-item__label" style="padding: 0">自定义事件:</label>
<div class="el-form-item__content">
<!-- <monaco-editor
v-model="event"
height="300"
:keyIndex="data.prop"
:options="options"
></monaco-editor> -->
</div>
</div>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
</div>
</template>
<script>
// import MonacoEditor from "../utils/monaco-editor";
export default {
name: "config-custom",
components: { },
props: ["data"],
data() {
return {
params: this.data.params || {},
event: this.data.event || {},
options: {
minimap: {
enabled: false,
},
},
};
},
methods: {},
watch: {
"data.params"(val) {
this.params = val || {};
},
"data.event"(val) {
this.event = val || {};
},
params(val) {
try {
this.data.params = eval("(" + val + ")");
} catch (e) {
// console.error(e)
}
},
event(val) {
try {
this.data.event = eval("(" + val + ")");
} catch (e) {
// console.error(e)
}
},
},
};
</script>
<template>
<div>
<template v-if="data.type.indexOf('range') != -1">
<el-form-item label="开始占位内容"
label-width="110px">
<el-input v-model="data.startPlaceholder"
clearable
placeholder="开始占位内容"></el-input>
</el-form-item>
<el-form-item label="结束占位内容"
label-width="110px">
<el-input v-model="data.endPlaceholder"
clearable
placeholder="结束占位内容"></el-input>
</el-form-item>
</template>
<el-form-item label="占位内容"
v-else>
<el-input v-model="data.placeholder"
clearable
placeholder="占位内容"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="显示格式化"
label-width="100px">
<el-input v-model="data.format"
clearable
placeholder="显示格式化"></el-input>
</el-form-item>
<el-form-item label="值格式化">
<el-input v-model="data.valueFormat"
clearable
placeholder="值格式化"></el-input>
</el-form-item>
<el-form-item label="取消范围联动"
label-width="110px"
v-if="['timerange', 'daterange', 'datetimerange'].includes(data.type)">
<el-switch v-model="data.unlinkPanels"></el-switch>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-date",
props: ['data'],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
}
}
},
methods: {
generateRule() {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
else this.validator.required = null
this.generateRule()
}
}
}
</script>
<template>
<div>
<template v-if="data.children && data.children.type !== 'form'">
<el-form-item label="对齐方式">
<el-select
v-model="data.children.align"
placeholder="对齐方式"
clearable
>
<el-option label="居左" value="left"></el-option>
<el-option label="居中" value="center"></el-option>
<el-option label="居右" value="right"></el-option>
</el-select>
</el-form-item>
<el-form-item label="头部对齐方式" label-width="110px">
<el-select
v-model="data.children.headerAlign"
placeholder="对齐方式"
clearable
>
<el-option label="居左" value="left"></el-option>
<el-option label="居中" value="center"></el-option>
<el-option label="居右" value="right"></el-option>
</el-select>
</el-form-item>
</template>
<template v-if="data.children">
<el-form-item label="表单格式">
<el-select
v-model="data.children.type"
placeholder="表单格式"
clearable
>
<el-option label="表格" value=""></el-option>
<el-option label="表单" value="form"></el-option>
</el-select>
</el-form-item>
<el-form-item label="序号" v-if="data.children.type == 'form'">
<el-switch v-model="data.children.index"></el-switch>
</el-form-item>
<el-form-item label="添加按钮">
<el-switch v-model="data.children.addBtn"></el-switch>
</el-form-item>
<el-form-item label="删除按钮">
<el-switch v-model="data.children.delBtn"></el-switch>
</el-form-item>
</template>
<el-form-item label="是否只读">
<el-switch v-model="data.readonly"></el-switch>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<div class=" el-form-item--small el-form--label-top" style="padding: 13px">
<strong class="el-form-item__label" style="padding: 0">初始化数据:</strong>
<div class="el-form-item__content">
<draggable
tag="ul"
:list="data.dynamicData"
:group="{ name: 'dynamic' }"
ghost-class="ghost"
handle=".drag-item"
>
<li v-for="(item, index) in data.dynamicData" :key="index">
<i class="drag-item el-icon-s-operation"></i>
<el-input
style="margin-right: 5px"
size="mini"
clearable
v-model="data.dynamicData[index][column.prop]"
:placeholder="column.label"
v-for="(column,columnIndex) in columns"
:key="columnIndex"
></el-input>
<el-button
@click="handleRemoveFields(index)"
circle
plain
type="danger"
size="mini"
icon="el-icon-minus"
class="del-btn"
></el-button>
</li>
</draggable>
<div style="margin-left: 22px">
<el-button type="text" @click="handleAddFields">添加列 </el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import Draggable from "vuedraggable"
export default {
name: "config-dynamic",
props: {
data: Object,
},
components: { Draggable },
methods: {
handleRemoveFields(index) {
this.data.dynamicData.splice(index, 1)
},
handleAddFields() {
if (!this.data.dynamicData) {
this.$set(this.data, "dynamicData", [])
}
this.data.dynamicData.push({})
},
},
computed: {
columns() {
return this.data.children.column
},
},
}
</script>
<style lang="scss" scoped>
ul > li {
flex-wrap: wrap;
padding: 0 20px;
position: relative;
.drag-item {
position: absolute;
left: 0;
top: 10px;
font-size: 16px;
cursor: move;
margin-right: 5px;
}
.del-btn {
position: absolute;
right: 0;
top: 6px;
padding: 4px;
margin-left: 5px;
}
.el-input {
width: 30%;
}
}
</style>
<template>
<div>
<el-form-item label="开启折叠">
<el-switch v-model="data.arrow"></el-switch>
</el-form-item>
<el-form-item label="默认展开" v-if="data.arrow">
<el-switch v-model="data.collapse"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-group",
props: ["data"],
data() {
return {
iconList: [
{
label: "element-ui",
list: [
"el-icon-info",
"el-icon-error",
"el-icon-success",
"el-icon-warning",
"el-icon-question",
],
},
],
}
},
}
</script>
<style lang="scss" scoped></style>
import Custom from './custom.vue'
import Input from './input.vue'
import Textarea from './textarea.vue'
import Number from './number.vue'
import Dynamic from './dynamic.vue'
import Switch from './switch.vue'
import Rate from './rate.vue'
import Slider from './slider.vue'
import Color from './color.vue'
import Select from './select.vue'
import Tree from './tree.vue'
import Date from './date.vue'
import Upload from './upload.vue'
import UEditor from './ueditor.vue'
import Map from './map.vue'
import Group from './group.vue'
import Array from './array.vue'
import Title from './title.vue'
const components = [
Custom,
Input,
Textarea,
Number,
Dynamic,
Switch,
Rate,
Slider,
Color,
Select,
Tree,
Date,
UEditor,
Upload,
Map,
Group,
Array,
Title
]
const Config = {
install (Vue) {
if (this.installed) return
this.installed = true
components.map(component => {
Vue.component(component.name, component);
})
}
}
export default Config
<template>
<div>
<el-form-item label="占位内容">
<el-input
v-model="data.placeholder"
clearable
placeholder="占位内容"
></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value" clearable placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="前缀">
<el-input v-model="data.prepend" clearable placeholder="前缀"></el-input>
</el-form-item>
<el-form-item label="后缀">
<el-input v-model="data.append" clearable placeholder="后缀"></el-input>
</el-form-item>
<el-form-item label="是否为牙位">
<el-switch v-model="data.toothBit"></el-switch>
</el-form-item>
<el-form-item label="最大长度">
<el-input-number
v-model="data.maxlength"
controls-position="right"
placeholder="最大长度"
></el-input-number>
</el-form-item>
<el-form-item label="显示计数" v-if="data.type != 'password'">
<el-switch v-model="data.showWordLimit"></el-switch>
</el-form-item>
<el-form-item label="显示密码" v-if="data.type == 'password'">
<el-switch v-model="data.showPassword"></el-switch>
</el-form-item>
<el-form-item label="是否只读">
<el-switch v-model="data.readonly"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
<el-input
v-if="data.required"
v-model.lazy="data.pattern"
placeholder="正则表达式"
></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-input",
props: ["data"],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null,
},
}
},
methods: {
generateRule() {
const rules = []
Object.keys(this.validator).forEach((key) => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
"data.required": function (val) {
if (val)
this.validator.required = {
required: true,
message: `${this.data.label}必须填写`,
}
else this.validator.required = null
this.generateRule()
},
"data.pattern": function (val) {
if (val)
this.validator.pattern = {
pattern: new RegExp(val),
message: `${this.data.label}格式不匹配`,
}
else this.validator.pattern = null
// delete this.data.pattern
this.generateRule()
},
},
}
</script>
<template>
<div>
<el-form-item label="默认值">
<a href="https://avuejs.com/doc/plugins/map-plugins"
target="_blank"
style="color: #409EFF;">详细文档</a><br>
<el-input v-model="data.value"
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-map",
props: ['data'],
data () {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
}
}
},
methods: {
generateRule () {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
else this.validator.required = null
this.generateRule()
}
}
}
</script>
<template>
<div>
<el-form-item label="占位内容">
<el-input
v-model="data.placeholder"
clearable
placeholder="占位内容"
></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value" clearable placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="后缀">
<el-input v-model="data.append" clearable placeholder="后缀"></el-input>
</el-form-item>
<el-form-item label="最小值">
<el-input-number
v-model="data.minRows"
controls-position="right"
placeholder="最小值"
></el-input-number>
</el-form-item>
<el-form-item label="最大值">
<el-input-number
v-model="data.maxRows"
controls-position="right"
placeholder="最大值"
></el-input-number>
</el-form-item>
<el-form-item label="步长">
<el-input-number
v-model="data.step"
controls-position="right"
placeholder="步长"
></el-input-number>
</el-form-item>
<el-form-item label="数值精度">
<el-input-number
v-model="data.precision"
controls-position="right"
placeholder="数值精度"
:min="0"
:max="10"
></el-input-number>
</el-form-item>
<el-form-item label="开启控制器" label-width="100px">
<el-switch v-model="data.controls"></el-switch>
</el-form-item>
<el-form-item label="控制器位置" label-width="100px" v-if="data.controls">
<el-radio v-model="data.controlsPosition" label="">默认 </el-radio>
<el-radio v-model="data.controlsPosition" label="right"></el-radio>
</el-form-item>
<el-form-item label="是否只读">
<el-switch v-model="data.readonly"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
<el-input
v-if="data.required"
v-model.lazy="data.pattern"
clearable
placeholder="正则表达式"
></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-number",
props: ["data"],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null,
},
}
},
methods: {
generateRule() {
const rules = []
Object.keys(this.validator).forEach((key) => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
"data.required": function (val) {
if (val)
this.validator.required = {
required: true,
message: `${this.data.label}必须填写`,
}
else this.validator.required = null
this.generateRule()
},
"data.pattern": function (val) {
if (val)
this.validator.pattern = {
pattern: new RegExp(val),
message: `${this.data.label}格式不匹配`,
}
else this.validator.pattern = null
// delete this.data.pattern
this.generateRule()
},
},
}
</script>
<template>
<div>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="最大星数">
<el-input-number v-model="data.max"
controls-position="right"
placeholder="最大星数"></el-input-number>
</el-form-item>
<el-form-item label="是否显示文本"
label-width="110px">
<el-switch v-model="data.showText"></el-switch>
</el-form-item>
<el-form-item label="自定义文本"
label-width="110px"
v-if="data.showText">
<el-tag :key="index"
size="small"
v-for="(tag,index) in data.texts"
closable
@close="handleTextClose(tag)">{{tag}}
</el-tag>
<el-input class="input-new-tag"
v-if="textVisible"
v-model="textValue"
size="mini"
ref="textTag"
clearable
@keyup.enter.native="handleTextConfirm"
@blur="handleTextConfirm">
</el-input>
<el-button v-if="!textVisible && data.texts.length < data.max"
@click="showTextInput"
size="mini"
icon="el-icon-plus"
circle
style="margin-left: 5px;"></el-button>
</el-form-item>
<el-form-item label="自定义颜色"
label-width="110px">
<el-tag :key="index"
v-for="(tag,index) in data.colors"
closable
size="small"
@close="handleColorClose(tag)"
:style="{color: tag}">{{tag}}
</el-tag>
<el-color-picker v-model="colorValue"
size="mini"
@change="handleColorConfirm"
class="color-picker"></el-color-picker>
</el-form-item>
<!-- <el-form-item label="自定义图标">-->
<!-- <el-tag :key="index" v-for="(tag,index) in data.iconClasses" closable @close="handleIconClose(tag)">{{tag}}-->
<!-- </el-tag>-->
<!-- <el-input class="input-new-tag"-->
<!-- v-if="iconVisible"-->
<!-- v-model="iconValue"-->
<!-- size="mini"-->
<!-- ref="iconTag"-->
<!-- @keyup.enter.native="handleIconConfirm"-->
<!-- @blur="handleIconConfirm">-->
<!-- </el-input>-->
<!-- <el-button v-else @click="showIconInput" size="mini" icon="el-icon-plus" circle-->
<!-- style="margin-left: 5px;"></el-button>-->
<!-- </el-form-item>-->
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-rate",
props: ['data'],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
},
textVisible: false,
textValue: '',
colorVisible: false,
colorValue: '',
iconVisible: false,
iconValue: ''
}
},
methods: {
generateRule() {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
handleTextClose(tag) {
this.data.texts.splice(this.data.texts.indexOf(tag), 1);
},
showTextInput() {
this.textVisible = true;
this.$nextTick(() => {
this.$refs.textTag.$refs.input.focus();
});
},
handleTextConfirm() {
if (this.textValue) this.data.texts.push(this.textValue);
this.textVisible = false;
this.textValue = '';
},
handleColorClose(tag) {
this.data.colors.splice(this.data.colors.indexOf(tag), 1);
},
handleColorConfirm() {
if (this.colorValue) this.data.colors.push(this.colorValue);
this.colorValue = '';
},
// handleIconClose(tag) {
// this.data.iconClasses.splice(this.data.iconClasses.indexOf(tag), 1);
// },
// showIconInput() {
// this.iconVisible = true;
// this.$nextTick(() => {
// this.$refs.iconTag.$refs.input.focus();
// });
// },
// handleIconConfirm() {
// if (this.iconValue) this.data.iconClasses.push(this.iconValue);
// this.iconVisible = false;
// this.iconValue = '';
// }
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
else this.validator.required = null
this.generateRule()
},
}
}
</script>
<style lang="scss" scoped>
.el-tag {
vertical-align: top;
}
.el-tag + .el-tag {
margin-left: 5px;
}
.input-new-tag {
width: 90px;
margin-left: 5px;
vertical-align: bottom;
}
.color-picker {
left: 10px;
vertical-align: top;
}
</style>
<template>
<div>
<el-form-item v-if="data.type == 'select'" label="占位内容">
<el-input
v-model="data.placeholder"
clearable
placeholder="占位内容"
></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value" clearable placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="字典">
<el-select
v-model="data.dicType"
placeholder="选择字典"
style="width: 100%"
@change="dicTypeChange"
clearable
filterable
>
<el-option
:label="item.name"
:value="item.type"
v-for="item in dictList"
:key="item.id"
></el-option>
</el-select>
</el-form-item>
<div class="el-form-item--small el-form--label-top" style="padding: 13px">
<strong class="el-form-item__label" style="padding: 0"
>字典数据示例:</strong
>
<div class="el-form-item__content">
<draggable
tag="ul"
:list="data.dicData"
:group="{ name: 'dic' }"
ghost-class="ghost"
handle=".drag-item"
>
<li v-for="(item, index) in data.dicData" :key="index">
<i
class="drag-item el-icon-s-operation"
style="font-size: 16px; margin: 0 5px; cursor: move"
></i>
<el-input
style="margin-right: 5px"
size="mini"
readonly
clearable
v-model="item.label"
placeholder="label"
></el-input>
<el-input
:style="{
'margin-right': data.type == 'select' ? '5px' : '0',
}"
size="mini"
clearable
readonly
v-model="item.value"
placeholder="value"
></el-input>
<!-- <el-input
v-if="data.type == 'select'"
size="mini"
clearable
v-model="item.desc"
placeholder="描述"
></el-input> -->
<el-button
@click="handleRemoveFields(index)"
circle
plain
type="danger"
size="mini"
icon="el-icon-minus"
style="padding: 4px; margin-left: 5px"
></el-button>
</li>
</draggable>
<!-- <div style="margin-left: 22px">
<el-button type="text" @click="handleAddFields">添加列 </el-button>
</div> -->
</div>
</div>
<!-- <div class="el-form-item el-form-item--small el-form--label-top">
<label class="el-form-item__label" style="padding: 0"
>字典key配置:</label
>
<div class="el-form-item__content">
<ul>
<li v-for="(value, key) in data.props" :key="key">
<span style="width: 50px">{{ key }}</span>
<el-input
size="mini"
v-model="data.props[key]"
clearable
placeholder="key配置"
></el-input>
</li>
</ul>
</div>
</div> -->
<!-- <el-form-item
v-if="data.dicOption == 'remote'"
label="重新请求字典(crud)"
label-width="150px"
>
<el-switch v-model="data.dicFlag"></el-switch>
</el-form-item> -->
<template v-if="data.type == 'select'">
<el-form-item label="是否多选">
<el-switch v-model="data.multiple"></el-switch>
</el-form-item>
<!-- <el-form-item label="是否可拖拽" label-width="110px" v-if="data.multiple">
<template slot="label">
<el-link
:underline="false"
href="https://avuejs.com/doc/form/form-select-drag"
target="_blank"
>是否可拖拽 <i class="el-icon-question"></i
></el-link>
</template>
<el-switch v-model="data.drag"></el-switch>
</el-form-item> -->
<el-form-item
label="多选数量限制"
label-width="110px"
v-if="data.multiple"
>
<el-input-number
v-model="data.limit"
controls-position="right"
placeholder="多选限制"
:min="0"
:max="data.dicData.length"
></el-input-number>
</el-form-item>
<!-- <div class="el-form-item el-form-item--small el-form--label-top">
<label class="el-form-item__label" style="padding: 0">级联配置:</label>
<div class="el-form-item__content">
<draggable
tag="ul"
:list="data.cascaderItem"
:group="{ name: 'cascaderItem' }"
ghost-class="ghost"
handle=".drag-item"
>
<li v-for="(item, index) in data.cascaderItem" :key="index">
<i
class="drag-item el-icon-s-operation"
style="font-size: 16px; margin: 0 5px; cursor: move"
></i>
<el-input
size="mini"
v-model="data.cascaderItem[index]"
clearable
placeholder="级联属性值"
></el-input>
<el-button
@click="handleRemoveCascaderItemFields(index)"
circle
plain
type="danger"
size="mini"
icon="el-icon-minus"
style="padding: 4px; margin-left: 5px"
>
</el-button>
</li>
</draggable>
<div style="margin-left: 22px">
<el-button type="text" @click="handleAddCascaderItemFields"
>添加列</el-button
>
</div>
</div>
</div>
<el-form-item
v-if="data.cascaderItem && data.cascaderItem.length > 0"
label="级联默认选中"
label-width="110px"
>
<el-input-number
v-model="data.cascaderIndex"
controls-position="right"
placeholder="级联默认选中"
:min="0"
></el-input-number>
</el-form-item> -->
<el-form-item label="是否可清空" label-width="110px">
<el-switch v-model="data.clearable"></el-switch>
</el-form-item>
<el-form-item label="是否可搜索" label-width="110px">
<el-switch v-model="data.filterable"></el-switch>
</el-form-item>
</template>
<template v-if="data.type == 'checkbox'">
<el-form-item label="开启排斥项">
<el-switch v-model="data.repel"></el-switch>
<el-input
v-if="data.repel"
v-model.lazy="data.repelValue"
placeholder="排斥项值(value)"
></el-input>
</el-form-item>
</template>
<!-- <template v-if="['radio', 'checkbox'].includes(data.type)">
<el-form-item label="边框" v-if="!data.button">
<el-switch v-model="data.border"></el-switch>
</el-form-item>
<el-form-item label="按钮" v-if="!data.border">
<el-switch v-model="data.button"></el-switch>
</el-form-item>
</template> -->
<!-- <el-form-item label="尺寸" v-if="data.border || data.button">
<el-radio-group v-model="data.size" size="mini">
<el-radio-button label="medium">正常</el-radio-button>
<el-radio-button label="small">小</el-radio-button>
<el-radio-button label="mini">超小</el-radio-button>
</el-radio-group>
</el-form-item> -->
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
</div>
</template>
<script>
import Draggable from "vuedraggable"
import { mapGetters } from "vuex"
export default {
name: "config-select",
props: ["data"],
components: { Draggable },
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null,
},
option: {
column: [
{
type: "input",
prop: "key",
label: "key",
},
{
type: "input",
prop: "value",
label: "value",
},
],
},
}
},
computed: {
...mapGetters({
dictList: ["dict/dictSet"],
dictMap: ["dict/dictMap"],
}),
},
methods: {
dicTypeChange(type) {
this.data.dicData = this.deepClone(this.dictMap[type])
},
generateRule() {
const rules = []
Object.keys(this.validator).forEach((key) => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
handleRemoveFields(index) {
this.data.dicData.splice(index, 1)
},
handleAddFields() {
const i = Math.ceil(Math.random() * 99999)
this.data.dicData.push({ label: `字段${i}`, value: `col_${i}` })
},
handleRemoveCascaderItemFields(index) {
this.data.cascaderItem.splice(index, 1)
},
handleAddCascaderItemFields() {
this.data.cascaderItem.push("")
},
handleTabClick({ name }) {
if (name == "remote" && !this.data.dicQueryConfig)
this.data.dicQueryConfig = []
},
},
watch: {
"data.required": function (val) {
if (val)
this.validator.required = {
required: true,
message: `请选择${this.data.label}`,
}
else this.validator.required = null
this.generateRule()
},
},
}
</script>
<template>
<div>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="最小值">
<el-input-number v-model="data.min"
controls-position="right"
placeholder="最小值"
:max="data.max - 1"
:min="0"></el-input-number>
</el-form-item>
<el-form-item label="最大值">
<el-input-number v-model="data.max"
controls-position="right"
placeholder="最大值"
:min="data.min + 1"></el-input-number>
</el-form-item>
<el-form-item label="步长">
<el-input-number v-model="data.step"
controls-position="right"
placeholder="步长"
:min="1"
:max="data.max - data.min"></el-input-number>
</el-form-item>
<el-form-item label="显示间隔点"
label-width="100px">
<el-switch v-model="data.showStops"></el-switch>
</el-form-item>
<el-form-item label="显示输入框"
label-width="100px">
<el-switch v-model="data.showInput"></el-switch>
</el-form-item>
<el-form-item label="范围">
<el-switch v-model="data.range"></el-switch>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-slider",
props: ['data']
}
</script>
<template>
<div>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="自定义">
<el-button type="text"
@click="handleDicClear"
class="danger">清空
</el-button>
<div class="dic"
v-for="(item, index) in data.dicData"
:key="index">
<el-input size="mini"
v-model="item.label"
placeholder="自定义文字"
clearable
style="margin-right: 5px"></el-input>
<el-input size="mini"
v-model="item.value"
clearable
placeholder="自定义值"></el-input>
</div>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-switch",
props: ['data'],
methods: {
handleDicClear() {
this.data.dicData = [{ label: '', value: '0' }, { label: '', value: '1' }]
}
},
}
</script>
<style lang="scss" scoped>
.dic {
display: flex;
margin-bottom: 5px;
}
</style>
<template>
<div>
<el-form-item label="开启折叠">
<el-switch v-model="data.arrow"></el-switch>
</el-form-item>
<el-form-item label="默认展开" v-if="data.arrow">
<el-switch v-model="data.collapse"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-tabs",
props: ["data"],
data() {
return {
iconList: [
{
label: "element-ui",
list: [
"el-icon-info",
"el-icon-error",
"el-icon-success",
"el-icon-warning",
"el-icon-question",
],
},
],
}
},
}
</script>
<style lang="scss" scoped></style>
<template>
<div>
<el-form-item label="占位内容">
<el-input v-model="data.placeholder"
type="textarea"
autosize
clearable
placeholder="占位内容"></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value"
clearable
placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="最大长度">
<el-input-number v-model="data.maxlength"
controls-position="right"
placeholder="最大长度"></el-input-number>
</el-form-item>
<el-form-item label="显示计数">
<el-switch v-model="data.showWordLimit"></el-switch>
</el-form-item>
<el-form-item label="最小行">
<el-input-number v-model="data.minRows"
controls-position="right"
placeholder="最小行"
:min="1"></el-input-number>
</el-form-item>
<el-form-item label="最大行">
<el-input-number v-model="data.maxRows"
controls-position="right"
placeholder="最大行"
:min="2"></el-input-number>
</el-form-item>
<el-form-item label="是否只读">
<el-switch v-model="data.readonly"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
<el-input v-if="data.required"
v-model.lazy="data.pattern"
clearable
placeholder="正则表达式"></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-textarea",
props: ['data'],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null
}
}
},
methods: {
generateRule() {
const rules = [];
Object.keys(this.validator).forEach(key => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
},
watch: {
'data.required': function (val) {
if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
else this.validator.required = null
this.generateRule()
},
'data.pattern': function (val) {
if (val) this.validator.pattern = { pattern: new RegExp(val), message: `${this.data.label}格式不匹配` }
else this.validator.pattern = null
// delete this.data.pattern
this.generateRule()
}
}
}
</script>
<template>
<div>
<el-form-item label="默认值">
<el-input v-model="data.value" clearable placeholder="默认值"></el-input>
</el-form-item>
<!-- <el-form-item label="距左边边距" label-width="100px">
<el-input
v-model="data.styles.marginLeft"
clearable
placeholder="距左边边距"
></el-input>
</el-form-item> -->
<el-form-item label="文字位置">
<el-select
v-model="data.styles.textAlign"
placeholder="文字位置"
clearable
>
<el-option
v-for="item in textAlignOpt"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="颜色">
<el-color-picker
v-model="data.styles.color"
size="mini"
></el-color-picker>
</el-form-item>
<el-form-item label="字体大小">
<el-input
v-model="data.styles.fontSize"
clearable
placeholder="字体大小"
></el-input>
</el-form-item>
<el-form-item label="粗体">
<el-select v-model="data.styles.fontWeight" placeholder="粗体" clearable>
<el-option
v-for="item in options"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</el-form-item>
</div>
</template>
<script>
export default {
name: "config-title",
props: ["data"],
data() {
return {
options: [
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900",
"blod",
"bloder",
"inherit",
"initial",
"lighter",
"normal",
"revert",
"unset",
],
textAlignOpt: [
{
label: "居左",
value: "left",
},
{
label: "居中",
value: "center",
},
{
label: "居右",
value: "right",
},
],
}
},
}
</script>
<template>
<div>
<el-form-item label="占位内容">
<el-input
v-model="data.placeholder"
clearable
placeholder="占位内容"
></el-input>
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="data.value" clearable placeholder="默认值"></el-input>
</el-form-item>
<el-form-item label="字典">
<el-select
v-model="data.dicType"
placeholder="选择字典"
style="width: 100%"
clearable
filterable
@change="dicTypeChange"
>
<el-option
:label="item.name"
:value="item.type"
v-for="item in dictList"
:key="item.id"
></el-option>
</el-select>
</el-form-item>
<div class=" el-form-item--small el-form--label-top" style="padding: 13px">
<strong class="el-form-item__label" style="padding: 0"
>字典数据示例:</strong
>
<div class="el-form-item__content">
<el-tree
ref="tree"
:data="data.dicData"
default-expand-all
draggable
node-key="value"
:expand-on-click-node="false"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>
<strong>{{ data.label }}</strong>
<span> ({{ data.value }})</span>
</span>
<span>
<!-- <el-button
type="text"
size="mini"
icon="el-icon-plus"
@click="handleNodeAdd(data)"
></el-button>
<el-button class="warning" type="text" size="mini" icon="el-icon-edit"
@click="handleNodeEdit(data)"></el-button> -->
<el-button
class="danger"
type="text"
size="mini"
icon="el-icon-delete"
@click="handleNodeRemove(node, data)"
></el-button>
</span>
</span>
</el-tree>
<!-- <div style="margin-left: 22px">
<el-button type="text" @click="handleParentNodeAdd"
>添加父级
</el-button>
</div> -->
</div>
</div>
<!-- <div class="el-form-item el-form-item--small el-form--label-top">
<label class="el-form-item__label" style="padding: 0"
>字典key配置:</label
>
<div class="el-form-item__content">
<ul>
<li v-for="(value, key) in data.props" :key="key">
<span style="width: 50px">{{ key }}</span>
<el-input
size="mini"
v-model="data.props[key]"
placeholder="key配置"
></el-input>
</li>
</ul>
</div>
</div>
<el-form-item v-if="data.dicOption == 'remote'" label="重新请求字典(crud)">
<el-switch v-model="data.dicFlag"></el-switch>
</el-form-item>
<template v-if="data.type == 'tree'">
<el-form-item label="当有子级时,是否可选择父级" label-width="200px">
<el-switch v-model="data.parent"></el-switch>
</el-form-item>
</template> -->
<template v-if="data.type == 'cascader'">
<el-form-item label="选项分隔符" label-width="100px">
<el-input
v-model="data.separator"
clearable
placeholder="选项分隔符"
></el-input>
</el-form-item>
<el-form-item label="是否显示选中值的完整路径" label-width="200px">
<el-switch v-model="data.showAllLevels"></el-switch>
</el-form-item>
<el-form-item label="是否可搜索">
<el-switch v-model="data.filterable"></el-switch>
</el-form-item>
</template>
<el-form-item label="是否多选">
<el-switch v-model="data.multiple"></el-switch>
</el-form-item>
<el-form-item label="是否禁用">
<el-switch v-model="data.disabled"></el-switch>
</el-form-item>
<el-form-item label="是否可见">
<el-switch v-model="data.display"></el-switch>
</el-form-item>
<el-form-item label="是否必填">
<el-switch v-model="data.required"></el-switch>
</el-form-item>
<el-dialog
:visible.sync="dialogVisible"
:rules="dialogRules"
:before-close="beforeClose"
>
<el-form ref="dialogForm" :model="dialogForm" label-width="80px">
<el-form-item label="label">
<el-input v-model="dialogForm.label" placeholder="label"></el-input>
</el-form-item>
<el-form-item label="value">
<el-input
v-model="dialogForm.value"
placeholder="value"
:type="this.dialogInputType"
>
<el-select
v-model="dialogInputType"
slot="append"
placeholder="数据类型"
style="width: 100px"
>
<el-option label="String" value="text"></el-option>
<el-option label="Number" value="number"></el-option>
</el-select>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="handleDialogAdd"
v-if="dialogStatus == 'add'"
>确 定</el-button
>
<!-- <el-button type="primary" @click="handleDialogUpdate" v-else>确 定</el-button>-->
</span>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex"
export default {
name: "config-tree",
props: ["data"],
data() {
return {
validator: {
type: null,
required: null,
pattern: null,
length: null,
},
dialogForm: {},
dialogVisible: false,
dialogRules: {
label: { required: true, message: "请输入label" },
value: { required: true, message: "请输入value" },
},
dialogStatus: "add",
selectData: undefined,
dialogInputType: "text",
option: {
column: [
{
type: "input",
prop: "key",
label: "key",
},
{
type: "input",
prop: "value",
label: "value",
},
],
},
}
},
computed: {
...mapGetters({
dictList: ["dict/dictSet"],
dictMap: ["dict/dictMap"],
}),
},
methods: {
dicTypeChange(type) {
this.data.dicData = this.deepClone(this.dictMap[type])
},
generateRule() {
const rules = []
Object.keys(this.validator).forEach((key) => {
if (this.validator[key]) rules.push(this.validator[key])
})
this.data.rules = rules
},
handleTabClick({ name }) {
if (name == "remote" && !this.data.dicQueryConfig)
this.data.dicQueryConfig = []
},
handleParentNodeAdd() {
this.selectData = undefined
this.dialogStatus = "add"
this.dialogVisible = true
},
handleNodeAdd(data) {
this.selectData = data
this.dialogStatus = "add"
this.dialogVisible = true
},
handleNodeRemove(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
},
handleDialogAdd() {
this.$refs.dialogForm.validate((valid) => {
if (valid) {
const { label, value } = this.dialogForm
const node = this.$refs.tree.getNode(value)
if (node) this.$message.error("value重复")
else {
const data = this.selectData
const newNode = {
label,
value:
this.dialogInputType == "number" ? new Number(value) : value,
}
if (data) {
if (!data.children) this.$set(data, "children", [])
data.children.push(newNode)
} else {
this.$set(this.data.dicData, this.data.dicData.length, newNode)
}
this.beforeClose()
}
}
})
},
beforeClose() {
this.$refs.dialogForm.clearValidate()
this.dialogForm = {}
this.dialogVisible = false
},
},
watch: {
"data.required": function (val) {
if (val)
this.validator.required = {
required: true,
message: `请选择${this.data.label}`,
}
else this.validator.required = null
this.generateRule()
},
"data.multiple": function (val) {
if (val) this.data.defaultValue = []
else delete this.data.defaultValue
},
},
}
</script>
<style lang="scss" scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import Config from './config'
import FormDesign from './index.vue'
export default {
install (Vue) {
Vue.use(Config)
Vue.component('Avue' + FormDesign.name, FormDesign);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export const stringify = (json) => {
let count = 0;
let list = [];
let str = JSON.stringify(json, function (key, val) {
if (typeof val === 'function') {
list.push(val + '');
const result = '$code{' + count + '}$code'
count = count + 1;
return result
}
return val;
}, 2);
let startCode = '$code{';
let endCode = '}$code';
list.forEach((ele, index) => {
str = str.replace(startCode + index + endCode, startCode + ele + endCode)
})
for (let i = 0; i < count; i++) {
str = str.replace('"' + startCode, '').replace(endCode + '"', '')
}
return str
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
const viewGenerator = require("zx-templates/view/prompt");
const curdGenerator = require("zx-templates/curd/prompt");
const componentGenerator = require("zx-templates/component/prompt");
const mockGenerator = require("zx-templates/mock/prompt");
const vuexGenerator = require("zx-templates/vuex/prompt");
module.exports = function (plop) {
plop.setGenerator("view", viewGenerator);
plop.setGenerator("curd", curdGenerator);
plop.setGenerator("component", componentGenerator);
plop.setGenerator("mock&api", mockGenerator);
plop.setGenerator("vuex", vuexGenerator);
};
module.exports = {
plugins: {
autoprefixer: {},
},
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment