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;