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 }} + +
+ + +
@@ -67,7 +105,7 @@