diff --git a/package.json b/package.json index 4dca0f6..b8ba805 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "tinymce": "^5.10.7", "view-design": "^4.7.0", "vue": "2.6.10", + "vue-amap": "^0.5.10", "vue-count-to": "^1.0.13", "vue-router": "3.0.6", "vuedraggable": "^2.24.3", diff --git a/public/index.html b/public/index.html index 0daf6ee..c38cb27 100644 --- a/public/index.html +++ b/public/index.html @@ -12,7 +12,7 @@ securityJsCode: '0d59d0a3fa5483849b52b0edc4bc97ec', } - + diff --git a/src/api/system/customForm.js b/src/api/system/customForm.js index d9e9198..06d9c1c 100644 --- a/src/api/system/customForm.js +++ b/src/api/system/customForm.js @@ -65,3 +65,11 @@ export function relationDestroy(params) { params }) } + +export function clone (params) { + return request({ + method: 'get', + url: '/api/admin/custom-form/clone-table', + params + }) +} diff --git a/src/components/XyMap/index.vue b/src/components/XyMap/index.vue index a8546ed..08578f4 100644 --- a/src/components/XyMap/index.vue +++ b/src/components/XyMap/index.vue @@ -24,17 +24,22 @@ export default { watch: { map(newVal) { if(!newVal) return + let info = { + ...newVal, + latitude: newVal.location.lat, + longitude: newVal.location.lng, + } let res = '' if(typeof this.resultFormat === 'string') { - res = newVal[this.resultFormat] + res = info[this.resultFormat] } if(this.resultFormat instanceof Array) { - res = this.resultFormat.map(i => newVal[i])?.toString() + res = this.resultFormat.map(i => info[i])?.toString() } if(typeof this.resultFormat === 'object' && (!this.resultFormat instanceof Array)) { let obj = {} for(let key in this.resultFormat) { - obj[key] = newVal[this.resultFormat[key]] + obj[key] = info[this.resultFormat[key]] } res = obj; } diff --git a/src/components/XyTable/index.vue b/src/components/XyTable/index.vue index 26959ba..7e9e2a5 100644 --- a/src/components/XyTable/index.vue +++ b/src/components/XyTable/index.vue @@ -149,7 +149,7 @@ export default { }, btnWidth: { type: Number, - default: 200, + default: 220, }, // 分页相关 @@ -204,10 +204,9 @@ export default { return metrics.width; }, initLoad() { + if (this.height) return; let clientHeight = document.documentElement.clientHeight; - let lxheader = document - .querySelector(".v-header") - .getBoundingClientRect(); + let lxheader = document.querySelector(".v-header")?.getBoundingClientRect(); let lxHeader_height = lxheader.height + 25; //查询 头部 let paginationHeight = 37; //分页的高度 let topHeight = 50; //页面 头部 diff --git a/src/draggable.js b/src/draggable.js new file mode 100644 index 0000000..16e3989 --- /dev/null +++ b/src/draggable.js @@ -0,0 +1,59 @@ +import Vue from 'vue'; +export const defineDirective = () => { + Vue.directive('draggable', { + bind (el, binding) { + //是否移动端 + if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + return + } + + document.onselectstart = () => false + let dom = el + + el.onmousedown = e => { + e.stopPropagation(); + e.preventDefault(); + //鼠标按下,计算当前元素距离可视区的距离 + let disX = e.clientX - dom.offsetLeft; + let disY = e.clientY - dom.offsetTop; + document.onmousemove = e => { + binding.value(true) + e.stopPropagation(); + //通过事件委托,计算移动的距离 + let l = e.clientX - disX; + let t = e.clientY - disY; + //移动当前元素 + dom.style.left = l + "px" + dom.style.top = t + "px" + } + document.onmouseup = e => { + e.stopPropagation(); + document.onmousemove = null; + document.onmouseup = null; + let content = dom.getBoundingClientRect() + let {x,y} = content + let bkg = { width: window.innerWidth, height: window.innerHeight } + if(x < 0){ + dom.style.left = 0 + "px" + } + if(x > (bkg.width - content.width)){ + dom.style.left = (bkg.width - content.width) + "px" + } + if(y < 0){ + dom.style.top = 0 + "px" + } + if(y > (bkg.height - content.height)){ + dom.style.top = (bkg.height - content.height) + "px" + } + + + }; + el.onclick = e => { + binding.value(false) + } + //return false不加的话可能导致黏连,就是拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效 + //return false; + }; + }, + }) +} diff --git a/src/main.js b/src/main.js index 2d7aa25..f203997 100644 --- a/src/main.js +++ b/src/main.js @@ -89,7 +89,32 @@ Vue.prototype.$integrateData = (target,value) => { } } } +// 高德地图 +import AMap from 'vue-amap'; +Vue.use(AMap); +// 初始化vue-amap +AMap.initAMapApiLoader({ + // 高德的key + key: '795a757114c371f42cee1f8efa527684', + // 插件集合 (插件按需引入) + plugin: ['AMap.Autocomplete','AMap.Geocoder','AMap.PlaceSearch', 'AMap.Scale', 'AMap.OverView', 'AMap.ToolBar', 'AMap.MapType', + 'AMap.PolyEditor', 'AMap.CircleEditor', 'AMap.DistrictSearch','AMap.CircleMarker','AMap.Polyline','AMap.MarkerClusterer' + // 'AMap.Object3DLayer', 'AMap.Object3D' + ] +}); +//高德的安全密钥 +window._AMapSecurityConfig = { + securityJsCode: '0d59d0a3fa5483849b52b0edc4bc97ec', +} +// 解决地图刷新显示不出来 +const amapKeys = Object.keys(localStorage).filter(key => key.match(/^_AMap_/)) +amapKeys.forEach(key => { + // console.log(key) + localStorage.removeItem(key) +}) +import { defineDirective } from './draggable'; +defineDirective(); new Vue({ el: '#app', router, diff --git a/src/router/index.js b/src/router/index.js index 5e39379..395107a 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,112 +1,107 @@ -import Vue from 'vue' -import Router from 'vue-router' - -Vue.use(Router) - -/* Layout */ -import Layout from '@/layout' - -/** - * Note: sub-menu only appear when route children.length >= 1 - * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html - * - * hidden: true if set true, item will not show in the sidebar(default is false) - * alwaysShow: true if set true, will always show the root menu - * if not set alwaysShow, when item has more than one children route, - * it will becomes nested mode, otherwise not show the root menu - * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb - * name:'router-name' the name is used by (must set!!!) - * meta : { - roles: ['admin','editor'] control the page roles (you can set multiple roles) - title: 'title' the name show in sidebar and breadcrumb (recommend set) - icon: 'svg-name'/'el-icon-x' the icon show in the sidebar - breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) - activeMenu: '/example/list' if set path, the sidebar will highlight the path you set - } - */ - -/** - * constantRoutes - * a base page that does not have permission requirements - * all roles can be accessed - */ -export const constantRoutes = [{ - path: '/login', - component: () => import('@/views/login/index'), - hidden: true - }, - - { - path: '/404', - component: () => import('@/views/404'), - hidden: true - }, - { - path: '/test', - component: () => import('@/views/component/test.vue'), - hidden: true - }, - { - path: '/info', - component: Layout, - children: [{ - path: 'password', - component: () => import('@/views/system/password'), - name: '密码修改', - meta: { - title: '密码修改' - } - }], - hidden: true - }, - - { - path: '/', - component: Layout, - redirect: '/dashboard', - children: [{ - path: 'dashboard', - name: '系统首页', - component: () => import('@/views/dashboard/index'), - meta: { - title: '系统首页', - icon: 'dashboard' - } - }, ] - } +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +/* Layout */ +import Layout from '@/layout' + +/** + * Note: sub-menu only appear when route children.length >= 1 + * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html + * + * hidden: true if set true, item will not show in the sidebar(default is false) + * alwaysShow: true if set true, will always show the root menu + * if not set alwaysShow, when item has more than one children route, + * it will becomes nested mode, otherwise not show the root menu + * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb + * name:'router-name' the name is used by (must set!!!) + * meta : { + roles: ['admin','editor'] control the page roles (you can set multiple roles) + title: 'title' the name show in sidebar and breadcrumb (recommend set) + icon: 'svg-name'/'el-icon-x' the icon show in the sidebar + breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) + activeMenu: '/example/list' if set path, the sidebar will highlight the path you set + } + */ + +/** + * constantRoutes + * a base page that does not have permission requirements + * all roles can be accessed + */ +export const constantRoutes = [{ + path: '/login', + component: () => import('@/views/login/index'), + hidden: true + }, + + { + path: '/404', + component: () => import('@/views/404'), + hidden: true + }, + { + path: '/info', + component: Layout, + children: [{ + path: 'password', + component: () => import('@/views/system/password'), + name: '密码修改', + meta: { + title: '密码修改' + } + }], + hidden: true + }, + + { + path: '/', + component: Layout, + redirect: '/dashboard', + children: [{ + path: 'dashboard', + name: '系统首页', + component: () => import('@/views/dashboard/index'), + meta: { + title: '系统首页', + icon: 'dashboard' + } + }, ] + } ] - - -/** - * asyncRoutes - * the routes that need to be dynamically loaded based on user roles - */ -export const asyncRoutes = [ - - - // 404 page must be placed at the end !!! - { - path: '*', - redirect: '/404', - hidden: true - } -] - -const createRouter = () => new Router({ - // mode: 'history', // require service support - scrollBehavior: () => ({ - y: 0 - }), - routes: constantRoutes -}) - -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 -} - + + +/** + * asyncRoutes + * the routes that need to be dynamically loaded based on user roles + */ +export const asyncRoutes = [ + + + // 404 page must be placed at the end !!! + { + path: '*', + redirect: '/404', + hidden: true + } +] + +const createRouter = () => new Router({ + // mode: 'history', // require service support + scrollBehavior: () => ({ + y: 0 + }), + routes: constantRoutes +}) + +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 +} + export default router diff --git a/src/store/modules/form.js b/src/store/modules/form.js index 4ffde47..0c2fa4e 100644 --- a/src/store/modules/form.js +++ b/src/store/modules/form.js @@ -1,5 +1,7 @@ -import { save, index, destroy } from "@/api/system/customFormField"; -import { Message } from "element-ui"; +import {index} from "@/api/system/customFormField"; +import {show,save} from "@/api/system/customForm"; +import {Message} from "element-ui"; + const state = { formList: [], //更个表单配置信息 copyFormListId: [], //备份原始的字段id数组,以做删除 @@ -37,31 +39,50 @@ const mutations = { }; const actions = { - submit: ({ state, commit }) => { + submit: ({ state, commit }, tableId) => { return new Promise((resolve, reject) => { - state.formList.forEach((item,index) => { - item.sort = index + 1 - }) - let formListId = state.formList.filter((i) => !!i.id).map((i) => i.id); - let deleteIds = state.copyFormListId.filter( - (i) => !formListId.includes(i) - ); - let promiseAll = [ - ...state.formList.map((i) => save(i)), - ...deleteIds.map((i) => destroy({ id: i })), - ]; - Promise.all(promiseAll) - .then((res) => { + show({ id: tableId }).then(res => { + state.formList.forEach((item,index) => { + item.sort = index + 1 + }) + res.fields = state.formList + save(res).then(res1 => { Message({ - type: "success", - message: "保存成功", - }); - resolve(res); + type: 'success', + message: res1.msg + }) + resolve(res1) + }).catch(err1 => { + reject(err1) }) - .catch((err) => { - reject(err); - }); - }); + }).catch(err => { + reject(err) + }) + }) + // return new Promise((resolve, reject) => { + // state.formList.forEach((item,index) => { + // item.sort = index + 1 + // }) + // let formListId = state.formList.filter((i) => !!i.id).map((i) => i.id); + // let deleteIds = state.copyFormListId.filter( + // (i) => !formListId.includes(i) + // ); + // let promiseAll = [ + // ...state.formList.map((i) => save(i)), + // ...deleteIds.map((i) => destroy({ id: i })), + // ]; + // Promise.all(promiseAll) + // .then((res) => { + // Message({ + // type: "success", + // message: "保存成功", + // }); + // resolve(res); + // }) + // .catch((err) => { + // reject(err); + // }); + // }); }, getFormList: ({ state, commit }, custom_form_id) => { return new Promise((resolve, reject) => { diff --git a/src/views/assets/assetsHistory.vue b/src/views/assets/assetsHistory.vue new file mode 100644 index 0000000..f20a2fe --- /dev/null +++ b/src/views/assets/assetsHistory.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/src/views/component/detail.vue b/src/views/component/detail.vue index 5f01508..599b63b 100644 --- a/src/views/component/detail.vue +++ b/src/views/component/detail.vue @@ -13,16 +13,206 @@ @back="$router.back()" > + + + + +
图集
+ + + + + +
+ + + {{ + contentFormat(item) + }} + + +
+ + +
资产历史
+ + + {{activity.content}} + + +
+
+
diff --git a/src/views/component/dialog.vue b/src/views/component/dialog.vue index ab17c76..ee53b4b 100644 --- a/src/views/component/dialog.vue +++ b/src/views/component/dialog.vue @@ -1,8 +1,9 @@ + + + diff --git a/src/views/component/table.vue b/src/views/component/table.vue index 81573e3..b67f58b 100644 --- a/src/views/component/table.vue +++ b/src/views/component/table.vue @@ -248,8 +248,12 @@ :table-item="table" @detail=" (row) => { - $refs['drawer'].setId(row.id); - $refs['drawer'].show(); + $router.push({ + path: '/assetsDetail', + query: { + id: row.id + } + }) } " @editor=" @@ -260,6 +264,14 @@ } " > + + @@ -300,6 +313,7 @@ import LxHeader from "@/components/LxHeader/index.vue"; import headerContent from "@/components/LxHeader/XyContent.vue"; import drawer from "@/views/component/drawer.vue"; import imports from "./imports.vue"; +import assetsHistory from "@/views/assets/assetsHistory.vue"; export default { components: { LxHeader, @@ -307,6 +321,8 @@ export default { headerContent, drawer, imports, + + assetsHistory }, mixins: [authMixin], provide: { @@ -411,16 +427,7 @@ export default { ['admins',[]] ]) let { fields, relation } = res; - let fieldRes = (await fieldIndex( - { - page: 1, - page_size: 999, - custom_form_id: this.customForm.customFormId, - sort_name: "sort", - sort_type: "asc", - }, - false - )).data; + let fieldRes = fields.sort((a,b) => a.sort - b.sort) if ( !fields || !relation || @@ -431,27 +438,37 @@ export default { } console.log(fieldRes) fieldRes?.forEach((i, index) => { - i._relations = relation.find((j) => j.local_key === i.field); - if (i.select_item && typeof i.select_item === 'object') { - let keys = Object.keys(i.select_item) - i._params = keys.map(key => { + i._relations = relation.find( + (j) => j.link_table_name.split("_")[1] === i.field + ); + if (i.select_item && typeof i.select_item === "object") { + let keys = Object.keys(i.select_item); + i._params = keys.map((key) => { return { key, - value: i.select_item[key] - } - }) + value: /^\d*$/.test(i.select_item[key]) + ? Number(i.select_item[key]) + : i.select_item[key], + }; + }); } if (i.edit_input === 'file' || i.edit_input === 'files') { return } if (i._relations) { if (baseTable.get(i._relations.link_table_name)) { - baseTable.get(i._relations.link_table_name)().then(res => i._params = res) + baseTable + .get(i._relations.link_table_name)() + .then((res) => { + i._params = res.data; + }); } else { i._params = i._relations.parameter_id - ? getparameter({ id: i._relations.parameter_id },false).then((res) => { - i._params = res.detail; - }) + ? getparameter({ id: i._relations.parameter_id }, false).then( + (res) => { + i._params = res.detail; + } + ) : this.index({ table_name: i._relations.link_table_name, page: 1, @@ -462,32 +479,41 @@ export default { } } }); - this.form = fields; - console.log(111, this.form); - this.table = this.form + this.form = fieldRes || []; + this.form ?.filter((i) => i.list_show) - .map((i) => { + .forEach((i) => { let linkOb = {}; - if (i.select_item && typeof i.select_item === 'object') { - let keys = Object.keys(i.select_item) - linkOb.customFn = row => { - let paramMap = new Map() - keys.forEach(key => { - paramMap.set(i.select_item[key],key) - }) - + if (i.edit_input === "richtext") { + linkOb.customFn = (row) => { return ( - - { paramMap.get(row[i.field]?.toString()) } - - ) - } +
+ ); + }; + } + if ( + i.select_item && + typeof i.select_item === "object" && + !(i.select_item instanceof Array) + ) { + let keys = Object.keys(i.select_item); + linkOb.customFn = (row) => { + let paramMap = new Map(); + keys.forEach((key) => { + paramMap.set(i.select_item[key], key); + }); + + return {paramMap.get(row[i.field]?.toString())}; + }; } if (i._relations) { - let { link_relation, foreign_key, link_with_name } = i._relations - if (link_relation === 'newHasOne' || link_relation === 'hasOne') { - linkOb.customFn = row => { + let { link_relation, foreign_key, link_with_name } = i._relations; + if (link_relation === "newHasOne" || link_relation === "hasOne") { + linkOb.customFn = (row) => { if (i.edit_input === "file") { return ( - { row[link_with_name]?.name || + {row[link_with_name]?.name || row[link_with_name]?.no || - row[link_with_name]?.value } + row[link_with_name]?.value} ); } - } + }; } - if (link_relation === "hasMany" || link_relation === 'newHasMany') { + if (link_relation === "hasMany" || link_relation === "newHasMany") { linkOb.customFn = (row) => { - return ( -
- {row[link_with_name]?.map((o) => ( - {o?.name || o?.no || o?.value} - ))} -
- ); + if (i.edit_input === "files") { + return ( +
+ {row[link_with_name]?.map((o) => ( + + { o?.original_name || o?.name } + + ))} +
+ ) + } else { + return ( +
+ {row[link_with_name]?.map((o) => ( +

+ {o?.name || + o?.no || + o?.value || + o?.biaoti || + o?.mingcheng} +

+ ))} +
+ ); + } }; } } - return Object.assign( - { - prop: i.field, - label: i.name, - width: i.width, - fixed: i.is_fixed, - }, - linkOb + this.table.push( + Object.assign( + { + prop: i.field, + label: i.name, + width: i.width, + fixed: i.is_fixed, + }, + linkOb + ) ); }); this.table.unshift({ diff --git a/src/views/component/test.vue b/src/views/component/test.vue deleted file mode 100644 index 2d811d8..0000000 --- a/src/views/component/test.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - diff --git a/src/views/system/components/formEditor.vue b/src/views/system/components/formEditor.vue index c436d4b..3333018 100644 --- a/src/views/system/components/formEditor.vue +++ b/src/views/system/components/formEditor.vue @@ -234,7 +234,7 @@ export default { }, submit() { - this.$store.dispatch("form/submit").then((res) => { + this.$store.dispatch("form/submit",this.custom_form_id).then((res) => { setTimeout(() => { update({ id: this.custom_form_id }) .then((res) => { diff --git a/src/views/system/form.vue b/src/views/system/form.vue index 6001fb6..ed4f05a 100644 --- a/src/views/system/form.vue +++ b/src/views/system/form.vue @@ -3,12 +3,28 @@
- +
- - + +
@@ -22,20 +38,48 @@ :destroy-action="destroy" :border="true" :table-item="table" - @editor="row => { - $refs['addForm'].setType('editor'); - $refs['addForm'].setId(row.id); - $refs['addForm'].show(); - }"> + @editor=" + (row) => { + $refs['addForm'].setType('editor'); + $refs['addForm'].setId(row.id); + $refs['addForm'].show(); + } + " + > @@ -46,7 +90,7 @@