From 62cec2d363ac43cce944afa667b8b5eba0a5fa2d Mon Sep 17 00:00:00 2001 From: xy <271556543@qq.com> Date: Mon, 2 Sep 2024 18:09:55 +0800 Subject: [PATCH] init --- package.json | 4 +- src/main.js | 12 +- src/utils/formBuilder.js | 356 +++++++++++++++++++++++++++++++++ src/utils/formBuilderMap.js | 26 +-- src/views/flow/DesktopForm.vue | 130 ++++++++++++ src/views/flow/MobileForm.vue | 17 ++ src/views/flow/create.vue | 24 ++- 7 files changed, 550 insertions(+), 19 deletions(-) create mode 100644 src/utils/formBuilder.js create mode 100644 src/views/flow/DesktopForm.vue create mode 100644 src/views/flow/MobileForm.vue diff --git a/package.json b/package.json index 38bacf8..822d903 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,12 @@ "normalize.css": "7.0.0", "nprogress": "0.2.0", "path-to-regexp": "2.4.0", + "vant": "^2.13.2", "vue": "2.6.10", "vue-router": "3.0.6", "vuex": "3.1.0", - "vxe-table": "^3.8.22" + "vxe-table": "^3.8.22", + "moment": "^2.29.4" }, "devDependencies": { "@vue/cli-plugin-babel": "4.4.4", diff --git a/src/main.js b/src/main.js index 56c3010..803b1a7 100644 --- a/src/main.js +++ b/src/main.js @@ -29,9 +29,9 @@ if (process.env.NODE_ENV === 'production') { } // set ElementUI lang to EN -Vue.use(ElementUI, { locale }) +//Vue.use(ElementUI, { locale }) // 如果想要中文版 element-ui,按如下方式声明 -// Vue.use(ElementUI) +Vue.use(ElementUI) import { VxeIcon, VxeTable, VxeColumn, VxeColgroup, VxeTableEditModule, VxeTableValidatorModule, VxeModal, VxeToolbar } from "vxe-table"; import "vxe-table/styles/index.scss" Vue.use(VxeTableEditModule); @@ -45,6 +45,14 @@ Vue.use(VxeToolbar); Vue.config.productionTip = false +//vant +import Vant from 'vant' +Vue.use(Vant) + +//moment +import moment from 'moment' +Vue.prototype.$moment = moment; + import { setToken,getToken } from "@/utils/auth" if (window.__POWERED_BY_WUJIE__) { let instance; diff --git a/src/utils/formBuilder.js b/src/utils/formBuilder.js new file mode 100644 index 0000000..171079c --- /dev/null +++ b/src/utils/formBuilder.js @@ -0,0 +1,356 @@ +import formBuilderMap from './formBuilderMap' +import { CreateElement } from 'vue' +import moment from 'moment' +import { getToken } from "@/utils/auth"; +/** + * @param {String} device 'desktop' or 'mobile' + * @param {Object} info field参数 + * @param {CreateElement} h +**/ +export default function (device, info,h ) { + let formItem; + if (device === 'desktop') { + switch (info.type) { + case 'text': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + value: this.form[info.name], + clearable: true, + placeholder: info.help_text + }, + attrs: { + placeholder: info.help_text + }, + on: { + input: e => { + this.form[info.name] = e + } + } + }) + break; + case 'textarea': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + type: 'textarea', + autosize: { + minRows: 2 + }, + value: this.form[info.name], + clearable: true, + placeholder: info.help_text + }, + attrs: { + placeholder: info.help_text + }, + on: { + input: e => { + this.form[info.name] = e + } + } + }) + break; + case 'date': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + type: 'date', + 'value-format': 'yyyy-MM-dd', + format: 'yyyy年MM月dd日', + value: this.form[info.name], + clearable: true, + placeholder: info.help_text, + 'picker-options': { + shortcuts: [ + { + text: '一年前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'years').toDate()); + } + }, + { + text: '一月前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'months').toDate()); + } + }, + { + text: '一周前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'weeks').toDate()); + + } + }, + { + text: '今天', + onClick(picker) { + picker.$emit('pick', new Date()); + } + }, + { + text: '一周后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'weeks').toDate()); + } + }, + { + text: '一月后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'months').toDate()); + } + }, + { + text: '一年后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'years').toDate()); + } + }, + ] + } + }, + attrs: { + placeholder: info.help_text + }, + style: { + width: '100%' + }, + on: { + input: e => { + this.$set(this.form,info.name,e) + } + } + }) + break; + case 'datetime': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + type: 'datetime', + 'value-format': 'yyyy-MM-dd', + format: 'yyyy年MM月dd日', + value: this.form[info.name], + clearable: true, + placeholder: info.help_text, + 'picker-options': { + shortcuts: [ + { + text: '一年前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'years').toDate()); + } + }, + { + text: '一月前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'months').toDate()); + } + }, + { + text: '一周前', + onClick(picker) { + picker.$emit('pick', moment().subtract(1,'weeks').toDate()); + + } + }, + { + text: '今天', + onClick(picker) { + picker.$emit('pick', new Date()); + } + }, + { + text: '一周后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'weeks').toDate()); + } + }, + { + text: '一月后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'months').toDate()); + } + }, + { + text: '一年后', + onClick(picker) { + picker.$emit('pick', moment().add(1,'years').toDate()); + } + }, + ] + } + }, + style: { + width: '100%' + }, + attrs: { + placeholder: info.help_text + }, + on: { + input: e => { + this.$set(this.form,info.name,e) + } + } + }) + break; + case 'select': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + value: this.form[info.name], + clearable: true, + placeholder: info.help_text + }, + attrs: { + placeholder: info.help_text + }, + on: { + input: e => { + this.$set(this.form,info.name,e) + } + } + },[1,2,3].map(option => ( + h('el-option',{ + props: { + label: option, + value: option + } + }) + ))) + break; + case 'radio': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + value: this.form[info.name], + }, + attrs: { + placeholder: info.help_text + }, + on: { + input: e => { + this.$set(this.form,info.name,e) + } + } + },[1,2,3].map(option => ( + h('el-radio',{ + props: { + label: option + } + },option) + ))) + break; + case 'file': + formItem = h(formBuilderMap(device).get(info.type),{ + props: { + action: process.env.VUE_APP_UPLOAD_API, + headers: { + Authorization: `Bearer ${getToken()}`, + }, + multiple: true, + fileList: this.file[info.name], + beforeUpload: (file) => { + if ((file.size / 1024 / 1024) > (20)) { + this.$message({ + type: "warning", + message: "上传图片大小超过20Mb!", + }); + return false; + } + }, + onSuccess: (response, file, fileList) => { + this.file[info.name] = fileList; + }, + onRemove: (file, fileList) => { + this.file[info.name] = fileList; + }, + onError: (err, file, fileList) => { + this.file[info.name] = fileList; + this.$message({ + type: "warning", + message: err, + }); + } + }, + scopedSlots: { + file: (scope) => { + let { file } = scope; + return [ + h("div", {}, [ + h("i", { + class: { + "el-icon-circle-check": + file.status === + "success", + "el-icon-loading": + file.status === + "uploading", + }, + style: { + color: + file.status === + "success" + ? "green" + : "", + }, + }), + h( + "a", + { + attrs: { + href: file.url, + download: file.name, + }, + class: { + "uploaded-a": + file.status === + "success", + }, + style: { + padding: "0 4px", + }, + }, + file.name + ), + ]), + h("i", { + class: "el-icon-close", + on: { + ["click"]: () => { + this.$set(this.file, info.field, this.file[info.field].filter((item) => item !== file)) + } + }, + }), + ]; + } + } + },[ + h( + "el-button", + { + slot: "trigger", + props: { + size: "small", + type: "primary", + }, + }, + "选取文件" + ), + h( + "div", + { + class: "el-upload__tip", + slot: "tip", + }, + "文件不超过20Mb" + ) + ]) + } + return h('el-form-item',{ + props: { + prop: info.name, + label: info.label + }, + style: { + 'grid-column-start': info.gs_x, + 'grid-column-end': info.gs_x + info.gs_width, + 'grid-row-start': info.gs_y, + 'grid-row-end': info.gs_y + info.gs_height + } + },[formItem]) + } +} diff --git a/src/utils/formBuilderMap.js b/src/utils/formBuilderMap.js index 6db2e06..246f7b8 100644 --- a/src/utils/formBuilderMap.js +++ b/src/utils/formBuilderMap.js @@ -2,7 +2,7 @@ export default function (device) { return device === 'desktop' ? new Map([ ['text', 'el-input'], - ['text', 'el-input'], + ['textarea', 'el-input'], ['date', 'el-date-picker'], ['datetime', 'el-date-picker'], ['select', 'el-select'], @@ -16,18 +16,18 @@ export default function (device) { ['sign', 'el-image'] ]) : new Map([ - ['text', 'el-input'], - ['text', 'el-input'], - ['date', 'el-date-picker'], - ['datetime', 'el-date-picker'], - ['select', 'el-select'], - ['radio', 'el-radio-group'], - ['file', 'el-upload'], - ['label', 'el-tag'], + ['text', 'van-field'], + ['textarea', 'van-field'], + ['date', 'van-cell'], + ['datetime', 'van-datetime-picker'], + ['select', 'van-picker'], + ['radio', 'van-radio-group'], + ['file', 'van-uploader'], + ['label', 'van-tag'], ['static', 'el-link'], - ['hr', 'el-divider'], - ['choice', 'el-select'], - ['choices', 'el-select'], - ['sign', 'el-image'] + ['hr', 'van-divide'], + ['choice', 'van-picker'], + ['choices', 'van-checkbox'], + ['sign', 'van-image'] ]) } diff --git a/src/views/flow/DesktopForm.vue b/src/views/flow/DesktopForm.vue new file mode 100644 index 0000000..9eba155 --- /dev/null +++ b/src/views/flow/DesktopForm.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/views/flow/MobileForm.vue b/src/views/flow/MobileForm.vue new file mode 100644 index 0000000..98b6b2f --- /dev/null +++ b/src/views/flow/MobileForm.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/views/flow/create.vue b/src/views/flow/create.vue index 3045760..e445fe0 100644 --- a/src/views/flow/create.vue +++ b/src/views/flow/create.vue @@ -6,19 +6,36 @@ @@ -29,7 +46,8 @@ export default { .container { padding: 20px; } - +.form-container { +} @media (max-width: 768px) { .container { padding: 10px;