From 01497346c9294c79ea35a3eb5a55d00421017f5b Mon Sep 17 00:00:00 2001
From: xy <271556543@qq.com>
Date: Tue, 24 Sep 2024 18:11:04 +0800
Subject: [PATCH] 1
---
src/api/me.js | 6 +-
src/layout/components/Sidebar/index.vue | 8 +-
src/main.js | 13 +-
src/permission.js | 7 +-
src/router/index.js | 131 +++++-----
src/store/modules/permission.js | 2 +-
src/utils/formBuilder.js | 319 +++++++++++++++++++++++-
src/utils/formBuilderMap.js | 2 +-
src/views/flow/MobileForm.vue | 31 ++-
src/views/flow/components/assign.vue | 100 +++++++-
src/views/flow/components/share.vue | 2 +-
src/views/flow/create.vue | 14 +-
src/views/flow/index.vue | 12 +-
src/views/flow/list.vue | 55 +++-
vue.config.js | 4 +-
15 files changed, 581 insertions(+), 125 deletions(-)
diff --git a/src/api/me.js b/src/api/me.js
index 4c8c501..f654981 100644
--- a/src/api/me.js
+++ b/src/api/me.js
@@ -27,11 +27,11 @@ export function logout() {
export function permissions () {
return request({
- url: `/api/${window.MODULE_NAME||process.env.VUE_APP_MODULE_NAME}/auth/permissions`,
- method: "post",
+ url: `/api/auth/module-permissions/${window.MODULE_NAME||window.location.pathname.replaceAll(/\//g,"")||process.env.VUE_APP_MODULE_NAME}`,
+ method: "get",
isLoading: false,
params: {
- module: window.MODULE_NAME||process.env.VUE_APP_MODULE_NAME
+ module: window.MODULE_NAME||window.location.pathname.replaceAll(/\//g,"")||process.env.VUE_APP_MODULE_NAME
}
})
}
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
index 9a9a9cd..7763285 100644
--- a/src/layout/components/Sidebar/index.vue
+++ b/src/layout/components/Sidebar/index.vue
@@ -12,7 +12,7 @@
:collapse-transition="false"
mode="vertical"
>
-
+
@@ -31,11 +31,9 @@ export default {
components: { Hamburger, SidebarItem, Logo },
computed: {
...mapGetters([
- 'sidebar'
+ 'sidebar',
+ 'permission_routes'
]),
- routes() {
- return this.$router.options.routes
- },
activeMenu() {
const route = this.$route
const { meta, path } = route
diff --git a/src/main.js b/src/main.js
index decb6a5..5b694c8 100644
--- a/src/main.js
+++ b/src/main.js
@@ -68,7 +68,7 @@ if (window.__POWERED_BY_WUJIE__) {
render: h => h(App)
}).$mount("#app")
window.MODULE_NAME = window.$wujie?.props?.module_name;
- console.log(444,window.MODULE_NAME)
+ console.log('token-wujie',window.MODULE_NAME)
setToken(window.$wujie?.props?.auth_token)
router.push('/')
};
@@ -76,6 +76,17 @@ if (window.__POWERED_BY_WUJIE__) {
instance.$destroy();
};
} else {
+ if (window.top !== window.self) {
+ // 当前页面在iframe中
+ window._IN_IFRAME = true;
+ window.addEventListener("message",function (e) {
+ const { module_name, auth_token } = e.data;
+ window.MODULE_NAME = module_name;
+ console.log('token',auth_token)
+ setToken(auth_token)
+ router.push('/')
+ })
+ }
new Vue({
router,
store,
diff --git a/src/permission.js b/src/permission.js
index d6eec0d..ac3a513 100644
--- a/src/permission.js
+++ b/src/permission.js
@@ -19,16 +19,14 @@ router.beforeEach(async(to, from, next) => {
// determine whether the user has logged in
const hasToken = getToken()
-
+ console.log(4444,hasToken)
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
- //TODO:
- next()
- return
+
if (store.state.permission.addRoutes && store.state.permission.addRoutes instanceof Array && store.state.permission.addRoutes.length > 0) {
next()
} else {
@@ -36,7 +34,6 @@ router.beforeEach(async(to, from, next) => {
// get user info
const { roles } = await store.dispatch('user/getInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
-
// dynamically add accessible routes
router.addRoutes(accessRoutes)
diff --git a/src/router/index.js b/src/router/index.js
index 1d3cdc4..0c2bf09 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,10 +1,10 @@
-import Vue from 'vue'
-import Router from 'vue-router'
+import Vue from "vue";
+import Router from "vue-router";
-Vue.use(Router)
+Vue.use(Router);
/* Layout */
-import Layout from '@/layout'
+import Layout from "@/layout";
/**
* Note: sub-menu only appear when route children.length >= 1
@@ -32,92 +32,77 @@ import Layout from '@/layout'
*/
export const constantRoutes = [
{
- path: '/login',
- component: () => import('@/views/login/index'),
- hidden: true
+ path: "/login",
+ component: () => import("@/views/login/index"),
+ hidden: true,
},
{
- path: '/404',
- component: () => import('@/views/404'),
- hidden: true
+ path: "/404",
+ component: () => import("@/views/404"),
+ hidden: true,
},
{
- path: '/',
+ path: "/",
component: Layout,
- redirect: '/dashboard',
- meta: { title: '首页', icon: 'dashboard' },
- children: [{
- path: 'dashboard',
- name: 'Dashboard',
- component: () => import('@/views/dashboard/index'),
- meta: { title: '首页', icon: 'dashboard' }
- }]
+ redirect: "/dashboard",
+ meta: { title: "首页", icon: "dashboard" },
+ children: [
+ {
+ path: "dashboard",
+ name: "Dashboard",
+ component: () => import("@/views/dashboard/index"),
+ meta: { title: "首页", icon: "dashboard" },
+ },
+ ],
},
{
- path: '/flow',
+ path: "/flow",
component: Layout,
- redirect: '/flow/create',
- meta: { title: '流程', icon: 'tree' },
- children: [{
- path: 'index',
- name: 'flowIndex',
- component: () => import('@/views/flow/index.vue'),
- meta: { title: '流程创建', icon: 'tree' }
- },{
- path: 'list/:type',
- name: 'flowList',
- hidden: true,
- component: () => import('@/views/flow/list.vue'),
- },{
- path: 'list/created-by-me',
- name: 'created-by-me',
- meta: { title: '流程监管', icon: 'table' }
- },{
- path: 'list/fav',
- name: 'fav',
- meta: { title: '我收藏的', icon: 'fav' }
- },{
- path: 'list/todo',
- name: 'todo',
- meta: { title: '待办流程', icon: 'todo' }
- },{
- path: 'list/handled',
- name: 'handled',
- meta: { title: '办理过的', icon: 'flow-through-me' }
- },{
- path: 'create',
- name: 'create',
- component: () => import('@/views/flow/create'),
- hidden: true
- },{
- path: 'detail',
- name: 'detail',
- component: () => import('@/views/flow/create'),
- hidden: true
- }]
- }
+ redirect: "/flow/create",
+ hidden: true,
+ meta: { title: "流程", icon: "tree" },
+ children: [
+ {
+ path: "list/:type",
+ name: "flowList",
+ hidden: true,
+ component: () => import("@/views/flow/list.vue"),
+ },
+ {
+ path: "create",
+ name: "create",
+ component: () => import("@/views/flow/create"),
+ hidden: true,
+ },
+ {
+ path: "detail",
+ name: "detail",
+ component: () => import("@/views/flow/create"),
+ hidden: true,
+ },
+ ],
+ },
// 404 page must be placed at the end !!!
//{ path: '*', redirect: '/404', hidden: true }
-]
-export const asyncRoutes = [
-
-]
+];
+export const asyncRoutes = [];
-const createRouter = () => new Router({
- // mode: 'history', // require service support
- scrollBehavior: () => ({ y: 0 }),
- routes: constantRoutes,
-})
+const createRouter = () =>
+ new Router({
+ // mode: 'history', // require service support
+ scrollBehavior: () => ({ y: 0 }),
+ routes: constantRoutes,
+ });
-const router = createRouter()
+const router = createRouter();
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
- const newRouter = createRouter()
- router.matcher = newRouter.matcher // reset router
+ const newRouter = createRouter();
+ router.matcher = newRouter.matcher; // reset router
}
-export default router
+export default router;
diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js
index 0029e20..9f5f268 100644
--- a/src/store/modules/permission.js
+++ b/src/store/modules/permission.js
@@ -25,7 +25,7 @@ export function filterAsyncRoutes(routes) {
let tmp= {
key: `key-${route.id}`,
path: route.path === '#' ? '' : route.path,
- component: componentHandle(route.path, route),
+ component: componentHandle(route.url, route),
name: route.name,
hidden: !route.visible,
meta: {
diff --git a/src/utils/formBuilder.js b/src/utils/formBuilder.js
index 1e608bf..4e6e151 100644
--- a/src/utils/formBuilder.js
+++ b/src/utils/formBuilder.js
@@ -9,15 +9,16 @@ import { deepCopy } from "@/utils/index";
* @param {CreateElement} h
* @param {Object} row 子表单的row
* @param {Boolean} pWrite 主表单中子表单字段是否可写
+ * @param {Boolean} pReadable
* @return {VNode} 主表单包含el-form-item 子表单表单组件
**/
-export default function formBuilder(device, info, h, row, pWrite = false) {
+export default function formBuilder(device, info, h, row, pWrite = false,pReadable = false) {
let formItem;
//下拉选项
- if (info?.stub) {
- options = info?.stub?.split("|") || [];
- } else if (info?.selection_model) {
+ if (info?.selection_model) {
options = info.selection_model_items;
+ } else if (info?.stub) {
+ options = info?.stub?.split(/\n/) || [];
}
let options;
if (device === "desktop") {
@@ -238,6 +239,8 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
value: row ? row[info.name] : this.form[info.name],
clearable: true,
placeholder: info.help_text,
+ multiple: !!info.multiple,
+ 'multiple-limit': info.multiple,
},
style: {
width: "100%",
@@ -444,10 +447,15 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
value: row ? row[info.name] : this.form[info.name],
clearable: true,
placeholder: info.help_text,
+ multiple: !!info.multiple,
+ 'multiple-limit': info.multiple,
},
attrs: {
placeholder: info.help_text,
},
+ style: {
+ width: "100%",
+ },
on: {
input: (e) => {
row
@@ -459,8 +467,8 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
options.map((option) =>
h("el-option", {
props: {
- label: option,
- value: option,
+ label: typeof option === "object" ? option.name : option,
+ value: typeof option === "object" ? option.id : option,
},
})
)
@@ -479,6 +487,9 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
attrs: {
placeholder: info.help_text,
},
+ style: {
+ width: '100%'
+ },
on: {
input: (e) => {
row
@@ -615,7 +626,8 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
subField,
h,
row,
- info._writeable
+ info._writeable,
+ info._readable,
);
},
},
@@ -820,6 +832,7 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
on: {
click: (_) => {
this.vanCalendarOption.forFormName = info.name;
+ this.vanCalendarOption.originalObj = row;
this.$set(this.vanCalendarOption, "isShow", true);
},
},
@@ -839,32 +852,307 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
on: {
click: (_) => {
this.vanTimePickerOption.forFormName = info.name;
+ this.vanTimePickerOption.originalObj = row;
this.$set(this.vanTimePickerOption, "isShow", true);
},
},
});
break;
case "select":
+ let findValue = options.find((i) =>
+ typeof i === "object"
+ ? i.id === (row ? row[info.name] : this.form[info.name])
+ : i === (row ? row[info.name] : this.form[info.name])
+ );
formItem = h("van-field", {
props: {
readonly: true,
clickable: true,
name: info.name,
label: info.label,
- value: row ? row[info.name] : this.form[info.name],
+ value: typeof findValue === "object" ? findValue.name : findValue,
clearable: true,
placeholder: info.help_text,
},
on: {
click: (_) => {
this.vanPopupOption.forFormName = info.name;
+ this.vanPopupOption.originalObj = row;
this.$set(this.vanPopupOption, "columns", options);
this.$set(this.vanPopupOption, "isShow", true);
},
},
});
break;
+ case "file":
+ formItem = h('van-cell',{
+ props: {
+ title: info.label,
+ }
+ },[
+ h(
+ formBuilderMap(device).get(info.type),
+ {
+ props: {
+ action: process.env.VUE_APP_UPLOAD_API,
+ headers: {
+ Authorization: `Bearer ${getToken()}`,
+ },
+ accept:
+ "application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ 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) => {
+ fileList.forEach((file) => {
+ if (file.response?.data && !file.response?.code) {
+ file.response = file.response.data;
+ }
+ });
+ 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: "mini",
+ type: "primary",
+ },
+ },
+ "选取文件"
+ ),
+ h(
+ "div",
+ {
+ class: "el-upload__tip",
+ slot: "tip",
+ },
+ "文件不超过20Mb"
+ ),
+ ]
+ )
+ ])
+ break;
case "relation":
+ let copySubForm = deepCopy(this.form[info.name][0])
+ formItem = h("div", [
+ h("van-cell", {
+ props: {
+ "arrow-direction": "down",
+ title: info.label,
+ },
+ },[
+ h('van-button',{
+ props: {
+ type: 'info',
+ icon: 'plus',
+ size: 'small'
+ },
+ on: {
+ 'click':_ => {
+ this.form[info.name].push(copySubForm)
+ }
+ }
+ },'新增')
+ ]),
+ h(
+ "div",
+ this.form[info.name].map((sForm, sIndex) =>
+ h(
+ "van-cell-group",
+ {
+ props: {
+ inset: false
+ }
+ },
+ [
+ h("van-cell", {
+ props: {
+ title: info.label + "-" + (sIndex + 1)
+ }
+ },[
+ h('van-button',{
+ props: {
+ size: 'mini',
+ type: 'danger',
+ icon: 'minus'
+ },
+ on: {
+ click: _ => {
+ this.form[info.name].splice(sIndex, 1)
+ }
+ }
+ },'删除')
+ ]),
+ h(
+ "van-form",
+ {
+ props: {
+ "scroll-to-error": true,
+ },
+ style: {
+ margin: '0 10px'
+ }
+ },
+ Array.from(this.subForm)
+ .map((i) => i[1]?.customModel?.fields)
+ ?.flat()
+ .map((subField) =>
+ formBuilder.bind(this)(
+ device,
+ subField,
+ h,
+ sForm,
+ info._writeable,
+ )
+ )
+ ),
+ ]
+ )
+ )
+ ),
+ ]);
+ break;
+ }
+ } else if(info._readable || pReadable) {
+ switch (info.type) {
+ case "date":
+ formItem = h(
+ "van-cell",
+ {
+ props: {
+ title: info.label,
+ value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日") : ''
+ }
+ }
+ );
+ break;
+ case "datetime":
+ formItem = h(
+ "van-cell",
+ {
+ props: {
+ title: info.label,
+ value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日 HH时mm分ss秒") : ''
+ }
+ },
+ );
+ break;
+ case "select":
+ let findValue = options.find((i) =>
+ typeof i === "object"
+ ? i.id === this.form[info.name]
+ : i === this.form[info.name]
+ );
+ formItem = h(
+ "van-cell",
+ {
+ props: {
+ title: info.label,
+ value: typeof findValue === "object" ? findValue.name : findValue
+ }
+ },
+ );
+ break;
+ case 'file':
+ formItem = h(
+ "van-cell",
+ {
+ props: {
+ title: info.label,
+ }
+ },
+ this.file[info.name].map(file => h("div", {}, [
+ h(
+ "a",
+ {
+ attrs: {
+ href: file.url,
+ download: file.name,
+ },
+ class: {
+ "uploaded-a": file.status === "success",
+ },
+ style: {
+ padding: "0 4px",
+ },
+ },
+ file.name
+ ),
+ ]))
+ );
+ break
+ case 'relation':
formItem = h("div", [
h("van-cell", {
props: {
@@ -894,6 +1182,9 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
props: {
"scroll-to-error": true,
},
+ style: {
+ margin: '0 10px'
+ }
},
Array.from(this.subForm)
.map((i) => i[1]?.customModel?.fields)
@@ -904,7 +1195,8 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
subField,
h,
sForm,
- info._writeable
+ info._writeable,
+ info._readable
)
)
),
@@ -914,8 +1206,15 @@ export default function formBuilder(device, info, h, row, pWrite = false) {
),
]);
break;
+ default:
+ formItem = h('van-cell',{
+ props: {
+ title: info.label,
+ value: row ? row[info.name] : this.form[info.name]
+ }
+ })
}
- return formItem;
}
+ return formItem;
}
}
diff --git a/src/utils/formBuilderMap.js b/src/utils/formBuilderMap.js
index 246f7b8..a4067d2 100644
--- a/src/utils/formBuilderMap.js
+++ b/src/utils/formBuilderMap.js
@@ -22,7 +22,7 @@ export default function (device) {
['datetime', 'van-datetime-picker'],
['select', 'van-picker'],
['radio', 'van-radio-group'],
- ['file', 'van-uploader'],
+ ['file', 'el-upload'],
['label', 'van-tag'],
['static', 'el-link'],
['hr', 'van-divide'],
diff --git a/src/views/flow/MobileForm.vue b/src/views/flow/MobileForm.vue
index 19bc7fd..8424292 100644
--- a/src/views/flow/MobileForm.vue
+++ b/src/views/flow/MobileForm.vue
@@ -50,16 +50,19 @@ export default {
showControl: {},
vanCalendarOption: {
isShow: false,
- forFormName: ""
+ forFormName: "",
+ originalObj: ""
},
vanTimePickerOption: {
isShow: false,
- forFormName: ""
+ forFormName: "",
+ originalObj: ""
},
vanPopupOption: {
isShow: false,
forFormName: "",
- columns: []
+ columns: [],
+ originalObj: ""
}
}
},
@@ -112,9 +115,14 @@ export default {
on: {
input: e => {
this.$set(this.vanCalendarOption,'isShow',e)
+ this.$set(this.vanCalendarOption,'isShow',false)
},
confirm: date => {
- this.$set(this.form,this.vanCalendarOption.forFormName,moment(date).format('YYYY-MM-DD'))
+ if(typeof this.vanCalendarOption.originalObj === 'object') {
+ this.$set(this.vanCalendarOption.originalObj,this.vanCalendarOption.forFormName,moment(date).format('YYYY-MM-DD'))
+ } else {
+ this.$set(this.form,this.vanCalendarOption.forFormName,moment(date).format('YYYY-MM-DD'))
+ }
this.$set(this.vanCalendarOption,'isShow',false)
}
}
@@ -138,8 +146,13 @@ export default {
},
on: {
confirm: time => {
- this.$set(this.form,this.vanTimePickerOption.forFormName,moment(time).format('YYYY-MM-DD HH:mm:ss'))
-
+ if(typeof this.vanTimePickerOption.originalObj === 'object') {
+ console.log(this.vanTimePickerOption.originalObj)
+ this.$set(this.vanTimePickerOption.originalObj,this.vanTimePickerOption.forFormName,moment(time).format('YYYY-MM-DD HH:mm:ss'))
+ } else {
+ this.$set(this.form,this.vanTimePickerOption.forFormName,moment(time).format('YYYY-MM-DD HH:mm:ss'))
+ }
+ this.$set(this.vanTimePickerOption,'isShow',false)
},
cancel: _ => {
this.$set(this.vanTimePickerOption,'isShow',false)
@@ -168,7 +181,11 @@ export default {
},
on: {
confirm: value => {
- this.$set(this.form,this.vanPopupOption.forFormName,typeof value === 'object' ? value['id'] : value)
+ if(typeof this.vanPopupOption.originalObj === 'object') {
+ this.$set(this.vanPopupOption.originalObj,this.vanPopupOption.forFormName,typeof value === 'object' ? value['id'] : value)
+ } else {
+ this.$set(this.form,this.vanPopupOption.forFormName,typeof value === 'object' ? value['id'] : value)
+ }
this.$set(this.vanPopupOption,'isShow',false)
},
cancel: _ => {
diff --git a/src/views/flow/components/assign.vue b/src/views/flow/components/assign.vue
index d7ee3ff..91fdf54 100644
--- a/src/views/flow/components/assign.vue
+++ b/src/views/flow/components/assign.vue
@@ -46,15 +46,53 @@
承办人员
-
-
-
-
{{ group.name }}
-
{{ user.name }}
+
+
+
+
+
{{ group.name }}
+
{{ user.name }}
+
+
+
+
+
+
+
+
+
{{ group.name }}
+
{{ user.name }}
+
+
+
+
+
+
+
+
+
+
抄送人员
+
+
+
+ 全选
+
+
+
+
{{ group.name }}
+
{{ user.name }}{{ user.position ? `(${user.position})` : '' }}
+
+
+
+
+