Commit 9ab6f4b663d8853476cdd57c3011d3b5e8098f8e
1 parent
0304e06a
Jeecg-Boot 2.2.0 版本发布 | 重磅升级
Showing
335 changed files
with
18928 additions
and
10839 deletions
Too many changes to show.
To preserve performance only 40 of 335 files are displayed.
.github/ISSUE_TEMPLATE.md
0 → 100644
README.md
... | ... | @@ -7,12 +7,12 @@ |
7 | 7 | Jeecg-Boot 快速开发平台(前后端分离版本) |
8 | 8 | =============== |
9 | 9 | |
10 | -当前最新版本: 2.1.4(发布日期:2020-02-24) | |
10 | +当前最新版本: 2.2.0(发布日期:2020-05-06) | |
11 | 11 | |
12 | 12 | |
13 | 13 | [](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE) |
14 | 14 | [](http://www.jeecg.com) |
15 | -[](https://github.com/zhangdaiscott/jeecg-boot) | |
15 | +[](https://github.com/zhangdaiscott/jeecg-boot) | |
16 | 16 | [](https://github.com/zhangdaiscott/jeecg-boot) |
17 | 17 | [](https://github.com/zhangdaiscott/jeecg-boot) |
18 | 18 | |
... | ... |
ant-design-vue-jeecg/README.md
ant-design-vue-jeecg/idea.config.js
... | ... | @@ -6,19 +6,19 @@ function resolve (dir) { |
6 | 6 | } |
7 | 7 | |
8 | 8 | module.exports = { |
9 | - context: path.resolve(__dirname, './'), | |
10 | - resolve: { | |
11 | - extensions: ['.js', '.vue', '.json'], | |
12 | - alias: { | |
13 | - 'config': resolve('config'), | |
14 | - '@': resolve('src'), | |
15 | - '@views': resolve('src/views'), | |
16 | - '@comp': resolve('src/components'), | |
17 | - '@core': resolve('src/core'), | |
18 | - '@utils': resolve('src/utils'), | |
19 | - '@entry': resolve('src/entry'), | |
20 | - '@router': resolve('src/router'), | |
21 | - '@store': resolve('src/store') | |
22 | - } | |
23 | - } | |
24 | -} | |
9 | + context: path.resolve(__dirname, './'), | |
10 | + resolve: { | |
11 | + extensions: ['.js', '.vue', '.json'], | |
12 | + alias: { | |
13 | + 'config': resolve('config'), | |
14 | + '@': resolve('src'), | |
15 | + '@views': resolve('src/views'), | |
16 | + '@comp': resolve('src/components'), | |
17 | + '@core': resolve('src/core'), | |
18 | + '@utils': resolve('src/utils'), | |
19 | + '@entry': resolve('src/entry'), | |
20 | + '@router': resolve('src/router'), | |
21 | + '@store': resolve('src/store') | |
22 | + } | |
23 | + }, | |
24 | +} | |
25 | 25 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/package.json
1 | 1 | { |
2 | 2 | "name": "vue-antd-jeecg", |
3 | - "version": "2.1.4", | |
3 | + "version": "2.2.0", | |
4 | 4 | "private": true, |
5 | 5 | "scripts": { |
6 | - "pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ", | |
6 | + "pre": "yarn --registry https://registry.npm.taobao.org || cnpm install || npm install --registry https://registry.npm.taobao.org ", | |
7 | 7 | "serve": "vue-cli-service serve", |
8 | 8 | "build": "vue-cli-service build", |
9 | 9 | "lint": "vue-cli-service lint" |
10 | 10 | }, |
11 | 11 | "dependencies": { |
12 | - "@antv/data-set": "^0.10.2", | |
13 | - "@jeecg/antd-online-214": "^2.1.41", | |
12 | + "@antv/data-set": "^0.11.2", | |
13 | + "@jeecg/antd-online-beta220": "^1.0.1", | |
14 | 14 | "@tinymce/tinymce-vue": "^2.0.0", |
15 | - "ant-design-vue": "^1.4.11", | |
16 | - "apexcharts": "^3.6.5", | |
15 | + "ant-design-vue": "^1.5.2", | |
16 | + "area-data": "^5.0.6", | |
17 | 17 | "axios": "^0.18.0", |
18 | 18 | "clipboard": "^2.0.4", |
19 | 19 | "codemirror": "^5.46.0", |
... | ... | @@ -25,22 +25,20 @@ |
25 | 25 | "md5": "^2.2.1", |
26 | 26 | "nprogress": "^0.2.0", |
27 | 27 | "tinymce": "^5.1.4", |
28 | + "tui-editor": "^1.4.10", | |
28 | 29 | "viser-vue": "^2.4.4", |
29 | 30 | "vue": "^2.6.10", |
30 | - "vue-apexcharts": "^1.3.2", | |
31 | - "vue-class-component": "^6.0.0", | |
31 | + "vue-area-linkage": "^5.1.0", | |
32 | 32 | "vue-cropper": "^0.4.8", |
33 | 33 | "vue-i18n": "^8.7.0", |
34 | 34 | "vue-loader": "^15.7.0", |
35 | 35 | "vue-ls": "^3.2.0", |
36 | 36 | "vue-photo-preview": "^1.1.3", |
37 | 37 | "vue-print-nb-jeecg": "^1.0.9", |
38 | - "vue-property-decorator": "^7.3.0", | |
39 | 38 | "vue-router": "^3.0.1", |
40 | 39 | "vue-splitpane": "^1.0.4", |
41 | 40 | "vuedraggable": "^2.20.0", |
42 | - "vuex": "^3.0.1", | |
43 | - "vuex-class": "^0.3.1" | |
41 | + "vuex": "^3.1.0" | |
44 | 42 | }, |
45 | 43 | "devDependencies": { |
46 | 44 | "@babel/polyfill": "^7.2.5", |
... | ... | @@ -49,9 +47,10 @@ |
49 | 47 | "@vue/cli-service": "^3.3.0", |
50 | 48 | "@vue/eslint-config-standard": "^4.0.0", |
51 | 49 | "babel-eslint": "^10.0.1", |
50 | + "compression-webpack-plugin": "^3.1.0", | |
52 | 51 | "eslint": "^5.16.0", |
53 | 52 | "eslint-plugin-vue": "^5.1.0", |
54 | - "html-webpack-plugin": "^4.0.0-beta.11", | |
53 | + "html-webpack-plugin": "^4.2.0", | |
55 | 54 | "less": "^3.9.0", |
56 | 55 | "less-loader": "^4.1.0", |
57 | 56 | "vue-template-compiler": "^2.6.10" |
... | ... | @@ -91,7 +90,7 @@ |
91 | 90 | "vue/no-use-v-if-with-v-for": 0, |
92 | 91 | "vue/html-closing-bracket-newline": 0, |
93 | 92 | "vue/no-parsing-error": 0, |
94 | - "no-console": 0, | |
93 | + "no-console": 0, | |
95 | 94 | "no-tabs": 0, |
96 | 95 | "indent": [1, 4] |
97 | 96 | } |
... | ... |
ant-design-vue-jeecg/public/color.less
... | ... | @@ -7679,3 +7679,23 @@ font.medium { |
7679 | 7679 | font.weak { |
7680 | 7680 | color: #f5222d; |
7681 | 7681 | } |
7682 | + | |
7683 | + | |
7684 | +// begin -------- JAreaLinkage 三级联动样式 -------------- | |
7685 | +.cascader-menu-list .cascader-menu-option.hover, | |
7686 | +.cascader-menu-list .cascader-menu-option:hover { | |
7687 | + background-color: color(~`colorPalette("@{primary-color}", 1)`); | |
7688 | +} | |
7689 | + | |
7690 | +.area-selectable-list .area-select-option.hover { | |
7691 | + background-color: color(~`colorPalette("@{primary-color}", 1)`); | |
7692 | +} | |
7693 | + | |
7694 | +.area-select:hover { | |
7695 | + border-color: @primary-color; | |
7696 | +} | |
7697 | + | |
7698 | +.area-select:active { | |
7699 | + box-shadow: 0 0 0 2px color(~`colorPalette("@{primary-color}", 1)`); | |
7700 | +} | |
7701 | +// end -------- JAreaLinkage 三级联动样式 -------------- | |
7682 | 7702 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/api/GroupRequest.js
0 → 100644
1 | +import Vue from 'vue' | |
2 | + | |
3 | +/** | |
4 | + * 将一个请求分组 | |
5 | + * | |
6 | + * @param getPromise 传入一个可以获取到Promise对象的方法 | |
7 | + * @param groupId 分组ID,如果不传或者为空则不分组 | |
8 | + * @param expire 过期时间,默认 半分钟 | |
9 | + */ | |
10 | +export function httpGroupRequest(getPromise, groupId, expire = 1000 * 30) { | |
11 | + if (groupId == null || groupId === '') { | |
12 | + console.log("--------popup----------getFrom DB-------with---no--groupId ") | |
13 | + return getPromise() | |
14 | + } | |
15 | + | |
16 | + if (Vue.ls.get(groupId)) { | |
17 | + console.log("---------popup--------getFrom Cache--------groupId = " + groupId) | |
18 | + return Promise.resolve(Vue.ls.get(groupId)); | |
19 | + } else { | |
20 | + console.log("--------popup----------getFrom DB---------groupId = " + groupId) | |
21 | + } | |
22 | + | |
23 | + // 还没有发出请求,就发出第一次的请求 | |
24 | + return getPromise().then(res => { | |
25 | + Vue.ls.set(groupId, res, expire); | |
26 | + return Promise.resolve(res); | |
27 | + }) | |
28 | +} | |
29 | + | |
30 | + | |
... | ... |
ant-design-vue-jeecg/src/api/api.js
1 | -import { getAction,deleteAction,putAction,postAction} from '@/api/manage' | |
1 | +import { getAction, deleteAction, putAction, postAction, httpAction } from '@/api/manage' | |
2 | +import Vue from 'vue' | |
3 | +import {UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types" | |
2 | 4 | |
3 | -////根路径 | |
4 | -// const doMian = "/jeecg-boot/"; | |
5 | -////图片预览请求地址 | |
6 | -// const imgView = "http://localhost:8080/jeecg-boot/sys/common/view/"; | |
7 | 5 | |
8 | 6 | //角色管理 |
9 | 7 | const addRole = (params)=>postAction("/sys/role/add",params); |
10 | 8 | const editRole = (params)=>putAction("/sys/role/edit",params); |
11 | -// const getRoleList = (params)=>getAction("/sys/role/list",params); | |
12 | -// const deleteRole = (params)=>deleteAction("/sys/role/delete",params); | |
13 | -// const deleteRoleList = (params)=>deleteAction("/sys/role/deleteBatch",params); | |
14 | 9 | const checkRoleCode = (params)=>getAction("/sys/role/checkRoleCode",params); |
15 | 10 | const queryall = (params)=>getAction("/sys/role/queryall",params); |
16 | 11 | |
... | ... | @@ -19,8 +14,6 @@ const addUser = (params)=>postAction("/sys/user/add",params); |
19 | 14 | const editUser = (params)=>putAction("/sys/user/edit",params); |
20 | 15 | const queryUserRole = (params)=>getAction("/sys/user/queryUserRole",params); |
21 | 16 | const getUserList = (params)=>getAction("/sys/user/list",params); |
22 | -// const deleteUser = (params)=>deleteAction("/sys/user/delete",params); | |
23 | -// const deleteUserList = (params)=>deleteAction("/sys/user/deleteBatch",params); | |
24 | 17 | const frozenBatch = (params)=>putAction("/sys/user/frozenBatch",params); |
25 | 18 | //验证用户是否存在 |
26 | 19 | const checkOnlyUser = (params)=>getAction("/sys/user/checkOnlyUser",params); |
... | ... | @@ -31,20 +24,15 @@ const changePassword = (params)=>putAction("/sys/user/changePassword",params); |
31 | 24 | const addPermission= (params)=>postAction("/sys/permission/add",params); |
32 | 25 | const editPermission= (params)=>putAction("/sys/permission/edit",params); |
33 | 26 | const getPermissionList = (params)=>getAction("/sys/permission/list",params); |
34 | -/*update_begin author:wuxianquan date:20190908 for:添加查询一级菜单和子菜单查询api */ | |
35 | 27 | const getSystemMenuList = (params)=>getAction("/sys/permission/getSystemMenuList",params); |
36 | 28 | const getSystemSubmenu = (params)=>getAction("/sys/permission/getSystemSubmenu",params); |
37 | 29 | const getSystemSubmenuBatch = (params) => getAction('/sys/permission/getSystemSubmenuBatch', params) |
38 | -/*update_end author:wuxianquan date:20190908 for:添加查询一级菜单和子菜单查询api */ | |
39 | 30 | |
40 | -// const deletePermission = (params)=>deleteAction("/sys/permission/delete",params); | |
41 | -// const deletePermissionList = (params)=>deleteAction("/sys/permission/deleteBatch",params); | |
42 | 31 | const queryTreeList = (params)=>getAction("/sys/permission/queryTreeList",params); |
43 | 32 | const queryTreeListForRole = (params)=>getAction("/sys/role/queryTreeList",params); |
44 | 33 | const queryListAsync = (params)=>getAction("/sys/permission/queryListAsync",params); |
45 | 34 | const queryRolePermission = (params)=>getAction("/sys/permission/queryRolePermission",params); |
46 | 35 | const saveRolePermission = (params)=>postAction("/sys/permission/saveRolePermission",params); |
47 | -//const queryPermissionsByUser = (params)=>getAction("/sys/permission/queryByUser",params); | |
48 | 36 | const queryPermissionsByUser = (params)=>getAction("/sys/permission/getUserPermissionByToken",params); |
49 | 37 | const loadAllRoleIds = (params)=>getAction("/sys/permission/loadAllRoleIds",params); |
50 | 38 | const getPermissionRuleList = (params)=>getAction("/sys/permission/getPermRuleListByPermId",params); |
... | ... | @@ -66,24 +54,26 @@ const saveDeptRolePermission = (params)=>postAction("/sys/sysDepartPermission/sa |
66 | 54 | const queryMyDepartTreeList = (params)=>getAction("/sys/sysDepart/queryMyDeptTreeList",params); |
67 | 55 | |
68 | 56 | //日志管理 |
69 | -//const getLogList = (params)=>getAction("/sys/log/list",params); | |
70 | 57 | const deleteLog = (params)=>deleteAction("/sys/log/delete",params); |
71 | 58 | const deleteLogList = (params)=>deleteAction("/sys/log/deleteBatch",params); |
72 | 59 | |
73 | 60 | //数据字典 |
74 | 61 | const addDict = (params)=>postAction("/sys/dict/add",params); |
75 | 62 | const editDict = (params)=>putAction("/sys/dict/edit",params); |
76 | -//const getDictList = (params)=>getAction("/sys/dict/list",params); | |
77 | 63 | const treeList = (params)=>getAction("/sys/dict/treeList",params); |
78 | -// const delDict = (params)=>deleteAction("/sys/dict/delete",params); | |
79 | -//const getDictItemList = (params)=>getAction("/sys/dictItem/list",params); | |
80 | 64 | const addDictItem = (params)=>postAction("/sys/dictItem/add",params); |
81 | 65 | const editDictItem = (params)=>putAction("/sys/dictItem/edit",params); |
82 | -//const delDictItem = (params)=>deleteAction("/sys/dictItem/delete",params); | |
83 | -//const delDictItemList = (params)=>deleteAction("/sys/dictItem/deleteBatch",params); | |
84 | 66 | |
85 | 67 | //字典标签专用(通过code获取字典数组) |
86 | 68 | export const ajaxGetDictItems = (code, params)=>getAction(`/sys/dict/getDictItems/${code}`,params); |
69 | +//从缓存中获取字典配置 | |
70 | +function getDictItemsFromCache(dictCode) { | |
71 | + if (Vue.ls.get(UI_CACHE_DB_DICT_DATA) && Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode]) { | |
72 | + let dictItems = Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode]; | |
73 | + console.log("-----------getDictItemsFromCache----------dictCode="+dictCode+"---- dictItems=",dictItems) | |
74 | + return dictItems; | |
75 | + } | |
76 | +} | |
87 | 77 | |
88 | 78 | //系统通告 |
89 | 79 | const doReleaseData = (params)=>getAction("/sys/annountCement/doReleaseData",params); |
... | ... | @@ -91,23 +81,18 @@ const doReovkeData = (params)=>getAction("/sys/annountCement/doReovkeData",param |
91 | 81 | //获取系统访问量 |
92 | 82 | const getLoginfo = (params)=>getAction("/sys/loginfo",params); |
93 | 83 | const getVisitInfo = (params)=>getAction("/sys/visitInfo",params); |
94 | -//数据日志访问 | |
95 | -// const getDataLogList = (params)=>getAction("/sys/dataLog/list",params); | |
96 | 84 | |
97 | 85 | // 根据部门主键查询用户信息 |
98 | 86 | const queryUserByDepId = (params)=>getAction("/sys/user/queryUserByDepId",params); |
99 | - | |
100 | -// 查询用户角色表里的所有信息 | |
101 | -const queryUserRoleMap = (params)=>getAction("/sys/user/queryUserRoleMap",params); | |
102 | 87 | // 重复校验 |
103 | 88 | const duplicateCheck = (params)=>getAction("/sys/duplicate/check",params); |
104 | 89 | // 加载分类字典 |
105 | 90 | const loadCategoryData = (params)=>getAction("/sys/category/loadAllData",params); |
106 | 91 | const checkRuleByCode = (params) => getAction('/sys/checkRule/checkByCode', params) |
92 | +//我的通告 | |
93 | +const getUserNoticeInfo= (params)=>getAction("/sys/sysAnnouncementSend/getMyAnnouncementSend",params); | |
107 | 94 | |
108 | 95 | export { |
109 | - // imgView, | |
110 | - // doMian, | |
111 | 96 | addRole, |
112 | 97 | editRole, |
113 | 98 | checkRoleCode, |
... | ... | @@ -147,7 +132,6 @@ export { |
147 | 132 | getLoginfo, |
148 | 133 | getVisitInfo, |
149 | 134 | queryUserByDepId, |
150 | - queryUserRoleMap, | |
151 | 135 | duplicateCheck, |
152 | 136 | queryTreeListForRole, |
153 | 137 | getSystemMenuList, |
... | ... | @@ -160,7 +144,9 @@ export { |
160 | 144 | queryTreeListForDeptRole, |
161 | 145 | queryDeptRolePermission, |
162 | 146 | saveDeptRolePermission, |
163 | - queryMyDepartTreeList | |
147 | + queryMyDepartTreeList, | |
148 | + getUserNoticeInfo, | |
149 | + getDictItemsFromCache | |
164 | 150 | } |
165 | 151 | |
166 | 152 | |
... | ... |
ant-design-vue-jeecg/src/api/login.js
... | ... | @@ -55,4 +55,19 @@ export function logout(logoutToken) { |
55 | 55 | 'X-Access-Token': logoutToken |
56 | 56 | } |
57 | 57 | }) |
58 | +} | |
59 | + | |
60 | +/** | |
61 | + * 第三方登录 | |
62 | + * @param token | |
63 | + * @returns {*} | |
64 | + */ | |
65 | +export function thirdLogin(token) { | |
66 | + return axios({ | |
67 | + url: `/thirdLogin/getLoginUser/${token}`, | |
68 | + method: 'get', | |
69 | + headers: { | |
70 | + 'Content-Type': 'application/json;charset=UTF-8' | |
71 | + } | |
72 | + }) | |
58 | 73 | } |
59 | 74 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/api/manage.js
1 | +import Vue from 'vue' | |
1 | 2 | import { axios } from '@/utils/request' |
2 | 3 | |
3 | 4 | const api = { |
... | ... | @@ -113,16 +114,64 @@ export function downFile(url,parameter){ |
113 | 114 | } |
114 | 115 | |
115 | 116 | /** |
116 | - * 获取文件访问路径 | |
117 | + * 下载文件 | |
118 | + * @param url 文件路径 | |
119 | + * @param fileName 文件名 | |
120 | + * @param parameter | |
121 | + * @returns {*} | |
122 | + */ | |
123 | +export function downloadFile(url, fileName, parameter) { | |
124 | + return downFile(url, parameter).then((data) => { | |
125 | + if (!data || data.size === 0) { | |
126 | + Vue.prototype['$message'].warning('文件下载失败') | |
127 | + return | |
128 | + } | |
129 | + if (typeof window.navigator.msSaveBlob !== 'undefined') { | |
130 | + window.navigator.msSaveBlob(new Blob([data]), fileName) | |
131 | + } else { | |
132 | + let url = window.URL.createObjectURL(new Blob([data])) | |
133 | + let link = document.createElement('a') | |
134 | + link.style.display = 'none' | |
135 | + link.href = url | |
136 | + link.setAttribute('download', fileName) | |
137 | + document.body.appendChild(link) | |
138 | + link.click() | |
139 | + document.body.removeChild(link) //下载完成移除元素 | |
140 | + window.URL.revokeObjectURL(url) //释放掉blob对象 | |
141 | + } | |
142 | + }) | |
143 | +} | |
144 | + | |
145 | +/** | |
146 | + * 文件上传 用于富文本上传图片 | |
147 | + * @param url | |
148 | + * @param parameter | |
149 | + * @returns {*} | |
150 | + */ | |
151 | +export function uploadAction(url,parameter){ | |
152 | + return axios({ | |
153 | + url: url, | |
154 | + data: parameter, | |
155 | + method:'post' , | |
156 | + headers: { | |
157 | + 'Content-Type': 'multipart/form-data', // 文件上传 | |
158 | + }, | |
159 | + }) | |
160 | +} | |
161 | + | |
162 | +/** | |
163 | + * 获取文件服务访问路径 | |
117 | 164 | * @param avatar |
118 | - * @param imgerver | |
119 | - * @param str | |
165 | + * @param subStr | |
120 | 166 | * @returns {*} |
121 | 167 | */ |
122 | -export function getFileAccessHttpUrl(avatar,imgerver,subStr) { | |
123 | - if(avatar && avatar.indexOf(subStr) != -1 ){ | |
168 | +export function getFileAccessHttpUrl(avatar,subStr) { | |
169 | + if(!subStr) subStr = 'http' | |
170 | + if(avatar && avatar.startsWith(subStr)){ | |
124 | 171 | return avatar; |
125 | 172 | }else{ |
126 | - return imgerver + "/" + avatar; | |
173 | + if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){ | |
174 | + return window._CONFIG['staticDomainURL'] + "/" + avatar; | |
175 | + } | |
127 | 176 | } |
128 | 177 | } |
... | ... |
ant-design-vue-jeecg/src/assets/less/JAreaLinkage.less
0 → 100644
1 | +.area-zoom-in-top-enter-active, | |
2 | +.area-zoom-in-top-leave-active { | |
3 | + opacity: 1; | |
4 | + transform: scaleY(1); | |
5 | +} | |
6 | + | |
7 | +.area-zoom-in-top-enter, | |
8 | +.area-zoom-in-top-leave-active { | |
9 | + opacity: 0; | |
10 | + transform: scaleY(0); | |
11 | +} | |
12 | + | |
13 | +.area-select { | |
14 | + box-sizing: border-box; | |
15 | + margin: 0; | |
16 | + padding: 0; | |
17 | + color: rgba(0, 0, 0, 0.65); | |
18 | + font-size: 14px; | |
19 | + font-variant: tabular-nums; | |
20 | + line-height: 1.5; | |
21 | + list-style: none; | |
22 | + font-feature-settings: 'tnum'; | |
23 | + position: relative; | |
24 | + outline: 0; | |
25 | + display: block; | |
26 | + background-color: #fff; | |
27 | + border: 1px solid #d9d9d9; | |
28 | + border-top-width: 1.02px; | |
29 | + border-radius: 4px; | |
30 | + outline: none; | |
31 | + transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); | |
32 | + -webkit-user-select: none; | |
33 | + -ms-user-select: none; | |
34 | + user-select: none; | |
35 | +} | |
36 | + | |
37 | +.area-select-wrap .area-select { | |
38 | + display: inline-block; | |
39 | +} | |
40 | + | |
41 | +.area-select * { | |
42 | + box-sizing: border-box; | |
43 | +} | |
44 | + | |
45 | +.area-select:hover { | |
46 | + border-color: #40a9ff; | |
47 | + border-right-width: 1px !important; | |
48 | + outline: 0; | |
49 | +} | |
50 | + | |
51 | + | |
52 | +.area-select:active { | |
53 | + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | |
54 | +} | |
55 | + | |
56 | +.area-select.small { | |
57 | + width: 126px; | |
58 | +} | |
59 | + | |
60 | +.area-select.medium { | |
61 | + width: 160px; | |
62 | +} | |
63 | + | |
64 | +.area-select.large { | |
65 | + width: 194px; | |
66 | +} | |
67 | + | |
68 | +.area-select.is-disabled { | |
69 | + background: #eceff5; | |
70 | + cursor: not-allowed; | |
71 | +} | |
72 | + | |
73 | +.area-select.is-disabled:hover { | |
74 | + border-color: #e1e2e6; | |
75 | +} | |
76 | + | |
77 | +.area-select.is-disabled .area-selected-trigger { | |
78 | + cursor: not-allowed; | |
79 | +} | |
80 | + | |
81 | +.area-select .area-selected-trigger { | |
82 | + position: relative; | |
83 | + display: block; | |
84 | + font-size: 14px; | |
85 | + cursor: pointer; | |
86 | + margin: 0; | |
87 | + overflow: hidden; | |
88 | + white-space: nowrap; | |
89 | + text-overflow: ellipsis; | |
90 | + height: 100%; | |
91 | + padding: 8px 20px 7px 12px; | |
92 | +} | |
93 | + | |
94 | +.area-select .area-select-icon { | |
95 | + position: absolute; | |
96 | + top: 50%; | |
97 | + margin-top: -2px; | |
98 | + right: 6px; | |
99 | + content: ""; | |
100 | + width: 0; | |
101 | + height: 0; | |
102 | + border: 6px solid transparent; | |
103 | + border-top-color: rgba(0, 0, 0, 0.25); | |
104 | + transition: all .3s linear; | |
105 | + transform-origin: center; | |
106 | +} | |
107 | + | |
108 | +.area-select .area-select-icon.active { | |
109 | + margin-top: -8px; | |
110 | + transform: rotate(180deg); | |
111 | +} | |
112 | + | |
113 | +.area-selectable-list-wrap { | |
114 | + position: absolute; | |
115 | + width: 100%; | |
116 | + max-height: 275px; | |
117 | + z-index: 15000; | |
118 | + background-color: #fff; | |
119 | + box-sizing: border-box; | |
120 | + overflow-x: auto; | |
121 | + margin: 2px 0; | |
122 | + border-radius: 4px; | |
123 | + outline: none; | |
124 | + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | |
125 | + | |
126 | + transition: opacity 0.15s, transform 0.3s !important; | |
127 | + transform-origin: center top !important; | |
128 | +} | |
129 | + | |
130 | +.area-selectable-list { | |
131 | + position: relative; | |
132 | + margin: 0; | |
133 | + padding: 6px 0; | |
134 | + width: 100%; | |
135 | + font-size: 14px; | |
136 | + color: #565656; | |
137 | + list-style: none; | |
138 | +} | |
139 | + | |
140 | +.area-selectable-list .area-select-option { | |
141 | + position: relative; | |
142 | + white-space: nowrap; | |
143 | + overflow: hidden; | |
144 | + text-overflow: ellipsis; | |
145 | + cursor: pointer; | |
146 | + padding: 0 15px 0 10px; | |
147 | + height: 32px; | |
148 | + line-height: 32px; | |
149 | +} | |
150 | + | |
151 | +.area-selectable-list .area-select-option.hover { | |
152 | + background-color: #e6f7ff; | |
153 | +} | |
154 | + | |
155 | +.area-selectable-list .area-select-option.selected { | |
156 | + color: rgba(0, 0, 0, 0.65); | |
157 | + font-weight: 600; | |
158 | + background-color: #efefef; | |
159 | +} | |
160 | + | |
161 | +.cascader-menu-list-wrap { | |
162 | + position: absolute; | |
163 | + white-space: nowrap; | |
164 | + z-index: 15000; | |
165 | + background-color: #fff; | |
166 | + box-sizing: border-box; | |
167 | + overflow: hidden; | |
168 | + font-size: 0; | |
169 | + margin: 2px 0; | |
170 | + border-radius: 4px; | |
171 | + outline: none; | |
172 | + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | |
173 | + | |
174 | + transition: opacity 0.15s, transform 0.3s !important; | |
175 | + transform-origin: center top !important; | |
176 | +} | |
177 | + | |
178 | +.cascader-menu-list { | |
179 | + position: relative; | |
180 | + margin: 0; | |
181 | + font-size: 14px; | |
182 | + color: #565656; | |
183 | + padding: 6px 0; | |
184 | + list-style: none; | |
185 | + display: inline-block; | |
186 | + height: 204px; | |
187 | + overflow-x: hidden; | |
188 | + overflow-y: auto; | |
189 | + min-width: 160px; | |
190 | + vertical-align: top; | |
191 | + background-color: #fff; | |
192 | + border-right: 1px solid #e4e7ed; | |
193 | +} | |
194 | + | |
195 | +.cascader-menu-list:last-child { | |
196 | + border-right: none; | |
197 | +} | |
198 | + | |
199 | +.cascader-menu-list .cascader-menu-option { | |
200 | + position: relative; | |
201 | + white-space: nowrap; | |
202 | + overflow: hidden; | |
203 | + text-overflow: ellipsis; | |
204 | + cursor: pointer; | |
205 | + padding: 0 15px 0 10px; | |
206 | + height: 32px; | |
207 | + line-height: 32px; | |
208 | +} | |
209 | + | |
210 | +.cascader-menu-list .cascader-menu-option.hover, | |
211 | +.cascader-menu-list .cascader-menu-option:hover { | |
212 | + background-color: #e6f7ff; | |
213 | +} | |
214 | + | |
215 | +.cascader-menu-list .cascader-menu-option.selected { | |
216 | + color: rgba(0, 0, 0, 0.65); | |
217 | + font-weight: 600; | |
218 | + background-color: #efefef; | |
219 | +} | |
220 | + | |
221 | +.cascader-menu-list .cascader-menu-option.cascader-menu-extensible:after { | |
222 | + position: absolute; | |
223 | + top: 50%; | |
224 | + margin-top: -4px; | |
225 | + right: 5px; | |
226 | + content: ""; | |
227 | + width: 0; | |
228 | + height: 0; | |
229 | + border: 4px solid transparent; | |
230 | + border-left-color: #a1a4ad; | |
231 | +} | |
232 | + | |
233 | +.cascader-menu-list::-webkit-scrollbar, | |
234 | +.area-selectable-list-wrap::-webkit-scrollbar { | |
235 | + width: 8px; | |
236 | + background: transparent; | |
237 | +} | |
238 | + | |
239 | +.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:decremen, | |
240 | +.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:end:decrement, | |
241 | +.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:increment, | |
242 | +.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:start:increment, | |
243 | +.cascader-menu-list::-webkit-scrollbar-button:vertical:decremen, | |
244 | +.cascader-menu-list::-webkit-scrollbar-button:vertical:end:decrement, | |
245 | +.cascader-menu-list::-webkit-scrollbar-button:vertical:increment, | |
246 | +.cascader-menu-list::-webkit-scrollbar-button:vertical:start:increment { | |
247 | + display: none; | |
248 | +} | |
249 | + | |
250 | +.cascader-menu-list::-webkit-scrollbar-thumb:vertical, | |
251 | +.area-selectable-list-wrap::-webkit-scrollbar-thumb:vertical { | |
252 | + background-color: #b8b8b8; | |
253 | + border-radius: 4px; | |
254 | +} | |
255 | + | |
256 | +.cascader-menu-list::-webkit-scrollbar-thumb:vertical:hover, | |
257 | +.area-selectable-list-wrap::-webkit-scrollbar-thumb:vertical:hover { | |
258 | + background-color: #777; | |
259 | +} | |
0 | 260 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/assets/less/TableExpand.less
0 → 100644
1 | +/** [表格主题样式一] 表格强制列不换行 */ | |
2 | +.j-table-force-nowrap { | |
3 | + td, th { | |
4 | + white-space: nowrap; | |
5 | + } | |
6 | + | |
7 | + .ant-table-selection-column { | |
8 | + padding: 12px 22px !important; | |
9 | + } | |
10 | + | |
11 | + /** 列自适应,弊端会导致列宽失效 */ | |
12 | + &.ant-table-wrapper .ant-table-content { | |
13 | + overflow-x: auto; | |
14 | + } | |
15 | +} | |
... | ... |
ant-design-vue-jeecg/src/assets/less/common.less
1 | 1 | |
2 | 2 | /*列表上方操作按钮区域*/ |
3 | 3 | .ant-card-body .table-operator { |
4 | - margin-bottom: 18px; | |
4 | + margin-bottom: 8px; | |
5 | 5 | } |
6 | 6 | /** Button按钮间距 */ |
7 | 7 | .table-operator .ant-btn { |
8 | - margin: 8px 8px 0 0; | |
8 | + margin: 0 8px 8px 0; | |
9 | +} | |
10 | +.table-operator .ant-btn-group .ant-btn { | |
11 | + margin: 0; | |
12 | +} | |
13 | + | |
14 | +.table-operator .ant-btn-group .ant-btn:last-child { | |
15 | + margin: 0 8px 8px 0; | |
9 | 16 | } |
10 | 17 | /*列表td的padding设置 可以控制列表大小*/ |
11 | 18 | .ant-table-tbody .ant-table-row td { |
... | ... | @@ -45,3 +52,7 @@ |
45 | 52 | /*erp风格子表外框padding设置*/ |
46 | 53 | .ant-card-wider-padding.cust-erp-sub-tab>.ant-card-body{padding:5px 12px} |
47 | 54 | |
55 | +/* 内嵌子表背景颜色 */ | |
56 | +.j-inner-table-wrapper /deep/ .ant-table-expanded-row .ant-table-wrapper .ant-table-tbody .ant-table-row { | |
57 | + background-color: #FFFFFF; | |
58 | +} | |
48 | 59 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/cas/sso.js
... | ... | @@ -8,14 +8,14 @@ const init = (callback) => { |
8 | 8 | console.log("-------单点登录开始-------"); |
9 | 9 | let token = Vue.ls.get(ACCESS_TOKEN); |
10 | 10 | let st = getUrlParam("ticket"); |
11 | - var sevice = "http://"+window.location.host+"/"; | |
11 | + let sevice = "http://"+window.location.host+"/"; | |
12 | 12 | if(token){ |
13 | 13 | loginSuccess(callback); |
14 | 14 | }else{ |
15 | 15 | if(st){ |
16 | 16 | validateSt(st,sevice,callback); |
17 | 17 | }else{ |
18 | - var serviceUrl = encodeURIComponent(sevice); | |
18 | + let serviceUrl = encodeURIComponent(sevice); | |
19 | 19 | window.location.href = window._CONFIG['casPrefixUrl']+"/login?service="+serviceUrl; |
20 | 20 | } |
21 | 21 | } |
... | ... | @@ -26,14 +26,14 @@ const SSO = { |
26 | 26 | }; |
27 | 27 | |
28 | 28 | function getUrlParam(paraName) { |
29 | - var url = document.location.toString(); | |
30 | - var arrObj = url.split("?"); | |
29 | + let url = document.location.toString(); | |
30 | + let arrObj = url.split("?"); | |
31 | 31 | |
32 | 32 | if (arrObj.length > 1) { |
33 | - var arrPara = arrObj[1].split("&"); | |
34 | - var arr; | |
33 | + let arrPara = arrObj[1].split("&"); | |
34 | + let arr; | |
35 | 35 | |
36 | - for (var i = 0; i < arrPara.length; i++) { | |
36 | + for (let i = 0; i < arrPara.length; i++) { | |
37 | 37 | arr = arrPara[i].split("="); |
38 | 38 | |
39 | 39 | if (arr != null && arr[0] == paraName) { |
... | ... | @@ -57,8 +57,8 @@ function validateSt(ticket,service,callback){ |
57 | 57 | if(res.success){ |
58 | 58 | loginSuccess(callback); |
59 | 59 | }else{ |
60 | - var sevice = "http://"+window.location.host+"/"; | |
61 | - var serviceUrl = encodeURIComponent(sevice); | |
60 | + let sevice = "http://"+window.location.host+"/"; | |
61 | + let serviceUrl = encodeURIComponent(sevice); | |
62 | 62 | window.location.href = window._CONFIG['casPrefixUrl']+"/login?service="+serviceUrl; |
63 | 63 | } |
64 | 64 | }).catch((err) => { |
... | ... |
ant-design-vue-jeecg/src/components/Ellipsis/Ellipsis.vue
1 | 1 | <script> |
2 | - import Tooltip from 'ant-design-vue/es/tooltip' | |
3 | 2 | import { cutStrByFullLength, getStrFullLength } from '@/components/_util/StringUtil' |
4 | -/* | |
5 | - const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined; | |
6 | - | |
7 | - const TooltipOverlayStyle = { | |
8 | - overflowWrap: 'break-word', | |
9 | - wordWrap: 'break-word', | |
10 | - }; | |
11 | -*/ | |
12 | 3 | |
13 | 4 | export default { |
14 | 5 | name: 'Ellipsis', |
15 | - components: { | |
16 | - Tooltip | |
17 | - }, | |
18 | 6 | props: { |
19 | 7 | prefixCls: { |
20 | 8 | type: String, |
21 | 9 | default: 'ant-pro-ellipsis' |
22 | 10 | }, |
23 | 11 | tooltip: { |
24 | - type: Boolean | |
12 | + type: Boolean, | |
13 | + default: true, | |
25 | 14 | }, |
26 | 15 | length: { |
27 | 16 | type: Number, |
28 | - required: true | |
17 | + default: 25, | |
29 | 18 | }, |
30 | 19 | lines: { |
31 | 20 | type: Number, |
... | ... | @@ -36,28 +25,25 @@ |
36 | 25 | default: false |
37 | 26 | } |
38 | 27 | }, |
39 | - methods: { | |
40 | - getStrDom (str) { | |
41 | - return ( | |
42 | - <span>{ cutStrByFullLength(str, this.length) + '...' }</span> | |
43 | - ) | |
44 | - }, | |
45 | - getTooltip ( fullStr) { | |
28 | + methods: {}, | |
29 | + render() { | |
30 | + const { tooltip, length } = this.$props | |
31 | + let text = '' | |
32 | + // 处理没有default插槽时的特殊情况 | |
33 | + if (this.$slots.default) { | |
34 | + text = this.$slots.default.map(vNode => vNode.text).join('') | |
35 | + } | |
36 | + // 判断是否显示 tooltip | |
37 | + if (tooltip && getStrFullLength(text) > length) { | |
46 | 38 | return ( |
47 | - <Tooltip> | |
48 | - <template slot="title">{ fullStr }</template> | |
49 | - { this.getStrDom(fullStr) } | |
50 | - </Tooltip> | |
39 | + <a-tooltip> | |
40 | + <template slot="title">{text}</template> | |
41 | + <span>{cutStrByFullLength(text, this.length) + '…'}</span> | |
42 | + </a-tooltip> | |
51 | 43 | ) |
44 | + } else { | |
45 | + return (<span>{text}</span>) | |
52 | 46 | } |
53 | - }, | |
54 | - render () { | |
55 | - const { tooltip, length } = this.$props | |
56 | - let str = this.$slots.default.map(vNode => vNode.text).join("") | |
57 | - const strDom = tooltip && getStrFullLength(str) > length ? this.getTooltip(str) : this.getStrDom(str); | |
58 | - return ( | |
59 | - strDom | |
60 | - ) | |
61 | 47 | } |
62 | 48 | } |
63 | 49 | </script> |
64 | 50 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/_util/Area.js
0 → 100644
1 | +import { pcaa } from 'area-data' | |
2 | + | |
3 | +/** | |
4 | + * 省市区 | |
5 | + */ | |
6 | +export default class Area { | |
7 | + /** | |
8 | + * 构造器 | |
9 | + * @param express | |
10 | + */ | |
11 | + constructor() { | |
12 | + let arr = [] | |
13 | + const province = pcaa['86'] | |
14 | + Object.keys(province).map(key=>{ | |
15 | + arr.push({id:key, text:province[key], pid:'86'}); | |
16 | + const city = pcaa[key]; | |
17 | + Object.keys(city).map(key2=>{ | |
18 | + arr.push({id:key2, text:city[key2], pid:key}); | |
19 | + const qu = pcaa[key2]; | |
20 | + Object.keys(qu).map(key3=>{ | |
21 | + arr.push({id:key3, text:qu[key3], pid:key2}); | |
22 | + }) | |
23 | + }) | |
24 | + }) | |
25 | + this.all = arr; | |
26 | + } | |
27 | + | |
28 | + get pca(){ | |
29 | + return this.all; | |
30 | + } | |
31 | + | |
32 | + getCode(text){ | |
33 | + if(!text || text.length==0){ | |
34 | + return '' | |
35 | + } | |
36 | + for(let item of this.all){ | |
37 | + if(item.text === text){ | |
38 | + return item.id; | |
39 | + } | |
40 | + } | |
41 | + } | |
42 | + | |
43 | + getText(code){ | |
44 | + if(!code || code.length==0){ | |
45 | + return '' | |
46 | + } | |
47 | + let arr = [] | |
48 | + this.getAreaBycode(code,arr); | |
49 | + return arr.join('/') | |
50 | + } | |
51 | + | |
52 | + getRealCode(code){ | |
53 | + let arr = [] | |
54 | + this.getPcode(code, arr) | |
55 | + return arr; | |
56 | + } | |
57 | + | |
58 | + getPcode(id, arr){ | |
59 | + for(let item of this.all){ | |
60 | + if(item.id === id){ | |
61 | + arr.unshift(id) | |
62 | + if(item.pid != '86'){ | |
63 | + this.getPcode(item.pid,arr) | |
64 | + } | |
65 | + } | |
66 | + } | |
67 | + } | |
68 | + | |
69 | + getAreaBycode(code,arr){ | |
70 | + //console.log("this.all.length",this.all) | |
71 | + for(let item of this.all){ | |
72 | + if(item.id === code){ | |
73 | + arr.unshift(item.text); | |
74 | + this.getAreaBycode(item.pid,arr) | |
75 | + } | |
76 | + } | |
77 | + } | |
78 | + | |
79 | +} | |
0 | 80 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/chart/StackBar.vue
0 → 100644
1 | +<template> | |
2 | + <div> | |
3 | + <v-chart :forceFit="true" :height="height" :data="data"> | |
4 | + <v-coord type="rect" direction="LB" /> | |
5 | + <v-tooltip /> | |
6 | + <v-legend /> | |
7 | + <v-axis dataKey="State" :label="label" /> | |
8 | + <v-stack-bar position="State*流程数量" color="流程状态" /> | |
9 | + </v-chart> | |
10 | + </div> | |
11 | + | |
12 | +</template> | |
13 | + | |
14 | +<script> | |
15 | + const DataSet = require('@antv/data-set'); | |
16 | + | |
17 | + export default { | |
18 | + name: 'StackBar', | |
19 | + props: { | |
20 | + dataSource: { | |
21 | + type: Array, | |
22 | + required: true, | |
23 | + default: () => [ | |
24 | + { 'State': '请假', '流转中': 25, '已归档': 18 }, | |
25 | + { 'State': '出差', '流转中': 30, '已归档': 20 }, | |
26 | + { 'State': '加班', '流转中': 38, '已归档': 42}, | |
27 | + { 'State': '用车', '流转中': 51, '已归档': 67} | |
28 | + ] | |
29 | + }, | |
30 | + height: { | |
31 | + type: Number, | |
32 | + default: 254 | |
33 | + } | |
34 | + }, | |
35 | + data() { | |
36 | + return { | |
37 | + label: { offset: 12 } | |
38 | + } | |
39 | + }, | |
40 | + computed: { | |
41 | + data() { | |
42 | + const dv = new DataSet.View().source(this.dataSource); | |
43 | + dv.transform({ | |
44 | + type: 'fold', | |
45 | + fields: ['流转中', '已归档'], | |
46 | + key: '流程状态', | |
47 | + value: '流程数量', | |
48 | + retains: ['State'], | |
49 | + }); | |
50 | + return dv.rows; | |
51 | + } | |
52 | + } | |
53 | + } | |
54 | +</script> | |
0 | 55 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/chart/chart.scss deleted
ant-design-vue-jeecg/src/components/dict/JDictSelectTag.vue
... | ... | @@ -3,6 +3,10 @@ |
3 | 3 | <a-radio v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio> |
4 | 4 | </a-radio-group> |
5 | 5 | |
6 | + <a-radio-group v-else-if="tagType=='radioButton'" buttonStyle="solid" @change="handleInput" :value="getValueSting" :disabled="disabled"> | |
7 | + <a-radio-button v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio-button> | |
8 | + </a-radio-group> | |
9 | + | |
6 | 10 | <a-select v-else-if="tagType=='select'" :getPopupContainer = "(target) => target.parentNode" :placeholder="placeholder" :disabled="disabled" :value="getValueSting" @change="handleInput"> |
7 | 11 | <a-select-option :value="undefined">请选择</a-select-option> |
8 | 12 | <a-select-option v-for="(item, key) in dictOptions" :key="key" :value="item.value"> |
... | ... | @@ -14,7 +18,7 @@ |
14 | 18 | </template> |
15 | 19 | |
16 | 20 | <script> |
17 | - import {ajaxGetDictItems} from '@/api/api' | |
21 | + import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api' | |
18 | 22 | |
19 | 23 | export default { |
20 | 24 | name: "JDictSelectTag", |
... | ... | @@ -52,11 +56,17 @@ |
52 | 56 | }, |
53 | 57 | computed: { |
54 | 58 | getValueSting(){ |
55 | - return this.value ? this.value.toString() : null; | |
59 | + return this.value != null ? this.value.toString() : null; | |
56 | 60 | }, |
57 | 61 | }, |
58 | 62 | methods: { |
59 | 63 | initDictData() { |
64 | + //优先从缓存中读取字典配置 | |
65 | + if(getDictItemsFromCache(this.dictCode)){ | |
66 | + this.dictOptions = getDictItemsFromCache(this.dictCode); | |
67 | + return | |
68 | + } | |
69 | + | |
60 | 70 | //根据字典Code, 初始化字典数组 |
61 | 71 | ajaxGetDictItems(this.dictCode, null).then((res) => { |
62 | 72 | if (res.success) { |
... | ... |
ant-design-vue-jeecg/src/components/dict/JDictSelectUtil.js
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | * date: 20190109 |
5 | 5 | */ |
6 | 6 | |
7 | -import {ajaxGetDictItems} from '@/api/api' | |
7 | +import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api' | |
8 | 8 | import {getAction} from '@/api/manage' |
9 | 9 | |
10 | 10 | /** |
... | ... | @@ -16,6 +16,13 @@ export async function initDictOptions(dictCode) { |
16 | 16 | if (!dictCode) { |
17 | 17 | return '字典Code不能为空!'; |
18 | 18 | } |
19 | + //优先从缓存中读取字典配置 | |
20 | + if(getDictItemsFromCache(dictCode)){ | |
21 | + let res = {} | |
22 | + res.result = getDictItemsFromCache(dictCode); | |
23 | + res.success = true; | |
24 | + return res; | |
25 | + } | |
19 | 26 | //获取字典数组 |
20 | 27 | let res = await ajaxGetDictItems(dictCode); |
21 | 28 | return res; |
... | ... | @@ -28,16 +35,25 @@ export async function initDictOptions(dictCode) { |
28 | 35 | * @return String |
29 | 36 | */ |
30 | 37 | export function filterDictText(dictOptions, text) { |
31 | - //--update-begin----author:sunjianlei---date:20191025------for:修复字典替换方法在字典没有加载完成之前报错的问题、修复没有找到字典时返回空值的问题--- | |
32 | - if (dictOptions instanceof Array) { | |
33 | - for (let dictItem of dictOptions) { | |
34 | - if (text === dictItem.value) { | |
35 | - return dictItem.text | |
38 | + // --update-begin----author:sunjianlei---date:20200323------for: 字典翻译 text 允许逗号分隔 --- | |
39 | + if (text != null && dictOptions instanceof Array) { | |
40 | + let result = [] | |
41 | + // 允许多个逗号分隔 | |
42 | + let splitText = text.toString().trim().split(',') | |
43 | + for (let txt of splitText) { | |
44 | + let dictText = txt | |
45 | + for (let dictItem of dictOptions) { | |
46 | + if (txt === dictItem.value.toString()) { | |
47 | + dictText = dictItem.text | |
48 | + break | |
49 | + } | |
36 | 50 | } |
51 | + result.push(dictText) | |
37 | 52 | } |
53 | + return result.join(',') | |
38 | 54 | } |
39 | 55 | return text |
40 | -//--update-end----author:sunjianlei---date:20191025------for:修复字典替换方法在字典没有加载完成之前报错的问题、修复没有找到字典时返回空值的问题--- | |
56 | + // --update-end----author:sunjianlei---date:20200323------for: 字典翻译 text 允许逗号分隔 --- | |
41 | 57 | } |
42 | 58 | |
43 | 59 | /** |
... | ... | @@ -49,24 +65,28 @@ export function filterDictText(dictOptions, text) { |
49 | 65 | export function filterMultiDictText(dictOptions, text) { |
50 | 66 | //js “!text” 认为0为空,所以做提前处理 |
51 | 67 | if(text === 0 || text === '0'){ |
52 | - for (let dictItem of dictOptions) { | |
53 | - if (text == dictItem.value) { | |
54 | - return dictItem.text | |
68 | + if(dictOptions){ | |
69 | + for (let dictItem of dictOptions) { | |
70 | + if (text == dictItem.value) { | |
71 | + return dictItem.text | |
72 | + } | |
55 | 73 | } |
56 | 74 | } |
57 | 75 | } |
58 | 76 | |
59 | - if(!text || !dictOptions || dictOptions.length==0){ | |
77 | + if(!text || text=='null' || !dictOptions || dictOptions.length==0){ | |
60 | 78 | return "" |
61 | 79 | } |
62 | 80 | let re = ""; |
63 | 81 | text = text.toString() |
64 | 82 | let arr = text.split(",") |
65 | 83 | dictOptions.forEach(function (option) { |
66 | - for(let i=0;i<arr.length;i++){ | |
67 | - if (arr[i] === option.value) { | |
68 | - re += option.text+","; | |
69 | - break; | |
84 | + if(option){ | |
85 | + for(let i=0;i<arr.length;i++){ | |
86 | + if (arr[i] === option.value) { | |
87 | + re += option.text+","; | |
88 | + break; | |
89 | + } | |
70 | 90 | } |
71 | 91 | } |
72 | 92 | }); |
... | ... | @@ -81,20 +101,42 @@ export function filterMultiDictText(dictOptions, text) { |
81 | 101 | * @param children |
82 | 102 | * @returns string |
83 | 103 | */ |
84 | -export async function ajaxFilterDictText(dictCode, key) { | |
104 | +export function filterDictTextByCache(dictCode, key) { | |
105 | + if(key==null ||key.length==0){ | |
106 | + return; | |
107 | + } | |
85 | 108 | if (!dictCode) { |
86 | 109 | return '字典Code不能为空!'; |
87 | 110 | } |
88 | - //console.log(`key : ${key}`); | |
89 | - if (!key) { | |
90 | - return ''; | |
91 | - } | |
92 | - //通过请求读取字典文本 | |
93 | - let res = await getAction(`/sys/dict/getDictText/${dictCode}/${key}`); | |
94 | - if (res.success) { | |
95 | - // console.log('restult: '+ res.result); | |
96 | - return res.result; | |
97 | - } else { | |
98 | - return ''; | |
111 | + //优先从缓存中读取字典配置 | |
112 | + if(getDictItemsFromCache(dictCode)){ | |
113 | + let item = getDictItemsFromCache(dictCode).filter(t => t["value"] == key) | |
114 | + if(item && item.length>0){ | |
115 | + return item[0]["text"] | |
116 | + } | |
99 | 117 | } |
118 | +} | |
119 | + | |
120 | +/** 通过code获取字典数组 */ | |
121 | +export async function getDictItems(dictCode, params) { | |
122 | + //优先从缓存中读取字典配置 | |
123 | + if(getDictItemsFromCache(dictCode)){ | |
124 | + let desformDictItems = getDictItemsFromCache(dictCode).map(item => ({...item, label: item.text})) | |
125 | + return desformDictItems; | |
126 | + } | |
127 | + | |
128 | + //缓存中没有,就请求后台 | |
129 | + return await ajaxGetDictItems(dictCode, params).then(({success, result}) => { | |
130 | + if (success) { | |
131 | + let res = result.map(item => ({...item, label: item.text})) | |
132 | + console.log('------- 从DB中获取到了字典-------dictCode : ', dictCode, res) | |
133 | + return Promise.resolve(res) | |
134 | + } else { | |
135 | + console.error('getDictItems error: : ', res) | |
136 | + return Promise.resolve([]) | |
137 | + } | |
138 | + }).catch((res) => { | |
139 | + console.error('getDictItems error: ', res) | |
140 | + return Promise.resolve([]) | |
141 | + }) | |
100 | 142 | } |
101 | 143 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/dict/JMultiSelectTag.vue
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | :disabled="disabled" |
11 | 11 | mode="multiple" |
12 | 12 | :placeholder="placeholder" |
13 | + :getPopupContainer="(node) => node.parentNode" | |
13 | 14 | allowClear> |
14 | 15 | <a-select-option |
15 | 16 | v-for="(item,index) in dictOptions" |
... | ... | @@ -24,7 +25,7 @@ |
24 | 25 | </template> |
25 | 26 | |
26 | 27 | <script> |
27 | - import {ajaxGetDictItems} from '@/api/api' | |
28 | + import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api' | |
28 | 29 | export default { |
29 | 30 | name: 'JMultiSelectTag', |
30 | 31 | props: { |
... | ... | @@ -49,12 +50,18 @@ |
49 | 50 | this.tagType = this.type |
50 | 51 | } |
51 | 52 | //获取字典数据 |
52 | - this.initDictData(); | |
53 | + //this.initDictData(); | |
53 | 54 | }, |
54 | 55 | watch:{ |
55 | 56 | options: function(val){ |
56 | 57 | this.setCurrentDictOptions(val); |
57 | 58 | }, |
59 | + dictCode:{ | |
60 | + immediate:true, | |
61 | + handler() { | |
62 | + this.initDictData() | |
63 | + }, | |
64 | + }, | |
58 | 65 | value (val) { |
59 | 66 | if(!val){ |
60 | 67 | this.arrayValue = [] |
... | ... | @@ -68,6 +75,11 @@ |
68 | 75 | if(this.options && this.options.length>0){ |
69 | 76 | this.dictOptions = [...this.options] |
70 | 77 | }else{ |
78 | + //优先从缓存中读取字典配置 | |
79 | + if(getDictItemsFromCache(this.dictCode)){ | |
80 | + this.dictOptions = getDictItemsFromCache(this.dictCode); | |
81 | + return | |
82 | + } | |
71 | 83 | //根据字典Code, 初始化字典数组 |
72 | 84 | ajaxGetDictItems(this.dictCode, null).then((res) => { |
73 | 85 | if (res.success) { |
... | ... |
ant-design-vue-jeecg/src/components/dict/JSearchSelectTag.vue
... | ... | @@ -4,6 +4,8 @@ |
4 | 4 | v-if="async" |
5 | 5 | showSearch |
6 | 6 | labelInValue |
7 | + :disabled="disabled" | |
8 | + :getPopupContainer="(node) => node.parentNode" | |
7 | 9 | @search="loadData" |
8 | 10 | :placeholder="placeholder" |
9 | 11 | v-model="selectedAsyncValue" |
... | ... | @@ -19,7 +21,9 @@ |
19 | 21 | |
20 | 22 | <a-select |
21 | 23 | v-else |
24 | + :getPopupContainer="(node) => node.parentNode" | |
22 | 25 | showSearch |
26 | + :disabled="disabled" | |
23 | 27 | :placeholder="placeholder" |
24 | 28 | optionFilterProp="children" |
25 | 29 | style="width: 100%" |
... | ... | @@ -35,7 +39,7 @@ |
35 | 39 | </template> |
36 | 40 | |
37 | 41 | <script> |
38 | - import { ajaxGetDictItems } from '@/api/api' | |
42 | + import { ajaxGetDictItems,getDictItemsFromCache } from '@/api/api' | |
39 | 43 | import debounce from 'lodash/debounce'; |
40 | 44 | import { getAction } from '../../api/manage' |
41 | 45 | |
... | ... | @@ -43,7 +47,7 @@ |
43 | 47 | name: 'JSearchSelectTag', |
44 | 48 | props:{ |
45 | 49 | disabled: Boolean, |
46 | - value: String, | |
50 | + value: [String, Number], | |
47 | 51 | dict: String, |
48 | 52 | dictOptions: Array, |
49 | 53 | async: Boolean, |
... | ... | @@ -71,8 +75,12 @@ |
71 | 75 | immediate:true, |
72 | 76 | handler(val){ |
73 | 77 | if(!val){ |
74 | - this.selectedValue=[] | |
75 | - this.selectedAsyncValue=[] | |
78 | + if(val==0){ | |
79 | + this.initSelectValue() | |
80 | + }else{ | |
81 | + this.selectedValue=[] | |
82 | + this.selectedAsyncValue=[] | |
83 | + } | |
76 | 84 | }else{ |
77 | 85 | this.initSelectValue() |
78 | 86 | } |
... | ... | @@ -100,7 +108,7 @@ |
100 | 108 | }) |
101 | 109 | } |
102 | 110 | }else{ |
103 | - this.selectedValue = this.value | |
111 | + this.selectedValue = this.value.toString() | |
104 | 112 | } |
105 | 113 | }, |
106 | 114 | loadData(value){ |
... | ... | @@ -132,11 +140,28 @@ |
132 | 140 | this.options = [...this.dictOptions] |
133 | 141 | }else{ |
134 | 142 | //根据字典Code, 初始化字典数组 |
135 | - ajaxGetDictItems(this.dict, null).then((res) => { | |
136 | - if (res.success) { | |
137 | - this.options = res.result; | |
138 | - } | |
139 | - }) | |
143 | + let dictStr = '' | |
144 | + if(this.dict){ | |
145 | + let arr = this.dict.split(',') | |
146 | + if(arr[0].indexOf('where')>0){ | |
147 | + let tbInfo = arr[0].split('where') | |
148 | + dictStr = tbInfo[0].trim()+','+arr[1]+','+arr[2]+','+encodeURIComponent(tbInfo[1]) | |
149 | + }else{ | |
150 | + dictStr = this.dict | |
151 | + } | |
152 | + if (this.dict.indexOf(",") == -1) { | |
153 | + //优先从缓存中读取字典配置 | |
154 | + if (getDictItemsFromCache(this.dictCode)) { | |
155 | + this.options = getDictItemsFromCache(this.dictCode); | |
156 | + return | |
157 | + } | |
158 | + } | |
159 | + ajaxGetDictItems(dictStr, null).then((res) => { | |
160 | + if (res.success) { | |
161 | + this.options = res.result; | |
162 | + } | |
163 | + }) | |
164 | + } | |
140 | 165 | } |
141 | 166 | } |
142 | 167 | }, |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JAreaLinkage.vue
0 → 100644
1 | +<template> | |
2 | + <div v-if="!reloading" class="j-area-linkage"> | |
3 | + <area-cascader | |
4 | + v-if="_type === enums.type[0]" | |
5 | + :value="innerValue" | |
6 | + :data="pcaa" | |
7 | + :level="1" | |
8 | + :style="{width}" | |
9 | + v-bind="$attrs" | |
10 | + v-on="_listeners" | |
11 | + @change="handleChange" | |
12 | + /> | |
13 | + <area-select | |
14 | + v-else-if="_type === enums.type[1]" | |
15 | + :value="innerValue" | |
16 | + :data="pcaa" | |
17 | + :level="2" | |
18 | + v-bind="$attrs" | |
19 | + v-on="_listeners" | |
20 | + @change="handleChange" | |
21 | + /> | |
22 | + <div v-else> | |
23 | + <span style="color:red;"> Bad type value: {{_type}}</span> | |
24 | + </div> | |
25 | + </div> | |
26 | +</template> | |
27 | + | |
28 | +<script> | |
29 | + import { pcaa } from 'area-data' | |
30 | + import Area from '@/components/_util/Area' | |
31 | + | |
32 | + export default { | |
33 | + name: 'JAreaLinkage', | |
34 | + props: { | |
35 | + value: { | |
36 | + type: String, | |
37 | + required:false | |
38 | + }, | |
39 | + // 组件的类型,可选值: | |
40 | + // select 下拉样式 | |
41 | + // cascader 级联样式(默认) | |
42 | + type: { | |
43 | + type: String, | |
44 | + default: 'cascader' | |
45 | + }, | |
46 | + width: { | |
47 | + type: String, | |
48 | + default: '100%' | |
49 | + } | |
50 | + }, | |
51 | + data() { | |
52 | + return { | |
53 | + pcaa, | |
54 | + innerValue: [], | |
55 | + usedListeners: ['change'], | |
56 | + enums: { | |
57 | + type: ['cascader', 'select'] | |
58 | + }, | |
59 | + reloading: false, | |
60 | + areaData:'' | |
61 | + } | |
62 | + }, | |
63 | + computed: { | |
64 | + _listeners() { | |
65 | + let listeners = { ...this.$listeners } | |
66 | + // 去掉已使用的事件,防止冲突 | |
67 | + this.usedListeners.forEach(key => { | |
68 | + delete listeners[key] | |
69 | + }) | |
70 | + return listeners | |
71 | + }, | |
72 | + _type() { | |
73 | + if (this.enums.type.includes(this.type)) { | |
74 | + return this.type | |
75 | + } else { | |
76 | + console.error(`JAreaLinkage的type属性只能接收指定的值(${this.enums.type.join('|')})`) | |
77 | + return this.enums.type[0] | |
78 | + } | |
79 | + }, | |
80 | + }, | |
81 | + watch: { | |
82 | + value: { | |
83 | + immediate: true, | |
84 | + handler() { | |
85 | + this.loadDataByValue(this.value) | |
86 | + } | |
87 | + }, | |
88 | + }, | |
89 | + created() { | |
90 | + this.initAreaData(); | |
91 | + }, | |
92 | + methods: { | |
93 | + /** 通过 value 反推 options */ | |
94 | + loadDataByValue(value) { | |
95 | + if(!value || value.length==0){ | |
96 | + this.innerValue = [] | |
97 | + this.reloading = true; | |
98 | + setTimeout(()=>{ | |
99 | + this.reloading = false | |
100 | + },100) | |
101 | + }else{ | |
102 | + this.initAreaData(); | |
103 | + let arr = this.areaData.getRealCode(value); | |
104 | + this.innerValue = arr | |
105 | + } | |
106 | + }, | |
107 | + /** 通过地区code获取子级 */ | |
108 | + loadDataByCode(value) { | |
109 | + let options = [] | |
110 | + let data = pcaa[value] | |
111 | + if (data) { | |
112 | + for (let key in data) { | |
113 | + if (data.hasOwnProperty(key)) { | |
114 | + options.push({ value: key, label: data[key], }) | |
115 | + } | |
116 | + } | |
117 | + return options | |
118 | + } else { | |
119 | + return [] | |
120 | + } | |
121 | + }, | |
122 | + /** 判断是否有子节点 */ | |
123 | + hasChildren(options) { | |
124 | + options.forEach(option => { | |
125 | + let data = this.loadDataByCode(option.value) | |
126 | + option.isLeaf = data.length === 0 | |
127 | + }) | |
128 | + }, | |
129 | + handleChange(values) { | |
130 | + let value = values[values.length - 1] | |
131 | + this.$emit('change', value) | |
132 | + }, | |
133 | + initAreaData(){ | |
134 | + if(!this.areaData){ | |
135 | + this.areaData = new Area(); | |
136 | + } | |
137 | + }, | |
138 | + | |
139 | + }, | |
140 | + model: { prop: 'value', event: 'change' }, | |
141 | + } | |
142 | +</script> | |
143 | + | |
144 | +<style lang="less" scoped> | |
145 | + .j-area-linkage { | |
146 | + height:40px; | |
147 | + /deep/ .area-cascader-wrap .area-select { | |
148 | + width: 100%; | |
149 | + } | |
150 | + | |
151 | + /deep/ .area-select .area-selected-trigger { | |
152 | + line-height: 1.15; | |
153 | + } | |
154 | + } | |
155 | + | |
156 | +</style> | |
0 | 157 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JCategorySelect.vue
... | ... | @@ -96,7 +96,7 @@ |
96 | 96 | loadRoot(){ |
97 | 97 | let param = { |
98 | 98 | pid:this.pid, |
99 | - pcode:this.pcode, | |
99 | + pcode:!this.pcode?'0':this.pcode, | |
100 | 100 | condition:this.condition |
101 | 101 | } |
102 | 102 | getAction(this.url,param).then(res=>{ |
... | ... | @@ -122,8 +122,6 @@ |
122 | 122 | this.treeValue = [] |
123 | 123 | }else{ |
124 | 124 | getAction(this.view,{ids:this.value}).then(res=>{ |
125 | - console.log(124345) | |
126 | - console.log(124345,res) | |
127 | 125 | if(res.success){ |
128 | 126 | let values = this.value.split(',') |
129 | 127 | this.treeValue = res.result.map((item, index) => ({ |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JCodeEditor.vue
1 | 1 | <template> |
2 | 2 | <div v-bind="fullScreenParentProps"> |
3 | - <a-icon v-if="fullScreen" class="full-screen-icon" type="fullscreen" @click="()=>fullCoder=!fullCoder"/> | |
3 | + <a-icon v-if="fullScreen" class="full-screen-icon" :type="iconType" @click="()=>fullCoder=!fullCoder"/> | |
4 | 4 | |
5 | 5 | <div class="code-editor-cust full-screen-child"> |
6 | 6 | <textarea ref="textarea"></textarea> |
... | ... | @@ -91,6 +91,7 @@ |
91 | 91 | return { |
92 | 92 | // 内部真实的内容 |
93 | 93 | code: '', |
94 | + iconType: 'fullscreen', | |
94 | 95 | hasCode:false, |
95 | 96 | // 默认的语法类型 |
96 | 97 | mode: 'javascript', |
... | ... | @@ -155,6 +156,15 @@ |
155 | 156 | } |
156 | 157 | }, |
157 | 158 | watch: { |
159 | + fullCoder:{ | |
160 | + handler(value) { | |
161 | + if(value){ | |
162 | + this.iconType="fullscreen-exit" | |
163 | + }else{ | |
164 | + this.iconType="fullscreen" | |
165 | + } | |
166 | + } | |
167 | + }, | |
158 | 168 | // value: { |
159 | 169 | // immediate: false, |
160 | 170 | // handler(value) { |
... | ... | @@ -408,6 +418,7 @@ |
408 | 418 | .full-screen-child { |
409 | 419 | min-height: 120px; |
410 | 420 | max-height: 320px; |
421 | + overflow:hidden; | |
411 | 422 | } |
412 | 423 | |
413 | 424 | } |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JDate.vue
ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue
... | ... | @@ -11,13 +11,13 @@ |
11 | 11 | <a-col> |
12 | 12 | <!-- 操作按钮 --> |
13 | 13 | <div v-if="actionButton" class="action-button"> |
14 | - <a-button type="primary" icon="plus" @click="handleClickAdd">新增</a-button> | |
14 | + <a-button type="primary" icon="plus" @click="handleClickAdd" :disabled="disabled">新增</a-button> | |
15 | 15 | <span class="gap"></span> |
16 | 16 | <template v-if="selectedRowIds.length>0"> |
17 | 17 | <a-popconfirm |
18 | 18 | :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" |
19 | 19 | @confirm="handleConfirmDelete"> |
20 | - <a-button type="primary" icon="minus">删除</a-button> | |
20 | + <a-button type="primary" icon="minus" :disabled="disabled">删除</a-button> | |
21 | 21 | <span class="gap"></span> |
22 | 22 | </a-popconfirm> |
23 | 23 | <template v-if="showClearSelectButton"> |
... | ... | @@ -79,7 +79,12 @@ |
79 | 79 | <span>暂无数据</span> |
80 | 80 | </div> |
81 | 81 | <!-- v-model="rows"--> |
82 | - <draggable :value="rows" handle=".td-ds-icons" @end="handleDragMoveEnd"> | |
82 | + <draggable | |
83 | + :value="rows" | |
84 | + handle=".td-ds-icons" | |
85 | + @start="handleDragMoveStart" | |
86 | + @end="handleDragMoveEnd" | |
87 | + > | |
83 | 88 | |
84 | 89 | <!-- 动态生成tr --> |
85 | 90 | <template v-for="(row,rowIndex) in rows"> |
... | ... | @@ -200,6 +205,7 @@ |
200 | 205 | @change="(v)=>handleChangeSelectCommon(v,id,row,col)" |
201 | 206 | @search="(v)=>handleSearchSelect(v,id,row,col)" |
202 | 207 | @blur="(v)=>handleBlurSearch(v,id,row,col)" |
208 | + allowClear | |
203 | 209 | > |
204 | 210 | |
205 | 211 | <!--<template v-for="(opt,optKey) in col.options">--> |
... | ... | @@ -236,12 +242,43 @@ |
236 | 242 | :trigger-change="true" |
237 | 243 | :showTime="col.type === formTypes.datetime" |
238 | 244 | :dateFormat="col.type === formTypes.date? 'YYYY-MM-DD':'YYYY-MM-DD HH:mm:ss'" |
245 | + allowClear | |
239 | 246 | @change="(v)=>handleChangeJDateCommon(v,id,row,col,col.type === formTypes.datetime)"/> |
240 | 247 | |
241 | 248 | </span> |
242 | 249 | </a-tooltip> |
243 | 250 | </template> |
244 | 251 | |
252 | + <!-- input_pop --> | |
253 | + <template v-else-if="col.type === formTypes.input_pop"> | |
254 | + <a-tooltip | |
255 | + :key="i" | |
256 | + :id="id" | |
257 | + placement="top" | |
258 | + :title="(tooltips[id] || {}).title" | |
259 | + :visible="(tooltips[id] || {}).visible || false" | |
260 | + :autoAdjustOverflow="true" | |
261 | + :getPopupContainer="getParentContainer"> | |
262 | + <span | |
263 | + @mouseover="()=>{handleMouseoverCommono(row,col)}" | |
264 | + @mouseout="()=>{handleMouseoutCommono(row,col)}"> | |
265 | + <j-input-pop | |
266 | + :id="id" | |
267 | + :key="i" | |
268 | + :width="300" | |
269 | + :height="210" | |
270 | + :pop-container="`${caseId}tbody`" | |
271 | + v-bind="buildProps(row,col)" | |
272 | + style="width: 100%;" | |
273 | + :value="jInputPopValues[id]" | |
274 | + :getCalendarContainer="getParentContainer" | |
275 | + :placeholder="replaceProps(col, col.placeholder)" | |
276 | + @change="(v)=>handleChangeJInputPopCommon(v,id,row,col)"> | |
277 | + </j-input-pop> | |
278 | + </span> | |
279 | + </a-tooltip> | |
280 | + </template> | |
281 | + | |
245 | 282 | <div v-else-if="col.type === formTypes.upload" :key="i"> |
246 | 283 | <template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]"> |
247 | 284 | <a-input |
... | ... | @@ -340,10 +377,11 @@ |
340 | 377 | :placeholder="replaceProps(col, col.placeholder)" |
341 | 378 | style="width: 100%;" |
342 | 379 | :value="getPopupValue(id)" |
343 | - :field="col.key" | |
344 | - :org-fields="col.orgFieldse" | |
380 | + :field="col.field || col.key" | |
381 | + :org-fields="col.orgFields" | |
345 | 382 | :dest-fields="col.destFields" |
346 | 383 | :code="col.popupCode" |
384 | + :groupId="caseId" | |
347 | 385 | @input="(value,others)=>popupCallback(value,others,id,row,col,rowIndex)"/> |
348 | 386 | </span> |
349 | 387 | </a-tooltip> |
... | ... | @@ -353,34 +391,42 @@ |
353 | 391 | <!-- update-beign-author:taoyan date:0827 for:文件/图片逻辑新增 --> |
354 | 392 | <div v-else-if="col.type === formTypes.file" :key="i"> |
355 | 393 | <template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]"> |
356 | - <a-input | |
357 | - :key="fileKey" | |
358 | - :readOnly="true" | |
359 | - :value="file.name" | |
360 | - > | |
361 | - <template slot="addonBefore" style="width: 30px"> | |
362 | - <a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`"> | |
363 | - <a-icon type="loading"/> | |
364 | - </a-tooltip> | |
365 | - <a-tooltip v-else-if="file.status==='done'" title="上传完成"> | |
366 | - <a-icon type="check-circle" style="color:#00DB00;"/> | |
367 | - </a-tooltip> | |
368 | - <a-tooltip v-else title="上传失败"> | |
369 | - <a-icon type="exclamation-circle" style="color:red;"/> | |
370 | - </a-tooltip> | |
371 | - </template> | |
394 | + <div :key="fileKey" style="position: relative;"> | |
395 | + <a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`"> | |
396 | + <a-icon type="loading" style="color:red;"/> | |
397 | + <span style="color:red;margin-left:5px">{{ file.status }}</span> | |
398 | + </a-tooltip> | |
372 | 399 | |
373 | - <template slot="addonAfter" style="width: 30px"> | |
374 | - <a-tooltip title="删除并重新上传"> | |
375 | - <a-icon | |
376 | - v-if="file.status!=='uploading'" | |
377 | - type="close-circle" | |
378 | - style="cursor: pointer;" | |
379 | - @click="()=>handleClickDelFile(id)"/> | |
380 | - </a-tooltip> | |
381 | - </template> | |
400 | + <a-tooltip v-else-if="file.status==='done'" :title="file.name"> | |
401 | + <a-icon type="paper-clip" /> | |
402 | + <span style="margin-left:5px">{{ getEllipsisWord(file.name,5) }}</span> | |
403 | + </a-tooltip> | |
382 | 404 | |
383 | - </a-input> | |
405 | + <a-tooltip v-else :title="file.name"> | |
406 | + <a-icon type="paper-clip" style="color:red;"/> | |
407 | + <span style="color:red;margin-left:5px">{{ getEllipsisWord(file.name,5) }}</span> | |
408 | + </a-tooltip> | |
409 | + | |
410 | + <template style="width: 30px"> | |
411 | + <a-dropdown :trigger="['click']" placement="bottomRight" :getPopupContainer="getParentContainer" style="margin-left: 10px;"> | |
412 | + <a-tooltip title="操作" :getPopupContainer="getParentContainer"> | |
413 | + <a-icon v-if="file.status!=='uploading'" type="setting" style="cursor: pointer;"/> | |
414 | + </a-tooltip> | |
415 | + | |
416 | + <a-menu slot="overlay"> | |
417 | + <a-menu-item v-if="col.allowDownload!==false" @click="handleClickDownFileByUrl(id)"> | |
418 | + <span><a-icon type="download"/> 下载</span> | |
419 | + </a-menu-item> | |
420 | + <a-menu-item @click="handleClickDelFile(id)"> | |
421 | + <span><a-icon type="delete"/> 删除</span> | |
422 | + </a-menu-item> | |
423 | + <a-menu-item @click="handleMoreOperation(id)"> | |
424 | + <span><a-icon type="bars" /> 更多</span> | |
425 | + </a-menu-item> | |
426 | + </a-menu> | |
427 | + </a-dropdown> | |
428 | + </template> | |
429 | + </div> | |
384 | 430 | </template> |
385 | 431 | |
386 | 432 | <div :hidden="uploadValues[id] != null"> |
... | ... | @@ -407,7 +453,7 @@ |
407 | 453 | v-bind="buildProps(row,col)" |
408 | 454 | @change="(v)=>handleChangeUpload(v,id,row,col)" |
409 | 455 | > |
410 | - <a-button icon="upload">{{ col.placeholder }}</a-button> | |
456 | + <a-button icon="upload">上传文件</a-button> | |
411 | 457 | </a-upload> |
412 | 458 | </span> |
413 | 459 | </a-tooltip> |
... | ... | @@ -418,7 +464,15 @@ |
418 | 464 | <div v-else-if="col.type === formTypes.image" :key="i"> |
419 | 465 | <template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]"> |
420 | 466 | <div :key="fileKey" style="position: relative;"> |
421 | - <img :src="getCellImageView(id)" style="height:32px;max-width:100px !important;" alt="无图片"/> | |
467 | + <template v-if="!uploadValues[id] || !(uploadValues[id]['url'] || uploadValues[id]['path'] || uploadValues[id]['message'])"> | |
468 | + <a-icon type="loading"/> | |
469 | + </template> | |
470 | + <template v-else-if="uploadValues[id]['path']"> | |
471 | + <img class="j-editable-image" :src="getCellImageView(id)" alt="无图片" @click="handleMoreOperation(id,'img')"/> | |
472 | + </template> | |
473 | + <template v-else> | |
474 | + <a-icon type="exclamation-circle" style="color: red;" @click="handleClickShowImageError(id)"/> | |
475 | + </template> | |
422 | 476 | <template slot="addonBefore" style="width: 30px"> |
423 | 477 | <a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`"> |
424 | 478 | <a-icon type="loading"/> |
... | ... | @@ -432,13 +486,26 @@ |
432 | 486 | </template> |
433 | 487 | |
434 | 488 | <template style="width: 30px"> |
435 | - <a-tooltip title="删除并重新上传" style="margin-left:5px"> | |
436 | - <a-icon | |
437 | - v-if="file.status!=='uploading'" | |
438 | - type="close-circle" | |
439 | - style="cursor: pointer;" | |
440 | - @click="()=>handleClickDelFile(id)"/> | |
441 | - </a-tooltip> | |
489 | + <a-dropdown :trigger="['click']" placement="bottomRight" :getPopupContainer="getParentContainer" style="margin-left: 10px;"> | |
490 | + <a-tooltip title="操作" :getPopupContainer="getParentContainer"> | |
491 | + <a-icon | |
492 | + v-if="file.status!=='uploading'" | |
493 | + type="setting" | |
494 | + style="cursor: pointer;"/> | |
495 | + </a-tooltip> | |
496 | + | |
497 | + <a-menu slot="overlay"> | |
498 | + <a-menu-item v-if="col.allowDownload!==false" @click="handleClickDownFileByUrl(id)"> | |
499 | + <span><a-icon type="download"/> 下载</span> | |
500 | + </a-menu-item> | |
501 | + <a-menu-item @click="handleClickDelFile(id)"> | |
502 | + <span><a-icon type="delete"/> 删除</span> | |
503 | + </a-menu-item> | |
504 | + <a-menu-item @click="handleMoreOperation(id,'img')"> | |
505 | + <span><a-icon type="bars" /> 更多</span> | |
506 | + </a-menu-item> | |
507 | + </a-menu> | |
508 | + </a-dropdown> | |
442 | 509 | </template> |
443 | 510 | |
444 | 511 | </div> |
... | ... | @@ -468,7 +535,7 @@ |
468 | 535 | v-bind="buildProps(row,col)" |
469 | 536 | @change="(v)=>handleChangeUpload(v,id,row,col)" |
470 | 537 | > |
471 | - <a-button icon="upload">请上传图片</a-button> | |
538 | + <a-button icon="upload">上传图片</a-button> | |
472 | 539 | </a-upload> |
473 | 540 | </span> |
474 | 541 | </a-tooltip> |
... | ... | @@ -599,7 +666,7 @@ |
599 | 666 | :text="slotValues[id]" |
600 | 667 | :value="slotValues[id]" |
601 | 668 | :column="col" |
602 | - :rowId="removeCaseId(row.id)" | |
669 | + :rowId="getCleanId(row.id)" | |
603 | 670 | :getValue="()=>_getValueForSlot(row.id)" |
604 | 671 | :caseId="caseId" |
605 | 672 | :allValues="_getAllValuesForSlot()" |
... | ... | @@ -621,8 +688,45 @@ |
621 | 688 | </template> |
622 | 689 | </draggable> |
623 | 690 | |
691 | + | |
692 | + <!-- 统计行 --> | |
693 | + <div | |
694 | + v-if="showStatisticsRow" | |
695 | + class="tr" | |
696 | + :style="{ | |
697 | + ...buildTrStyle(rows.length), | |
698 | + height: '32px' | |
699 | + }" | |
700 | + > | |
701 | + <div v-if="dragSort" class="td td-ds" :style="style.tdLeftDs"> | |
702 | + </div> | |
703 | + <div v-if="rowSelection" class="td td-cb" :style="style.tdLeft"> | |
704 | + 统计 | |
705 | + </div> | |
706 | + <div v-if="rowNumber" class="td td-num" :style="style.tdLeft"> | |
707 | + <span v-if="!rowSelection">统计</span> | |
708 | + </div> | |
709 | + | |
710 | + <!-- 右侧动态生成td --> | |
711 | + <template v-for="col in columns"> | |
712 | + <div | |
713 | + :key="col.key" | |
714 | + class="td" | |
715 | + v-show="col.type !== formTypes.hidden" | |
716 | + :style="buildTdStyle(col)" | |
717 | + > | |
718 | + <span | |
719 | + v-show="col.type === formTypes.inputNumber" | |
720 | + style="padding: 0 5px;" | |
721 | + >{{statisticsColumns[col.key]}}</span> | |
722 | + </div> | |
723 | + </template> | |
724 | + | |
725 | + </div> | |
726 | + | |
624 | 727 | </div> |
625 | 728 | </div> |
729 | + <j-file-pop ref="filePop" @ok="handleFileSuccess"></j-file-pop> | |
626 | 730 | </div> |
627 | 731 | </a-spin> |
628 | 732 | </template> |
... | ... | @@ -632,17 +736,25 @@ |
632 | 736 | import Draggable from 'vuedraggable' |
633 | 737 | import { ACCESS_TOKEN } from '@/store/mutation-types' |
634 | 738 | import { FormTypes, VALIDATE_NO_PASSED } from '@/utils/JEditableTableUtil' |
635 | - import { cloneObject, randomString } from '@/utils/util' | |
739 | + import { cloneObject, randomString, randomNumber } from '@/utils/util' | |
636 | 740 | import JDate from '@/components/jeecg/JDate' |
637 | 741 | import { initDictOptions } from '@/components/dict/JDictSelectUtil' |
638 | - | |
742 | + import { getFileAccessHttpUrl } from '@/api/manage'; | |
743 | + import JInputPop from '@/components/jeecg/minipop/JInputPop' | |
744 | + import JFilePop from '@/components/jeecg/minipop/JFilePop' | |
639 | 745 | |
640 | 746 | // 行高,需要在实例加载完成前用到 |
641 | 747 | let rowHeight = 61 |
642 | 748 | |
643 | 749 | export default { |
644 | 750 | name: 'JEditableTable', |
645 | - components: { JDate, Draggable }, | |
751 | + components: { JDate, Draggable, JInputPop, JFilePop }, | |
752 | + provide() { | |
753 | + return { | |
754 | + parentIsJEditableTable: true, | |
755 | + getDestroyCleanGroupRequest: () => this.destroyCleanGroupRequest, | |
756 | + } | |
757 | + }, | |
646 | 758 | props: { |
647 | 759 | // 列信息 |
648 | 760 | columns: { |
... | ... | @@ -704,8 +816,15 @@ |
704 | 816 | }, |
705 | 817 | data() { |
706 | 818 | return { |
819 | + // 是否首次运行 | |
820 | + isFirst: true, | |
821 | + // 当前实例是否是行编辑 | |
822 | + isJEditableTable: true, | |
707 | 823 | // caseId,用于防止有多个实例的时候会冲突 |
824 | + caseIdPrefix: '_jet-', | |
708 | 825 | caseId: `_jet-${randomString(6)}-`, |
826 | + // 临时ID标识,凡是以该标识结尾的ID都是临时ID,不添加到数据库中 | |
827 | + tempId: `_tid-${randomString(6)}`, | |
709 | 828 | // 存储document element 对象 |
710 | 829 | el: { |
711 | 830 | inputTable: null, |
... | ... | @@ -733,6 +852,8 @@ |
733 | 852 | checkboxValues: {}, |
734 | 853 | // 绑定 jdate 的值 |
735 | 854 | jdateValues: {}, |
855 | + // 绑定jinputpop | |
856 | + jInputPopValues:{}, | |
736 | 857 | // 绑定插槽数据 |
737 | 858 | slotValues: {}, |
738 | 859 | // file 信息 |
... | ... | @@ -751,7 +872,15 @@ |
751 | 872 | // 存储显示tooltip的信息 |
752 | 873 | tooltips: {}, |
753 | 874 | // 存储没有通过验证的inputId |
754 | - notPassedIds: [] | |
875 | + notPassedIds: [], | |
876 | + | |
877 | + // 当前是否正在拖拽排序 | |
878 | + dragging: false, | |
879 | + // 是否有统计列 | |
880 | + hasStatisticsColumn: false, | |
881 | + statisticsColumns: {}, | |
882 | + // 只有在行编辑被销毁时才主动清空GroupRequest的内存 | |
883 | + destroyCleanGroupRequest: false, | |
755 | 884 | } |
756 | 885 | }, |
757 | 886 | created() { |
... | ... | @@ -764,7 +893,15 @@ |
764 | 893 | computed: { |
765 | 894 | // expandHeight = rows.length * rowHeight |
766 | 895 | getExpandHeight() { |
767 | - return this.rows.length * this.rowHeight | |
896 | + let length = this.rows.length * this.rowHeight | |
897 | + if (this.showStatisticsRow) { | |
898 | + length += 34 | |
899 | + } | |
900 | + return length | |
901 | + }, | |
902 | + // 是否显示统计行 | |
903 | + showStatisticsRow() { | |
904 | + return this.hasStatisticsColumn && this.rows.length > 0 | |
768 | 905 | }, |
769 | 906 | // 获取是否选择了部分 |
770 | 907 | getSelectIndeterminate() { |
... | ... | @@ -792,6 +929,7 @@ |
792 | 929 | return Vue.ls.get(ACCESS_TOKEN) |
793 | 930 | }, |
794 | 931 | realTrWidth() { |
932 | + let splice = ' + ' | |
795 | 933 | let calcWidth = 'calc(' |
796 | 934 | this.columns.forEach((column, i) => { |
797 | 935 | let { type, width } = column |
... | ... | @@ -804,12 +942,12 @@ |
804 | 942 | } else { |
805 | 943 | calcWidth += '120px' |
806 | 944 | } |
807 | - | |
808 | - if (i < this.columns.length - 1) { | |
809 | - calcWidth += ' + ' | |
810 | - } | |
945 | + calcWidth += splice | |
811 | 946 | } |
812 | 947 | }) |
948 | + if (calcWidth.endsWith(splice)) { | |
949 | + calcWidth = calcWidth.substring(0, calcWidth.length - splice.length) | |
950 | + } | |
813 | 951 | calcWidth += ')' |
814 | 952 | // console.log('calcWidth: ', calcWidth) |
815 | 953 | return calcWidth |
... | ... | @@ -836,125 +974,8 @@ |
836 | 974 | handler: function (newValue) { |
837 | 975 | // 兼容IE |
838 | 976 | this.getElementPromise('tbody').then(() => { |
839 | - | |
840 | 977 | this.initialize() |
841 | - | |
842 | - let rows = [] | |
843 | - let checkboxValues = {} | |
844 | - let selectValues = {} | |
845 | - let jdateValues = {} | |
846 | - let slotValues = {} | |
847 | - let uploadValues = {} | |
848 | - let popupValues = {} | |
849 | - let radioValues = {} | |
850 | - let multiSelectValues = {} | |
851 | - let searchSelectValues = {} | |
852 | - | |
853 | - // 禁用行的id | |
854 | - let disabledRowIds = (this.disabledRowIds || []) | |
855 | - newValue.forEach((data, newValueIndex) => { | |
856 | - // 判断源数据是否带有id | |
857 | - if (data.id == null || data.id === '') { | |
858 | - data.id = this.removeCaseId(this.generateId() + newValueIndex) | |
859 | - } | |
860 | - | |
861 | - let value = { id: this.caseId + data.id } | |
862 | - let row = { id: value.id } | |
863 | - let disabled = false | |
864 | - this.columns.forEach(column => { | |
865 | - let inputId = column.key + value.id | |
866 | - let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString() | |
867 | - if (column.type === FormTypes.checkbox) { | |
868 | - | |
869 | - // 判断是否设定了customValue(自定义值) | |
870 | - if (column.customValue instanceof Array) { | |
871 | - let customValue = (column.customValue[0] || '').toString() | |
872 | - checkboxValues[inputId] = (sourceValue === customValue) | |
873 | - } else { | |
874 | - checkboxValues[inputId] = sourceValue | |
875 | - } | |
876 | - | |
877 | - } else if (column.type === FormTypes.select) { | |
878 | - if (sourceValue) { | |
879 | - // 判断是否是多选 | |
880 | - selectValues[inputId] = (column.props || {})['mode'] === 'multiple' ? sourceValue.split(',') : sourceValue | |
881 | - } else { | |
882 | - selectValues[inputId] = undefined | |
883 | - } | |
884 | - | |
885 | - } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) { | |
886 | - jdateValues[inputId] = sourceValue | |
887 | - | |
888 | - } else if (column.type === FormTypes.slot) { | |
889 | - if (sourceValue !== 0 && !sourceValue) { | |
890 | - slotValues[inputId] = column.defaultValue | |
891 | - } else { | |
892 | - slotValues[inputId] = sourceValue | |
893 | - } | |
894 | - | |
895 | - } else if (column.type === FormTypes.popup) { | |
896 | - popupValues[inputId] = sourceValue | |
897 | - } else if (column.type === FormTypes.radio) { | |
898 | - radioValues[inputId] = sourceValue | |
899 | - } else if (column.type === FormTypes.sel_search) { | |
900 | - searchSelectValues[inputId] = sourceValue | |
901 | - } else if (column.type === FormTypes.list_multi) { | |
902 | - if (sourceValue.length > 0) { | |
903 | - multiSelectValues[inputId] = sourceValue.split(',') | |
904 | - } else { | |
905 | - multiSelectValues[inputId] = [] | |
906 | - } | |
907 | - } else if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) { | |
908 | - if (sourceValue) { | |
909 | - let fileName = sourceValue.substring(sourceValue.lastIndexOf('/') + 1) | |
910 | - uploadValues[inputId] = { | |
911 | - name: fileName, | |
912 | - status: 'done', | |
913 | - path: sourceValue | |
914 | - } | |
915 | - } | |
916 | - } else { | |
917 | - value[column.key] = sourceValue | |
918 | - } | |
919 | - | |
920 | - // 解析disabledRows | |
921 | - for (let columnKey in this.disabledRows) { | |
922 | - // 判断是否有该属性 | |
923 | - if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) { | |
924 | - if (disabled !== true) { | |
925 | - let temp = this.disabledRows[columnKey] | |
926 | - // 禁用规则可以是一个数组 | |
927 | - if (temp instanceof Array) { | |
928 | - disabled = temp.includes(data[columnKey]) | |
929 | - } else { | |
930 | - disabled = (temp === data[columnKey]) | |
931 | - } | |
932 | - if (disabled) { | |
933 | - disabledRowIds.push(row.id) | |
934 | - } | |
935 | - } | |
936 | - } | |
937 | - } | |
938 | - }) | |
939 | - this.inputValues.push(value) | |
940 | - rows.push(row) | |
941 | - }) | |
942 | - this.disabledRowIds = disabledRowIds | |
943 | - this.checkboxValues = checkboxValues | |
944 | - this.selectValues = selectValues | |
945 | - this.jdateValues = jdateValues | |
946 | - this.slotValues = slotValues | |
947 | - this.rows = rows | |
948 | - this.uploadValues = uploadValues | |
949 | - this.popupValues = popupValues | |
950 | - this.radioValues = radioValues | |
951 | - this.multiSelectValues = multiSelectValues | |
952 | - this.searchSelectValues = searchSelectValues | |
953 | - | |
954 | - // 更新form表单的值 | |
955 | - this.$nextTick(() => { | |
956 | - this.updateFormValues() | |
957 | - }) | |
978 | + this._pushByDataSource(newValue) | |
958 | 979 | }) |
959 | 980 | } |
960 | 981 | }, |
... | ... | @@ -988,7 +1009,7 @@ |
988 | 1009 | }, |
989 | 1010 | // 当selectRowIds改变时触发事件 |
990 | 1011 | selectedRowIds(newValue) { |
991 | - this.$emit('selectRowChange', cloneObject(newValue).map(i => this.removeCaseId(i))) | |
1012 | + this.$emit('selectRowChange', cloneObject(newValue).map(i => this.getCleanId(i))) | |
992 | 1013 | } |
993 | 1014 | }, |
994 | 1015 | mounted() { |
... | ... | @@ -1008,8 +1029,6 @@ |
1008 | 1029 | |
1009 | 1030 | thead.scrollLeft = event.target.scrollLeft |
1010 | 1031 | |
1011 | - // vm.recalcTrHiddenItem(event.target.scrollTop) | |
1012 | - | |
1013 | 1032 | vm.recalcTrHiddenItem(event.target.scrollTop) |
1014 | 1033 | |
1015 | 1034 | } |
... | ... | @@ -1038,36 +1057,42 @@ |
1038 | 1057 | |
1039 | 1058 | /** 初始化列表 */ |
1040 | 1059 | initialize() { |
1041 | - // inputValues:用来存储input表单的值 | |
1042 | - // 数组里的每项都是一个对象,对象里每个key都是input的rowKey,值就是input的值,其中有个id的字段来区分 | |
1043 | - // 示例: | |
1044 | - // [{ | |
1045 | - // id: "_jet-4sp0iu-15541771111770" | |
1046 | - // dbDefaultVal: "aaa", | |
1047 | - // dbFieldName: "bbb", | |
1048 | - // dbFieldTxt: "ccc", | |
1049 | - // dbLength: 32 | |
1050 | - // }] | |
1051 | - this.inputValues = [] | |
1052 | 1060 | this.visibleTrEls = [] |
1053 | - this.rows = [] | |
1054 | - this.deleteIds = [] | |
1055 | - this.selectValues = {} | |
1056 | - this.checkboxValues = {} | |
1057 | - this.jdateValues = {} | |
1058 | - this.slotValues = {} | |
1059 | - this.selectedRowIds = [] | |
1060 | - this.tooltips = {} | |
1061 | - this.notPassedIds = [] | |
1062 | - this.uploadValues = [] | |
1063 | - this.popupValues = [] | |
1064 | - this.radioValues = [] | |
1065 | - this.multiSelectValues = [] | |
1066 | - this.searchSelectValues = [] | |
1067 | - this.scrollTop = 0 | |
1068 | - this.$nextTick(() => { | |
1069 | - this.getElement('tbody').scrollTop = 0 | |
1070 | - }) | |
1061 | + // 判断是否是首次进入该方法,如果是就不清空行,防止删除了预添加的数据 | |
1062 | + if (!this.isFirst) { | |
1063 | + // inputValues:用来存储input表单的值 | |
1064 | + // 数组里的每项都是一个对象,对象里每个key都是input的rowKey,值就是input的值,其中有个id的字段来区分 | |
1065 | + // 示例: | |
1066 | + // [{ | |
1067 | + // id: "_jet-4sp0iu-15541771111770" | |
1068 | + // dbDefaultVal: "aaa", | |
1069 | + // dbFieldName: "bbb", | |
1070 | + // dbFieldTxt: "ccc", | |
1071 | + // dbLength: 32 | |
1072 | + // }] | |
1073 | + this.inputValues = [] | |
1074 | + this.rows = [] | |
1075 | + this.deleteIds = [] | |
1076 | + this.selectValues = {} | |
1077 | + this.checkboxValues = {} | |
1078 | + this.jdateValues = {} | |
1079 | + this.jInputPopValues = {} | |
1080 | + this.slotValues = {} | |
1081 | + this.selectedRowIds = [] | |
1082 | + this.tooltips = {} | |
1083 | + this.notPassedIds = [] | |
1084 | + this.uploadValues = [] | |
1085 | + this.popupValues = [] | |
1086 | + this.radioValues = [] | |
1087 | + this.multiSelectValues = [] | |
1088 | + this.searchSelectValues = [] | |
1089 | + this.scrollTop = 0 | |
1090 | + this.$nextTick(() => { | |
1091 | + this.getElement('tbody').scrollTop = 0 | |
1092 | + }) | |
1093 | + } else { | |
1094 | + this.isFirst = false | |
1095 | + } | |
1071 | 1096 | }, |
1072 | 1097 | |
1073 | 1098 | /** 同步滚动条状态 */ |
... | ... | @@ -1105,94 +1130,212 @@ |
1105 | 1130 | rows = this.rows || [] |
1106 | 1131 | } |
1107 | 1132 | let timestamp = new Date().getTime() |
1108 | - return `${this.caseId}${timestamp}${rows.length}` | |
1133 | + return `${this.caseId}${timestamp}${rows.length}${randomNumber(6)}${this.tempId}` | |
1109 | 1134 | }, |
1110 | 1135 | /** push 一条数据 */ |
1111 | - push(record, update = true, rows, insertIndex = null) { | |
1136 | + push(record, update = true, rows, insertIndex = null, setDefaultValue = true) { | |
1137 | + return this._pushByDataSource([record], [insertIndex], update, rows, setDefaultValue) | |
1138 | + }, | |
1139 | + | |
1140 | + /** | |
1141 | + * push 数据 | |
1142 | + * | |
1143 | + * @param dataSource 数据源 | |
1144 | + * @param insertIndexes 行插入位置,和dataSource的下标一一对应 | |
1145 | + * @param update 是否更新 | |
1146 | + * @param rows 若不传就使用 this.rows | |
1147 | + * @param setDefaultValue 是否填充默认值 | |
1148 | + * | |
1149 | + */ | |
1150 | + _pushByDataSource(dataSource, insertIndexes = null, update = true, rows = null, setDefaultValue = false) { | |
1112 | 1151 | if (!(rows instanceof Array)) { |
1113 | - rows = cloneObject(this.rows) || [] | |
1114 | - } | |
1115 | - | |
1116 | - if (record.id == null) { | |
1117 | - record.id = this.generateId(rows) | |
1118 | - // let timestamp = new Date().getTime() | |
1119 | - // record.id = `${this.caseId}${timestamp}${rows.length}` | |
1120 | - } | |
1121 | - if (record.id.indexOf(this.caseId) === -1) { | |
1122 | - record.id = this.caseId + record.id | |
1123 | - } | |
1124 | - let row = { id: record.id } | |
1125 | - let value = { id: row.id } | |
1126 | - let checkboxValues = Object.assign({}, this.checkboxValues) | |
1127 | - let selectValues = Object.assign({}, this.selectValues) | |
1128 | - let jdateValues = Object.assign({}, this.jdateValues) | |
1129 | - let slotValues = Object.assign({}, this.slotValues) | |
1130 | - this.columns.forEach(column => { | |
1131 | - let key = column.key | |
1132 | - let inputId = key + row.id | |
1133 | - // record中是否有该列的值 | |
1134 | - let recordHasValue = record[key] != null | |
1135 | - if (column.type === FormTypes.input) { | |
1136 | - value[key] = recordHasValue ? record[key] : (column.defaultValue || (column.defaultValue === 0 ? 0 : '')) | |
1137 | - | |
1138 | - } else if (column.type === FormTypes.inputNumber) { | |
1139 | - // 判断是否是排序字段,如果是就赋最大值 | |
1140 | - if (column.isOrder === true) { | |
1141 | - value[key] = this.getInputNumberMaxValue(column) + 1 | |
1142 | - } else { | |
1143 | - value[key] = recordHasValue ? record[key] : (column.defaultValue || (column.defaultValue === 0 ? 0 : '')) | |
1144 | - } | |
1152 | + rows = [...this.rows] || [] | |
1153 | + } | |
1154 | + let checkboxValues = { ...this.checkboxValues } | |
1155 | + let selectValues = { ...this.selectValues } | |
1156 | + let jdateValues = { ...this.jdateValues } | |
1157 | + let jInputPopValues = { ...this.jInputPopValues } | |
1158 | + let slotValues = { ...this.slotValues } | |
1159 | + let uploadValues = { ...this.uploadValues } | |
1160 | + let popupValues = { ...this.popupValues } | |
1161 | + let radioValues = { ...this.radioValues } | |
1162 | + let multiSelectValues = { ...this.multiSelectValues } | |
1163 | + let searchSelectValues = { ...this.searchSelectValues } | |
1164 | + // 禁用行的id | |
1165 | + let disabledRowIds = (this.disabledRowIds || []) | |
1166 | + dataSource.forEach((data, newValueIndex) => { | |
1167 | + // 不能直接更改数据源的id | |
1168 | + let dataId = data.id | |
1169 | + // 判断源数据是否带有id | |
1170 | + if (dataId == null || dataId === '') { | |
1171 | + dataId = this.generateId(rows) | |
1172 | + } else if(!this.hasCaseId(dataId)) { | |
1173 | + dataId = this.caseId + dataId | |
1174 | + } | |
1175 | + let row = { id: dataId } | |
1176 | + let value = { id: dataId } | |
1177 | + let disabled = false | |
1178 | + this.columns.forEach(column => { | |
1179 | + let inputId = column.key + value.id | |
1180 | + let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString() | |
1145 | 1181 | |
1146 | - } else if (column.type === FormTypes.checkbox) { | |
1147 | - checkboxValues[inputId] = recordHasValue ? record[key] : column.defaultChecked | |
1182 | + let defaultValue = null; | |
1183 | + if (setDefaultValue) { | |
1184 | + defaultValue = column.defaultValue || (column.defaultValue === 0 ? 0 : '') | |
1185 | + if (defaultValue instanceof Array) { | |
1186 | + defaultValue = defaultValue.join(',') | |
1187 | + } | |
1148 | 1188 | |
1149 | - } else if (column.type === FormTypes.select) { | |
1150 | - let selected = column.defaultValue | |
1151 | - if (selected !== 0 && !selected) { | |
1152 | - selected = undefined | |
1189 | + sourceValue = (typeof sourceValue === 'number' || sourceValue) ? sourceValue : defaultValue | |
1153 | 1190 | } |
1154 | - // 判断多选 | |
1155 | - if (typeof selected === 'string' && (column.props || {})['mode'] === 'multiple') { | |
1156 | - selected = selected.split(',') | |
1157 | - } | |
1158 | - selectValues[inputId] = recordHasValue ? record[key] : selected | |
1191 | + let sourceValueIsEmpty = (sourceValue == null || sourceValue === '') | |
1159 | 1192 | |
1160 | - } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) { | |
1161 | - jdateValues[inputId] = recordHasValue ? record[key] : column.defaultValue | |
1193 | + if (column.type === FormTypes.inputNumber) { | |
1194 | + // 判断是否是排序字段,如果是就赋最大值 | |
1195 | + if (column.isOrder === true) { | |
1196 | + value[column.key] = this.getInputNumberMaxValue(column) + 1 | |
1197 | + } else { | |
1198 | + value[column.key] = sourceValue | |
1199 | + } | |
1200 | + // 判断是否是统计列 | |
1201 | + if (column.statistics) { | |
1202 | + this.hasStatisticsColumn = true | |
1203 | + if (!this.statisticsColumns[column.key]) { | |
1204 | + this.$set(this.statisticsColumns, column.key, 0) | |
1205 | + } | |
1206 | + } | |
1162 | 1207 | |
1163 | - } else if (column.type === FormTypes.slot) { | |
1164 | - slotValues[inputId] = recordHasValue ? record[key] : (column.defaultValue || '') | |
1208 | + } else if (column.type === FormTypes.checkbox) { | |
1209 | + // 判断是否设定了customValue(自定义值) | |
1210 | + if (column.customValue instanceof Array) { | |
1211 | + let customValue = (column.customValue[0] || '').toString() | |
1212 | + if (sourceValueIsEmpty && setDefaultValue) { | |
1213 | + sourceValue = column.defaultChecked ? customValue : sourceValue | |
1214 | + } | |
1215 | + checkboxValues[inputId] = (sourceValue === customValue) | |
1216 | + } else { | |
1217 | + if (sourceValueIsEmpty && setDefaultValue) { | |
1218 | + checkboxValues[inputId] = !!column.defaultChecked | |
1219 | + } else { | |
1220 | + checkboxValues[inputId] = sourceValue | |
1221 | + } | |
1222 | + } | |
1165 | 1223 | |
1166 | - } else { | |
1167 | - value[key] = recordHasValue ? record[key] : '' | |
1224 | + } else if (column.type === FormTypes.select) { | |
1225 | + if (!sourceValueIsEmpty) { | |
1226 | + // 判断是否是多选 | |
1227 | + if (typeof sourceValue === 'string' && (column.props || {})['mode'] === 'multiple') { | |
1228 | + sourceValue = sourceValue.split(',') | |
1229 | + } | |
1230 | + selectValues[inputId] = sourceValue | |
1231 | + } else { | |
1232 | + selectValues[inputId] = undefined | |
1233 | + } | |
1234 | + | |
1235 | + } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) { | |
1236 | + jdateValues[inputId] = sourceValue | |
1237 | + | |
1238 | + } else if (column.type === FormTypes.slot) { | |
1239 | + slotValues[inputId] = sourceValue | |
1240 | + | |
1241 | + } else if (column.type === FormTypes.popup) { | |
1242 | + popupValues[inputId] = sourceValue | |
1243 | + } else if (column.type === FormTypes.input_pop) { | |
1244 | + jInputPopValues[inputId] = sourceValue | |
1245 | + } else if (column.type === FormTypes.radio) { | |
1246 | + radioValues[inputId] = sourceValue | |
1247 | + } else if (column.type === FormTypes.sel_search) { | |
1248 | + searchSelectValues[inputId] = sourceValue | |
1249 | + } else if (column.type === FormTypes.list_multi) { | |
1250 | + if (typeof sourceValue === 'string' && sourceValue.length > 0) { | |
1251 | + multiSelectValues[inputId] = sourceValue.split(',') | |
1252 | + } else { | |
1253 | + multiSelectValues[inputId] = [] | |
1254 | + } | |
1255 | + } else if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) { | |
1256 | + if (sourceValue) { | |
1257 | + let fileName = '' | |
1258 | + if (sourceValue.indexOf(',') > 0) { | |
1259 | + let sourceValue2 = sourceValue.split(',')[0] | |
1260 | + fileName = sourceValue2.substring(sourceValue2.lastIndexOf('/') + 1) | |
1261 | + } else { | |
1262 | + fileName = sourceValue.substring(sourceValue.lastIndexOf('/') + 1) | |
1263 | + } | |
1264 | + uploadValues[inputId] = { | |
1265 | + name: fileName, | |
1266 | + status: 'done', | |
1267 | + path: sourceValue | |
1268 | + } | |
1269 | + } | |
1270 | + } else { | |
1271 | + value[column.key] = sourceValue | |
1272 | + } | |
1273 | + | |
1274 | + // 解析disabledRows | |
1275 | + for (let columnKey in this.disabledRows) { | |
1276 | + // 判断是否有该属性 | |
1277 | + if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) { | |
1278 | + if (disabled !== true) { | |
1279 | + let temp = this.disabledRows[columnKey] | |
1280 | + // 禁用规则可以是一个数组 | |
1281 | + if (temp instanceof Array) { | |
1282 | + disabled = temp.includes(data[columnKey]) | |
1283 | + } else { | |
1284 | + disabled = (temp === data[columnKey]) | |
1285 | + } | |
1286 | + if (disabled) { | |
1287 | + disabledRowIds.push(row.id) | |
1288 | + } | |
1289 | + } | |
1290 | + } | |
1291 | + } | |
1292 | + }) | |
1293 | + // 插入行而不是添加到最后 | |
1294 | + let added = false | |
1295 | + if (insertIndexes instanceof Array) { | |
1296 | + let insertIndex = insertIndexes[newValueIndex] | |
1297 | + if (typeof insertIndex === 'number') { | |
1298 | + added = true | |
1299 | + rows.splice(insertIndex, 0, row) | |
1300 | + this.inputValues.splice(insertIndex, 0, value) | |
1301 | + } | |
1302 | + } | |
1303 | + if (!added) { | |
1304 | + rows.push(row) | |
1305 | + this.inputValues.push(value) | |
1168 | 1306 | } |
1169 | 1307 | }) |
1170 | - if (typeof insertIndex === 'number') { | |
1171 | - rows.splice(insertIndex, 0, row) | |
1172 | - this.inputValues.splice(insertIndex, 0, value) | |
1173 | - } else { | |
1174 | - rows.push(row) | |
1175 | - this.inputValues.push(value) | |
1176 | - } | |
1177 | - this.checkboxValues = checkboxValues | |
1178 | - this.selectValues = selectValues | |
1179 | - this.jdateValues = jdateValues | |
1180 | - this.slotValues = slotValues | |
1181 | - | |
1308 | + // 启用了拖动排序,就重新计算排序编号 | |
1182 | 1309 | if (this.dragSort) { |
1183 | 1310 | this.inputValues.forEach((item, index) => { |
1184 | 1311 | item[this.dragSortKey] = (index + 1) |
1185 | 1312 | }) |
1186 | 1313 | } |
1187 | - | |
1314 | + this.disabledRowIds = disabledRowIds | |
1315 | + this.checkboxValues = checkboxValues | |
1316 | + this.selectValues = selectValues | |
1317 | + this.jdateValues = jdateValues | |
1318 | + this.jInputPopValues = jInputPopValues | |
1319 | + this.slotValues = slotValues | |
1320 | + this.uploadValues = uploadValues | |
1321 | + this.popupValues = popupValues | |
1322 | + this.radioValues = radioValues | |
1323 | + this.multiSelectValues = multiSelectValues | |
1324 | + this.searchSelectValues = searchSelectValues | |
1325 | + // 重新计算所有统计列 | |
1326 | + this.recalcAllStatisticsColumns() | |
1327 | + // 更新到 dom | |
1188 | 1328 | if (update) { |
1189 | 1329 | this.rows = rows |
1330 | + | |
1331 | + // 更新form表单的值 | |
1190 | 1332 | this.$nextTick(() => { |
1191 | 1333 | this.updateFormValues() |
1192 | 1334 | }) |
1193 | 1335 | } |
1194 | 1336 | return rows |
1195 | 1337 | }, |
1338 | + | |
1196 | 1339 | /** 获取某一数字输入框列中的最大的值 */ |
1197 | 1340 | getInputNumberMaxValue(column) { |
1198 | 1341 | let maxNum = 0 |
... | ... | @@ -1219,9 +1362,8 @@ |
1219 | 1362 | let rows = this.rows |
1220 | 1363 | let row |
1221 | 1364 | for (let i = 0; i < num; i++) { |
1222 | - // row = { id: `${this.caseId}${timestamp}${rows.length}` } | |
1223 | - row = { id: this.generateId(rows) } | |
1224 | - rows = this.push(row, false, rows) | |
1365 | + rows = this.push({}, false, rows) | |
1366 | + row = rows[rows.length - 1] | |
1225 | 1367 | } |
1226 | 1368 | this.rows = rows |
1227 | 1369 | |
... | ... | @@ -1232,7 +1374,7 @@ |
1232 | 1374 | this.$emit('added', { |
1233 | 1375 | row: (() => { |
1234 | 1376 | let r = Object.assign({}, row) |
1235 | - r.id = this.removeCaseId(r.id) | |
1377 | + r.id = this.getCleanId(r.id) | |
1236 | 1378 | return r |
1237 | 1379 | })(), |
1238 | 1380 | target: this |
... | ... | @@ -1275,7 +1417,7 @@ |
1275 | 1417 | this.$emit('inserted', { |
1276 | 1418 | rows: newRows.map(row => { |
1277 | 1419 | let r = cloneObject(row) |
1278 | - r.id = this.removeCaseId(r.id) | |
1420 | + r.id = this.getCleanId(r.id) | |
1279 | 1421 | return r |
1280 | 1422 | }), |
1281 | 1423 | num, insertIndex, |
... | ... | @@ -1300,10 +1442,12 @@ |
1300 | 1442 | |
1301 | 1443 | let rows = cloneObject(this.rows) |
1302 | 1444 | ids.forEach(removeId => { |
1445 | + removeId = this.getCleanId(removeId) | |
1303 | 1446 | // 找到每个id对应的真实index并删除 |
1304 | 1447 | const findAndDelete = (arr) => { |
1305 | 1448 | for (let i = 0; i < arr.length; i++) { |
1306 | - if (arr[i].id === removeId || arr[i].id === this.caseId + removeId) { | |
1449 | + let currentId = this.getCleanId(arr[i].id) | |
1450 | + if (currentId === removeId) { | |
1307 | 1451 | arr.splice(i, 1) |
1308 | 1452 | return true |
1309 | 1453 | } |
... | ... | @@ -1314,7 +1458,7 @@ |
1314 | 1458 | // 找到values对应的index,并删除 |
1315 | 1459 | findAndDelete(this.inputValues) |
1316 | 1460 | // 将caseId去除 |
1317 | - let id = this.removeCaseId(removeId) | |
1461 | + let id = this.getCleanId(removeId) | |
1318 | 1462 | this.deleteIds.push(id) |
1319 | 1463 | } |
1320 | 1464 | }) |
... | ... | @@ -1323,15 +1467,19 @@ |
1323 | 1467 | this.$nextTick(() => { |
1324 | 1468 | // 更新formValues |
1325 | 1469 | this.updateFormValues() |
1470 | + // 重新计算统计 | |
1471 | + this.recalcAllStatisticsColumns() | |
1326 | 1472 | }) |
1327 | 1473 | return true |
1328 | 1474 | }, |
1329 | 1475 | |
1330 | 1476 | /** 获取表格表单里的值(异步版) */ |
1331 | 1477 | getValuesAsync(options = {}, callback) { |
1332 | - let { validate, rowIds } = options | |
1478 | + let { validate, rowIds, deleteTempId } = options | |
1333 | 1479 | if (typeof validate !== 'boolean') validate = true |
1334 | 1480 | if (!(rowIds instanceof Array)) rowIds = null |
1481 | + // 是否删除临时ID,默认为 false | |
1482 | + if (typeof deleteTempId !== 'boolean') deleteTempId = false | |
1335 | 1483 | // console.log('options:', { validate, rowIds }) |
1336 | 1484 | |
1337 | 1485 | let asyncCount = 0 |
... | ... | @@ -1349,7 +1497,7 @@ |
1349 | 1497 | rowIdsFlag = true |
1350 | 1498 | } else { |
1351 | 1499 | for (let rowId of rowIds) { |
1352 | - if (rowId === value.id || `${this.caseId}${rowId}` === value.id) { | |
1500 | + if (this.getCleanId(rowId) === this.getCleanId(value.id)) { | |
1353 | 1501 | rowIdsFlag = true |
1354 | 1502 | break |
1355 | 1503 | } |
... | ... | @@ -1379,6 +1527,9 @@ |
1379 | 1527 | } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) { |
1380 | 1528 | value[column.key] = this.jdateValues[inputId] |
1381 | 1529 | |
1530 | + } else if (column.type === FormTypes.input_pop) { | |
1531 | + value[column.key] = this.jInputPopValues[inputId] | |
1532 | + | |
1382 | 1533 | } else if (column.type === FormTypes.upload) { |
1383 | 1534 | value[column.key] = cloneObject(this.uploadValues[inputId] || null) |
1384 | 1535 | |
... | ... | @@ -1432,10 +1583,14 @@ |
1432 | 1583 | handleValidateOneInput(results) |
1433 | 1584 | } |
1434 | 1585 | }) |
1435 | - // 将caseId去除 | |
1436 | - value.id = this.removeCaseId(value.id) | |
1437 | - values.push(value) | |
1586 | + // 删除 tempId | |
1587 | + if (deleteTempId && this.isTempId(value.id)) { | |
1588 | + delete value.id | |
1589 | + } else { | |
1590 | + value.id = this.getCleanId(value.id) | |
1591 | + } | |
1438 | 1592 | |
1593 | + values.push(value) | |
1439 | 1594 | } |
1440 | 1595 | |
1441 | 1596 | if (validate === true) { |
... | ... | @@ -1450,7 +1605,7 @@ |
1450 | 1605 | callback({ error, values }) |
1451 | 1606 | } |
1452 | 1607 | } |
1453 | - }, 50) | |
1608 | + }, 10) | |
1454 | 1609 | |
1455 | 1610 | return { error, values } |
1456 | 1611 | }, |
... | ... | @@ -1469,9 +1624,9 @@ |
1469 | 1624 | }) |
1470 | 1625 | }, |
1471 | 1626 | /** getValues的Promise版 */ |
1472 | - getValuesPromise(validate = true, rowIds) { | |
1627 | + getValuesPromise(validate = true, rowIds, deleteTempId) { | |
1473 | 1628 | return new Promise((resolve, reject) => { |
1474 | - this.getValuesAsync({ validate, rowIds }, ({ error, values }) => { | |
1629 | + this.getValuesAsync({ validate, rowIds, deleteTempId }, ({ error, values }) => { | |
1475 | 1630 | if (error === 0) { |
1476 | 1631 | resolve(values) |
1477 | 1632 | } else { |
... | ... | @@ -1485,10 +1640,10 @@ |
1485 | 1640 | return cloneObject(this.deleteIds) |
1486 | 1641 | }, |
1487 | 1642 | /** 获取所有的数据,包括values、deleteIds */ |
1488 | - getAll(validate) { | |
1643 | + getAll(validate, deleteTempId) { | |
1489 | 1644 | return new Promise((resolve, reject) => { |
1490 | 1645 | let deleteIds = this.getDeleteIds() |
1491 | - this.getValuesPromise(validate).then((values) => { | |
1646 | + this.getValuesPromise(validate, null, deleteTempId).then((values) => { | |
1492 | 1647 | resolve({ values, deleteIds }) |
1493 | 1648 | }).catch(error => { |
1494 | 1649 | reject(error) |
... | ... | @@ -1496,8 +1651,8 @@ |
1496 | 1651 | }) |
1497 | 1652 | }, |
1498 | 1653 | /** Sync 获取所有的数据,包括values、deleteIds */ |
1499 | - getAllSync(validate, rowIds) { | |
1500 | - let result = this.getValuesSync({ validate, rowIds }) | |
1654 | + getAllSync(validate, rowIds, deleteTempId) { | |
1655 | + let result = this.getValuesSync({ validate, rowIds, deleteTempId }) | |
1501 | 1656 | result.deleteIds = this.getDeleteIds() |
1502 | 1657 | return result |
1503 | 1658 | }, |
... | ... | @@ -1511,6 +1666,7 @@ |
1511 | 1666 | selectValues: this.selectValues, |
1512 | 1667 | checkboxValues: this.checkboxValues, |
1513 | 1668 | jdateValues: this.jdateValues, |
1669 | + jInputPopValues: this.jInputPopValues, | |
1514 | 1670 | slotValues: this.slotValues, |
1515 | 1671 | uploadValues: this.uploadValues, |
1516 | 1672 | popupValues: this.popupValues, |
... | ... | @@ -1524,13 +1680,14 @@ |
1524 | 1680 | |
1525 | 1681 | values.forEach(item => { |
1526 | 1682 | let { rowKey, values: newValues } = item |
1683 | + rowKey = this.getCleanId(rowKey) | |
1527 | 1684 | for (let newValueKey in newValues) { |
1528 | 1685 | if (newValues.hasOwnProperty(newValueKey)) { |
1529 | 1686 | let newValue = newValues[newValueKey] |
1530 | 1687 | let edited = false // 已被修改 |
1531 | 1688 | this.inputValues.forEach(value => { |
1532 | 1689 | // 在inputValues中找到了该字段 |
1533 | - if (`${this.caseId}${rowKey}` === value.id) { | |
1690 | + if (rowKey === this.getCleanId(value.id)) { | |
1534 | 1691 | if (value.hasOwnProperty(newValueKey)) { |
1535 | 1692 | edited = true |
1536 | 1693 | value[newValueKey] = newValue |
... | ... | @@ -1539,28 +1696,48 @@ |
1539 | 1696 | }) |
1540 | 1697 | let modelKey = `${newValueKey}${this.caseId}${rowKey}` |
1541 | 1698 | // 在 selectValues 中寻找值 |
1542 | - if (!edited && this.selectValues.hasOwnProperty(modelKey)) { | |
1699 | + if (!edited) { | |
1543 | 1700 | if (newValue !== 0 && !newValue) { |
1544 | - this.selectValues[modelKey] = undefined | |
1701 | + edited = this.setOneValue(this.selectValues, modelKey, undefined) | |
1545 | 1702 | } else { |
1546 | - this.selectValues[modelKey] = newValue | |
1703 | + edited = this.setOneValue(this.selectValues, modelKey, newValue) | |
1547 | 1704 | } |
1548 | - edited = true | |
1549 | 1705 | } |
1550 | 1706 | // 在 checkboxValues 中寻找值 |
1551 | - if (!edited && this.checkboxValues.hasOwnProperty(modelKey)) { | |
1552 | - this.checkboxValues[modelKey] = newValue | |
1553 | - edited = true | |
1707 | + if (!edited) { | |
1708 | + edited = this.setOneValue(this.checkboxValues, modelKey, newValue) | |
1554 | 1709 | } |
1555 | 1710 | // 在 jdateValues 中寻找值 |
1556 | - if (!edited && this.jdateValues.hasOwnProperty(modelKey)) { | |
1557 | - this.jdateValues[modelKey] = newValue | |
1558 | - edited = true | |
1711 | + if (!edited) { | |
1712 | + edited = this.setOneValue(this.jdateValues, modelKey, newValue) | |
1713 | + } | |
1714 | + // 在 jInputPopValues 中寻找值 | |
1715 | + if (!edited) { | |
1716 | + edited = this.setOneValue(this.jInputPopValues, modelKey, newValue) | |
1559 | 1717 | } |
1560 | 1718 | // 在 slotValues 中寻找值 |
1561 | - if (!edited && this.slotValues.hasOwnProperty(modelKey)) { | |
1562 | - this.slotValues[modelKey] = newValue | |
1563 | - edited = true | |
1719 | + if (!edited) { | |
1720 | + edited = this.setOneValue(this.slotValues, modelKey, newValue) | |
1721 | + } | |
1722 | + // 在 uploadValues 中寻找值 | |
1723 | + if (!edited) { | |
1724 | + edited = this.setOneValue(this.uploadValues, modelKey, newValue) | |
1725 | + } | |
1726 | + // 在 popupValues 中寻找值 | |
1727 | + if (!edited) { | |
1728 | + edited = this.setOneValue(this.popupValues, modelKey, newValue) | |
1729 | + } | |
1730 | + // 在 radioValues 中寻找值 | |
1731 | + if (!edited) { | |
1732 | + edited = this.setOneValue(this.radioValues, modelKey, newValue) | |
1733 | + } | |
1734 | + // 在 multiSelectValues 中寻找值 | |
1735 | + if (!edited) { | |
1736 | + edited = this.setOneValue(this.multiSelectValues, modelKey, newValue) | |
1737 | + } | |
1738 | + // 在 searchSelectValues 中寻找值 | |
1739 | + if (!edited) { | |
1740 | + edited = this.setOneValue(this.searchSelectValues, modelKey, newValue) | |
1564 | 1741 | } |
1565 | 1742 | } |
1566 | 1743 | } |
... | ... | @@ -1568,6 +1745,24 @@ |
1568 | 1745 | // 强制更新formValues |
1569 | 1746 | this.forceUpdateFormValues() |
1570 | 1747 | }, |
1748 | + setOneValue(valuesObject, modelKey, value) { | |
1749 | + let key = this.valuesHasOwnProperty(valuesObject, modelKey) | |
1750 | + if (key) { | |
1751 | + this.$set(valuesObject, key, value) | |
1752 | + return true | |
1753 | + } | |
1754 | + return false | |
1755 | + }, | |
1756 | + valuesHasOwnProperty(values, ownProperty) { | |
1757 | + let key = ownProperty | |
1758 | + if (values.hasOwnProperty(key)) { | |
1759 | + return key | |
1760 | + } | |
1761 | + if (values.hasOwnProperty(key + this.tempId)) { | |
1762 | + return key + this.tempId | |
1763 | + } | |
1764 | + return null | |
1765 | + }, | |
1571 | 1766 | |
1572 | 1767 | /** 跳转到指定位置 */ |
1573 | 1768 | // jumpToId(id, element) { |
... | ... | @@ -1602,44 +1797,40 @@ |
1602 | 1797 | |
1603 | 1798 | const nextThen = res => { |
1604 | 1799 | let [passed, message] = res |
1605 | - if (passed == null) { | |
1606 | - // debugger | |
1607 | - } | |
1608 | - if (passed == null && tooltips[inputId].visible != null) { | |
1609 | - return | |
1610 | - } | |
1611 | - passed = passed == null ? true : passed | |
1612 | - tooltips[inputId].visible = !passed | |
1613 | - tooltips[inputId].passed = passed | |
1614 | - let index = notPassedIds.indexOf(inputId) | |
1615 | - let borderColor = null, boxShadow = null | |
1616 | - if (!passed) { | |
1617 | - tooltips[inputId].title = this.replaceProps(column, message) | |
1618 | - borderColor = 'red' | |
1619 | - boxShadow = `0 0 0 2px rgba(255, 0, 0, 0.2)` | |
1620 | - if (index === -1) notPassedIds.push(inputId) | |
1621 | - } else { | |
1622 | - if (index !== -1) notPassedIds.splice(index, 1) | |
1623 | - } | |
1624 | - | |
1625 | - let element = document.getElementById(inputId) | |
1626 | - if (element != null) { | |
1627 | - // select 在 .ant-select-selection 上设置 border-color | |
1628 | - if (column.type === FormTypes.select) { | |
1629 | - element = element.getElementsByClassName('ant-select-selection')[0] | |
1630 | - } | |
1631 | - // jdate 在 input 上设置 border-color | |
1632 | - if (column.type === FormTypes.date || column.type === FormTypes.datetime) { | |
1633 | - element = element.getElementsByTagName('input')[0] | |
1634 | - } | |
1635 | - // upload 在 .ant-upload .ant-btn 上设置 border-color | |
1636 | - if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) { | |
1637 | - element = element.getElementsByClassName('ant-upload')[0].getElementsByClassName('ant-btn')[0] | |
1800 | + // !(passed == null && tooltips[inputId].visible != null) | |
1801 | + if (passed != null) { | |
1802 | + tooltips[inputId].visible = !passed | |
1803 | + tooltips[inputId].passed = passed | |
1804 | + let index = notPassedIds.indexOf(inputId) | |
1805 | + let borderColor = null, boxShadow = null | |
1806 | + if (!passed) { | |
1807 | + tooltips[inputId].title = this.replaceProps(column, message) | |
1808 | + borderColor = 'red' | |
1809 | + boxShadow = `0 0 0 2px rgba(255, 0, 0, 0.2)` | |
1810 | + if (index === -1) notPassedIds.push(inputId) | |
1811 | + } else { | |
1812 | + if (index !== -1) notPassedIds.splice(index, 1) | |
1638 | 1813 | } |
1639 | - element.style.borderColor = borderColor | |
1640 | - element.style.boxShadow = boxShadow | |
1641 | - if (element.tagName === 'SPAN') { | |
1642 | - element.style.display = 'block' | |
1814 | + | |
1815 | + let element = document.getElementById(inputId) | |
1816 | + if (element != null) { | |
1817 | + // select 在 .ant-select-selection 上设置 border-color | |
1818 | + if (column.type === FormTypes.select) { | |
1819 | + element = element.getElementsByClassName('ant-select-selection')[0] | |
1820 | + } | |
1821 | + // jdate 在 input 上设置 border-color | |
1822 | + if (column.type === FormTypes.date || column.type === FormTypes.datetime) { | |
1823 | + element = element.getElementsByTagName('input')[0] | |
1824 | + } | |
1825 | + // upload 在 .ant-upload .ant-btn 上设置 border-color | |
1826 | + if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) { | |
1827 | + element = element.getElementsByClassName('ant-upload')[0].getElementsByClassName('ant-btn')[0] | |
1828 | + } | |
1829 | + element.style.borderColor = borderColor | |
1830 | + element.style.boxShadow = boxShadow | |
1831 | + if (element.tagName === 'SPAN') { | |
1832 | + element.style.display = 'block' | |
1833 | + } | |
1643 | 1834 | } |
1644 | 1835 | } |
1645 | 1836 | // 是否更新到data |
... | ... | @@ -1656,16 +1847,16 @@ |
1656 | 1847 | |
1657 | 1848 | if (typeof passed === 'function') { |
1658 | 1849 | let executed = false |
1659 | - passed(validType, value, row, column, (flag, msg) => { | |
1850 | + passed(validType, value, { id: this.getCleanId(row.id) }, { ...column }, (flag, msg) => { | |
1660 | 1851 | if (executed) return |
1661 | 1852 | executed = true |
1662 | 1853 | if (typeof msg === 'string') { |
1663 | 1854 | message = msg |
1664 | 1855 | } |
1665 | - if (flag == null || flag === true) { | |
1666 | - nextThen([true, message]) | |
1856 | + if (flag == null) { | |
1857 | + nextThen([null, message]) | |
1667 | 1858 | } else { |
1668 | - nextThen([false, message]) | |
1859 | + nextThen([!!flag, message]) | |
1669 | 1860 | } |
1670 | 1861 | }, this) |
1671 | 1862 | } else { |
... | ... | @@ -1710,17 +1901,17 @@ |
1710 | 1901 | |
1711 | 1902 | // 兼容 online 的规则 |
1712 | 1903 | let foo = [ |
1713 | - { title: '6到16位数字', value: 'n6-16', pattern: /\d{6,18}/ }, | |
1904 | + { title: '6到16位数字', value: 'n6-16', pattern: /^\d{6,18}$/ }, | |
1714 | 1905 | { title: '6到16位任意字符', value: '*6-16', pattern: /^.{6,16}$/ }, |
1906 | + { title: '6到18位字母', value: 's6-18', pattern: /^[a-z|A-Z]{6,18}$/ }, | |
1715 | 1907 | { title: '网址', value: 'url', pattern: /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/ }, |
1716 | 1908 | { title: '电子邮件', value: 'e', pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/ }, |
1717 | 1909 | { title: '手机号码', value: 'm', pattern: /^1[3456789]\d{9}$/ }, |
1718 | 1910 | { title: '邮政编码', value: 'p', pattern: /^[1-9]\d{5}$/ }, |
1719 | 1911 | { title: '字母', value: 's', pattern: /^[A-Z|a-z]+$/ }, |
1720 | - { title: '数字', value: 'n', pattern: /^-?\d+\.?\d*$/ }, | |
1912 | + { title: '数字', value: 'n', pattern: /^-?\d+(\.?\d+|\d?)$/ }, | |
1721 | 1913 | { title: '整数', value: 'z', pattern: /^-?\d+$/ }, |
1722 | 1914 | { title: '非空', value: '*', pattern: /^.+$/ }, |
1723 | - { title: '6到18位字符串', value: 's6-18', pattern: /^.{6,18}$/ }, | |
1724 | 1915 | { title: '金额', value: 'money', pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/ }, |
1725 | 1916 | ] |
1726 | 1917 | let flag = false |
... | ... | @@ -1793,6 +1984,43 @@ |
1793 | 1984 | this.updateFormValues() |
1794 | 1985 | }, |
1795 | 1986 | |
1987 | + // 重新计算所有统计列 | |
1988 | + recalcAllStatisticsColumns() { | |
1989 | + if (this.hasStatisticsColumn) { | |
1990 | + Object.keys(this.statisticsColumns).forEach(key => this.recalcOneStatisticsColumn(key)) | |
1991 | + } | |
1992 | + }, | |
1993 | + // 重新计算单个统计列 | |
1994 | + recalcOneStatisticsColumn(key) { | |
1995 | + if (this.hasStatisticsColumn) { | |
1996 | + if (this.statisticsColumns.hasOwnProperty(key)) { | |
1997 | + // 计算合计值 | |
1998 | + let count = 0 | |
1999 | + this.inputValues.forEach(item => { | |
2000 | + let value = item[key] | |
2001 | + if (value && count !== '-') { | |
2002 | + try { | |
2003 | + count += Number.parseInt(value) | |
2004 | + } catch (e) { | |
2005 | + count = '-' | |
2006 | + } | |
2007 | + } | |
2008 | + }) | |
2009 | + this.statisticsColumns[key] = count | |
2010 | + } | |
2011 | + } | |
2012 | + }, | |
2013 | + | |
2014 | + /** 获取某个统计字段的值 */ | |
2015 | + getStatisticsValue(key) { | |
2016 | + if (this.hasStatisticsColumn) { | |
2017 | + if (this.statisticsColumns.hasOwnProperty(key)) { | |
2018 | + return this.statisticsColumns[key] | |
2019 | + } | |
2020 | + } | |
2021 | + return null | |
2022 | + }, | |
2023 | + | |
1796 | 2024 | /** 全选或取消全选 */ |
1797 | 2025 | handleChangeCheckedAll() { |
1798 | 2026 | let selectedRowIds = [] |
... | ... | @@ -1835,7 +2063,7 @@ |
1835 | 2063 | }, |
1836 | 2064 | /** 用于搜索下拉框中的内容 */ |
1837 | 2065 | handleSelectFilterOption(input, option, column) { |
1838 | - if (column.allowSearch === true) { | |
2066 | + if (column.allowSearch === true || column.allowInput === true) { | |
1839 | 2067 | return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 |
1840 | 2068 | } |
1841 | 2069 | return true |
... | ... | @@ -1879,6 +2107,8 @@ |
1879 | 2107 | } |
1880 | 2108 | |
1881 | 2109 | } |
2110 | + // 做单个表单验证 | |
2111 | + this.validateOneInput(value, row, col, this.notPassedIds, true, 'blur') | |
1882 | 2112 | }, |
1883 | 2113 | |
1884 | 2114 | /** 触发已拖动事件 */ |
... | ... | @@ -1886,8 +2116,16 @@ |
1886 | 2116 | this.$emit('dragged', { oldIndex, newIndex, target: this }) |
1887 | 2117 | }, |
1888 | 2118 | |
2119 | + handleDragMoveStart(event) { | |
2120 | + this.dragging = true | |
2121 | + this.$refs.scrollView.style.overflow = 'hidden' | |
2122 | + }, | |
2123 | + | |
1889 | 2124 | /** 拖动结束,交换inputValue中的值 */ |
1890 | 2125 | handleDragMoveEnd(event) { |
2126 | + this.dragging = false | |
2127 | + this.$refs.scrollView.style.overflow = 'auto' | |
2128 | + | |
1891 | 2129 | let { oldIndex, newIndex, item: { dataset: { idx: dataIdx } } } = event |
1892 | 2130 | |
1893 | 2131 | // 由于动态显示隐藏行导致index有误差,需要算出真实的index |
... | ... | @@ -1965,16 +2203,17 @@ |
1965 | 2203 | }, |
1966 | 2204 | /** input事件 */ |
1967 | 2205 | handleInputCommono(target, index, row, column) { |
2206 | + let oldValue = this.inputValues[index][column.key] || '' | |
1968 | 2207 | let { value, dataset, selectionStart } = target |
1969 | 2208 | let type = FormTypes.input |
1970 | 2209 | let change = true |
1971 | 2210 | if (`${dataset.inputNumber}` === 'true') { |
1972 | 2211 | type = FormTypes.inputNumber |
1973 | - let replace = value.replace(/[^0-9]/g, '') | |
1974 | - if (value !== replace) { | |
2212 | + // 判断输入的值是否匹配数字正则表达式,不匹配就还原 | |
2213 | + if (!/^-?\d+\.?\d*$/.test(value) && (value !== '' && value !== '-')) { | |
1975 | 2214 | change = false |
1976 | - value = replace | |
1977 | - target.value = replace | |
2215 | + value = oldValue | |
2216 | + target.value = value | |
1978 | 2217 | if (typeof selectionStart === 'number') { |
1979 | 2218 | target.selectionStart = selectionStart - 1 |
1980 | 2219 | target.selectionEnd = selectionStart - 1 |
... | ... | @@ -1986,6 +2225,10 @@ |
1986 | 2225 | // 做单个表单验证 |
1987 | 2226 | this.validateOneInput(value, row, column, this.notPassedIds, true, 'input') |
1988 | 2227 | |
2228 | + if (type === FormTypes.inputNumber) { | |
2229 | + this.recalcOneStatisticsColumn(column.key) | |
2230 | + } | |
2231 | + | |
1989 | 2232 | // 触发valueChange 事件 |
1990 | 2233 | if (change) { |
1991 | 2234 | this.elemValueChange(type, row, column, value) |
... | ... | @@ -2000,7 +2243,16 @@ |
2000 | 2243 | this.elemValueChange(FormTypes.slot, row, column, value) |
2001 | 2244 | }, |
2002 | 2245 | handleBlurCommono(target, index, row, column) { |
2003 | - let { value } = target | |
2246 | + let { value, dataset } = target | |
2247 | + if (dataset && `${dataset.inputNumber}` === 'true') { | |
2248 | + // 判断输入的值是否匹配数字正则表达式,不匹配就置空 | |
2249 | + if (!/^-?\d+\.?\d*$/.test(value)) { | |
2250 | + value = '' | |
2251 | + } else { | |
2252 | + value = Number.parseFloat(value) | |
2253 | + } | |
2254 | + target.value = value | |
2255 | + } | |
2004 | 2256 | // 做单个表单验证 |
2005 | 2257 | this.validateOneInput(value, row, column, this.notPassedIds, true, 'blur') |
2006 | 2258 | }, |
... | ... | @@ -2030,6 +2282,13 @@ |
2030 | 2282 | this.elemValueChange(FormTypes.date, row, column, value) |
2031 | 2283 | } |
2032 | 2284 | }, |
2285 | + handleChangeJInputPopCommon(value, id, row, column){ | |
2286 | + this.jInputPopValues = this.bindValuesChange(value, id, 'jInputPopValues') | |
2287 | + // 做单个表单验证 | |
2288 | + this.validateOneInput(value, row, column, this.notPassedIds, true, 'change') | |
2289 | + // 触发valueChange 事件 | |
2290 | + this.elemValueChange(FormTypes.input_pop, row, column, value) | |
2291 | + }, | |
2033 | 2292 | handleChangeUpload(info, id, row, column) { |
2034 | 2293 | let { file } = info |
2035 | 2294 | let value = { |
... | ... | @@ -2042,11 +2301,26 @@ |
2042 | 2301 | if (column.responseName && file.response) { |
2043 | 2302 | value['responseName'] = file.response[column.responseName] |
2044 | 2303 | } |
2045 | - if (file.status == 'done') { | |
2304 | + if (file.status === 'done') { | |
2046 | 2305 | value['path'] = file.response[column.responseName] |
2306 | + } else if (file.status === 'error') { | |
2307 | + value['message'] = file.response.message || '未知错误' | |
2047 | 2308 | } |
2048 | 2309 | this.uploadValues = this.bindValuesChange(value, id, 'uploadValues') |
2049 | 2310 | }, |
2311 | + handleMoreOperation(id,flag){ | |
2312 | + //console.log("this.uploadValues[id]",this.uploadValues[id]) | |
2313 | + let path = '' | |
2314 | + if(this.uploadValues && this.uploadValues[id]){ | |
2315 | + path = this.uploadValues[id].path | |
2316 | + } | |
2317 | + this.$refs.filePop.show(id,path,flag) | |
2318 | + }, | |
2319 | + handleFileSuccess(obj){ | |
2320 | + if(obj.id){ | |
2321 | + this.uploadValues = this.bindValuesChange(obj, obj.id, 'uploadValues') | |
2322 | + } | |
2323 | + }, | |
2050 | 2324 | /** 记录用到数据绑定的组件的值 */ |
2051 | 2325 | bindValuesChange(value, id, key) { |
2052 | 2326 | // let values = Object.assign({}, this[key]) |
... | ... | @@ -2074,7 +2348,7 @@ |
2074 | 2348 | let column = Object.assign({}, columnSource) |
2075 | 2349 | // 将caseId去除 |
2076 | 2350 | let row = Object.assign({}, rowSource) |
2077 | - row.id = this.removeCaseId(row.id) | |
2351 | + row.id = this.getCleanId(row.id) | |
2078 | 2352 | // 获取整行的数据 |
2079 | 2353 | let { values } = this.getValuesSync({ validate: false, rowIds: [row.id] }) |
2080 | 2354 | if (values.length > 0) { |
... | ... | @@ -2083,10 +2357,37 @@ |
2083 | 2357 | this.$emit('valueChange', { type, row, column, value, target: this }) |
2084 | 2358 | }, |
2085 | 2359 | |
2360 | + /** 获取干净的ID(不包含任何杂质的ID) */ | |
2361 | + getCleanId(id) { | |
2362 | + id = this.removeCaseId(id) | |
2363 | + id = this.removeTempId(id) | |
2364 | + return id | |
2365 | + }, | |
2366 | + | |
2367 | + /** 判断某个ID是否包含了caseId */ | |
2368 | + hasCaseId(id) { | |
2369 | + return id && id.startsWith(this.caseId) | |
2370 | + }, | |
2371 | + | |
2086 | 2372 | /** 将caseId去除 */ |
2087 | 2373 | removeCaseId(id) { |
2088 | - let remove = id.split(this.caseId)[1] | |
2089 | - return remove ? remove : id | |
2374 | + if (this.hasCaseId(id)) { | |
2375 | + return id.substring(this.caseId.length, id.length) | |
2376 | + } | |
2377 | + return id | |
2378 | + }, | |
2379 | + | |
2380 | + // 判断 id 是否是临时Id | |
2381 | + isTempId(id) { | |
2382 | + return (id || '').endsWith(this.tempId) | |
2383 | + }, | |
2384 | + | |
2385 | + /** 将tempId去除 */ | |
2386 | + removeTempId(id) { | |
2387 | + if (this.isTempId(id)) { | |
2388 | + return id.substring(0, id.length - this.tempId.length) | |
2389 | + } | |
2390 | + return id; | |
2090 | 2391 | }, |
2091 | 2392 | |
2092 | 2393 | handleClickDelFile(id) { |
... | ... | @@ -2095,10 +2396,28 @@ |
2095 | 2396 | handleClickDownloadFile(id) { |
2096 | 2397 | let { path } = this.uploadValues[id] || {} |
2097 | 2398 | if (path) { |
2098 | - let url = window._CONFIG['staticDomainURL'] + '/' + path | |
2399 | + let url = getFileAccessHttpUrl(path) | |
2400 | + window.open(url) | |
2401 | + } | |
2402 | + }, | |
2403 | + handleClickDownFileByUrl(id){ | |
2404 | + let { url,path } = this.uploadValues[id] || {} | |
2405 | + if (!url || url.length===0) { | |
2406 | + if(path && path.length>0){ | |
2407 | + url = getFileAccessHttpUrl(path.split(',')[0]) | |
2408 | + } | |
2409 | + } | |
2410 | + if(url){ | |
2099 | 2411 | window.open(url) |
2100 | 2412 | } |
2101 | 2413 | }, |
2414 | + handleClickShowImageError(id) { | |
2415 | + let currUploadObj = this.uploadValues[id] || null | |
2416 | + if (currUploadObj && currUploadObj['message']) { | |
2417 | + this.$error({ title: '上传出错', content: '错误信息:' + currUploadObj['message'], maskClosable: true }) | |
2418 | + } | |
2419 | + }, | |
2420 | + | |
2102 | 2421 | /** 加载数据字典并合并到 options */ |
2103 | 2422 | _loadDictConcatToOptions(column) { |
2104 | 2423 | initDictOptions(column.dictCode).then((res) => { |
... | ... | @@ -2122,7 +2441,11 @@ |
2122 | 2441 | /* --- 以下是辅助方法,多用于动态构造页面中的数据 --- */ |
2123 | 2442 | |
2124 | 2443 | /** 辅助方法:打印日志 */ |
2125 | - log: console.log, | |
2444 | + log() { | |
2445 | + if (this.$attrs.logger) { | |
2446 | + console.log.apply(null, arguments) | |
2447 | + } | |
2448 | + }, | |
2126 | 2449 | |
2127 | 2450 | getVM() { |
2128 | 2451 | return this |
... | ... | @@ -2265,11 +2588,15 @@ |
2265 | 2588 | /** 预览图片地址 */ |
2266 | 2589 | getCellImageView(id) { |
2267 | 2590 | let currUploadObj = this.uploadValues[id] || null |
2268 | - if (currUploadObj && currUploadObj['path']) { | |
2269 | - return window._CONFIG['staticDomainURL'] + '/' + currUploadObj['path'] | |
2270 | - } else { | |
2271 | - return '' | |
2591 | + if (currUploadObj) { | |
2592 | + if(currUploadObj['url']){ | |
2593 | + return currUploadObj['url']; | |
2594 | + }else if(currUploadObj['path']){ | |
2595 | + let readpath = currUploadObj['path'].split(',')[0] | |
2596 | + return getFileAccessHttpUrl(readpath) | |
2597 | + } | |
2272 | 2598 | } |
2599 | + return '' | |
2273 | 2600 | }, |
2274 | 2601 | /** popup回调 */ |
2275 | 2602 | popupCallback(value, others, id, row, column, index) { |
... | ... | @@ -2277,7 +2604,18 @@ |
2277 | 2604 | this.popupValues[id] = value |
2278 | 2605 | if (others) { |
2279 | 2606 | Object.keys(others).map((key) => { |
2280 | - this.inputValues[index][key] = others[key] | |
2607 | + this.columns.map(k=>{ | |
2608 | + if(k.key === key){ | |
2609 | + let tempId = id.substring(id.indexOf(this.caseIdPrefix)) | |
2610 | + if(k.type === 'date'){ | |
2611 | + this.handleChangeJDateCommon(others[key], key+tempId, {id:tempId}, k, false) | |
2612 | + }else if(k.type === 'datetime'){ | |
2613 | + this.handleChangeJDateCommon(others[key], key+tempId, {id:tempId}, k, true) | |
2614 | + }else{ | |
2615 | + this.inputValues[index][key] = others[key] | |
2616 | + } | |
2617 | + } | |
2618 | + }) | |
2281 | 2619 | }) |
2282 | 2620 | } |
2283 | 2621 | // 做单个表单验证 |
... | ... | @@ -2315,9 +2653,20 @@ |
2315 | 2653 | filterOption(input, option) { |
2316 | 2654 | return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 |
2317 | 2655 | }, |
2656 | + getEllipsisWord(content, len){ | |
2657 | + if(!content || content.length==0){ | |
2658 | + return '' | |
2659 | + } | |
2660 | + if(content.length>len){ | |
2661 | + return content.substr(0,len) | |
2662 | + } | |
2663 | + return content; | |
2664 | + } | |
2318 | 2665 | |
2319 | - | |
2320 | - } | |
2666 | + }, | |
2667 | + beforeDestroy() { | |
2668 | + this.destroyCleanGroupRequest = true | |
2669 | + }, | |
2321 | 2670 | } |
2322 | 2671 | </script> |
2323 | 2672 | |
... | ... | @@ -2538,6 +2887,21 @@ |
2538 | 2887 | |
2539 | 2888 | } |
2540 | 2889 | |
2890 | + .j-editable-image { | |
2891 | + height: 32px; | |
2892 | + max-width: 100px !important; | |
2893 | + cursor: pointer; | |
2894 | + | |
2895 | + &:hover { | |
2896 | + opacity: 0.8; | |
2897 | + } | |
2898 | + | |
2899 | + &:active { | |
2900 | + opacity: 0.6; | |
2901 | + } | |
2902 | + | |
2903 | + } | |
2904 | + | |
2541 | 2905 | } |
2542 | 2906 | |
2543 | 2907 | } |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JEditor.vue
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | import 'tinymce/plugins/colorpicker' |
24 | 24 | import 'tinymce/plugins/textcolor' |
25 | 25 | import 'tinymce/plugins/fullscreen' |
26 | + import { uploadAction,getFileAccessHttpUrl } from '@/api/manage' | |
26 | 27 | export default { |
27 | 28 | components: { |
28 | 29 | Editor |
... | ... | @@ -65,8 +66,21 @@ |
65 | 66 | menubar: false, |
66 | 67 | toolbar_drawer: false, |
67 | 68 | images_upload_handler: (blobInfo, success) => { |
68 | - const img = 'data:image/jpeg;base64,' + blobInfo.base64() | |
69 | - success(img) | |
69 | + let formData = new FormData() | |
70 | + formData.append('file', blobInfo.blob(), blobInfo.filename()); | |
71 | + formData.append('biz', "jeditor"); | |
72 | + formData.append("jeditor","1"); | |
73 | + uploadAction(window._CONFIG['domianURL']+"/sys/common/upload", formData).then((res) => { | |
74 | + if (res.success) { | |
75 | + if(res.message == 'local'){ | |
76 | + const img = 'data:image/jpeg;base64,' + blobInfo.base64() | |
77 | + success(img) | |
78 | + }else{ | |
79 | + let img = getFileAccessHttpUrl(res.message) | |
80 | + success(img) | |
81 | + } | |
82 | + } | |
83 | + }) | |
70 | 84 | } |
71 | 85 | }, |
72 | 86 | myValue: this.value |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JFormContainer.vue
1 | 1 | <template> |
2 | 2 | <div :class="disabled?'jeecg-form-container-disabled':''"> |
3 | - <fieldset disabled> | |
3 | + <fieldset :disabled="disabled"> | |
4 | 4 | <slot name="detail"></slot> |
5 | 5 | </fieldset> |
6 | 6 | <slot name="edit"></slot> |
... | ... | @@ -46,4 +46,16 @@ |
46 | 46 | -ms-pointer-events: none; |
47 | 47 | pointer-events: none; |
48 | 48 | } |
49 | + | |
50 | + .jeecg-form-container-disabled .ant-upload-select{display:none} | |
51 | + .jeecg-form-container-disabled .ant-upload-list{cursor:grabbing} | |
52 | + .jeecg-form-container-disabled fieldset[disabled] .ant-upload-list{ | |
53 | + -ms-pointer-events: auto !important; | |
54 | + pointer-events: auto !important; | |
55 | + } | |
56 | + | |
57 | + .jeecg-form-container-disabled .ant-upload-list-item-actions .anticon-delete, | |
58 | + .jeecg-form-container-disabled .ant-upload-list-item .anticon-close{ | |
59 | + display: none; | |
60 | + } | |
49 | 61 | </style> |
50 | 62 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JGraphicCode.vue deleted
1 | -<template> | |
2 | - <div class="gc-canvas" @click="reloadPic"> | |
3 | - <canvas id="gc-canvas" :width="contentWidth" :height="contentHeight"></canvas> | |
4 | - </div> | |
5 | -</template> | |
6 | - | |
7 | -<script> | |
8 | - import { getAction } from '@/api/manage' | |
9 | - | |
10 | - export default { | |
11 | - name: 'JGraphicCode', | |
12 | - props: { | |
13 | - length:{ | |
14 | - type: Number, | |
15 | - default: 4 | |
16 | - }, | |
17 | - fontSizeMin: { | |
18 | - type: Number, | |
19 | - default: 20 | |
20 | - }, | |
21 | - fontSizeMax: { | |
22 | - type: Number, | |
23 | - default: 45 | |
24 | - }, | |
25 | - backgroundColorMin: { | |
26 | - type: Number, | |
27 | - default: 180 | |
28 | - }, | |
29 | - backgroundColorMax: { | |
30 | - type: Number, | |
31 | - default: 240 | |
32 | - }, | |
33 | - colorMin: { | |
34 | - type: Number, | |
35 | - default: 50 | |
36 | - }, | |
37 | - colorMax: { | |
38 | - type: Number, | |
39 | - default: 160 | |
40 | - }, | |
41 | - lineColorMin: { | |
42 | - type: Number, | |
43 | - default: 40 | |
44 | - }, | |
45 | - lineColorMax: { | |
46 | - type: Number, | |
47 | - default: 180 | |
48 | - }, | |
49 | - dotColorMin: { | |
50 | - type: Number, | |
51 | - default: 0 | |
52 | - }, | |
53 | - dotColorMax: { | |
54 | - type: Number, | |
55 | - default: 255 | |
56 | - }, | |
57 | - contentWidth: { | |
58 | - type: Number, | |
59 | - default:136 | |
60 | - }, | |
61 | - contentHeight: { | |
62 | - type: Number, | |
63 | - default: 38 | |
64 | - }, | |
65 | - remote:{ | |
66 | - type:Boolean, | |
67 | - default:false, | |
68 | - required:false | |
69 | - } | |
70 | - }, | |
71 | - methods: { | |
72 | - // 生成一个随机数 | |
73 | - randomNum (min, max) { | |
74 | - return Math.floor(Math.random() * (max - min) + min) | |
75 | - }, | |
76 | - // 生成一个随机的颜色 | |
77 | - randomColor (min, max) { | |
78 | - let r = this.randomNum(min, max) | |
79 | - let g = this.randomNum(min, max) | |
80 | - let b = this.randomNum(min, max) | |
81 | - return 'rgb(' + r + ',' + g + ',' + b + ')' | |
82 | - }, | |
83 | - drawPic () { | |
84 | - this.randomCode().then(()=>{ | |
85 | - let canvas = document.getElementById('gc-canvas') | |
86 | - let ctx = canvas.getContext('2d') | |
87 | - ctx.textBaseline = 'bottom' | |
88 | - // 绘制背景 | |
89 | - ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax) | |
90 | - ctx.fillRect(0, 0, this.contentWidth, this.contentHeight) | |
91 | - // 绘制文字 | |
92 | - for (let i = 0; i < this.code.length; i++) { | |
93 | - this.drawText(ctx, this.code[i], i) | |
94 | - } | |
95 | - this.drawLine(ctx) | |
96 | - this.drawDot(ctx) | |
97 | - this.$emit("success",this.code) | |
98 | - }) | |
99 | - }, | |
100 | - drawText (ctx, txt, i) { | |
101 | - ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax) | |
102 | - let fontSize = this.randomNum(this.fontSizeMin, this.fontSizeMax) | |
103 | - ctx.font = fontSize + 'px SimHei' | |
104 | - let padding = 10; | |
105 | - let offset = (this.contentWidth-40)/(this.code.length-1) | |
106 | - let x=padding; | |
107 | - if(i>0){ | |
108 | - x = padding+(i*offset) | |
109 | - } | |
110 | - //let x = (i + 1) * (this.contentWidth / (this.code.length + 1)) | |
111 | - let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5) | |
112 | - if(fontSize>40){ | |
113 | - y=40 | |
114 | - } | |
115 | - var deg = this.randomNum(-10,10) | |
116 | - // 修改坐标原点和旋转角度 | |
117 | - ctx.translate(x, y) | |
118 | - ctx.rotate(deg * Math.PI / 180) | |
119 | - ctx.fillText(txt, 0, 0) | |
120 | - // 恢复坐标原点和旋转角度 | |
121 | - ctx.rotate(-deg * Math.PI / 180) | |
122 | - ctx.translate(-x, -y) | |
123 | - }, | |
124 | - drawLine (ctx) { | |
125 | - // 绘制干扰线 | |
126 | - for (let i = 0; i <1; i++) { | |
127 | - ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax) | |
128 | - ctx.beginPath() | |
129 | - ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) | |
130 | - ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) | |
131 | - ctx.stroke() | |
132 | - } | |
133 | - }, | |
134 | - drawDot (ctx) { | |
135 | - // 绘制干扰点 | |
136 | - for (let i = 0; i < 100; i++) { | |
137 | - ctx.fillStyle = this.randomColor(0, 255) | |
138 | - ctx.beginPath() | |
139 | - ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI) | |
140 | - ctx.fill() | |
141 | - } | |
142 | - }, | |
143 | - reloadPic(){ | |
144 | - this.drawPic() | |
145 | - }, | |
146 | - randomCode(){ | |
147 | - return new Promise((resolve)=>{ | |
148 | - if(this.remote==true){ | |
149 | - getAction("/sys/getCheckCode").then(res=>{ | |
150 | - console.log("aaaaa",res) | |
151 | - if(res.success){ | |
152 | - this.checkKey = res.result.key | |
153 | - this.code = window.atob(res.result.code) | |
154 | - resolve(); | |
155 | - }else{ | |
156 | - this.$message.error("生成验证码错误,请联系系统管理员") | |
157 | - this.code = 'BUG' | |
158 | - resolve(); | |
159 | - } | |
160 | - }).catch(()=>{ | |
161 | - console.log("生成验证码连接服务器异常") | |
162 | - this.code = 'BUG' | |
163 | - resolve(); | |
164 | - }) | |
165 | - }else{ | |
166 | - this.randomLocalCode(); | |
167 | - resolve(); | |
168 | - } | |
169 | - }) | |
170 | - }, | |
171 | - randomLocalCode(){ | |
172 | - let random = '' | |
173 | - //去掉了I l i o O | |
174 | - let str = "QWERTYUPLKJHGFDSAZXCVBNMqwertyupkjhgfdsazxcvbnm1234567890" | |
175 | - for(let i = 0; i < this.length; i++) { | |
176 | - let index = Math.floor(Math.random()*57); | |
177 | - random += str[index]; | |
178 | - } | |
179 | - this.code = random | |
180 | - }, | |
181 | - getLoginParam(){ | |
182 | - return { | |
183 | - checkCode:this.code, | |
184 | - checkKey:this.checkKey | |
185 | - } | |
186 | - } | |
187 | - }, | |
188 | - mounted () { | |
189 | - this.drawPic() | |
190 | - }, | |
191 | - data(){ | |
192 | - return { | |
193 | - code:"", | |
194 | - checkKey:"" | |
195 | - } | |
196 | - } | |
197 | - | |
198 | - } | |
199 | -</script> | |
200 | - | |
201 | -<style scoped> | |
202 | - | |
203 | -</style> | |
204 | 0 | \ No newline at end of file |
ant-design-vue-jeecg/src/components/jeecg/JImageUpload.vue
... | ... | @@ -44,7 +44,6 @@ |
44 | 44 | data(){ |
45 | 45 | return { |
46 | 46 | uploadAction:window._CONFIG['domianURL']+"/sys/common/upload", |
47 | - urlView:window._CONFIG['staticDomainURL'], | |
48 | 47 | uploadLoading:false, |
49 | 48 | picUrl:false, |
50 | 49 | headers:{}, |
... | ... | @@ -103,7 +102,7 @@ |
103 | 102 | let fileList = []; |
104 | 103 | let arr = paths.split(",") |
105 | 104 | for(var a=0;a<arr.length;a++){ |
106 | - let url = getFileAccessHttpUrl(arr[a],this.urlView,"http"); | |
105 | + let url = getFileAccessHttpUrl(arr[a]); | |
107 | 106 | fileList.push({ |
108 | 107 | uid: uidGenerator(), |
109 | 108 | name: getFileName(arr[a]), |
... | ... | @@ -156,7 +155,7 @@ |
156 | 155 | getAvatarView(){ |
157 | 156 | if(this.fileList.length>0){ |
158 | 157 | let url = this.fileList[0].url |
159 | - return getFileAccessHttpUrl(url,this.urlView,"http") | |
158 | + return getFileAccessHttpUrl(url) | |
160 | 159 | } |
161 | 160 | }, |
162 | 161 | handlePathChange(){ |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JInput.vue
... | ... | @@ -32,7 +32,12 @@ |
32 | 32 | handler:function(){ |
33 | 33 | this.initVal(); |
34 | 34 | } |
35 | - } | |
35 | + }, | |
36 | + // update-begin author:sunjianlei date:20200225 for:当 type 变化的时候重新计算值 ------ | |
37 | + type() { | |
38 | + this.backValue({ target: { value: this.inputVal } }) | |
39 | + }, | |
40 | + // update-end author:sunjianlei date:20200225 for:当 type 变化的时候重新计算值 ------ | |
36 | 41 | }, |
37 | 42 | model: { |
38 | 43 | prop: 'value', |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JMarkdownEditor/default-options.js
0 → 100644
1 | +export default { | |
2 | + minHeight: '200px', | |
3 | + previewStyle: 'vertical', | |
4 | + useCommandShortcut: true, | |
5 | + useDefaultHTMLSanitizer: true, | |
6 | + usageStatistics: false, | |
7 | + hideModeSwitch: false, | |
8 | + toolbarItems: [ | |
9 | + 'heading', | |
10 | + 'bold', | |
11 | + 'italic', | |
12 | + 'strike', | |
13 | + 'divider', | |
14 | + 'hr', | |
15 | + 'quote', | |
16 | + 'divider', | |
17 | + 'ul', | |
18 | + 'ol', | |
19 | + 'task', | |
20 | + 'indent', | |
21 | + 'outdent', | |
22 | + 'divider', | |
23 | + 'table', | |
24 | + 'image', | |
25 | + 'link', | |
26 | + 'divider', | |
27 | + 'code', | |
28 | + 'codeblock' | |
29 | + ] | |
30 | +} | |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JMarkdownEditor/index.vue
0 → 100644
1 | +<template> | |
2 | + <div :id="id" /> | |
3 | +</template> | |
4 | + | |
5 | +<script> | |
6 | +import 'codemirror/lib/codemirror.css' | |
7 | +import 'tui-editor/dist/tui-editor.css' | |
8 | +import 'tui-editor/dist/tui-editor-contents.css' | |
9 | + | |
10 | +import Editor from 'tui-editor' | |
11 | +import defaultOptions from './default-options' | |
12 | + | |
13 | +export default { | |
14 | + name: 'JMarkdownEditor', | |
15 | + props: { | |
16 | + value: { | |
17 | + type: String, | |
18 | + default: '' | |
19 | + }, | |
20 | + id: { | |
21 | + type: String, | |
22 | + required: false, | |
23 | + default() { | |
24 | + return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '') | |
25 | + } | |
26 | + }, | |
27 | + options: { | |
28 | + type: Object, | |
29 | + default() { | |
30 | + return defaultOptions | |
31 | + } | |
32 | + }, | |
33 | + mode: { | |
34 | + type: String, | |
35 | + default: 'markdown' | |
36 | + }, | |
37 | + height: { | |
38 | + type: String, | |
39 | + required: false, | |
40 | + default: '300px' | |
41 | + }, | |
42 | + language: { | |
43 | + type: String, | |
44 | + required: false, | |
45 | + default: 'en_US' | |
46 | + } | |
47 | + }, | |
48 | + data() { | |
49 | + return { | |
50 | + editor: null | |
51 | + } | |
52 | + }, | |
53 | + computed: { | |
54 | + editorOptions() { | |
55 | + const options = Object.assign({}, defaultOptions, this.options) | |
56 | + options.initialEditType = this.mode | |
57 | + options.height = this.height | |
58 | + options.language = this.language | |
59 | + return options | |
60 | + } | |
61 | + }, | |
62 | + watch: { | |
63 | + value(newValue, preValue) { | |
64 | + if (newValue !== preValue && newValue !== this.editor.getValue()) { | |
65 | + this.editor.setValue(newValue) | |
66 | + } | |
67 | + }, | |
68 | + language(val) { | |
69 | + this.destroyEditor() | |
70 | + this.initEditor() | |
71 | + }, | |
72 | + height(newValue) { | |
73 | + this.editor.height(newValue) | |
74 | + }, | |
75 | + mode(newValue) { | |
76 | + this.editor.changeMode(newValue) | |
77 | + } | |
78 | + }, | |
79 | + mounted() { | |
80 | + this.initEditor() | |
81 | + }, | |
82 | + destroyed() { | |
83 | + this.destroyEditor() | |
84 | + }, | |
85 | + methods: { | |
86 | + initEditor() { | |
87 | + this.editor = new Editor({ | |
88 | + el: document.getElementById(this.id), | |
89 | + ...this.editorOptions | |
90 | + }) | |
91 | + if (this.value) { | |
92 | + this.editor.setValue(this.value) | |
93 | + } | |
94 | + this.editor.on('change', () => { | |
95 | + this.$emit('change', this.editor.getValue()) | |
96 | + }) | |
97 | + }, | |
98 | + destroyEditor() { | |
99 | + if (!this.editor) return | |
100 | + this.editor.off('change') | |
101 | + this.editor.remove() | |
102 | + }, | |
103 | + setValue(value) { | |
104 | + this.editor.setValue(value) | |
105 | + }, | |
106 | + getValue() { | |
107 | + return this.editor.getValue() | |
108 | + }, | |
109 | + setHtml(value) { | |
110 | + this.editor.setHtml(value) | |
111 | + }, | |
112 | + getHtml() { | |
113 | + return this.editor.getHtml() | |
114 | + } | |
115 | + }, | |
116 | + model: { | |
117 | + prop: 'value', | |
118 | + event: 'change' | |
119 | + } | |
120 | +} | |
121 | +</script> | |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JModal/index.vue
1 | 1 | <template> |
2 | 2 | <a-modal |
3 | 3 | ref="modal" |
4 | - class="j-modal-box" | |
5 | - :class="{'fullscreen':innerFullscreen,'no-title':isNoTitle,'no-footer':isNoFooter,}" | |
4 | + :class="getClass(modalClass)" | |
5 | + :style="getStyle(modalStyle)" | |
6 | 6 | :visible="visible" |
7 | 7 | v-bind="_attrs" |
8 | 8 | v-on="$listeners" |
... | ... | @@ -38,6 +38,8 @@ |
38 | 38 | |
39 | 39 | <script> |
40 | 40 | |
41 | + import { getClass, getStyle } from '@/utils/props-util' | |
42 | + | |
41 | 43 | export default { |
42 | 44 | name: 'JModal', |
43 | 45 | props: { |
... | ... | @@ -47,13 +49,18 @@ |
47 | 49 | // 是否全屏弹窗,当全屏时无论如何都会禁止 body 滚动。可使用 .sync 修饰符 |
48 | 50 | fullscreen: { |
49 | 51 | type: Boolean, |
50 | - default: true | |
52 | + default: false | |
51 | 53 | }, |
52 | 54 | // 是否允许切换全屏(允许后右上角会出现一个按钮) |
53 | 55 | switchFullscreen: { |
54 | 56 | type: Boolean, |
55 | 57 | default: false |
56 | 58 | }, |
59 | + // 点击确定按钮的时候是否关闭弹窗 | |
60 | + okClose: { | |
61 | + type: Boolean, | |
62 | + default: true | |
63 | + }, | |
57 | 64 | }, |
58 | 65 | data() { |
59 | 66 | return { |
... | ... | @@ -73,6 +80,22 @@ |
73 | 80 | } |
74 | 81 | return attrs |
75 | 82 | }, |
83 | + modalClass() { | |
84 | + return { | |
85 | + 'j-modal-box': true, | |
86 | + 'fullscreen': this.innerFullscreen, | |
87 | + 'no-title': this.isNoTitle, | |
88 | + 'no-footer': this.isNoFooter, | |
89 | + } | |
90 | + }, | |
91 | + modalStyle() { | |
92 | + let style = {} | |
93 | + // 如果全屏就将top设为 0 | |
94 | + if (this.innerFullscreen) { | |
95 | + style['top'] = '0' | |
96 | + } | |
97 | + return style | |
98 | + }, | |
76 | 99 | isNoTitle() { |
77 | 100 | return !this.title && !this.allSlotsKeys.includes('title') |
78 | 101 | }, |
... | ... | @@ -90,7 +113,7 @@ |
90 | 113 | }, |
91 | 114 | // 切换全屏的按钮图标 |
92 | 115 | fullscreenButtonIcon() { |
93 | - return this.innerFullscreen ? 'fullscreen' : 'fullscreen-exit' | |
116 | + return this.innerFullscreen ? 'fullscreen-exit' : 'fullscreen' | |
94 | 117 | }, |
95 | 118 | }, |
96 | 119 | watch: { |
... | ... | @@ -105,12 +128,21 @@ |
105 | 128 | }, |
106 | 129 | methods: { |
107 | 130 | |
131 | + getClass(clazz) { | |
132 | + return { ...getClass(this), ...clazz } | |
133 | + }, | |
134 | + getStyle(style) { | |
135 | + return { ...getStyle(this), ...style } | |
136 | + }, | |
137 | + | |
108 | 138 | close() { |
109 | 139 | this.$emit('update:visible', false) |
110 | 140 | }, |
111 | 141 | |
112 | 142 | handleOk() { |
113 | - this.close() | |
143 | + if (this.okClose) { | |
144 | + this.close() | |
145 | + } | |
114 | 146 | }, |
115 | 147 | handleCancel() { |
116 | 148 | this.close() |
... | ... | @@ -167,6 +199,7 @@ |
167 | 199 | |
168 | 200 | .right { |
169 | 201 | width: 56px; |
202 | + position: inherit; | |
170 | 203 | |
171 | 204 | .ant-modal-close { |
172 | 205 | right: 56px; |
... | ... | @@ -180,5 +213,13 @@ |
180 | 213 | } |
181 | 214 | } |
182 | 215 | |
216 | + | |
217 | + } | |
218 | + | |
219 | + @media (max-width: 767px) { | |
220 | + .j-modal-box.fullscreen { | |
221 | + margin: 0; | |
222 | + max-width: 100vw; | |
223 | + } | |
183 | 224 | } |
184 | 225 | </style> |
185 | 226 | \ No newline at end of file |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue
1 | 1 | <template> |
2 | 2 | <div class="j-super-query-box"> |
3 | 3 | |
4 | - <div @click="visible=true"> | |
5 | - <slot> | |
6 | - <a-tooltip v-if="superQueryFlag" :mouseLeaveDelay="0.2"> | |
7 | - <template slot="title"> | |
8 | - <span>已有高级查询条件生效</span> | |
9 | - <a-divider type="vertical"/> | |
10 | - <a @click="handleReset">清空</a> | |
11 | - </template> | |
12 | - <a-button type="primary"> | |
13 | - <a-icon type="appstore" theme="twoTone" :spin="true"></a-icon> | |
4 | + <slot name="button" :isActive="superQueryFlag" :isMobile="izMobile" :open="handleOpen" :reset="handleReset"> | |
5 | + <a-tooltip v-if="superQueryFlag" v-bind="tooltipProps" :mouseLeaveDelay="0.2"> | |
6 | + <!-- begin 不知道为什么不加上这段代码就无法生效 --> | |
7 | + <span v-show="false">{{tooltipProps}}</span> | |
8 | + <!-- end 不知道为什么不加上这段代码就无法生效 --> | |
9 | + <template slot="title"> | |
10 | + <span>已有高级查询条件生效</span> | |
11 | + <a-divider type="vertical"/> | |
12 | + <a @click="handleReset">清空</a> | |
13 | + </template> | |
14 | + <a-button-group> | |
15 | + <a-button type="primary" @click="handleOpen"> | |
16 | + <a-icon type="appstore" theme="twoTone" spin/> | |
14 | 17 | <span>高级查询</span> |
15 | 18 | </a-button> |
16 | - </a-tooltip> | |
17 | - <a-button v-else type="primary" icon="filter" @click="visible=true">高级查询</a-button> | |
18 | - </slot> | |
19 | - </div> | |
19 | + <a-button v-if="izMobile" type="primary" icon="delete" @click="handleReset"/> | |
20 | + </a-button-group> | |
21 | + </a-tooltip> | |
22 | + <a-button v-else type="primary" icon="filter" @click="handleOpen">高级查询</a-button> | |
23 | + </slot> | |
20 | 24 | |
21 | - <a-modal | |
25 | + <j-modal | |
22 | 26 | title="高级查询构造器" |
23 | 27 | :width="1000" |
24 | 28 | :visible="visible" |
25 | 29 | @cancel="handleCancel" |
26 | 30 | :mask="false" |
31 | + :fullscreen="izMobile" | |
27 | 32 | class="j-super-query-modal" |
28 | - style="top:5%;max-height: 95%;"> | |
33 | + style="top:5%;max-height: 95%;" | |
34 | + > | |
29 | 35 | |
30 | 36 | <template slot="footer"> |
31 | 37 | <div style="float: left"> |
... | ... | @@ -40,7 +46,7 @@ |
40 | 46 | <a-row> |
41 | 47 | <a-col :sm="24" :md="24-5"> |
42 | 48 | |
43 | - <a-empty v-if="queryParamsModel.length === 0"> | |
49 | + <a-empty v-if="queryParamsModel.length === 0" style="margin-bottom: 12px;"> | |
44 | 50 | <div slot="description"> |
45 | 51 | <span>没有任何查询条件</span> |
46 | 52 | <a-divider type="vertical"/> |
... | ... | @@ -50,16 +56,20 @@ |
50 | 56 | |
51 | 57 | <a-form v-else layout="inline"> |
52 | 58 | |
53 | - <a-form-item label="过滤条件匹配" style="margin-bottom: 12px;"> | |
54 | - <a-select v-model="selectValue" :getPopupContainer="node=>node.parentNode"> | |
55 | - <a-select-option value="and">AND(所有条件都要求匹配)</a-select-option> | |
56 | - <a-select-option value="or">OR(条件中的任意一个匹配)</a-select-option> | |
57 | - </a-select> | |
58 | - </a-form-item> | |
59 | + <a-row style="margin-bottom: 12px;"> | |
60 | + <a-col :md="12" :xs="24"> | |
61 | + <a-form-item label="过滤条件匹配" :labelCol="{md: 6,xs:24}" :wrapperCol="{md: 18,xs:24}" style="width: 100%;"> | |
62 | + <a-select v-model="matchType" :getPopupContainer="node=>node.parentNode" style="width: 100%;"> | |
63 | + <a-select-option value="and">AND(所有条件都要求匹配)</a-select-option> | |
64 | + <a-select-option value="or">OR(条件中的任意一个匹配)</a-select-option> | |
65 | + </a-select> | |
66 | + </a-form-item> | |
67 | + </a-col> | |
68 | + </a-row> | |
59 | 69 | |
60 | 70 | <a-row type="flex" style="margin-bottom:10px" :gutter="16" v-for="(item, index) in queryParamsModel" :key="index"> |
61 | 71 | |
62 | - <a-col :span="8"> | |
72 | + <a-col :md="8" :xs="24" style="margin-bottom: 12px;"> | |
63 | 73 | <a-tree-select |
64 | 74 | showSearch |
65 | 75 | v-model="item.field" |
... | ... | @@ -75,22 +85,22 @@ |
75 | 85 | </a-tree-select> |
76 | 86 | </a-col> |
77 | 87 | |
78 | - <a-col :span="4"> | |
79 | - <a-select placeholder="匹配规则" v-model="item.rule" :getPopupContainer="node=>node.parentNode"> | |
88 | + <a-col :md="4" :xs="24" style="margin-bottom: 12px;"> | |
89 | + <a-select placeholder="匹配规则" :value="item.rule" :getPopupContainer="node=>node.parentNode" @change="handleRuleChange(item,$event)"> | |
80 | 90 | <a-select-option value="eq">等于</a-select-option> |
91 | + <a-select-option value="like">包含</a-select-option> | |
92 | + <a-select-option value="right_like">以..开始</a-select-option> | |
93 | + <a-select-option value="left_like">以..结尾</a-select-option> | |
94 | + <a-select-option value="in">在...中</a-select-option> | |
81 | 95 | <a-select-option value="ne">不等于</a-select-option> |
82 | 96 | <a-select-option value="gt">大于</a-select-option> |
83 | 97 | <a-select-option value="ge">大于等于</a-select-option> |
84 | 98 | <a-select-option value="lt">小于</a-select-option> |
85 | 99 | <a-select-option value="le">小于等于</a-select-option> |
86 | - <a-select-option value="right_like">以..开始</a-select-option> | |
87 | - <a-select-option value="left_like">以..结尾</a-select-option> | |
88 | - <a-select-option value="like">包含</a-select-option> | |
89 | - <a-select-option value="in">在...中</a-select-option> | |
90 | 100 | </a-select> |
91 | 101 | </a-col> |
92 | 102 | |
93 | - <a-col :span="8"> | |
103 | + <a-col :md="8" :xs="24" style="margin-bottom: 12px;"> | |
94 | 104 | <template v-if="item.dictCode"> |
95 | 105 | <template v-if="item.type === 'table-dict'"> |
96 | 106 | <j-popup |
... | ... | @@ -101,10 +111,14 @@ |
101 | 111 | :destFields="item.dictCode" |
102 | 112 | ></j-popup> |
103 | 113 | </template> |
104 | - <j-dict-select-tag v-else v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/> | |
114 | + <template v-else> | |
115 | + <j-multi-select-tag v-show="allowMultiple(item)" v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/> | |
116 | + <j-dict-select-tag v-show="!allowMultiple(item)" v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/> | |
117 | + </template> | |
105 | 118 | </template> |
119 | + <j-popup v-else-if="item.type === 'popup'" :value="item.val" v-bind="item.popup" group-id="superQuery" @input="(e,v)=>handleChangeJPopup(item,e,v)"/> | |
106 | 120 | <j-select-multi-user |
107 | - v-else-if="item.type === 'select-user'" | |
121 | + v-else-if="item.type === 'select-user' || item.type === 'sel_user'" | |
108 | 122 | v-model="item.val" |
109 | 123 | :buttons="false" |
110 | 124 | :multiple="false" |
... | ... | @@ -112,20 +126,34 @@ |
112 | 126 | :returnKeys="['id', item.customReturnField || 'username']" |
113 | 127 | /> |
114 | 128 | <j-select-depart |
115 | - v-else-if="item.type === 'select-depart'" | |
129 | + v-else-if="item.type === 'select-depart' || item.type === 'sel_depart'" | |
116 | 130 | v-model="item.val" |
117 | 131 | :multi="false" |
118 | 132 | placeholder="请选择部门" |
119 | 133 | :customReturnField="item.customReturnField || 'id'" |
120 | 134 | /> |
121 | - <a-select v-else-if="item.options instanceof Array" v-model="item.val" :options="item.options" allowClear placeholder="请选择"/> | |
135 | + <a-select | |
136 | + v-else-if="item.options instanceof Array" | |
137 | + v-model="item.val" | |
138 | + :options="item.options" | |
139 | + allowClear | |
140 | + placeholder="请选择" | |
141 | + :mode="allowMultiple(item)?'multiple':''" | |
142 | + /> | |
143 | + <j-area-linkage v-model="item.val" v-else-if="item.type==='area-linkage' || item.type==='pca'" style="width: 100%"/> | |
122 | 144 | <j-date v-else-if=" item.type=='date' " v-model="item.val" placeholder="请选择日期" style="width: 100%"></j-date> |
123 | 145 | <j-date v-else-if=" item.type=='datetime' " v-model="item.val" placeholder="请选择时间" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"></j-date> |
146 | + <a-time-picker v-else-if="item.type==='time'" :value="item.val ? moment(item.val,'HH:mm:ss') : null" format="HH:mm:ss" style="width: 100%" @change="(time,value)=>item.val=value"/> | |
124 | 147 | <a-input-number v-else-if=" item.type=='int'||item.type=='number' " style="width: 100%" placeholder="请输入数值" v-model="item.val"/> |
125 | 148 | <a-input v-else v-model="item.val" placeholder="请输入值"/> |
126 | 149 | </a-col> |
127 | 150 | |
128 | - <a-col :span="4"> | |
151 | + <a-col :md="4" :xs="0" style="margin-bottom: 12px;"> | |
152 | + <a-button @click="handleAdd" icon="plus"></a-button> | |
153 | + <a-button @click="handleDel( index )" icon="minus"></a-button> | |
154 | + </a-col> | |
155 | + | |
156 | + <a-col :md="0" :xs="24" style="margin-bottom: 12px;text-align: right;"> | |
129 | 157 | <a-button @click="handleAdd" icon="plus"></a-button> |
130 | 158 | <a-button @click="handleDel( index )" icon="minus"></a-button> |
131 | 159 | </a-col> |
... | ... | @@ -142,14 +170,14 @@ |
142 | 170 | 保存的查询 |
143 | 171 | </div> |
144 | 172 | |
145 | - <a-empty v-if="treeData.length === 0" class="j-super-query-history-empty" description="没有保存任何查询"/> | |
173 | + <a-empty v-if="saveTreeData.length === 0" class="j-super-query-history-empty" description="没有保存任何查询"/> | |
146 | 174 | <a-tree |
147 | 175 | v-else |
148 | 176 | class="j-super-query-history-tree" |
149 | 177 | showIcon |
150 | - :treeData="treeData" | |
178 | + :treeData="saveTreeData" | |
179 | + :selectedKeys="[]" | |
151 | 180 | @select="handleTreeSelect" |
152 | - @rightClick="handleTreeRightClick" | |
153 | 181 | > |
154 | 182 | </a-tree> |
155 | 183 | </a-card> |
... | ... | @@ -165,19 +193,24 @@ |
165 | 193 | <a-input v-model="prompt.value"></a-input> |
166 | 194 | </a-modal> |
167 | 195 | |
168 | - </a-modal> | |
196 | + </j-modal> | |
169 | 197 | </div> |
170 | 198 | </template> |
171 | 199 | |
172 | 200 | <script> |
201 | + import moment from 'moment' | |
173 | 202 | import * as utils from '@/utils/util' |
203 | + import { mixinDevice } from '@/utils/mixin' | |
174 | 204 | import JDate from '@/components/jeecg/JDate.vue' |
175 | 205 | import JSelectDepart from '@/components/jeecgbiz/JSelectDepart' |
176 | 206 | import JSelectMultiUser from '@/components/jeecgbiz/JSelectMultiUser' |
207 | + import JMultiSelectTag from '@/components/dict/JMultiSelectTag' | |
208 | + import JAreaLinkage from '@comp/jeecg/JAreaLinkage' | |
177 | 209 | |
178 | 210 | export default { |
179 | 211 | name: 'JSuperQuery', |
180 | - components: { JDate, JSelectDepart, JSelectMultiUser }, | |
212 | + mixins: [mixinDevice], | |
213 | + components: { JAreaLinkage, JMultiSelectTag, JDate, JSelectDepart, JSelectMultiUser }, | |
181 | 214 | props: { |
182 | 215 | /* |
183 | 216 | fieldList: [{ |
... | ... | @@ -208,14 +241,16 @@ |
208 | 241 | }, |
209 | 242 | |
210 | 243 | // 保存查询条件的唯一 code,通过该 code 区分 |
244 | + // 默认为 null,代表以当前路由全路径为区分Code | |
211 | 245 | saveCode: { |
212 | 246 | type: String, |
213 | - default: 'testSaveCode' | |
247 | + default: null | |
214 | 248 | } |
215 | 249 | |
216 | 250 | }, |
217 | 251 | data() { |
218 | 252 | return { |
253 | + moment, | |
219 | 254 | fieldTreeData: [], |
220 | 255 | |
221 | 256 | prompt: { |
... | ... | @@ -224,26 +259,40 @@ |
224 | 259 | }, |
225 | 260 | |
226 | 261 | visible: false, |
227 | - queryParamsModel: [{}], | |
262 | + queryParamsModel: [], | |
228 | 263 | treeIcon: <a-icon type="file-text"/>, |
229 | - treeData: [], | |
264 | + // 保存查询条件的treeData | |
265 | + saveTreeData: [], | |
230 | 266 | // 保存查询条件的前缀名 |
231 | 267 | saveCodeBefore: 'JSuperQuerySaved_', |
232 | - selectValue: 'and', | |
233 | - superQueryFlag: false | |
268 | + // 查询类型,过滤条件匹配(and、or) | |
269 | + matchType: 'and', | |
270 | + superQueryFlag: false, | |
234 | 271 | } |
235 | 272 | }, |
273 | + computed: { | |
274 | + izMobile() { | |
275 | + return this.device === 'mobile' | |
276 | + }, | |
277 | + tooltipProps() { | |
278 | + return this.izMobile ? { visible: false } : {} | |
279 | + }, | |
280 | + fullSaveCode() { | |
281 | + let saveCode = this.saveCode | |
282 | + if (saveCode == null || saveCode === '') { | |
283 | + saveCode = this.$route.fullPath | |
284 | + } | |
285 | + return this.saveCodeBefore + saveCode | |
286 | + }, | |
287 | + }, | |
236 | 288 | watch: { |
237 | 289 | // 当 saveCode 变化时,重新查询已保存的条件 |
238 | - saveCode: { | |
290 | + fullSaveCode: { | |
239 | 291 | immediate: true, |
240 | - handler(val) { | |
241 | - let list = this.$ls.get(this.saveCodeBefore + val) | |
292 | + handler() { | |
293 | + let list = this.$ls.get(this.fullSaveCode) | |
242 | 294 | if (list instanceof Array) { |
243 | - this.treeData = list.map(item => { | |
244 | - item.icon = this.treeIcon | |
245 | - return item | |
246 | - }) | |
295 | + this.saveTreeData = list.map(i => this.renderSaveTreeData(i)) | |
247 | 296 | } |
248 | 297 | } |
249 | 298 | }, |
... | ... | @@ -280,25 +329,35 @@ |
280 | 329 | |
281 | 330 | methods: { |
282 | 331 | show() { |
283 | - if (!this.queryParamsModel || this.queryParamsModel.length == 0) { | |
284 | - this.queryParamsModel = [{}] | |
332 | + if (!this.queryParamsModel || this.queryParamsModel.length === 0) { | |
333 | + this.resetLine() | |
285 | 334 | } |
286 | 335 | this.visible = true |
287 | 336 | }, |
288 | 337 | handleOk() { |
289 | 338 | if (!this.isNullArray(this.queryParamsModel)) { |
290 | 339 | let event = { |
291 | - matchType: this.selectValue, | |
292 | - params: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel)) | |
340 | + matchType: this.matchType, | |
341 | + params: this.removeEmptyObject(this.queryParamsModel) | |
342 | + } | |
343 | + // 移动端模式下关闭弹窗 | |
344 | + if (this.izMobile) { | |
345 | + this.visible = false | |
293 | 346 | } |
294 | - console.log('---高级查询参数--->', event) | |
295 | - this.emitCallback(event.params, event.matchType) | |
347 | + this.emitCallback(event) | |
296 | 348 | } else { |
297 | - this.emitCallback() | |
349 | + this.$message.warn("不能查询空条件") | |
298 | 350 | } |
299 | 351 | }, |
300 | - emitCallback(params, matchType) { | |
301 | - this.superQueryFlag = !!params | |
352 | + emitCallback(event = {}) { | |
353 | + let { params = [], matchType = this.matchType } = event | |
354 | + this.superQueryFlag = (params && params.length > 0) | |
355 | + for (let param of params) { | |
356 | + if (Array.isArray(param.val)) { | |
357 | + param.val = param.val.join(',') | |
358 | + } | |
359 | + } | |
360 | + console.debug('---高级查询参数--->', { params, matchType }) | |
302 | 361 | this.$emit(this.callback, params, matchType) |
303 | 362 | }, |
304 | 363 | handleCancel() { |
... | ... | @@ -309,27 +368,40 @@ |
309 | 368 | this.visible = false |
310 | 369 | }, |
311 | 370 | handleAdd() { |
312 | - this.queryParamsModel.push({}) | |
371 | + this.addNewLine() | |
372 | + }, | |
373 | + addNewLine() { | |
374 | + this.queryParamsModel.push({ rule: 'eq' }) | |
375 | + }, | |
376 | + resetLine() { | |
377 | + this.superQueryFlag = false | |
378 | + this.queryParamsModel = [] | |
379 | + this.addNewLine() | |
313 | 380 | }, |
314 | 381 | handleDel(index) { |
315 | 382 | this.queryParamsModel.splice(index, 1) |
316 | 383 | }, |
317 | 384 | handleSelected(node, item) { |
318 | - let { type, options, dictCode, dictTable, customReturnField } = node.dataRef | |
385 | + let { type, options, dictCode, dictTable, customReturnField, popup } = node.dataRef | |
319 | 386 | item['type'] = type |
320 | 387 | item['options'] = options |
321 | 388 | item['dictCode'] = dictCode |
322 | 389 | item['dictTable'] = dictTable |
323 | 390 | item['customReturnField'] = customReturnField |
391 | + if (popup) { | |
392 | + item['popup'] = popup | |
393 | + } | |
324 | 394 | this.$set(item, 'val', undefined) |
325 | 395 | }, |
396 | + handleOpen() { | |
397 | + this.show() | |
398 | + }, | |
326 | 399 | handleReset() { |
327 | - this.superQueryFlag = false | |
328 | - this.queryParamsModel = [{}] | |
400 | + this.resetLine() | |
329 | 401 | this.emitCallback() |
330 | 402 | }, |
331 | 403 | handleSave() { |
332 | - let queryParams = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel)) | |
404 | + let queryParams = this.removeEmptyObject(this.queryParamsModel) | |
333 | 405 | if (this.isNullArray(queryParams)) { |
334 | 406 | this.$message.warning('空条件不能保存') |
335 | 407 | } else { |
... | ... | @@ -338,56 +410,65 @@ |
338 | 410 | } |
339 | 411 | }, |
340 | 412 | handlePromptOk() { |
341 | - | |
342 | 413 | let { value } = this.prompt |
343 | - // 判断有没有重名 | |
344 | - | |
345 | - let filterList = this.treeData.filter(i => i.title === value) | |
414 | + if(!value){ | |
415 | + this.$message.warning('保存名称不能为空') | |
416 | + return | |
417 | + } | |
418 | + // 取出查询条件 | |
419 | + let records = this.removeEmptyObject(this.queryParamsModel) | |
420 | + // 判断有没有重名的 | |
421 | + let filterList = this.saveTreeData.filter(i => i.originTitle === value) | |
346 | 422 | if (filterList.length > 0) { |
347 | 423 | this.$confirm({ |
348 | 424 | content: `${value} 已存在,是否覆盖?`, |
349 | 425 | onOk: () => { |
350 | 426 | this.prompt.visible = false |
351 | - filterList[0].records = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel)) | |
427 | + filterList[0].records = records | |
352 | 428 | this.saveToLocalStore() |
353 | 429 | this.$message.success('保存成功') |
354 | 430 | } |
355 | 431 | }) |
356 | 432 | } else { |
433 | + // 没有重名的,直接添加 | |
357 | 434 | this.prompt.visible = false |
358 | - this.treeData.push({ | |
435 | + // 添加到树列表中 | |
436 | + this.saveTreeData.push(this.renderSaveTreeData({ | |
359 | 437 | title: value, |
360 | - icon: this.treeIcon, | |
361 | - records: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel)) | |
362 | - }) | |
438 | + matchType: this.matchType, | |
439 | + records: records | |
440 | + })) | |
441 | + // 保存到 LocalStore | |
363 | 442 | this.saveToLocalStore() |
364 | 443 | this.$message.success('保存成功') |
365 | 444 | } |
366 | - | |
367 | - | |
368 | 445 | }, |
369 | 446 | handleTreeSelect(idx, event) { |
370 | 447 | if (event.selectedNodes[0]) { |
371 | - this.queryParamsModel = utils.cloneObject(event.selectedNodes[0].data.props.records) | |
448 | + let { matchType, records } = event.selectedNodes[0].data.props | |
449 | + // 将保存的matchType取出,兼容旧数据,如果没有保存就还是使用原来的 | |
450 | + this.matchType = matchType || this.matchType | |
451 | + this.queryParamsModel = utils.cloneObject(records) | |
372 | 452 | } |
373 | 453 | }, |
374 | - handleTreeRightClick(args) { | |
454 | + handleRemoveSaveTreeItem(event, vNode) { | |
455 | + // 阻止事件冒泡 | |
456 | + event.stopPropagation() | |
457 | + | |
375 | 458 | this.$confirm({ |
376 | 459 | content: '是否删除当前查询?', |
377 | 460 | onOk: () => { |
378 | - let { node: { eventKey } } = args | |
379 | - this.treeData.splice(Number.parseInt(eventKey.substring(2)), 1) | |
461 | + let { eventKey } = vNode | |
462 | + this.saveTreeData.splice(Number.parseInt(eventKey.substring(2)), 1) | |
380 | 463 | this.saveToLocalStore() |
381 | - this.$message.success('删除成功') | |
382 | 464 | }, |
383 | 465 | }) |
384 | 466 | }, |
385 | 467 | |
386 | 468 | // 将查询保存到 LocalStore 里 |
387 | 469 | saveToLocalStore() { |
388 | - this.$ls.set(this.saveCodeBefore + this.saveCode, this.treeData.map(item => { | |
389 | - return { title: item.title, records: item.records } | |
390 | - })) | |
470 | + let saveValue = this.saveTreeData.map(({ originTitle, matchType, records }) => ({ title: originTitle, matchType, records })) | |
471 | + this.$ls.set(this.fullSaveCode, saveValue) | |
391 | 472 | }, |
392 | 473 | |
393 | 474 | isNullArray(array) { |
... | ... | @@ -404,18 +485,70 @@ |
404 | 485 | return false |
405 | 486 | }, |
406 | 487 | // 去掉数组中的空对象 |
407 | - removeEmptyObject(array) { | |
488 | + removeEmptyObject(arr) { | |
489 | + let array = utils.cloneObject(arr) | |
408 | 490 | for (let i = 0; i < array.length; i++) { |
409 | 491 | let item = array[i] |
410 | 492 | if (item == null || Object.keys(item).length <= 0) { |
411 | 493 | array.splice(i--, 1) |
412 | 494 | } else { |
413 | - // 去掉特殊属性 | |
414 | - delete item.options | |
495 | + if (Array.isArray(item.options)) { | |
496 | + // 如果有字典属性,就不需要保存 options 了 | |
497 | + if (item.dictCode) { | |
498 | + // 去掉特殊属性 | |
499 | + delete item.options | |
500 | + } | |
501 | + } | |
415 | 502 | } |
416 | 503 | } |
417 | 504 | return array |
418 | - } | |
505 | + }, | |
506 | + | |
507 | + /** 渲染保存查询条件的 title(加个删除按钮) */ | |
508 | + renderSaveTreeData(item) { | |
509 | + item.icon = this.treeIcon | |
510 | + item.originTitle = item['title'] | |
511 | + item.title = (fn, vNode) => { | |
512 | + let { originTitle } = vNode.dataRef | |
513 | + return ( | |
514 | + <div class="j-history-tree-title"> | |
515 | + <span>{originTitle}</span> | |
516 | + | |
517 | + <div class="j-history-tree-title-closer" onClick={e => this.handleRemoveSaveTreeItem(e, vNode)}> | |
518 | + <a-icon type="close-circle"/> | |
519 | + </div> | |
520 | + </div> | |
521 | + ) | |
522 | + } | |
523 | + return item | |
524 | + }, | |
525 | + | |
526 | + /** 判断是否允许多选 */ | |
527 | + allowMultiple(item) { | |
528 | + return item.rule === 'in' | |
529 | + }, | |
530 | + | |
531 | + handleRuleChange(item, newValue) { | |
532 | + let oldValue = item.rule | |
533 | + this.$set(item, 'rule', newValue) | |
534 | + // 上一个规则是否是 in,且type是字典或下拉 | |
535 | + if (oldValue === 'in') { | |
536 | + if (item.dictCode || item.options instanceof Array) { | |
537 | + let value = item.val | |
538 | + if (typeof item.val === 'string') { | |
539 | + value = item.val.split(',')[0] | |
540 | + } else if (Array.isArray(item.val)) { | |
541 | + value = item.val[0] | |
542 | + } | |
543 | + this.$set(item, 'val', value) | |
544 | + } | |
545 | + } | |
546 | + }, | |
547 | + | |
548 | + handleChangeJPopup(item, e, values) { | |
549 | + item.val = values[item.popup['destFields']] | |
550 | + }, | |
551 | + | |
419 | 552 | } |
420 | 553 | } |
421 | 554 | </script> |
... | ... | @@ -428,42 +561,76 @@ |
428 | 561 | |
429 | 562 | .j-super-query-modal { |
430 | 563 | |
431 | - .j-super-query-history-card /deep/ { | |
432 | - .ant-card-body, | |
433 | - .ant-card-head-title { | |
564 | + .j-super-query-history-card { | |
565 | + /deep/ .ant-card-body, | |
566 | + /deep/ .ant-card-head-title { | |
434 | 567 | padding: 0; |
435 | 568 | } |
436 | 569 | |
437 | - .ant-card-head { | |
570 | + /deep/ .ant-card-head { | |
438 | 571 | padding: 4px 8px; |
439 | 572 | min-height: initial; |
440 | 573 | } |
441 | 574 | } |
442 | 575 | |
443 | - .j-super-query-history-empty /deep/ { | |
444 | - .ant-empty-image { | |
576 | + .j-super-query-history-empty { | |
577 | + /deep/ .ant-empty-image { | |
445 | 578 | height: 80px; |
446 | 579 | line-height: 80px; |
447 | 580 | margin-bottom: 0; |
448 | 581 | } |
449 | 582 | |
450 | - img { | |
583 | + /deep/ img { | |
451 | 584 | width: 80px; |
452 | 585 | height: 65px; |
453 | 586 | } |
454 | 587 | |
455 | - .ant-empty-description { | |
588 | + /deep/ .ant-empty-description { | |
456 | 589 | color: #afafaf; |
457 | 590 | margin: 8px 0; |
458 | 591 | } |
459 | 592 | } |
460 | 593 | |
461 | - .j-super-query-history-tree /deep/ { | |
462 | - .ant-tree-switcher { | |
594 | + .j-super-query-history-tree { | |
595 | + | |
596 | + .j-history-tree-title { | |
597 | + width: calc(100% - 24px); | |
598 | + position: relative; | |
599 | + display: inline-block; | |
600 | + | |
601 | + &-closer { | |
602 | + color: #999999; | |
603 | + position: absolute; | |
604 | + top: 0; | |
605 | + right: 0; | |
606 | + width: 24px; | |
607 | + height: 24px; | |
608 | + text-align: center; | |
609 | + opacity: 0; | |
610 | + transition: opacity 0.3s, color 0.3s; | |
611 | + | |
612 | + &:hover { | |
613 | + color: #666666; | |
614 | + } | |
615 | + | |
616 | + &:active { | |
617 | + color: #333333; | |
618 | + } | |
619 | + } | |
620 | + | |
621 | + &:hover { | |
622 | + .j-history-tree-title-closer { | |
623 | + opacity: 1; | |
624 | + } | |
625 | + } | |
626 | + | |
627 | + } | |
628 | + | |
629 | + /deep/ .ant-tree-switcher { | |
463 | 630 | display: none; |
464 | 631 | } |
465 | 632 | |
466 | - .ant-tree-node-content-wrapper { | |
633 | + /deep/ .ant-tree-node-content-wrapper { | |
467 | 634 | width: 100%; |
468 | 635 | } |
469 | 636 | } |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JSwitch.vue
0 → 100644
1 | +<template> | |
2 | + <a-switch v-model="checkStatus" :disabled="disabled" @change="handleChange"/> | |
3 | +</template> | |
4 | +<script> | |
5 | + | |
6 | + export default { | |
7 | + name: 'JSwitch', | |
8 | + props: { | |
9 | + value:{ | |
10 | + type: String, | |
11 | + required: false | |
12 | + }, | |
13 | + disabled:{ | |
14 | + type: Boolean, | |
15 | + required: false, | |
16 | + default: false | |
17 | + }, | |
18 | + options:{ | |
19 | + type:Array, | |
20 | + required:false, | |
21 | + default:()=>['Y','N'] | |
22 | + } | |
23 | + }, | |
24 | + data () { | |
25 | + return { | |
26 | + checkStatus: false | |
27 | + } | |
28 | + }, | |
29 | + watch: { | |
30 | + value:{ | |
31 | + immediate: true, | |
32 | + handler(val){ | |
33 | + if(!val){ | |
34 | + this.checkStatus = false | |
35 | + this.$emit('change', this.options[1]); | |
36 | + }else{ | |
37 | + if(this.options[0]==val){ | |
38 | + this.checkStatus = true | |
39 | + }else{ | |
40 | + this.checkStatus = false | |
41 | + } | |
42 | + } | |
43 | + } | |
44 | + } | |
45 | + }, | |
46 | + methods: { | |
47 | + handleChange(checked){ | |
48 | + let flag = checked===false?this.options[1]:this.options[0]; | |
49 | + this.$emit('change', flag); | |
50 | + } | |
51 | + }, | |
52 | + model: { | |
53 | + prop: 'value', | |
54 | + event: 'change' | |
55 | + } | |
56 | + } | |
57 | +</script> | |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JTreeDict.vue
... | ... | @@ -180,7 +180,11 @@ |
180 | 180 | }, |
181 | 181 | onChange(value){ |
182 | 182 | console.log(value) |
183 | - this.$emit('change', value.value); | |
183 | + if(!value){ | |
184 | + this.$emit('change', ''); | |
185 | + }else{ | |
186 | + this.$emit('change', value.value); | |
187 | + } | |
184 | 188 | this.treeValue = value |
185 | 189 | }, |
186 | 190 | onSearch(value){ |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JTreeSelect.vue
ant-design-vue-jeecg/src/components/jeecg/JUpload.vue
1 | 1 | <template> |
2 | - <a-upload | |
3 | - name="file" | |
4 | - :multiple="true" | |
5 | - :action="uploadAction" | |
6 | - :headers="headers" | |
7 | - :data="{'biz':bizPath}" | |
8 | - :fileList="fileList" | |
9 | - :beforeUpload="beforeUpload" | |
10 | - @change="handleChange" | |
11 | - :disabled="disabled" | |
12 | - :returnUrl="returnUrl"> | |
13 | - <a-button> | |
14 | - <a-icon type="upload" />{{ text }} | |
15 | - </a-button> | |
16 | - </a-upload> | |
2 | + <div :id="containerId" style="position: relative"> | |
3 | + | |
4 | + <!-- ---------------------------- begin 图片左右换位置 ------------------------------------- --> | |
5 | + <div class="movety-container" :style="{top:top+'px',left:left+'px',display:moveDisplay}" style="padding:0 8px;position: absolute;z-index: 91;height: 32px;width: 104px;text-align: center;"> | |
6 | + <div :id="containerId+'-mover'" :class="showMoverTask?'uploadty-mover-mask':'movety-opt'" style="margin-top: 12px"> | |
7 | + <a @click="moveLast" style="margin: 0 5px;"><a-icon type="arrow-left" style="color: #fff;font-size: 16px"/></a> | |
8 | + <a @click="moveNext" style="margin: 0 5px;"><a-icon type="arrow-right" style="color: #fff;font-size: 16px"/></a> | |
9 | + </div> | |
10 | + </div> | |
11 | + <!-- ---------------------------- end 图片左右换位置 ------------------------------------- --> | |
12 | + | |
13 | + <a-upload | |
14 | + name="file" | |
15 | + :multiple="true" | |
16 | + :action="uploadAction" | |
17 | + :headers="headers" | |
18 | + :data="{'biz':bizPath}" | |
19 | + :fileList="fileList" | |
20 | + :beforeUpload="beforeUpload" | |
21 | + @change="handleChange" | |
22 | + :disabled="disabled" | |
23 | + :returnUrl="returnUrl" | |
24 | + :listType="complistType" | |
25 | + @preview="handlePreview" | |
26 | + :class="{'uploadty-disabled':disabled}"> | |
27 | + <template> | |
28 | + <div v-if="isImageComp"> | |
29 | + <a-icon type="plus" /> | |
30 | + <div class="ant-upload-text">{{ text }}</div> | |
31 | + </div> | |
32 | + <a-button v-else-if="buttonVisible"> | |
33 | + <a-icon type="upload" />{{ text }} | |
34 | + </a-button> | |
35 | + </template> | |
36 | + </a-upload> | |
37 | + <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel"> | |
38 | + <img alt="example" style="width: 100%" :src="previewImage" /> | |
39 | + </a-modal> | |
40 | + </div> | |
17 | 41 | </template> |
18 | 42 | |
19 | 43 | <script> |
... | ... | @@ -40,10 +64,21 @@ |
40 | 64 | data(){ |
41 | 65 | return { |
42 | 66 | uploadAction:window._CONFIG['domianURL']+"/sys/common/upload", |
43 | - urlDownload:window._CONFIG['staticDomainURL'], | |
44 | 67 | headers:{}, |
45 | 68 | fileList: [], |
46 | 69 | newFileList: [], |
70 | + uploadGoOn:true, | |
71 | + previewVisible: false, | |
72 | + //---------------------------- begin 图片左右换位置 ------------------------------------- | |
73 | + previewImage: '', | |
74 | + containerId:'', | |
75 | + top:'', | |
76 | + left:'', | |
77 | + moveDisplay:'none', | |
78 | + showMoverTask:false, | |
79 | + moverHold:false, | |
80 | + currentImg:'' | |
81 | + //---------------------------- end 图片左右换位置 ------------------------------------- | |
47 | 82 | } |
48 | 83 | }, |
49 | 84 | props:{ |
... | ... | @@ -90,23 +125,48 @@ |
90 | 125 | required:false, |
91 | 126 | default: true |
92 | 127 | }, |
128 | + number:{ | |
129 | + type:Number, | |
130 | + required:false, | |
131 | + default: 0 | |
132 | + }, | |
133 | + buttonVisible:{ | |
134 | + type:Boolean, | |
135 | + required:false, | |
136 | + default: true | |
137 | + }, | |
93 | 138 | }, |
94 | 139 | watch:{ |
95 | - value(val){ | |
96 | - if (val instanceof Array) { | |
97 | - if(this.returnUrl){ | |
98 | - this.initFileList(val.join(',')) | |
99 | - }else{ | |
100 | - this.initFileListArr(val); | |
140 | + value:{ | |
141 | + immediate: true, | |
142 | + handler() { | |
143 | + let val = this.value | |
144 | + if (val instanceof Array) { | |
145 | + if(this.returnUrl){ | |
146 | + this.initFileList(val.join(',')) | |
147 | + }else{ | |
148 | + this.initFileListArr(val); | |
149 | + } | |
150 | + } else { | |
151 | + this.initFileList(val) | |
101 | 152 | } |
102 | - } else { | |
103 | - this.initFileList(val) | |
104 | 153 | } |
105 | 154 | } |
106 | 155 | }, |
156 | + computed:{ | |
157 | + isImageComp(){ | |
158 | + return this.fileType === FILE_TYPE_IMG | |
159 | + }, | |
160 | + complistType(){ | |
161 | + return this.fileType === FILE_TYPE_IMG?'picture-card':'text' | |
162 | + } | |
163 | + }, | |
107 | 164 | created(){ |
108 | 165 | const token = Vue.ls.get(ACCESS_TOKEN); |
109 | - this.headers = {"X-Access-Token":token} | |
166 | + //---------------------------- begin 图片左右换位置 ------------------------------------- | |
167 | + this.headers = {"X-Access-Token":token}; | |
168 | + this.containerId = 'container-ty-'+new Date().getTime(); | |
169 | + //---------------------------- end 图片左右换位置 ------------------------------------- | |
110 | 170 | }, |
111 | 171 | |
112 | 172 | methods:{ |
... | ... | @@ -117,11 +177,12 @@ |
117 | 177 | } |
118 | 178 | let fileList = []; |
119 | 179 | for(var a=0;a<val.length;a++){ |
180 | + let url = getFileAccessHttpUrl(val[a].filePath); | |
120 | 181 | fileList.push({ |
121 | 182 | uid:uidGenerator(), |
122 | 183 | name:val[a].fileName, |
123 | 184 | status: 'done', |
124 | - url: val[a].filePath, | |
185 | + url: url, | |
125 | 186 | response:{ |
126 | 187 | status:"history", |
127 | 188 | message:val[a].filePath |
... | ... | @@ -141,7 +202,7 @@ |
141 | 202 | let fileList = []; |
142 | 203 | let arr = paths.split(",") |
143 | 204 | for(var a=0;a<arr.length;a++){ |
144 | - let url = getFileAccessHttpUrl(arr[a],this.urlDownload,"http"); | |
205 | + let url = getFileAccessHttpUrl(arr[a]); | |
145 | 206 | fileList.push({ |
146 | 207 | uid:uidGenerator(), |
147 | 208 | name:getFileName(arr[a]), |
... | ... | @@ -172,15 +233,12 @@ |
172 | 233 | this.$emit('change', path); |
173 | 234 | }, |
174 | 235 | beforeUpload(file){ |
236 | + this.uploadGoOn=true | |
175 | 237 | var fileType = file.type; |
176 | - if(fileType===FILE_TYPE_IMG){ | |
238 | + if(this.fileType===FILE_TYPE_IMG){ | |
177 | 239 | if(fileType.indexOf('image')<0){ |
178 | 240 | this.$message.warning('请上传图片'); |
179 | - return false; | |
180 | - } | |
181 | - }else if(fileType===FILE_TYPE_TXT){ | |
182 | - if(fileType.indexOf('image')>=0){ | |
183 | - this.$message.warning('请上传文件'); | |
241 | + this.uploadGoOn=false | |
184 | 242 | return false; |
185 | 243 | } |
186 | 244 | } |
... | ... | @@ -189,13 +247,19 @@ |
189 | 247 | }, |
190 | 248 | handleChange(info) { |
191 | 249 | console.log("--文件列表改变--") |
250 | + if(!info.file.status && this.uploadGoOn === false){ | |
251 | + info.fileList.pop(); | |
252 | + } | |
192 | 253 | let fileList = info.fileList |
193 | 254 | if(info.file.status==='done'){ |
255 | + if(this.number>0){ | |
256 | + fileList = fileList.slice(-this.number); | |
257 | + } | |
194 | 258 | if(info.file.response.success){ |
195 | 259 | fileList = fileList.map((file) => { |
196 | 260 | if (file.response) { |
197 | 261 | let reUrl = file.response.message; |
198 | - file.url = getFileAccessHttpUrl(reUrl,this.urlDownload,"http"); | |
262 | + file.url = getFileAccessHttpUrl(reUrl); | |
199 | 263 | } |
200 | 264 | return file; |
201 | 265 | }); |
... | ... | @@ -213,20 +277,16 @@ |
213 | 277 | this.handlePathChange() |
214 | 278 | }else{ |
215 | 279 | //returnUrl为false时返回文件名称、文件路径及文件大小 |
216 | - fileList = fileList.filter((file) => { | |
217 | - if (file.response) { | |
218 | - return file.response.success === true; | |
219 | - } | |
220 | - return false; | |
221 | - }).map((file) => { | |
280 | + this.newFileList = []; | |
281 | + for(var a=0;a<fileList.length;a++){ | |
222 | 282 | var fileJson = { |
223 | - fileName:file.name, | |
224 | - filePath:file.response.message, | |
225 | - fileSize:file.size | |
283 | + fileName:fileList[a].name, | |
284 | + filePath:fileList[a].response.message, | |
285 | + fileSize:fileList[a].size | |
226 | 286 | }; |
227 | 287 | this.newFileList.push(fileJson); |
228 | - this.$emit('change', this.newFileList); | |
229 | - }); | |
288 | + } | |
289 | + this.$emit('change', this.newFileList); | |
230 | 290 | } |
231 | 291 | } |
232 | 292 | }, |
... | ... | @@ -234,6 +294,115 @@ |
234 | 294 | //如有需要新增 删除逻辑 |
235 | 295 | console.log(file) |
236 | 296 | }, |
297 | + handlePreview(file){ | |
298 | + if(this.fileType === FILE_TYPE_IMG){ | |
299 | + this.previewImage = file.url || file.thumbUrl; | |
300 | + this.previewVisible = true; | |
301 | + }else{ | |
302 | + location.href=file.url | |
303 | + } | |
304 | + }, | |
305 | + handleCancel(){ | |
306 | + this.previewVisible = false; | |
307 | + }, | |
308 | + //---------------------------- begin 图片左右换位置 ------------------------------------- | |
309 | + moveLast(){ | |
310 | + //console.log(ev) | |
311 | + //console.log(this.fileList) | |
312 | + //console.log(this.currentImg) | |
313 | + let index = this.getIndexByUrl(); | |
314 | + if(index==0){ | |
315 | + this.$message.warn('未知的操作') | |
316 | + }else{ | |
317 | + let curr = this.fileList[index].url; | |
318 | + let last = this.fileList[index-1].url; | |
319 | + let arr =[] | |
320 | + for(let i=0;i<this.fileList.length;i++){ | |
321 | + if(i==index-1){ | |
322 | + arr.push(curr) | |
323 | + }else if(i==index){ | |
324 | + arr.push(last) | |
325 | + }else{ | |
326 | + arr.push(this.fileList[i].url) | |
327 | + } | |
328 | + } | |
329 | + this.currentImg = last | |
330 | + this.$emit('change',arr.join(',')) | |
331 | + } | |
332 | + }, | |
333 | + moveNext(){ | |
334 | + let index = this.getIndexByUrl(); | |
335 | + if(index==this.fileList.length-1){ | |
336 | + this.$message.warn('已到最后~') | |
337 | + }else{ | |
338 | + let curr = this.fileList[index].url; | |
339 | + let next = this.fileList[index+1].url; | |
340 | + let arr =[] | |
341 | + for(let i=0;i<this.fileList.length;i++){ | |
342 | + if(i==index+1){ | |
343 | + arr.push(curr) | |
344 | + }else if(i==index){ | |
345 | + arr.push(next) | |
346 | + }else{ | |
347 | + arr.push(this.fileList[i].url) | |
348 | + } | |
349 | + } | |
350 | + this.currentImg = next | |
351 | + this.$emit('change',arr.join(',')) | |
352 | + } | |
353 | + }, | |
354 | + getIndexByUrl(){ | |
355 | + for(let i=0;i<this.fileList.length;i++){ | |
356 | + if(this.fileList[i].url === this.currentImg || encodeURI(this.fileList[i].url) === this.currentImg){ | |
357 | + return i; | |
358 | + } | |
359 | + } | |
360 | + return -1; | |
361 | + } | |
362 | + }, | |
363 | + mounted(){ | |
364 | + const moverObj = document.getElementById(this.containerId+'-mover'); | |
365 | + moverObj.addEventListener('mouseover',()=>{ | |
366 | + this.moverHold = true | |
367 | + this.moveDisplay = 'block'; | |
368 | + }); | |
369 | + moverObj.addEventListener('mouseout',()=>{ | |
370 | + this.moverHold = false | |
371 | + this.moveDisplay = 'none'; | |
372 | + }); | |
373 | + let picList = document.getElementById(this.containerId)?document.getElementById(this.containerId).getElementsByClassName('ant-upload-list-picture-card'):[]; | |
374 | + if(picList && picList.length>0){ | |
375 | + picList[0].addEventListener('mouseover',(ev)=>{ | |
376 | + ev = ev || window.event; | |
377 | + let target = ev.target || ev.srcElement; | |
378 | + if('ant-upload-list-item-info' == target.className){ | |
379 | + this.showMoverTask=false | |
380 | + let item = target.parentElement | |
381 | + this.left = item.offsetLeft | |
382 | + this.top=item.offsetTop+item.offsetHeight-50; | |
383 | + this.moveDisplay = 'block'; | |
384 | + this.currentImg = target.getElementsByTagName('img')[0].src | |
385 | + } | |
386 | + | |
387 | + }); | |
388 | + | |
389 | + picList[0].addEventListener('mouseout',(ev)=>{ | |
390 | + ev = ev || window.event; | |
391 | + let target = ev.target || ev.srcElement; | |
392 | + //console.log('移除',target) | |
393 | + if('ant-upload-list-item-info' == target.className){ | |
394 | + this.showMoverTask=true | |
395 | + setTimeout(()=>{ | |
396 | + if(this.moverHold === false) | |
397 | + this.moveDisplay = 'none'; | |
398 | + },100) | |
399 | + } | |
400 | + if('ant-upload-list-item ant-upload-list-item-done' == target.className || 'ant-upload-list ant-upload-list-picture-card'== target.className){ | |
401 | + this.moveDisplay = 'none'; | |
402 | + } | |
403 | + }) | |
404 | + //---------------------------- end 图片左右换位置 ------------------------------------- | |
405 | + } | |
237 | 406 | }, |
238 | 407 | model: { |
239 | 408 | prop: 'value', |
... | ... | @@ -242,6 +411,24 @@ |
242 | 411 | } |
243 | 412 | </script> |
244 | 413 | |
245 | -<style scoped> | |
246 | - | |
414 | +<style lang="less"> | |
415 | +.uploadty-disabled{ | |
416 | + .ant-upload-list-item { | |
417 | + .anticon-close{ | |
418 | + display: none; | |
419 | + } | |
420 | + .anticon-delete{ | |
421 | + display: none; | |
422 | + } | |
423 | + } | |
424 | +} | |
425 | + //---------------------------- begin 图片左右换位置 ------------------------------------- | |
426 | + .uploadty-mover-mask{ | |
427 | + background-color: rgba(0, 0, 0, 0.5); | |
428 | + opacity: .8; | |
429 | + color: #fff; | |
430 | + height: 28px; | |
431 | + line-height: 28px; | |
432 | + } | |
433 | + //---------------------------- end 图片左右换位置 ------------------------------------- | |
247 | 434 | </style> |
248 | 435 | \ No newline at end of file |
... | ... |