zkthink
5 years ago
88 changed files with 18057 additions and 26 deletions
@ -0,0 +1,22 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
getList: `/authority//order/findReturnInterventionList`, |
||||
getInfo: `/authority/order/getReturnInterventionDetail` |
||||
} |
||||
export default { |
||||
// 售后平台介入列表
|
||||
getList(data) { |
||||
return axiosApi({ |
||||
method: 'POST', |
||||
url: apiList.getList, |
||||
data |
||||
}) |
||||
}, |
||||
getInfo(id) { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: `${apiList.getInfo}/${id}` |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,78 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/application/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/application` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/application` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/application` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/application/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/application/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/application/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,74 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/area/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/area` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/area` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/area` |
||||
}, |
||||
query: { |
||||
method: 'POST', |
||||
url: `/authority/area/query` |
||||
}, |
||||
tree: { |
||||
method: 'GET', |
||||
url: `/authority/area/tree` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page(data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
tree(data) { |
||||
return axiosApi({ |
||||
...apiList.tree, |
||||
data |
||||
}) |
||||
}, |
||||
query(data) { |
||||
return axiosApi({ |
||||
...apiList.query, |
||||
data |
||||
}) |
||||
}, |
||||
save(data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update(data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete(data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
check(code, id) { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: `/authority/area/check/` + code, |
||||
data: { id: id } |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,68 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/file/attachment/page` |
||||
}, |
||||
upload: { |
||||
method: 'POST', |
||||
url: `/file/attachment/upload` |
||||
}, |
||||
download: { |
||||
method: 'GET', |
||||
url: `/file/attachment/download` |
||||
}, |
||||
downloadBiz: { |
||||
method: 'GET', |
||||
url: `/file/attachment/download/biz` |
||||
}, |
||||
downloadUrl: { |
||||
method: 'GET', |
||||
url: `/file/attachment/download/url` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/file/attachment` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
upload (data) { |
||||
return axiosApi({ |
||||
...apiList.upload, |
||||
data |
||||
}) |
||||
}, |
||||
download (data) { |
||||
return axiosApi({ |
||||
...apiList.download, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
downloadBiz (data) { |
||||
return axiosApi({ |
||||
...apiList.downloadBiz, |
||||
data |
||||
}) |
||||
}, |
||||
downloadUrl (data) { |
||||
return axiosApi({ |
||||
...apiList.downloadUrl, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/dictionary/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/dictionary` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/dictionary` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/dictionary` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/loginLog/page` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/loginLog` |
||||
}, |
||||
clear: { |
||||
method: 'DELETE', |
||||
url: `/authority/loginLog/clear` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/loginLog/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/loginLog/export` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page(data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
delete(data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
clear(data) { |
||||
return axiosApi({ |
||||
...apiList.clear, |
||||
data |
||||
}) |
||||
}, |
||||
preview(data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export(data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
getPlatformMenu: `/authority/menu/tree`, |
||||
getAllMerchanMenu: `/authority/menu/getAllTenantMenu`, |
||||
getSpecialMerchantMenu: `/authority/menu/getSpecifiedTenantMenu`, |
||||
saveMenu: `/authority/menu/syncMenu` |
||||
} |
||||
export default { |
||||
// 平台所有菜单
|
||||
getPlatformMenu() { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: apiList.getPlatformMenu |
||||
}) |
||||
}, |
||||
// 查询所有商家菜单
|
||||
getAllMerchanMenu() { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: apiList.getAllMerchanMenu |
||||
}) |
||||
}, |
||||
// 查询指定商家菜单
|
||||
getSpecialMerchantMenu(id) { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: `${apiList.getSpecialMerchantMenu}/${id}` |
||||
}) |
||||
}, |
||||
// 同步菜单
|
||||
saveMenu(data) { |
||||
return axiosApi({ |
||||
method: 'POST', |
||||
url: apiList.saveMenu, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,85 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/msgs/msgsCenterInfo/page`, |
||||
method: 'POST' |
||||
}, |
||||
mark: { |
||||
url: `/msgs/msgsCenterInfo/mark`, |
||||
method: 'GET' |
||||
}, |
||||
save: { |
||||
url: `/msgs/msgsCenterInfo`, |
||||
method: 'POST' |
||||
}, |
||||
delete: { |
||||
url: `/msgs/msgsCenterInfo`, |
||||
method: 'DELETE' |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/msgs/msgsCenterInfo/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/msgs/msgsCenterInfo/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/msgs/msgsCenterInfo/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data, custom = {}) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data, |
||||
custom |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
mark (data) { |
||||
return axiosApi({ |
||||
...apiList.mark, |
||||
data |
||||
}) |
||||
}, |
||||
get (id) { |
||||
return axiosApi({ |
||||
url: `/msgs/msgsCenterInfo/${id}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,68 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/optLog/page` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/optLog` |
||||
}, |
||||
clear: { |
||||
method: 'DELETE', |
||||
url: `/authority/optLog/clear` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/optLog/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/optLog/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/optLog/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
clear (data) { |
||||
return axiosApi({ |
||||
...apiList.clear, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,78 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
allTree: { |
||||
method: 'GET', |
||||
url: `/authority/org/tree` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/org` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/org` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/org` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/org/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/org/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/org/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
allTree (data) { |
||||
return axiosApi({ |
||||
...apiList.allTree, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,79 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/parameter/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/parameter` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/parameter` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/parameter` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/parameter/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/parameter/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/parameter/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data, custom = {}) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data, |
||||
custom |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/resource/page` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/resource` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/resource` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/resource` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,129 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/authority/role/page`, |
||||
method: 'POST' |
||||
}, |
||||
save: { |
||||
url: `/authority/role`, |
||||
method: 'POST' |
||||
}, |
||||
update: { |
||||
url: `/authority/role`, |
||||
method: 'PUT' |
||||
}, |
||||
delete: { |
||||
url: `/authority/role`, |
||||
method: 'DELETE' |
||||
}, |
||||
saveUserRole: { |
||||
url: `/authority/role/user`, |
||||
method: 'POST' |
||||
}, |
||||
saveRoleAuthority: { |
||||
url: `/authority/role/authority`, |
||||
method: 'POST' |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/user/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/user/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/role/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
// formData: true,
|
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
get (id) { |
||||
return axiosApi({ |
||||
url: `/authority/role/${id}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
getDetails (id) { |
||||
return axiosApi({ |
||||
url: `/authority/role/details/${id}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
check (code) { |
||||
return axiosApi({ |
||||
url: `/authority/role/check/${code}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
saveUserRole (data) { |
||||
return axiosApi({ |
||||
...apiList.saveUserRole, |
||||
data |
||||
}) |
||||
}, |
||||
findUserIdByRoleId (roleId) { |
||||
return axiosApi({ |
||||
url: `/authority/role/user/${roleId}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
findAuthorityIdByRoleId (roleId) { |
||||
return axiosApi({ |
||||
url: `/authority/role/authority/${roleId}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
saveRoleAuthority (data) { |
||||
return axiosApi({ |
||||
...apiList.saveRoleAuthority, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/msgs/smsSendStatus/page`, |
||||
method: 'POST' |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/msgs/smsTask/page`, |
||||
method: 'POST' |
||||
}, |
||||
save: { |
||||
url: `/msgs/smsTask`, |
||||
method: 'POST' |
||||
}, |
||||
update: { |
||||
url: `/msgs/smsTask`, |
||||
method: 'PUT' |
||||
}, |
||||
delete: { |
||||
url: `/msgs/smsTask`, |
||||
method: 'DELETE' |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTask/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTask/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTask/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
get (id) { |
||||
return axiosApi({ |
||||
url: `/msgs/smsTask/${id}`, |
||||
method: 'GET' |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,89 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/msgs/smsTemplate/page`, |
||||
method: 'POST' |
||||
}, |
||||
save: { |
||||
url: `/msgs/smsTemplate`, |
||||
method: 'POST' |
||||
}, |
||||
update: { |
||||
url: `/msgs/smsTemplate`, |
||||
method: 'PUT' |
||||
}, |
||||
delete: { |
||||
url: `/msgs/smsTemplate`, |
||||
method: 'DELETE' |
||||
}, |
||||
check: { |
||||
url: `/msgs/smsTemplate/check`, |
||||
method: 'GET' |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTemplate/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTemplate/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/msgs/smsTemplate/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
check (customCode) { |
||||
const data = { customCode: customCode } |
||||
return axiosApi({ |
||||
...apiList.check, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,78 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
url: `/authority/station/page`, |
||||
method: 'POST' |
||||
}, |
||||
save: { |
||||
url: `/authority/station`, |
||||
method: 'POST' |
||||
}, |
||||
update: { |
||||
url: `/authority/station`, |
||||
method: 'PUT' |
||||
}, |
||||
delete: { |
||||
url: `/authority/station`, |
||||
method: 'DELETE' |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/station/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/station/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/station/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/systemApi/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/systemApi` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/systemApi` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/systemApi` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/systemApi/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/systemApi/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/systemApi/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page(data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
scan(serviceId) { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: `/${serviceId}/systemApiScan` |
||||
}) |
||||
}, |
||||
save(data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update(data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
delete(data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
preview(data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export(data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import(data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,57 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/tenant/page` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/tenant` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/tenant` |
||||
}, |
||||
saveInit: { |
||||
method: 'POST', |
||||
url: `/authority/tenant/init` |
||||
}, |
||||
remove: { |
||||
method: 'DELETE', |
||||
url: `/authority/tenant/remove` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page(data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save(data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
saveInit(data) { |
||||
return axiosApi({ |
||||
...apiList.saveInit, |
||||
data |
||||
}) |
||||
}, |
||||
update(data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
remove(data) { |
||||
return axiosApi({ |
||||
...apiList.remove, |
||||
data |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,135 @@
|
||||
import axiosApi from './AxiosApi.js' |
||||
|
||||
const apiList = { |
||||
page: { |
||||
method: 'POST', |
||||
url: `/authority/user/page` |
||||
}, |
||||
save: { |
||||
method: 'POST', |
||||
url: `/authority/user` |
||||
}, |
||||
update: { |
||||
method: 'PUT', |
||||
url: `/authority/user` |
||||
}, |
||||
updateBaseInfo: { |
||||
method: 'PUT', |
||||
url: `/authority/user/base` |
||||
}, |
||||
avatar: { |
||||
method: 'PUT', |
||||
url: `/authority/user/avatar` |
||||
}, |
||||
delete: { |
||||
method: 'DELETE', |
||||
url: `/authority/user` |
||||
}, |
||||
reset: { |
||||
method: 'GET', |
||||
url: `/authority/user/reset` |
||||
}, |
||||
updatePassword: { |
||||
method: 'PUT', |
||||
url: `/authority/user/password` |
||||
}, |
||||
reload: { |
||||
method: 'POST', |
||||
url: `/authority/user/reload` |
||||
}, |
||||
preview: { |
||||
method: 'POST', |
||||
url: `/authority/user/preview` |
||||
}, |
||||
export: { |
||||
method: 'POST', |
||||
url: `/authority/user/export` |
||||
}, |
||||
import: { |
||||
method: 'POST', |
||||
url: `/authority/user/import` |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
page (data) { |
||||
return axiosApi({ |
||||
...apiList.page, |
||||
data |
||||
}) |
||||
}, |
||||
save (data) { |
||||
return axiosApi({ |
||||
...apiList.save, |
||||
data |
||||
}) |
||||
}, |
||||
update (data) { |
||||
return axiosApi({ |
||||
...apiList.update, |
||||
data |
||||
}) |
||||
}, |
||||
updateBaseInfo (data) { |
||||
return axiosApi({ |
||||
...apiList.updateBaseInfo, |
||||
data |
||||
}) |
||||
}, |
||||
updatePassword (data) { |
||||
return axiosApi({ |
||||
...apiList.updatePassword, |
||||
data |
||||
}) |
||||
}, |
||||
delete (data) { |
||||
return axiosApi({ |
||||
...apiList.delete, |
||||
data |
||||
}) |
||||
}, |
||||
get (id) { |
||||
return axiosApi({ |
||||
method: 'GET', |
||||
url: `/authority/user/${id}` |
||||
}) |
||||
}, |
||||
reset (data) { |
||||
return axiosApi({ |
||||
...apiList.reset, |
||||
data |
||||
}) |
||||
}, |
||||
avatar (data) { |
||||
return axiosApi({ |
||||
...apiList.avatar, |
||||
data |
||||
}) |
||||
}, |
||||
reload (userId) { |
||||
return axiosApi({ |
||||
...apiList.reload, |
||||
formData: true, |
||||
data: { userId: userId } |
||||
}) |
||||
}, |
||||
preview (data) { |
||||
return axiosApi({ |
||||
...apiList.preview, |
||||
data |
||||
}) |
||||
}, |
||||
export (data) { |
||||
return axiosApi({ |
||||
...apiList.export, |
||||
responseType: "blob", |
||||
data |
||||
}) |
||||
}, |
||||
import (data) { |
||||
return axiosApi({ |
||||
...apiList.import, |
||||
data |
||||
}) |
||||
} |
||||
} |
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 598 B |
After Width: | Height: | Size: 610 B |
@ -0,0 +1,117 @@
|
||||
<template> |
||||
<div class="common-tree"> |
||||
<el-tree |
||||
:ref="treeRef" |
||||
:data="treeData" |
||||
:check-strictly="checkStrictly" |
||||
show-checkbox |
||||
:accordion="false" |
||||
node-key="id" |
||||
default-expand-all |
||||
:highlight-current="true" |
||||
:expand-on-click-node="false" |
||||
:filter-node-method="filterNodeMethod" |
||||
@check-change="checkChange" |
||||
@node-click="nodeClick" |
||||
@current-change="currentChange" |
||||
> |
||||
<span |
||||
slot-scope="{ data, node }" |
||||
class="custom-tree-node" |
||||
> |
||||
<span style="margin-right: 15px;">{{ data.label }}</span> |
||||
<slot |
||||
:data="data" |
||||
:node="node" |
||||
></slot> |
||||
<!-- <template v-if='data.id !== "0"'> --> |
||||
<!-- <span class='ope-btn' title='添加' @click='modify("onAdd", data, node)'> |
||||
<i class='el-icon-plus' /> |
||||
</span> |
||||
<span class='ope-btn' title='修改' @click='modify("onEdit", data, node)'> |
||||
<i class='el-icon-edit' /> |
||||
</span> |
||||
<span |
||||
class='ope-btn ope-btn-remove' |
||||
title='删除' |
||||
@click='modify("onDelete", data, node)' |
||||
v-if='!data.children' |
||||
> |
||||
<i class='el-icon-delete' /> |
||||
</span>--> |
||||
<!-- </template> --> |
||||
</span> |
||||
</el-tree> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
props: { |
||||
treeRef: { |
||||
type: String, |
||||
default: "treeRef" |
||||
}, |
||||
treeData: { |
||||
type: Array, |
||||
required: true, |
||||
default () { |
||||
return [] |
||||
} |
||||
}, |
||||
checkStrictly: { |
||||
type: Boolean, |
||||
default () { |
||||
return true |
||||
} |
||||
}, |
||||
opeBtns: { |
||||
type: Array, |
||||
default () { |
||||
return ['add', 'edit', 'remove'] |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
modify (type, data, node) { |
||||
window.event.stopPropagation() |
||||
this.$emit(type, data, node) |
||||
}, |
||||
checkChange (data, checked, childrenChecked) { |
||||
this.$emit('checkChange', data, checked, childrenChecked) |
||||
}, |
||||
nodeClick (data, node, tree) { |
||||
this.$emit('nodeClick', data, node, tree) |
||||
}, |
||||
currentChange (data, node) { |
||||
this.$emit('currentChange', data, node) |
||||
}, |
||||
filterNodeMethod (value, data) { |
||||
// reutrn this.$emit('filterNodeMethod', value, data, node) |
||||
if (!value) return true |
||||
return data.label.indexOf(value) !== -1 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss"> |
||||
.common-tree { |
||||
.el-tree-node__content { |
||||
height: 28px; |
||||
.custom-tree-node { |
||||
font-size: 14px; |
||||
height: 28px; |
||||
line-height: 28px; |
||||
width: 100%; |
||||
.status-item { |
||||
top: 4px; |
||||
} |
||||
.tree-icon { |
||||
vertical-align: middle; |
||||
float: right; |
||||
margin-right: 10px; |
||||
box-sizing: border-box; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,189 @@
|
||||
<template> |
||||
<el-dialog |
||||
v-el-drag-dialog :close-on-click-modal="false" :title="title" |
||||
:type="type" :visible.sync="isVisible" |
||||
:width="width" top="50px" @dragDialog="handleDrag" |
||||
> |
||||
<el-form |
||||
ref="form" :model="model" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item label="文件" prop="fileLength"> |
||||
<fileUpload |
||||
ref="fileRef" :accept-size="acceptSize" :auto-upload="false" |
||||
:limit="1" :accept="accept" |
||||
:action="action" @fileLengthVaild="fileLengthVaild" @setId="setIdAndSubmit" |
||||
> |
||||
<el-button slot="trigger" size="small" type="primary">选取文件</el-button> |
||||
<div slot="tip" class="el-upload__tip">文件不超过100MB</div> |
||||
</fileUpload> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button :disabled="disabled" plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import fileUpload from "@/components/ceres/fileUpload" |
||||
|
||||
export default { |
||||
name: 'CommonImport', |
||||
directives: { elDragDialog, fileUpload }, |
||||
components: { fileUpload }, |
||||
props: { |
||||
action: { |
||||
type: String, |
||||
required: true |
||||
}, |
||||
// 允许上传的文件大小 单位:字节 |
||||
acceptSize: { |
||||
type: Number, |
||||
default: 50 * 1024 * 1024 |
||||
}, |
||||
accept: { |
||||
type: String, |
||||
default: '.xls,.xlsx' |
||||
}, |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
model: this.initImport(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
fileLength: 0, |
||||
disabled: false, |
||||
rules: { |
||||
fileLength: { |
||||
required: true, trigger: "change", |
||||
validator: (rule, value, callback) => { |
||||
const vm = this |
||||
if (vm.fileLength === 0) { |
||||
callback(new Error("请上传文件")) |
||||
} else if (vm.fileLength > 1) { |
||||
callback(new Error("一次性只能上传1个文件")) |
||||
} else { |
||||
callback() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.$t('common.upload') |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initImport() { |
||||
return { |
||||
id: '', |
||||
bizId: '', |
||||
bizType: '', |
||||
file: null, |
||||
isSingle: false |
||||
} |
||||
}, |
||||
handleDrag() { |
||||
}, |
||||
// 附件长度校验 |
||||
fileLengthVaild(data) { |
||||
const vm = this |
||||
vm.fileLength = data || 0 |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
setModel(val) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.model = { ...val } |
||||
} |
||||
}, |
||||
close() { |
||||
this.$emit('close') |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.disabled = false |
||||
this.model = this.initImport() |
||||
this.$refs.fileRef.init({ |
||||
id: "" |
||||
}) |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
vm.disabled = true |
||||
vm.$refs.fileRef.submitFile(this.model.id, this.model.bizId, this.model.bizType) |
||||
}, |
||||
setIdAndSubmit(isUploadCompleted, response) { |
||||
const vm = this |
||||
if (isUploadCompleted) { |
||||
vm.disabled = false |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} else if (response && response['code'] === -9 && response['data']) { |
||||
// 原本是想要下载数据,但存在一些问题 |
||||
// commonApi.export(this.exportErrorUrl, {failList: response['data']}) |
||||
// .then(response => { |
||||
// downloadFile(response); |
||||
// }); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,368 @@
|
||||
<template> |
||||
<div> |
||||
<el-upload |
||||
:ref="uploadRef" |
||||
:accept="accept" |
||||
:action="action" |
||||
:auto-upload="autoUpload" |
||||
:before-remove="beforeRemove" |
||||
:class="isUpload === false ? 'hidebtn' : ''" |
||||
:data="fileOtherData" |
||||
:file-list="fileList" |
||||
:headers="headers" |
||||
:limit="limit" |
||||
:multiple="multiple" |
||||
:on-change="handleChange" |
||||
:on-error="handleError" |
||||
:on-exceed="handleExceed" |
||||
:on-preview="handlePreview" |
||||
:on-remove="handleRemove" |
||||
class="upload-demo" |
||||
> |
||||
<el-button |
||||
v-if="isUpload" size="small" type="primary" |
||||
>点击上传</el-button> |
||||
</el-upload> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import db from "@/utils/localstorage" |
||||
import commonApi from "@/api/Common.js" |
||||
import { copy } from '@/utils/utils' |
||||
import { Base64 } from 'js-base64' |
||||
|
||||
export default { |
||||
name: "FileUpload", |
||||
props: { |
||||
uploadRef: { |
||||
type: String, |
||||
default: "file1" |
||||
}, |
||||
// 是否多选 |
||||
multiple: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 是否自动上传 |
||||
autoUpload: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 是否上传文件 |
||||
isUpload: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 最大允许上传个数 |
||||
limit: { |
||||
type: Number, |
||||
default: null |
||||
}, |
||||
// 允许上传的文件类型 |
||||
accept: { |
||||
type: String, |
||||
default: "" |
||||
}, |
||||
action: { |
||||
type: String, |
||||
default: `${process.env.VUE_APP_BASE_API}/file/attachment/upload` |
||||
}, |
||||
// 允许上传的文件大小 单位:字节 |
||||
acceptSize: { |
||||
type: Number, |
||||
default: null |
||||
}, |
||||
// 默认额外上传数据 |
||||
fileOtherData: { |
||||
type: Object, |
||||
default: function() { |
||||
return { |
||||
id: null, |
||||
bizId: "", |
||||
bizType: "", |
||||
isSingle: false |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
// 默认附件列表 |
||||
fileList: [], |
||||
// 删除附件列表 |
||||
removeFileAry: [], |
||||
// 新增附件列表 |
||||
addFileAry: [], |
||||
// 上传成功的文件数 |
||||
successNum: 0, |
||||
// 上传失败的文件数 |
||||
errorNum: 0, |
||||
// 已上传的文件数 |
||||
uploadTotalNum: 0, |
||||
// 是否上传失败 |
||||
isUploadError: false |
||||
// action: `${process.env.VUE_APP_BASE_API}/file/attachment/upload` |
||||
} |
||||
}, |
||||
computed: { |
||||
headers() { |
||||
return { |
||||
token: 'Bearer ' + db.get("TOKEN", ""), |
||||
tenant: db.get("TENANT", "") || "", |
||||
Authorization: `Basic ${Base64.encode(`${process.env.VUE_APP_CLIENT_ID}:${process.env.VUE_APP_CLIENT_SECRET}`)}` |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
// 附件初始化 |
||||
init({ id, bizId, bizType, isSingle, isDetail }) { |
||||
const vm = this |
||||
vm.fileOtherData.bizId = bizId |
||||
vm.fileOtherData.id = id || "" |
||||
vm.fileOtherData.bizType = bizType |
||||
vm.fileOtherData.isSingle = isSingle || false |
||||
vm.fileList.length = 0 |
||||
vm.removeFileAry = [] |
||||
vm.addFileAry = [] |
||||
vm.$emit("fileLengthVaild", 0) |
||||
if (isDetail) { |
||||
vm.getAttachment() |
||||
} |
||||
vm.successNum = 0 |
||||
vm.errorNum = 0 |
||||
vm.uploadTotalNum = 0 |
||||
vm.$refs[vm.uploadRef].clearFiles() |
||||
}, |
||||
|
||||
handleChange(file, fileList) { |
||||
const vm = this |
||||
if (file.response) { |
||||
vm.uploadTotalNum += 1 |
||||
if (file.response.isSuccess) { |
||||
vm.fileOtherData.bizId = file.response.data.bizId |
||||
vm.successNum += 1 |
||||
} else { |
||||
setTimeout(() => { |
||||
vm.$message({ |
||||
message: file.name + "上传失败,原因:<br/>" + file.response.msg, |
||||
type: "error", |
||||
dangerouslyUseHTMLString: true, |
||||
showClose: true, |
||||
duration: 10000, |
||||
onClose: (msgs) => { |
||||
copy(msgs['message']) |
||||
vm.$message({ |
||||
message: "复制错误消息成功", |
||||
type: "success" |
||||
}) |
||||
} |
||||
}) |
||||
}, 0) |
||||
vm.isUploadError = false |
||||
vm.errorNum += 1 |
||||
} |
||||
vm.$emit("setId", vm.uploadTotalNum === fileList.length && vm.errorNum <= 0, file.response) |
||||
} else { |
||||
if (vm.acceptSize) { |
||||
const isLtAcceptSize = file.size > vm.acceptSize |
||||
|
||||
if (isLtAcceptSize) { |
||||
setTimeout(() => { |
||||
vm.$message.error( |
||||
"只能上传" + |
||||
vm.renderSize(vm.acceptSize) + |
||||
"的文件!已为您过滤文件:" + |
||||
file.name |
||||
) |
||||
}, 10) |
||||
|
||||
fileList.forEach((item, index) => { |
||||
if (item.uid === file.uid) { |
||||
fileList.splice(index, 1) |
||||
} |
||||
}) |
||||
} else { |
||||
if (!vm.isUploadError) { |
||||
vm.addFileAry.push(file.name) |
||||
} |
||||
vm.isUploadError = false |
||||
} |
||||
} else { |
||||
if (!vm.isUploadError) { |
||||
vm.addFileAry.push(file.name) |
||||
} |
||||
vm.isUploadError = false |
||||
} |
||||
vm.$emit("fileLengthVaild", vm.fileList.length + vm.addFileAry.length) |
||||
} |
||||
vm.$store.state.hasLoading = false |
||||
}, |
||||
// 附件上传失败 |
||||
handleError() { |
||||
const vm = this |
||||
vm.$message.error("附件上传失败,请重试") |
||||
vm.isUploadError = true |
||||
vm.$store.state.hasLoading = false |
||||
}, |
||||
renderSize(value) { |
||||
if (value == null || value == "") { |
||||
return "0 B" |
||||
} |
||||
const unitArr = new Array( |
||||
"B", |
||||
"KB", |
||||
"MB", |
||||
"GB", |
||||
"TB", |
||||
"PB", |
||||
"EB", |
||||
"ZB", |
||||
"YB" |
||||
) |
||||
let index = 0 |
||||
const srcsize = parseFloat(value) |
||||
index = Math.floor(Math.log(srcsize) / Math.log(1024)) |
||||
let size = srcsize / Math.pow(1024, index) |
||||
size = size.toFixed(2) |
||||
if (unitArr[index]) { |
||||
return size + unitArr[index] |
||||
} |
||||
return "文件太大" |
||||
}, |
||||
handlePreview(file) { |
||||
if (file.bizId) { |
||||
this.downLoadFile(file) |
||||
} |
||||
}, |
||||
beforeRemove(file) { |
||||
return this.$confirm("确定移除" + file.name, "删除确认") |
||||
}, |
||||
// 文件超出个数限制时的钩子 |
||||
handleExceed() { |
||||
const vm = this |
||||
vm.$message("当前最多允许上传" + vm.limit + "个文件") |
||||
}, |
||||
// 删除附件列表 |
||||
handleRemove(file) { |
||||
const vm = this |
||||
if (file.bizId) { |
||||
vm.removeFileAry.push(file.id) |
||||
vm.fileList.map((item, index) => { |
||||
if (item.name === file.name) { |
||||
vm.fileList.splice(index, 1) |
||||
return false |
||||
} |
||||
}) |
||||
} else { |
||||
vm.addFileAry.map((item, index) => { |
||||
if (item === file.name) { |
||||
vm.addFileAry.splice(index, 1) |
||||
return false |
||||
} |
||||
}) |
||||
} |
||||
vm.$emit("fileLengthVaild", vm.fileList.length + vm.addFileAry.length) |
||||
}, |
||||
// 服务器删除附件 |
||||
async deleteAttachment() { |
||||
const vm = this |
||||
const res = await commonApi.deleteAttachment({ |
||||
ids: vm.removeFileAry |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code !== 0) { |
||||
vm.$message(res.data.msg) |
||||
} else { |
||||
vm.removeFileAry = [] |
||||
} |
||||
} |
||||
}, |
||||
// 查询附件 |
||||
async getAttachment() { |
||||
const vm = this |
||||
const res = await commonApi.getAttachment({ |
||||
bizIds: vm.fileOtherData.bizId, |
||||
bizTypes: vm.fileOtherData.bizType |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code === 0) { |
||||
if (res.data.data.length > 0) { |
||||
const data = res.data.data[0].list |
||||
data.map(item => { |
||||
item.name = item.submittedFileName |
||||
}) |
||||
vm.fileList = data |
||||
vm.$emit("fileLengthVaild", vm.fileList.length) |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
// 查询附件 |
||||
async getAttachmentByArr(bizIds, bizTypes) { |
||||
const vm = this |
||||
const res = await commonApi.getAttachment({ |
||||
bizIds: bizIds, |
||||
bizTypes: bizTypes |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code === 0) { |
||||
if (res.data.data.length > 0) { |
||||
const data = res.data.data[0].list |
||||
data.map(item => { |
||||
item.name = item.submittedFileName |
||||
}) |
||||
vm.fileList = data |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
// 返回附件新增及删除数组长度 |
||||
handleBack() { |
||||
const vm = this |
||||
return { |
||||
addLength: vm.addFileAry.length, |
||||
removeLength: vm.removeFileAry.length |
||||
} |
||||
}, |
||||
// 附件上传服务器触发方法 |
||||
submitFile(id, bizId, bizType, tagId) { |
||||
const vm = this |
||||
vm.fileOtherData.id = id |
||||
if (bizId) { |
||||
vm.fileOtherData.bizId = bizId |
||||
vm.isUpload = true |
||||
} |
||||
if (tagId) { |
||||
vm.fileOtherData.tagId = tagId |
||||
} |
||||
vm.fileOtherData.bizType = bizType |
||||
if (vm.limitType(vm.$refs[vm.uploadRef].uploadFiles).length) { |
||||
return vm.$message.error('只能上传jpg/png/mp4格式的文件') |
||||
} |
||||
vm.$refs[vm.uploadRef].submit() |
||||
vm.addFileAry = [] |
||||
}, |
||||
// 附件下载 |
||||
async downLoadFile(data) { |
||||
const link = document.createElement("a") |
||||
link.href = data.url |
||||
link.download = data.name |
||||
link.click() |
||||
window.URL.revokeObjectURL(link.href) |
||||
}, |
||||
// 限制上传类型 |
||||
limitType(arr) { |
||||
return arr.filter(item => { |
||||
const t = item.raw.type |
||||
return t.indexOf('image') === -1 && t.indexOf('video') === -1 |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style> |
||||
.hidebtn .el-upload { |
||||
display: none; |
||||
} |
||||
</style> |
@ -0,0 +1,343 @@
|
||||
<template> |
||||
<div> |
||||
<el-upload |
||||
:ref="uploadRef" |
||||
:accept="accept" |
||||
:action="action" |
||||
:auto-upload="autoUpload" |
||||
:before-upload="beforeUpload" |
||||
:class="{ limit: showUploadBtn }" |
||||
:data="fileOtherData" |
||||
:file-list="imgFileList" |
||||
:headers="headers" |
||||
:limit="limit" |
||||
:multiple="multiple" |
||||
:on-change="handleChange" |
||||
:on-error="handleError" |
||||
:on-exceed="handleExceed" |
||||
:on-remove="handleRemove" |
||||
:show-file-list="showFileList" |
||||
class="avatar-uploader" |
||||
list-type="picture-card" |
||||
> |
||||
<img v-if="imageUrl" :src="imageUrl" class="avatar" /> |
||||
<i v-else class="el-icon-plus"></i> |
||||
</el-upload> |
||||
<el-dialog :visible.sync="dialogVisible"> |
||||
<img :src="dialogImageUrl" alt width="100%" /> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import db from "@/utils/localstorage" |
||||
import commonApi from "@/api/Common.js" |
||||
import { Base64 } from 'js-base64' |
||||
export default { |
||||
props: { |
||||
uploadRef: { |
||||
type: String, |
||||
default: "file1" |
||||
}, |
||||
// 是否多选 |
||||
multiple: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否自动上传 |
||||
autoUpload: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否显示上传列表 |
||||
showFileList: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 最大允许上传个数 |
||||
limit: { |
||||
type: Number, |
||||
default: null |
||||
}, |
||||
// 允许上传的文件类型 |
||||
accept: { |
||||
type: String, |
||||
default: "image/jpeg, image/gif, image/png, image/bmp" |
||||
}, |
||||
// 允许上传的文件大小 单位:字节 |
||||
acceptSize: { |
||||
type: Number, |
||||
default: null |
||||
}, |
||||
// 默认额外上传数据 |
||||
fileOtherData: { |
||||
type: Object, |
||||
default: function() { |
||||
return { |
||||
bizId: "", |
||||
bizType: "", |
||||
isSingle: false |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
imageUrl: "", |
||||
dialogImageUrl: "", |
||||
dialogVisible: false, |
||||
disabled: true, |
||||
// 默认附件列表 |
||||
imgFileList: [], |
||||
// 删除附件列表 |
||||
removeFileAry: [], |
||||
// 新增附件列表 |
||||
addFileAry: [], |
||||
// 是否上传失败 |
||||
isUploadError: false, |
||||
fileLength: 0, |
||||
action: `${process.env.VUE_APP_BASE_API}/file/attachment/upload` |
||||
} |
||||
}, |
||||
computed: { |
||||
showUploadBtn() { |
||||
return ( |
||||
this.showFileList && |
||||
this.addFileAry.length + this.imgFileList.length === this.limit |
||||
) |
||||
}, |
||||
headers() { |
||||
return { |
||||
token: 'Bearer ' + db.get("TOKEN", ""), |
||||
tenant: db.get("TENANT", "") || "", |
||||
Authorization: `Basic ${Base64.encode(`${process.env.VUE_APP_CLIENT_ID}:${process.env.VUE_APP_CLIENT_SECRET}`)}` |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
// 附件初始化 |
||||
init({ bizId, bizType, imageUrl, isSingle, isDetail }) { |
||||
const vm = this |
||||
vm.fileOtherData.bizId = bizId |
||||
vm.fileOtherData.bizType = bizType |
||||
vm.fileOtherData.isSingle = isSingle || false |
||||
// vm.imgFileList = [] |
||||
vm.imgFileList.length = 0 |
||||
vm.removeFileAry = [] |
||||
vm.addFileAry = [] |
||||
vm.imageUrl = imageUrl |
||||
vm.isUploadError = false |
||||
if (isDetail) { |
||||
vm.getAttachment() |
||||
} |
||||
}, |
||||
// 附件上传前触发 |
||||
beforeUpload() { |
||||
const vm = this |
||||
vm.$store.state.hasLoading = true |
||||
}, |
||||
// 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 |
||||
handleChange(file, fileList) { |
||||
const vm = this |
||||
if (file.response) { |
||||
if (file.response.isSuccess) { |
||||
const remoteFile = file.response.data |
||||
vm.fileOtherData.bizId = remoteFile.bizId |
||||
vm.imageUrl = remoteFile.url |
||||
vm.$emit("setId", remoteFile.bizId, remoteFile.url) |
||||
} else { |
||||
vm.$message.error(file.response.msg) |
||||
vm.isUploadError = false |
||||
} |
||||
} else { |
||||
if (vm.acceptSize) { |
||||
const isLtAcceptSize = file.size > vm.acceptSize |
||||
if (isLtAcceptSize) { |
||||
setTimeout(() => { |
||||
vm.$message.error( |
||||
"只能上传" + |
||||
vm.renderSize(vm.acceptSize) + |
||||
"的文件!已为您过滤文件:" + |
||||
file.name |
||||
) |
||||
}, 10) |
||||
|
||||
fileList.forEach((item, index) => { |
||||
if (item.uid === file.uid) { |
||||
fileList.splice(index, 1) |
||||
} |
||||
}) |
||||
} else { |
||||
if (!vm.isUploadError) { |
||||
vm.addFileAry.push(file.name) |
||||
} |
||||
vm.isUploadError = false |
||||
} |
||||
} |
||||
} |
||||
vm.$store.state.hasLoading = false |
||||
}, |
||||
renderSize(value) { |
||||
if (value == null || value == "") { |
||||
return "0 B" |
||||
} |
||||
const unitArr = new Array( |
||||
"B", |
||||
"KB", |
||||
"MB", |
||||
"GB", |
||||
"TB", |
||||
"PB", |
||||
"EB", |
||||
"ZB", |
||||
"YB" |
||||
) |
||||
let index = 0 |
||||
const srcsize = parseFloat(value) |
||||
index = Math.floor(Math.log(srcsize) / Math.log(1024)) |
||||
let size = srcsize / Math.pow(1024, index) |
||||
size = size.toFixed(2) |
||||
if (unitArr[index]) { |
||||
return size + unitArr[index] |
||||
} |
||||
return "文件太大" |
||||
}, |
||||
// 附件上传失败 |
||||
handleError() { |
||||
const vm = this |
||||
vm.$message.error("附件上传失败,请重试") |
||||
vm.isUploadError = true |
||||
vm.$store.state.hasLoading = false |
||||
if (!vm.showFileList) { |
||||
vm.imageUrl = "" |
||||
} |
||||
}, |
||||
// 查询附件 |
||||
async getAttachment() { |
||||
const vm = this |
||||
const res = await commonApi.getAttachment({ |
||||
bizIds: vm.fileOtherData.bizId, |
||||
bizTypes: vm.fileOtherData.bizType |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code === 0) { |
||||
if (res.data.data.length > 0) { |
||||
const data = res.data.data[0].list |
||||
data.map(item => { |
||||
item.name = item.submittedFileName |
||||
if (!vm.showFileList) { |
||||
vm.imageUrl = item.url |
||||
} |
||||
}) |
||||
vm.imgFileList = data |
||||
vm.$emit("fileLengthVaild", vm.imgFileList.length) |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
// 删除附件回调 |
||||
handleRemove(file) { |
||||
const vm = this |
||||
if (file.bizId) { |
||||
vm.removeFileAry.push(file.id) |
||||
vm.imgFileList.map((item, index) => { |
||||
if (item.bizId === file.bizId) { |
||||
vm.imgFileList.splice(index, 1) |
||||
return false |
||||
} |
||||
}) |
||||
} else { |
||||
vm.addFileAry.map((item, index) => { |
||||
if (item === file.name) { |
||||
vm.addFileAry.splice(index, 1) |
||||
return false |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
// 文件超出个数限制时的钩子 |
||||
handleExceed() { |
||||
const vm = this |
||||
vm.$message("当前最多允许上传" + vm.limit + "张图片") |
||||
}, |
||||
// 返回附件新增及删除数组长度 |
||||
handleBack() { |
||||
const vm = this |
||||
return { |
||||
addLength: vm.addFileAry.length, |
||||
removeLength: vm.removeFileAry.length |
||||
} |
||||
}, |
||||
// 服务器删除附件 |
||||
async deleteAttachment() { |
||||
const vm = this |
||||
const res = await commonApi.deleteAttachment({ |
||||
ids: vm.removeFileAry |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code !== 0) { |
||||
vm.$message(res.data.msg) |
||||
} |
||||
} |
||||
}, |
||||
// 附件上传服务器触发方法 |
||||
submitFile(bizId, bizType, isSingle) { |
||||
const vm = this |
||||
vm.fileOtherData.bizId = bizId |
||||
vm.fileOtherData.bizType = bizType |
||||
vm.fileOtherData.isSingle = isSingle |
||||
if (!vm.showFileList) { |
||||
const length = vm.$refs[vm.uploadRef].uploadFiles.length - 1 |
||||
vm.$refs[vm.uploadRef].uploadFiles = [ |
||||
vm.$refs[vm.uploadRef].uploadFiles[length] |
||||
] |
||||
vm.imgFileList.map(item => { |
||||
vm.removeFileAry.push(item.id) |
||||
}) |
||||
if (vm.imgFileList.length > 0) { |
||||
vm.deleteAttachment() |
||||
} |
||||
} |
||||
vm.$refs[vm.uploadRef].submit() |
||||
vm.$store.state.hasLoading = false |
||||
vm.addFileAry = [] |
||||
}, |
||||
// 服务器删除附件 |
||||
async deleteAttachmentByIds(ids) { |
||||
const vm = this |
||||
const res = await commonApi.deleteAttachment({ |
||||
ids: ids |
||||
}) |
||||
if (res.status === 200) { |
||||
if (res.data.code !== 0) { |
||||
vm.$message(res.data.msg) |
||||
} else { |
||||
vm.removeFileAry = [] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.avatar { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
/deep/.el-form-item__content { |
||||
line-height: 0; |
||||
} |
||||
/deep/.el-upload-list--picture-card .el-upload-list__item { |
||||
margin: 0 8px 0 0; |
||||
} |
||||
/deep/.el-upload--picture-card, |
||||
/deep/.el-upload-list--picture-card .el-upload-list__item { |
||||
width: 128px; |
||||
height: 128px; |
||||
} |
||||
.limit { |
||||
/deep/.el-upload--picture-card { |
||||
display: none; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,99 @@
|
||||
/** |
||||
* 判断终端以及浏览器 |
||||
* userAgent string User-Agent信息 |
||||
*/ |
||||
export const readUserAgent = ua => { |
||||
const data = { |
||||
terminal: '', |
||||
browser: '', |
||||
terminalType: {} |
||||
} |
||||
data.terminalType = { |
||||
trident: ua.indexOf('Trident') > -1, // IE内核
|
||||
presto: ua.indexOf('Presto') > -1, // opera内核
|
||||
webKit: ua.indexOf('AppleWebKit') > -1, // 苹果、谷歌内核
|
||||
gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, // 火狐内核
|
||||
mobile: !!ua.match(/AppleWebKit.*Mobile.*/), // 是否为移动终端
|
||||
ios: !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // ios终端
|
||||
android: ua.indexOf('Android') > -1 || ua.indexOf('Adr') > -1, // android终端
|
||||
iPhone: ua.indexOf('iPhone') > -1, // 是否为iPhone或者QQHD浏览器
|
||||
iPad: ua.indexOf('iPad') > -1, // 是否iPad
|
||||
webApp: ua.indexOf('Safari') === -1, // 是否web应该程序,没有头部与底部
|
||||
weixin: ua.indexOf('MicroMessenger') > -1, // 是否微信 (2015-01-22新增)
|
||||
qq: ua.match(/\sQQ/i) === ' qq' // 是否QQ
|
||||
} |
||||
if ( |
||||
data.terminalType.ios || |
||||
data.terminalType.iPhone || |
||||
data.terminalType.iPad |
||||
) { |
||||
data.terminal = '苹果' |
||||
} else if (data.terminalType.android) { |
||||
data.terminal = '安卓' |
||||
} else { |
||||
data.terminal = 'PC' |
||||
} |
||||
if (/msie/i.test(ua) && !/opera/.test(ua)) { |
||||
data.browser = 'IE' |
||||
} else if (/firefox/i.test(ua)) { |
||||
data.browser = 'Firefox' |
||||
} else if (/chrome/i.test(ua) && /webkit/i.test(ua) && /mozilla/i.test(ua)) { |
||||
data.browser = 'Chrome' |
||||
} else if (/opera/i.test(ua)) { |
||||
data.browser = 'Opera' |
||||
} else if (/iPad/i.test(ua)) { |
||||
data.browser = 'iPad' |
||||
} else if ( |
||||
/webkit/i.test(ua) && |
||||
!(/chrome/i.test(ua) && /webkit/i.test(ua) && /mozilla/i.test(ua)) |
||||
) { |
||||
data.browser = 'Safari' |
||||
} else { |
||||
data.browser = '未知' |
||||
} |
||||
return data |
||||
} |
||||
|
||||
// 格式化文件大小 单位:B、KB、MB、GB
|
||||
const renderSize = value => { |
||||
if (value == null || value == '') { |
||||
return "0 B" |
||||
} |
||||
var unitArr = new Array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") |
||||
var index = 0 |
||||
var srcsize = parseFloat(value) |
||||
index = Math.floor(Math.log(srcsize) / Math.log(1024)) |
||||
var size = srcsize / Math.pow(1024, index) |
||||
size = size.toFixed(2) |
||||
if (unitArr[index]) { |
||||
return size + unitArr[index] |
||||
} |
||||
return '文件太大' |
||||
} |
||||
|
||||
const convertEnum = obj => { |
||||
const list = [] |
||||
if (obj) { |
||||
for (const key in obj) { |
||||
list.push({ |
||||
text: obj[key], |
||||
value: key |
||||
}) |
||||
} |
||||
} |
||||
return list |
||||
} |
||||
|
||||
const copy = msg => { |
||||
if (msg) { |
||||
const oInput = document.createElement('input') // 创建一个隐藏input(重要!)
|
||||
oInput.value = msg // 赋值
|
||||
document.body.appendChild(oInput) |
||||
oInput.select() // 选择对象
|
||||
document.execCommand("Copy") // 执行浏览器复制命令
|
||||
oInput.className = 'oInput' |
||||
oInput.style.display = 'none' |
||||
} |
||||
} |
||||
|
||||
export { renderSize, convertEnum, copy } |
@ -0,0 +1,77 @@
|
||||
<template> |
||||
<div> |
||||
<div v-if="dialog.allow" class="allow"> |
||||
<h1>建议联系商家,由商家操作同意退款。</h1> |
||||
<p> |
||||
若你同意售后,客户申请的类型为仅退款时,将自动从商家账户退款给买家 若客户申请的类型为退款退货时,本售后将转为待买家退回物品的状态,有可能被商家拒收 |
||||
</p> |
||||
</div> |
||||
<div v-else class="refuse"> |
||||
<p>拒绝售后,本售后将自动关闭,但买家有权再次发起。</p> |
||||
</div> |
||||
|
||||
<el-form label-width="120px" :model="form"> |
||||
<el-form-item label="备注内容"> |
||||
<el-input v-model="form.remark" type="textarea" placeholder="请填写相关内容" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<div class="btn_list"> |
||||
<el-button type="primary">{{ dialog.btnName }}</el-button> |
||||
<el-button @click="cancel">取消</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
dialog: { |
||||
type: Object, |
||||
default: () => {} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
form: { |
||||
remark: '' |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
cancel() { |
||||
this.$emit('close') |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
h1 { |
||||
font-size:24px; |
||||
font-weight:500; |
||||
color:rgba(51,51,51,1); |
||||
text-align: center; |
||||
width: 50%; |
||||
margin: 30px auto; |
||||
} |
||||
p { |
||||
font-size:16px; |
||||
color:rgba(51,51,51,1); |
||||
text-align: center; |
||||
width: 50%; |
||||
margin: 30px auto; |
||||
} |
||||
|
||||
.btn_list { |
||||
width: 200px; |
||||
margin: 20px auto; |
||||
} |
||||
|
||||
/deep/ .el-textarea { |
||||
width: 100%; |
||||
textarea { |
||||
min-height: 150px !important; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,48 @@
|
||||
<template> |
||||
<div class="store_info_page"> |
||||
<p v-for="(item,index) in storeInfo" :key="index"> |
||||
<span>{{ item.name }}:</span> |
||||
<span>{{ item.value }}</span> |
||||
</p> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
storeInfo: [ |
||||
{ name: '下单账户', value: '和理智上', field: '' }, |
||||
{ name: '注册时间', value: '2020-06-30', field: '' }, |
||||
{ name: '手机号', value: '13966781258', field: '' }, |
||||
{ name: '订单总数', value: '12个', field: '' }, |
||||
{ name: '售后单数', value: '5个', field: '' }, |
||||
{ name: '售后成功率', value: '68%', field: '' } |
||||
] |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.store_info_page { |
||||
padding: 20px 10%; |
||||
overflow: hidden; |
||||
p { |
||||
width: 50%; |
||||
float: left; |
||||
span { |
||||
font-size: 16px; |
||||
color: #333333; |
||||
display: inline-block; |
||||
&:nth-of-type(1) { |
||||
width:130px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
color:#666666; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
|
@ -0,0 +1,87 @@
|
||||
<template> |
||||
<div class="logistics_info"> |
||||
<div class="logistics_com"> |
||||
<p v-for="(item,index) in list" :key="index"> |
||||
<span>{{ item.name }}:</span> |
||||
<span>{{ item.value }}</span> |
||||
</p> |
||||
</div> |
||||
<div class="logistics_status"> |
||||
<div>物流信息:</div> |
||||
<div> |
||||
<p v-for="(item,index) in logisticsList" :key="index"> |
||||
<span>{{ item.time }}</span> |
||||
<span>{{ item.status }}</span> |
||||
</p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
list: [ |
||||
{ name: '物流公司', value: '中通', field: '' }, |
||||
{ name: '运单号', value: '123123', field: '' } |
||||
], |
||||
logisticsList: [ |
||||
{ time: '2020/12/20 15:20:23', status: '正在派件', field: '' }, |
||||
{ time: '2020/12/20 15:20:23', status: '已从廊坊发货', field: '' }, |
||||
{ time: ' 2020/12/20 15:20:23', status: '已到达目的地', field: '' } |
||||
] |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.logistics_info { |
||||
padding: 20px 10%; |
||||
.logistics_com { |
||||
overflow: hidden; |
||||
margin-bottom: 30px; |
||||
p { |
||||
width: 50%; |
||||
float: left; |
||||
span { |
||||
font-size: 16px; |
||||
color: #333333; |
||||
display: inline-block; |
||||
&:nth-of-type(1) { |
||||
width:80px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
color:#666666; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.logistics_status { |
||||
overflow: hidden; |
||||
div { |
||||
font-size: 16px; |
||||
color: #333333; |
||||
float: left; |
||||
&:nth-of-type(1) { |
||||
width:80px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
width: calc(80% - 80px); |
||||
color:#666666; |
||||
p { |
||||
margin: 0; |
||||
margin-bottom: 20px; |
||||
span { |
||||
display: inline-block; |
||||
&:nth-of-type(2) { |
||||
margin-left: 50px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,206 @@
|
||||
<template> |
||||
<div class="order_info_page"> |
||||
<div class="order_info"> |
||||
<p v-for="(item,index) in orderInfo" :key="index"> |
||||
<span>{{ item.name }}:</span> |
||||
<span>{{ item.value }}</span> |
||||
</p> |
||||
</div> |
||||
<div class="detail_title"> |
||||
商品信息 |
||||
</div> |
||||
<div |
||||
v-for="(item,index) in shopList" |
||||
:key="index" |
||||
class="goods_list" |
||||
> |
||||
<div class="good_details"> |
||||
<ul> |
||||
<li> |
||||
<img :src="item.skuImg" /> |
||||
</li> |
||||
<li> |
||||
<p>{{ item.productName }}</p> |
||||
<p>{{ item.skuNameStr }}</p> |
||||
<p>SKU: {{ item.skuId }}</p> |
||||
</li> |
||||
<li> |
||||
<p>¥{{ item.sellPrice*item.buyNum }}</p> |
||||
<p>¥{{ `${item.sellPrice}*${item.buyNum}` }}</p> |
||||
</li> |
||||
<li> ¥{{ item.salePrice * item.buyNum }}</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
<div class="total"> |
||||
<ul> |
||||
<li></li> |
||||
<li></li> |
||||
<li> </li> |
||||
<li> |
||||
<p><span>订单总金额</span> <span>¥240</span> </p> |
||||
<p><span>物流费用</span> <span>¥40</span></p> |
||||
<p><span>平台优惠(618活动)</span> <span>-¥100</span></p> |
||||
<p><span>实付</span> <span>¥180</span></p> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
orderInfo: [ |
||||
{ name: '订单ID', value: '542543543', field: '' }, |
||||
{ name: '支付单号', value: '12353563', field: '' }, |
||||
{ name: '支付状态', value: '待发货', field: '' }, |
||||
{ name: '售后状态', value: '售后中', field: '' } |
||||
], |
||||
shopList: [ |
||||
{ skuImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg', |
||||
productName: 'DAD 气垫霜', skuNameStr: '粉色, 中瓶', skuId: '2525', sellPrice: '60', buyNum: '2', salePrice: '50' }, |
||||
{ skuImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg', |
||||
productName: 'DAD 气垫霜', skuNameStr: '粉色, 中瓶', skuId: '2525', sellPrice: '60', buyNum: '2', salePrice: '50' } |
||||
], |
||||
recordList: [ |
||||
{ title: '申请平台介入', name: '刘十', time: '2020-05-08 15:30:56', type: '问题描述', value: '不退款', img: '举证图片', |
||||
imgSrc: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg' }, |
||||
{ title: '拒绝退款', name: '王辉', time: '2020-04-08 17:30:20', type: '卖家留言', value: '不退款', img: '', imgSrc: '' }, |
||||
{ title: '发起了售后', name: '张强', time: '2020-03-25 13:25:45', type: '买家留言', value: '不要了, 买到的宝贝不符合预期', img: '', imgSrc: '' } |
||||
], |
||||
total: 200 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.order_info_page { |
||||
.order_info { |
||||
overflow: hidden; |
||||
p { |
||||
width: 50%; |
||||
float: left; |
||||
span { |
||||
font-size: 16px; |
||||
color: #333333; |
||||
display: inline-block; |
||||
&:nth-of-type(1) { |
||||
width:130px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
color:#666666; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.detail_title { |
||||
font-size: 24px; |
||||
color: #333333; |
||||
position: relative; |
||||
margin:50px 20px 20px; |
||||
&:before { |
||||
content: ''; |
||||
display: block; |
||||
position: absolute; |
||||
top: 5px; |
||||
left: -20px; |
||||
width: 4px; |
||||
height: 24px; |
||||
background-color: #3A68F2; |
||||
} |
||||
} |
||||
.goods_list { |
||||
.good_details { |
||||
border-bottom: 1px #E0E5EB solid; |
||||
ul { |
||||
overflow: hidden; |
||||
display: flex; |
||||
margin: 0; |
||||
padding: 30px 0; |
||||
list-style: none; |
||||
li { |
||||
flex:3; |
||||
display: flex; |
||||
// justify-content: center; |
||||
// align-items: center; |
||||
text-align: left; |
||||
img { |
||||
width: 90px; |
||||
height: 90px; |
||||
border-radius:4px; |
||||
font-size: 16px; |
||||
color: #333333; |
||||
} |
||||
&:nth-child(2),&:nth-child(3) { |
||||
display: block; |
||||
} |
||||
&:nth-child(3) { |
||||
p { |
||||
// text-align: center; |
||||
&:nth-child(1) { |
||||
font-weight: 600; |
||||
} |
||||
&:nth-child(2) { |
||||
font-size: 12px; |
||||
} |
||||
} |
||||
} |
||||
&:nth-child(4) { |
||||
font-weight: 600; |
||||
} |
||||
p { |
||||
margin: 0; |
||||
padding: 0; |
||||
height: 30px; |
||||
line-height: 30px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.total { |
||||
padding-left: 20px; |
||||
ul { |
||||
margin: 0; |
||||
padding: 30px 0; |
||||
display: flex; |
||||
list-style: none; |
||||
|
||||
li { |
||||
// height: 40px; |
||||
flex:3; |
||||
font-size: 16px; |
||||
color: #333333; |
||||
// justify-content: center; |
||||
// align-items: center; |
||||
&:nth-child(4) { |
||||
// font-weight: 600; |
||||
} |
||||
p { |
||||
margin: 0; |
||||
padding: 0; |
||||
height: 30px; |
||||
line-height: 30px; |
||||
width: 100%; |
||||
clear: both; |
||||
span { |
||||
display: inline-block; |
||||
float: left; |
||||
&:nth-of-type(1) { |
||||
width: 40%; |
||||
margin-right: 10%; |
||||
} |
||||
&:nth-of-type(2) { |
||||
width: 50%; |
||||
font-weight: 600; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,46 @@
|
||||
<template> |
||||
<div class="store_info_page"> |
||||
<p v-for="(item,index) in storeInfo" :key="index"> |
||||
<span>{{ item.name }}:</span> |
||||
<span>{{ item.value }}</span> |
||||
</p> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
storeInfo: [ |
||||
{ name: '店铺名称', value: '江山的店铺', field: '' }, |
||||
{ name: '合同有效期', value: '2020-06-30──2022-07-23', field: '' }, |
||||
{ name: '负责人', value: '江山', field: '' }, |
||||
{ name: '联系电话', value: '0755-56894556', field: '' }, |
||||
{ name: '联系地址', value: '广东省深圳市南山区科技园', field: '' } |
||||
] |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.store_info_page { |
||||
padding: 20px 10%; |
||||
overflow: hidden; |
||||
p { |
||||
width: 50%; |
||||
float: left; |
||||
span { |
||||
font-size: 16px; |
||||
color: #333333; |
||||
display: inline-block; |
||||
&:nth-of-type(1) { |
||||
width:130px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
color:#666666; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,462 @@
|
||||
<template> |
||||
<div class="detail_page"> |
||||
<div class="content"> |
||||
<div class="head_box"> |
||||
售后详情 |
||||
<div class="btn_list"> |
||||
<el-button @click="refuse">拒绝售后</el-button> |
||||
<el-button type="primary" @click="handle">同意售后</el-button> |
||||
</div> |
||||
</div> |
||||
<div class="detail"> |
||||
<div class="order_info"> |
||||
<p class="detail_title">订单信息</p> |
||||
<ul class="order_list"> |
||||
<li v-for="(item,index) in orderInfo" :key="index"> |
||||
<p>{{ item.name }}:</p> |
||||
<p :class="[{active: item.type ===1 || item.type ===2 || item.type ===4}]"> |
||||
<span @click="getInfo(item)">{{ item.value }}</span> |
||||
<span v-if="item.type ===3" class="active" @click="getInfo(item)"> |
||||
查看物流 |
||||
</span> |
||||
</p> |
||||
</li> |
||||
</ul> |
||||
|
||||
</div> |
||||
|
||||
<div class="after_sale_shop"> |
||||
<p class="detail_title">售后商品</p> |
||||
<div |
||||
v-for="(item,index) in shopList" |
||||
:key="index" |
||||
class="goods_list" |
||||
> |
||||
<div class="good_details"> |
||||
<ul> |
||||
<li> |
||||
<img :src="item.skuImg" /> |
||||
</li> |
||||
<li> |
||||
<p>{{ item.productName }}</p> |
||||
<p>{{ item.skuNameStr }}</p> |
||||
<p>SKU: {{ item.skuId }}</p> |
||||
</li> |
||||
<li> |
||||
<p>¥{{ item.sellPrice*item.buyNum }}</p> |
||||
<p>¥{{ `${item.sellPrice}*${item.buyNum}` }}</p> |
||||
</li> |
||||
<li> ¥{{ item.applyPrice * item.buyNum }}</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
<div class="total"> |
||||
<ul> |
||||
<li></li> |
||||
<li></li> |
||||
<li>退款总金额 </li> |
||||
<li>¥{{ total }}</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="after_sales_record"> |
||||
<p class="detail_title">协商历史</p> |
||||
<div v-for="(item,index) in recordList" :key="index" class="record_list"> |
||||
<div class="record_list_title"> |
||||
<p>{{ item.title }}</p> |
||||
<p>{{ item.name }}</p> |
||||
<p>{{ item.createTime }}</p> |
||||
</div> |
||||
<div class="record_list_content"> |
||||
<p> |
||||
<span>{{ item.type }}:</span> |
||||
<span>{{ item.actionNote }}</span> |
||||
</p> |
||||
<p v-if="item.img"> |
||||
<span>举证图片:</span> |
||||
<img :src="item.imgSrc" alt="" /> |
||||
</p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<Dialog |
||||
:title="dialog.title" |
||||
:visible.sync="dialog.visible" |
||||
:fullscreen="!true" |
||||
:before-close="close" |
||||
width="55%" |
||||
> |
||||
<orderInfo v-if="dialog.type===1" /> |
||||
<storeInfo v-if="dialog.type===2" /> |
||||
<logistics v-if="dialog.type===3" /> |
||||
<buyer v-if="dialog.type===4" /> |
||||
<afterSale v-if="dialog.type===5" :dialog="dialog" @close="close" /> |
||||
<!-- <goods v-if="dialog.type===1" :info="info" /> |
||||
<audit-log v-if="dialog.type===2" :info="info" /> --> |
||||
</Dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { Dialog } from 'element-ui' |
||||
import afterSale from './component/after-sales' |
||||
import buyer from './component/buyer' |
||||
import logistics from './component/logistics' |
||||
import orderInfo from './component/order-info' |
||||
import storeInfo from './component/store-info' |
||||
import AfterSale from '@/api/AfterSale' |
||||
export default { |
||||
components: { |
||||
Dialog, |
||||
afterSale, |
||||
buyer, |
||||
logistics, |
||||
orderInfo, |
||||
storeInfo |
||||
}, |
||||
data() { |
||||
return { |
||||
orderInfo: [ |
||||
{ name: '订单ID', value: '', type: 1, field: 'orderCode' }, |
||||
{ name: '售后订单ID', value: '', type: '', field: 'orderCode' }, |
||||
{ name: '支付时间', value: '', type: '', field: 'createTime' }, |
||||
{ name: '支付方式', value: '', type: '', field: 'payChannel' }, |
||||
{ name: '订单总金额', value: '', type: '', field: '' }, |
||||
{ name: '店铺名称', value: '', type: 2, field: 'memberAccount' }, |
||||
{ name: '物流单号', value: '', type: 3, field: 'logisticsNum' }, |
||||
{ name: '售后类型', value: '', type: '', field: 'returnType' }, |
||||
{ name: '买家账户', value: '', type: 4, field: 'recName' } |
||||
], |
||||
shopList: [ |
||||
{ skuImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg', |
||||
productName: 'DAD 气垫霜', skuNameStr: '粉色, 中瓶', skuId: '2525', sellPrice: '60', buyNum: '2', salePrice: '50' }, |
||||
{ skuImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg', |
||||
productName: 'DAD 气垫霜', skuNameStr: '粉色, 中瓶', skuId: '2525', sellPrice: '60', buyNum: '2', salePrice: '50' } |
||||
], |
||||
recordList: [ |
||||
{ title: '申请平台介入', name: '刘十', time: '2020-05-08 15:30:56', type: '问题描述', value: '不退款', img: '举证图片', |
||||
imgSrc: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=137628589,3436980029&fm=26&gp=0.jpg' }, |
||||
{ title: '拒绝退款', name: '王辉', time: '2020-04-08 17:30:20', type: '卖家留言', value: '不退款', img: '', imgSrc: '' }, |
||||
{ title: '发起了售后', name: '张强', time: '2020-03-25 13:25:45', type: '买家留言', value: '不要了, 买到的宝贝不符合预期', img: '', imgSrc: '' } |
||||
], |
||||
total: 0, |
||||
dialog: {} |
||||
} |
||||
}, |
||||
computed: { |
||||
query() { |
||||
return this.$route.query |
||||
} |
||||
}, |
||||
created() { |
||||
this.getDetails() |
||||
}, |
||||
methods: { |
||||
async getDetails() { |
||||
const res = await AfterSale.getInfo(this.query.id) |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
const o = resData.data |
||||
this.getOrderInfo(o) |
||||
this.shopList = o.orderProductDTOList |
||||
this.getTotal(o.orderProductDTOList) |
||||
this.recordList = o.moneyReturnActionHistoryList |
||||
console.log(o, 'rr') |
||||
} |
||||
}, |
||||
getTotal(data) { |
||||
if (data && data.length) { |
||||
data.forEach(item => { |
||||
this.total += item.applyPrice * item.buyNum |
||||
}) |
||||
} |
||||
}, |
||||
getOrderInfo(o) { |
||||
const payChannel = { |
||||
1: '微信支付', |
||||
2: '支付宝支付', |
||||
3: '余额支付' |
||||
} |
||||
const returnType = { |
||||
1: '无售后', |
||||
2: '退款', |
||||
3: '退货' |
||||
} |
||||
this.orderInfo.map(item => { |
||||
item.value = o[item.field] || '' |
||||
if (item.field === 'payChannel') { |
||||
item.value = payChannel[item.value] |
||||
} |
||||
if (item.field === 'returnType') { |
||||
item.value = returnType[item.value] |
||||
} |
||||
}) |
||||
}, |
||||
handle() { |
||||
this.dialog = { |
||||
title: '同意售后', |
||||
visible: true, |
||||
type: 5, |
||||
btnName: '同意售后', |
||||
allow: true |
||||
} |
||||
}, |
||||
refuse() { |
||||
this.dialog = { |
||||
title: '拒绝售后', |
||||
visible: true, |
||||
type: 5, |
||||
btnName: '拒绝售后' |
||||
} |
||||
}, |
||||
getInfo(item) { |
||||
if (item.type === 1) { |
||||
this.dialog = { |
||||
title: '订单信息', |
||||
visible: true, |
||||
type: item.type |
||||
} |
||||
} |
||||
|
||||
if (item.type === 2) { |
||||
this.dialog = { |
||||
title: '店铺信息', |
||||
visible: true, |
||||
type: item.type |
||||
} |
||||
} |
||||
|
||||
if (item.type === 3) { |
||||
this.dialog = { |
||||
title: '物流信息', |
||||
visible: true, |
||||
type: item.type |
||||
} |
||||
} |
||||
|
||||
if (item.type === 4) { |
||||
this.dialog = { |
||||
title: '买家信息', |
||||
visible: true, |
||||
type: item.type |
||||
} |
||||
} |
||||
}, |
||||
close() { |
||||
this.dialog = {} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.detail_page { |
||||
margin-top: 10px; |
||||
background-color: #fff; |
||||
height: calc(100% - 10px); |
||||
.content { |
||||
padding: 20px; |
||||
.head_box { |
||||
overflow: hidden; |
||||
height: 80px; |
||||
line-height: 80px; |
||||
font-size: 24px; |
||||
border-bottom: 1px solid #E0E5EB; |
||||
.btn_list { |
||||
display: inline-block; |
||||
float: right; |
||||
} |
||||
} |
||||
.detail , .after_sales_record{ |
||||
min-height: 500px; |
||||
background:rgba(255,255,255,1); |
||||
box-shadow:0px 0px 10px 0px rgba(51,51,51,0.15); |
||||
border-radius:4px; |
||||
padding: 1px 10% 20px; |
||||
margin-top: 15px; |
||||
|
||||
.detail_title { |
||||
font-size: 24px; |
||||
color: #333333; |
||||
position: relative; |
||||
margin:50px 20px 20px; |
||||
&:before { |
||||
content: ''; |
||||
display: block; |
||||
position: absolute; |
||||
top: 5px; |
||||
left: -20px; |
||||
width: 4px; |
||||
height: 24px; |
||||
background-color: #3A68F2; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.order_info { |
||||
.order_list { |
||||
padding-left: 20px; |
||||
overflow: hidden; |
||||
list-style: none; |
||||
li { |
||||
float: left; |
||||
width: calc(100% / 3); |
||||
margin-bottom: 30px; |
||||
p { |
||||
margin: 0; |
||||
padding: 0; |
||||
display: inline-block; |
||||
font-size: 16px; |
||||
color: #333333; |
||||
&:nth-child(1) { |
||||
width: 20%; |
||||
} |
||||
&:nth-child(2) { |
||||
color: #666666; |
||||
} |
||||
} |
||||
} |
||||
.active { |
||||
color: #3A68F2 !important; |
||||
&:hover { |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.after_sale_shop { |
||||
.goods_list { |
||||
padding-left: 20px; |
||||
.good_details { |
||||
border-bottom: 1px #E0E5EB solid; |
||||
ul { |
||||
overflow: hidden; |
||||
display: flex; |
||||
margin: 0; |
||||
padding: 30px 0; |
||||
li { |
||||
flex:3; |
||||
display: flex; |
||||
// justify-content: center; |
||||
// align-items: center; |
||||
text-align: left; |
||||
img { |
||||
width: 90px; |
||||
height: 90px; |
||||
border-radius:4px; |
||||
font-size: 16px; |
||||
color: #333333; |
||||
} |
||||
&:nth-child(2),&:nth-child(3) { |
||||
display: block; |
||||
} |
||||
&:nth-child(3) { |
||||
p { |
||||
// text-align: center; |
||||
&:nth-child(1) { |
||||
font-weight: 600; |
||||
} |
||||
&:nth-child(2) { |
||||
font-size: 12px; |
||||
} |
||||
} |
||||
} |
||||
&:nth-child(4) { |
||||
font-weight: 600; |
||||
} |
||||
p { |
||||
margin: 0; |
||||
padding: 0; |
||||
height: 30px; |
||||
line-height: 30px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.total { |
||||
padding-left: 20px; |
||||
ul { |
||||
margin: 0; |
||||
padding: 30px 0; |
||||
display: flex; |
||||
li { |
||||
// height: 40px; |
||||
flex:3; |
||||
font-size: 16px; |
||||
color: #333333; |
||||
display: flex; |
||||
// justify-content: center; |
||||
// align-items: center; |
||||
&:nth-child(4) { |
||||
font-weight: 600; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.after_sales_record { |
||||
p { |
||||
margin: 0; |
||||
padding:0 ; |
||||
font-size: 16px; |
||||
} |
||||
.record_list { |
||||
padding-left: 20px; |
||||
.record_list_title { |
||||
background: #F7F7F7; |
||||
overflow: hidden; |
||||
margin-bottom: 30px; |
||||
p { |
||||
float: left; |
||||
text-indent: 10px; |
||||
width: calc(100% / 3); |
||||
height: 36px; |
||||
line-height: 36px; |
||||
} |
||||
} |
||||
.record_list_content { |
||||
p { |
||||
overflow: hidden; |
||||
margin-bottom: 30px; |
||||
span { |
||||
display: block; |
||||
float: left; |
||||
width: 100px; |
||||
&:nth-of-type(2) { |
||||
text-indent: 10px; |
||||
} |
||||
&:nth-of-type(2) { |
||||
color: #666666; |
||||
width: calc(100% - 100px); |
||||
} |
||||
} |
||||
img { |
||||
width: 90px; |
||||
height: 90px; |
||||
border-radius: 4px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .el-dialog__wrapper { |
||||
.el-dialog__header { |
||||
height: 70px; |
||||
background-color: #3A68F2; |
||||
.el-dialog__title { |
||||
font-size:24px; |
||||
color: #fff; |
||||
} |
||||
} |
||||
} |
||||
|
||||
</style> |
@ -0,0 +1,233 @@
|
||||
<template> |
||||
<div class="after_sale_service_page"> |
||||
<div class="content"> |
||||
<el-tabs |
||||
v-model="formParams.queryType" |
||||
@tab-click="selectItem" |
||||
> |
||||
<el-tab-pane |
||||
v-for="(item, index) in tabList" |
||||
:key="index" |
||||
:label="item.name" |
||||
:name="item.id" |
||||
/> |
||||
</el-tabs> |
||||
<div class="toolbar"> |
||||
<el-form |
||||
:inline="true" |
||||
:model="formParams" |
||||
> |
||||
<el-form-item label="店铺名称/编号"> |
||||
<el-input v-model="formParams.keyword" size="mini" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="订单id"> |
||||
<el-input v-model="formParams.orderCode" size="mini" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="下单时间"> |
||||
<el-date-picker |
||||
v-model="date" |
||||
size="mini" |
||||
type="daterange" |
||||
range-separator="至" |
||||
start-placeholder="开始时间" |
||||
end-placeholder="结束时间" |
||||
value-format="yyyy-MM-dd" |
||||
@change="handleChange" |
||||
/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button |
||||
type="primary" |
||||
size="mini" |
||||
@click="query" |
||||
> |
||||
查询 |
||||
</el-button> |
||||
<el-button |
||||
plain |
||||
size="mini" |
||||
@click="reset" |
||||
> |
||||
重置 |
||||
</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
|
||||
<div class="content_table"> |
||||
<div class="table"> |
||||
<el-table |
||||
:data="tableData.returnInterventionDTOList" |
||||
border |
||||
style="width: 100%" |
||||
> |
||||
<el-table-column |
||||
prop="id" |
||||
label="订单id" |
||||
/> |
||||
<el-table-column |
||||
prop="storeName" |
||||
label="店铺名称" |
||||
/> |
||||
<el-table-column |
||||
prop="tenantCode" |
||||
label="店铺编码" |
||||
/> |
||||
<el-table-column |
||||
prop="returnProductCount" |
||||
label="售后商品数量" |
||||
/> |
||||
<el-table-column |
||||
v-if="formParams.queryType === '1'" |
||||
prop="applySum" |
||||
:formatter="getPrice" |
||||
label="退款金额" |
||||
/> |
||||
<el-table-column |
||||
v-else |
||||
prop="value5" |
||||
:formatter="getPrice" |
||||
label="订单金额" |
||||
/> |
||||
<el-table-column label="操作"> |
||||
<template |
||||
slot-scope="scope" |
||||
> |
||||
<el-button |
||||
v-if="formParams.queryType ==='1'" |
||||
type="text" |
||||
size="small" |
||||
@click.native.prevent="handle(scope.row.id)" |
||||
> |
||||
处理 |
||||
</el-button> |
||||
<el-button |
||||
type="text" |
||||
size="small" |
||||
@click.native.prevent="details(scope.row.id)" |
||||
> |
||||
查看 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="formParams.pageSize" |
||||
:page.sync="formParams.pageIndex" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import AfterSale from '@/api/AfterSale' |
||||
export default { |
||||
components: { |
||||
Pagination |
||||
}, |
||||
data() { |
||||
return { |
||||
formParams: { |
||||
keyword: '', |
||||
orderCode: '', |
||||
startTime: '', |
||||
endTime: '', |
||||
pageSize: 10, |
||||
pageIndex: 1, |
||||
queryType: '1' |
||||
}, |
||||
date: [], |
||||
tableData: {}, |
||||
tabList: [ |
||||
{ name: '待处理', id: '1' }, |
||||
{ name: '已处理', id: '2' } |
||||
] |
||||
} |
||||
}, |
||||
created() { |
||||
this.getList() |
||||
}, |
||||
methods: { |
||||
async getList() { |
||||
const res = await AfterSale.getList(this.formParams) |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
this.tableData = resData.data |
||||
} |
||||
}, |
||||
getPrice(item, row, value) { |
||||
return value / 100 |
||||
}, |
||||
query() { |
||||
this.getList() |
||||
}, |
||||
details(id) { |
||||
this.$router.push({ path: '/after-sale-service/details', query: { id }}) |
||||
}, |
||||
handle(id) { |
||||
this.$router.push({ path: '/after-sale-service/details', query: { id }}) |
||||
}, |
||||
reset() { |
||||
this.formParams = { |
||||
keyword: '', |
||||
orderCode: '', |
||||
startTime: '', |
||||
endTime: '', |
||||
pageSize: 10, |
||||
pageIndex: 1, |
||||
queryType: '1' |
||||
} |
||||
}, |
||||
fetch() { |
||||
this.getList() |
||||
}, |
||||
selectItem() { |
||||
this.getList() |
||||
}, |
||||
handleChange(value) { |
||||
this.formParams.startTime = (value && value[0]) || '' |
||||
this.formParams.endTime = (value && value[1]) || '' |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
|
||||
.after_sale_service_page { |
||||
padding: 10px 20px; |
||||
box-sizing: border-box; |
||||
.content { |
||||
background-color: #fff; |
||||
.toolbar { |
||||
padding: 10px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .el-table { |
||||
th { |
||||
background: #EEF3FF; |
||||
color:#333333; |
||||
font-size:16px; |
||||
font-weight: 400; |
||||
border-color: #E0E5EB; |
||||
text-align: center; |
||||
} |
||||
td { |
||||
font-size: 14px; |
||||
text-align: center; |
||||
color: #666666; |
||||
} |
||||
} |
||||
</style> |
||||
|
@ -0,0 +1,203 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :title="title" :type="type" |
||||
:visible.sync="isVisible" |
||||
:width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="resource" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.resource.code')" prop="code"> |
||||
<el-input v-model="resource.code" :disabled="type==='edit'" @keyup.enter.native="submitForm" /> |
||||
<p class="note">建议使用:作为分隔符,并以view、add、update、delete、export、import、download、upload等关键词结尾</p> |
||||
<p class="note">如:menu:add、 resource:view、 file:upload</p> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.resource.name')" prop="name" @keyup.enter.native="submitForm"> |
||||
<el-input v-model="resource.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.resource.describe')" prop="describe" @keyup.enter.native="submitForm"> |
||||
<el-input v-model="resource.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import resourceApi from '@/api/Resource.js' |
||||
|
||||
export default { |
||||
name: 'ResourceEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
resource: this.initResource(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
rules: { |
||||
code: [ |
||||
{ |
||||
required: true, |
||||
message: this.$t('rules.require'), |
||||
trigger: 'blur' |
||||
}, |
||||
{ |
||||
min: 1, |
||||
max: 255, |
||||
message: this.$t('rules.range4to10'), |
||||
trigger: 'blur' |
||||
}, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
if (!this.resource.id) { |
||||
// this.$get(`system/user/check/${value}`).then((r) => { |
||||
// if (!r.data) { |
||||
// callback(this.$t('rules.usernameExist')) |
||||
// } else { |
||||
// callback() |
||||
// } |
||||
// }) |
||||
} else { |
||||
// callback() |
||||
} |
||||
callback() |
||||
}, |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
name: { |
||||
required: true, |
||||
message: this.$t('rules.require'), |
||||
trigger: 'blur' |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.type === 'add' |
||||
? this.$t('common.add') |
||||
: this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initResource () { |
||||
return { |
||||
id: '', |
||||
name: '', |
||||
code: '', |
||||
describe: '' |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
setResource (val) { |
||||
const that = this |
||||
if (val) { |
||||
that.resource = { ...val } |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.resource = this.initResource() |
||||
}, |
||||
submitForm () { |
||||
const that = this |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
that.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const that = this |
||||
if (that.type === 'add') { |
||||
that.save() |
||||
} else { |
||||
that.update() |
||||
} |
||||
}, |
||||
save () { |
||||
const that = this |
||||
resourceApi.save(this.resource).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
that.isVisible = false |
||||
that.$message({ |
||||
message: that.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
that.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
resourceApi.update(this.resource).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
p.note { |
||||
font-size: 12px; |
||||
margin: 0; |
||||
padding: 0; |
||||
line-height: 1.4rem; |
||||
} |
||||
</style> |
@ -0,0 +1,477 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :title="$t('table.menu.icon')" :visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<el-input |
||||
v-model="name" class="filter-item search-item" clearable |
||||
placeholder="icon" |
||||
@keyup.native="searchIcon" |
||||
/> |
||||
<el-tabs v-model="activeName" style="margin-top: -1rem;"> |
||||
<el-tab-pane :label="$t('common.tab.common')" name="first"> |
||||
<ul> |
||||
<li v-for="icon in icons.commonIcons" :key="icon" class="icons-item"> |
||||
<span :class="{'active':activeIndex === icon}"> |
||||
<el-icon :class="icon" :title="icon" @click.native="chooseIcon(icon)" @dblclick.native="confirm" /> |
||||
</span> |
||||
<p>{{ icon }}</p> |
||||
</li> |
||||
</ul> |
||||
</el-tab-pane> |
||||
<el-tab-pane :label="$t('common.tab.directivity')" name="second"> |
||||
<ul> |
||||
<li v-for="icon in icons.directivityIcons" :key="icon"> |
||||
<span :class="{'active':activeIndex === icon}"> |
||||
<el-icon :class="icon" :title="icon" @click.native="chooseIcon(icon)" @dblclick.native="confirm" /> |
||||
</span> |
||||
<p>{{ icon }}</p> |
||||
</li> |
||||
</ul> |
||||
</el-tab-pane> |
||||
<el-tab-pane :label="$t('common.tab.solid')" name="third"> |
||||
<ul> |
||||
<li v-for="icon in icons.solidIcons" :key="icon"> |
||||
<span :class="{'active':activeIndex === icon}"> |
||||
<el-icon :class="icon" :title="icon" @click.native="chooseIcon(icon)" @dblclick.native="confirm" /> |
||||
</span> |
||||
<p>{{ icon }}</p> |
||||
</li> |
||||
</ul> |
||||
</el-tab-pane> |
||||
<el-tab-pane :label="$t('common.tab.food')" name="fourth"> |
||||
<ul> |
||||
<li v-for="icon in icons.foodIcons" :key="icon"> |
||||
<span :class="{'active':activeIndex === icon}"> |
||||
<el-icon :class="icon" :title="icon" @click.native="chooseIcon(icon)" @dblclick.native="confirm" /> |
||||
</span> |
||||
<p>{{ icon }}</p> |
||||
</li> |
||||
</ul> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="confirm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
const commonIcons = [ |
||||
'el-icon-eleme', 'el-icon-delete', 'el-icon-setting', 'el-icon-user', 'el-icon-phone-outline', |
||||
'el-icon-more-outline', 'el-icon-star-off', 'el-icon-goods', 'el-icon-warning-outline', 'el-icon-zoom-in', |
||||
'el-icon-zoom-out', 'el-icon-remove-outline', 'el-icon-circle-plus-outline', 'el-icon-circle-check', 'el-icon-circle-close', |
||||
'el-icon-help', 'el-icon-minus', 'el-icon-plus', 'el-icon-check', 'el-icon-close', 'el-icon-picture-outline', |
||||
'el-icon-picture-outline-round', 'el-icon-upload2', 'el-icon-download', 'el-icon-camera', 'el-icon-video-camera', |
||||
'el-icon-bell', 'el-icon-video-pause', 'el-icon-video-play', 'el-icon-refresh', 'el-icon-refresh-right', 'el-icon-refresh-left', |
||||
'el-icon-finished', 'el-icon-loading', 'el-icon-view', 'el-icon-c-scale-to-original', 'el-icon-date', 'el-icon-edit', |
||||
'el-icon-edit-outline', 'el-icon-folder', 'el-icon-folder-opened', 'el-icon-folder-add', 'el-icon-folder-remove', 'el-icon-folder-delete', |
||||
'el-icon-folder-checked', 'el-icon-tickets', 'el-icon-document-remove', 'el-icon-document-delete', 'el-icon-document-copy', |
||||
'el-icon-document-checked', 'el-icon-document', 'el-icon-document-add', 'el-icon-printer', 'el-icon-paperclip', |
||||
'el-icon-takeaway-box', 'el-icon-search', 'el-icon-monitor', 'el-icon-attract', |
||||
'el-icon-mobile', |
||||
'el-icon-scissors', |
||||
'el-icon-umbrella', |
||||
'el-icon-headset', |
||||
'el-icon-brush', |
||||
'el-icon-mouse', |
||||
'el-icon-coordinate', |
||||
'el-icon-magic-stick', |
||||
'el-icon-reading', |
||||
'el-icon-data-line', |
||||
'el-icon-data-board', |
||||
'el-icon-pie-chart', |
||||
'el-icon-data-analysis', |
||||
'el-icon-collection-tag', |
||||
'el-icon-film', |
||||
'el-icon-suitcase', |
||||
'el-icon-suitcase-1', |
||||
'el-icon-receiving', |
||||
'el-icon-collection', |
||||
'el-icon-files', |
||||
'el-icon-notebook-1', |
||||
'el-icon-notebook-2', |
||||
'el-icon-toilet-paper', |
||||
'el-icon-office-building', |
||||
'el-icon-school', |
||||
'el-icon-table-lamp', |
||||
'el-icon-house', |
||||
'el-icon-no-smoking', |
||||
'el-icon-smoking', |
||||
'el-icon-shopping-cart-full', |
||||
'el-icon-shopping-cart-1', |
||||
'el-icon-shopping-cart-2', |
||||
'el-icon-shopping-bag-1', |
||||
'el-icon-shopping-bag-2', |
||||
'el-icon-sold-out', |
||||
'el-icon-sell', |
||||
'el-icon-present', |
||||
'el-icon-box', |
||||
'el-icon-bank-card', |
||||
'el-icon-money', |
||||
'el-icon-coin', |
||||
'el-icon-wallet', |
||||
'el-icon-discount', |
||||
'el-icon-price-tag', |
||||
'el-icon-news', |
||||
'el-icon-guide', |
||||
'el-icon-male', |
||||
'el-icon-female', |
||||
'el-icon-thumb', |
||||
'el-icon-cpu', |
||||
'el-icon-link', |
||||
'el-icon-connection', |
||||
'el-icon-open', |
||||
'el-icon-turn-off', |
||||
'el-icon-set-up', |
||||
'el-icon-chat-round', |
||||
'el-icon-chat-line-round', |
||||
'el-icon-chat-square', |
||||
'el-icon-chat-dot-round', |
||||
'el-icon-chat-dot-square', |
||||
'el-icon-chat-line-square', |
||||
'el-icon-message', |
||||
'el-icon-postcard', |
||||
'el-icon-position', |
||||
'el-icon-turn-off-microphone', |
||||
'el-icon-microphone', |
||||
'el-icon-close-notification', |
||||
'el-icon-bangzhu', |
||||
'el-icon-time', |
||||
'el-icon-odometer', |
||||
'el-icon-crop', |
||||
'el-icon-aim', |
||||
'el-icon-switch-button', |
||||
'el-icon-full-screen', |
||||
'el-icon-copy-document', |
||||
'el-icon-mic', |
||||
'el-icon-stopwatch', |
||||
'el-icon-medal-1', |
||||
'el-icon-medal', |
||||
'el-icon-trophy', |
||||
'el-icon-trophy-1', |
||||
'el-icon-first-aid-kit', |
||||
'el-icon-discover', |
||||
'el-icon-place', |
||||
'el-icon-location-outline', |
||||
'el-icon-location-information', |
||||
'el-icon-add-location', |
||||
'el-icon-delete-location', |
||||
'el-icon-map-location', |
||||
'el-icon-alarm-clock', |
||||
'el-icon-timer', |
||||
'el-icon-watch-1', |
||||
'el-icon-watch', |
||||
'el-icon-lock', |
||||
'el-icon-unlock', |
||||
'el-icon-key', |
||||
'el-icon-service', |
||||
'el-icon-mobile-phone', |
||||
'el-icon-bicycle', |
||||
'el-icon-truck', |
||||
'el-icon-ship', |
||||
'el-icon-basketball', |
||||
'el-icon-football', |
||||
'el-icon-soccer', |
||||
'el-icon-baseball' |
||||
] |
||||
const directivityIcons = [ |
||||
'el-icon-d-caret', |
||||
'el-icon-caret-left', |
||||
'el-icon-caret-right', |
||||
'el-icon-caret-bottom', |
||||
'el-icon-caret-top', |
||||
'el-icon-bottom-left', |
||||
'el-icon-bottom-right', |
||||
'el-icon-back', |
||||
'el-icon-right', |
||||
'el-icon-bottom', |
||||
'el-icon-top', |
||||
'el-icon-top-left', |
||||
'el-icon-top-right', |
||||
'el-icon-arrow-left', |
||||
'el-icon-arrow-right', |
||||
'el-icon-arrow-down', |
||||
'el-icon-arrow-up', |
||||
'el-icon-d-arrow-left', |
||||
'el-icon-d-arrow-right', |
||||
'el-icon-sort', |
||||
'el-icon-sort-up', |
||||
'el-icon-sort-down', |
||||
'el-icon-rank' |
||||
] |
||||
const solidIcons = [ |
||||
'el-icon-question', |
||||
'el-icon-info', |
||||
'el-icon-remove', |
||||
'el-icon-circle-plus', |
||||
'el-icon-success', |
||||
'el-icon-error', |
||||
'el-icon-platform-eleme', |
||||
'el-icon-delete-solid', |
||||
'el-icon-s-tools', |
||||
'el-icon-user-solid', |
||||
'el-icon-phone', |
||||
'el-icon-star-on', |
||||
'el-icon-s-goods', |
||||
'el-icon-warning', |
||||
'el-icon-s-help', |
||||
'el-icon-picture', |
||||
'el-icon-upload', |
||||
'el-icon-camera-solid', |
||||
'el-icon-video-camera-solid', |
||||
'el-icon-message-solid', |
||||
'el-icon-s-cooperation', |
||||
'el-icon-s-order', |
||||
'el-icon-s-platform', |
||||
'el-icon-s-fold', |
||||
'el-icon-s-unfold', |
||||
'el-icon-s-operation', |
||||
'el-icon-s-promotion', |
||||
'el-icon-s-home', |
||||
'el-icon-s-release', |
||||
'el-icon-s-ticket', |
||||
'el-icon-s-management', |
||||
'el-icon-s-open', |
||||
'el-icon-s-shop', |
||||
'el-icon-s-marketing', |
||||
'el-icon-s-flag', |
||||
'el-icon-s-comment', |
||||
'el-icon-s-finance', |
||||
'el-icon-s-claim', |
||||
'el-icon-s-custom', |
||||
'el-icon-s-opportunity', |
||||
'el-icon-s-data', |
||||
'el-icon-s-check', |
||||
'el-icon-s-grid', |
||||
'el-icon-menu', |
||||
'el-icon-share', |
||||
'el-icon-d-caret', |
||||
'el-icon-caret-left', |
||||
'el-icon-caret-right', |
||||
'el-icon-caret-bottom', |
||||
'el-icon-caret-top', |
||||
'el-icon-location' |
||||
] |
||||
const foodIcons = [ |
||||
'el-icon-dish', |
||||
'el-icon-dish-1', |
||||
'el-icon-food', |
||||
'el-icon-chicken', |
||||
'el-icon-fork-spoon', |
||||
'el-icon-knife-fork', |
||||
'el-icon-burger', |
||||
'el-icon-tableware', |
||||
'el-icon-sugar', |
||||
'el-icon-dessert', |
||||
'el-icon-ice-cream', |
||||
'el-icon-hot-water', |
||||
'el-icon-water-cup', |
||||
'el-icon-coffee-cup', |
||||
'el-icon-cold-drink', |
||||
'el-icon-goblet', |
||||
'el-icon-goblet-full', |
||||
'el-icon-goblet-square', |
||||
'el-icon-goblet-square-full', |
||||
'el-icon-refrigerator', |
||||
'el-icon-grape', |
||||
'el-icon-watermelon', |
||||
'el-icon-cherry', |
||||
'el-icon-apple', |
||||
'el-icon-pear', |
||||
'el-icon-orange', |
||||
'el-icon-coffee', |
||||
'el-icon-ice-tea', |
||||
'el-icon-ice-drink', |
||||
'el-icon-milk-tea', |
||||
'el-icon-potato-strips', |
||||
'el-icon-lollipop', |
||||
'el-icon-ice-cream-square', |
||||
'el-icon-ice-cream-round' |
||||
] |
||||
export default { |
||||
name: 'Icons', |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
name: '', |
||||
icons: { |
||||
commonIcons, |
||||
directivityIcons, |
||||
solidIcons, |
||||
foodIcons |
||||
}, |
||||
activeIndex: '', |
||||
choosedIcon: '', |
||||
activeName: 'first', |
||||
screenWidth: 0, |
||||
width: this.initWidth() |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
} |
||||
} |
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '60%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
this.activeName = 'first' |
||||
this.choosedIcon = this.activeIndex = '' |
||||
}, |
||||
chooseIcon (icon) { |
||||
this.activeIndex = icon |
||||
this.choosedIcon = icon |
||||
}, |
||||
confirm () { |
||||
if (!this.choosedIcon) { |
||||
this.$message({ |
||||
message: this.$t('tips.chooseNothing'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$emit('choose', this.choosedIcon) |
||||
this.activeName = 'first' |
||||
this.choosedIcon = this.activeIndex = '' |
||||
}, |
||||
searchIcon () { |
||||
if (this.name.trim() === '') { |
||||
this.icons.commonIcons = commonIcons |
||||
this.icons.directivityIcons = directivityIcons |
||||
this.icons.solidIcons = solidIcons |
||||
this.icons.foodIcons = foodIcons |
||||
this.activeName = 'first' |
||||
} |
||||
const commonList = commonIcons.filter(item => item.indexOf(this.name) !== -1) |
||||
const directivityList = directivityIcons.filter(item => item.indexOf(this.name) !== -1) |
||||
const solidList = solidIcons.filter(item => item.indexOf(this.name) !== -1) |
||||
const foodIconsList = foodIcons.filter(item => item.indexOf(this.name) !== -1) |
||||
|
||||
this.icons.commonIcons = commonList |
||||
this.icons.directivityIcons = directivityList |
||||
this.icons.solidIcons = solidList |
||||
this.icons.foodIcons = foodIconsList |
||||
|
||||
if (commonList.length > 0) { |
||||
this.activeName = 'first' |
||||
return |
||||
} |
||||
|
||||
if (directivityList.length > 0) { |
||||
this.activeName = 'second' |
||||
return |
||||
} |
||||
|
||||
if (solidList.length > 0) { |
||||
this.activeName = 'third' |
||||
return |
||||
} |
||||
|
||||
if (foodIconsList.length > 0) { |
||||
this.activeName = 'fourth' |
||||
return |
||||
} |
||||
|
||||
this.activeName = 'first' |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.search-item { |
||||
margin: 0px 0 10px; |
||||
} |
||||
ul { |
||||
// overflow-y: auto; |
||||
// padding-left: 0rem; |
||||
// margin-top: 0rem; |
||||
padding: 0; |
||||
margin: 0; |
||||
overflow: auto; |
||||
zoom: 1; |
||||
height: 500px; |
||||
li { |
||||
// list-style: none; |
||||
// float: left; |
||||
// width: 60px; |
||||
// text-align: center; |
||||
// cursor: pointer; |
||||
// color: #555; |
||||
// transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out; |
||||
// position: relative; |
||||
// // margin: 3px 0; |
||||
// border-radius: 4px; |
||||
// background-color: #fff; |
||||
// overflow: hidden; |
||||
padding: 0; |
||||
float: left; |
||||
margin: 2px; |
||||
width: 100px; |
||||
text-align: center; |
||||
list-style: none; |
||||
cursor: pointer; |
||||
color: #5c6b77; |
||||
transition: all 0.2s ease; |
||||
position: relative; |
||||
} |
||||
span.active { |
||||
i { |
||||
border-radius: 2px; |
||||
border-color: #4a4a48; |
||||
background-color: #4a4a48; |
||||
color: #fff; |
||||
transition: all 0.3s; |
||||
} |
||||
} |
||||
i { |
||||
font-size: 1.7rem; |
||||
border: 1px solid #f1f1f1; |
||||
padding: 0.2rem; |
||||
margin: 0.3rem; |
||||
cursor: pointer; |
||||
&:hover { |
||||
border-radius: 2px; |
||||
border-color: #4a4a48; |
||||
background-color: #4a4a48; |
||||
color: #fff; |
||||
transition: all 0.3s; |
||||
} |
||||
} |
||||
li p { |
||||
word-break: break-all; |
||||
overflow: hidden; |
||||
margin: 2px 0; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,628 @@
|
||||
<template> |
||||
<div class="menu"> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="6" :xs="24"> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="label" :placeholder="$t('table.menu.label')" class="filter-item search-item" |
||||
clearable @keyup.enter.native="search" |
||||
/> |
||||
<el-tooltip class="item" content="新增/删除时,请先勾选菜单" effect="dark" placement="right"> |
||||
<el-dropdown |
||||
v-has-any-permission="['menu:add','menu:delete','menu:export']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['menu:add']" @click.native="add"> |
||||
{{ $t('table.add') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['menu:delete']" @click.native="deleteMenu"> |
||||
{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
</div> |
||||
<commonTree ref="menuTree" :tree-data="menuTree" @nodeClick="nodeClick"> |
||||
<template scope="treeNode"> |
||||
<span class="tree-icon"> |
||||
<i :class="treeNode.data.icon ? treeNode.data.icon : 'el-icon-document'"></i> |
||||
</span> |
||||
<span class="tree-icon"> |
||||
<el-badge :type="treeNode.data.isEnable ? 'success' :'danger'" class="status-item" is-dot /> |
||||
</span> |
||||
</template> |
||||
</commonTree> |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="8" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div slot="header" class="clearfix"> |
||||
<span>{{ menu.id === '' ? this.$t('common.add') : this.$t('common.edit') }}</span> |
||||
</div> |
||||
<div> |
||||
<el-form |
||||
ref="form" :model="menu" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.menu.parentId')" prop="parentId"> |
||||
<el-tooltip :content="$t('tips.topId')" class="item" effect="dark" placement="right"> |
||||
<el-input v-model="menu.parentId" readonly /> |
||||
</el-tooltip> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.menu.label')" prop="label"> |
||||
<el-input v-model="menu.label" /> |
||||
</el-form-item> |
||||
<!-- <el-form-item :label='$t("table.menu.type")' prop='type'> |
||||
<el-radio-group v-model='menu.type'> |
||||
<el-radio label='DIR'>目录</el-radio> |
||||
<el-radio label='MENU'>菜单</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item>--> |
||||
<el-form-item :label="$t('table.menu.path')" prop="path"> |
||||
<el-input v-model="menu.path" @keyup.native="menuPath" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.menu.component')" prop="component"> |
||||
<el-input v-model="menu.component" /> |
||||
<span>{{ menuComponent }}</span> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.menu.icon')" prop="icon"> |
||||
<el-input v-model="menu.icon"> |
||||
<el-button slot="append" icon="el-icon-brush" style="padding-left: 0;" @click="chooseIcons" /> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item :label="$t('table.status')" prop="isEnable"> |
||||
<el-switch |
||||
v-model="menu.isEnable" :active-text="$t('common.status.valid')" |
||||
:inactive-text="$t('common.status.invalid')" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item :label="$t('table.menu.isPublic')" prop="isPublic"> |
||||
<el-switch |
||||
v-model="menu.isPublic" :active-text="$t('common.yes')" |
||||
:inactive-text="$t('common.no')" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-form-item :label="$t('table.menu.sortValue')" prop="sortValue"> |
||||
<el-input-number v-model="menu.sortValue" :max="100" :min="0" @change="handleNumChange" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.menu.group')" prop="group"> |
||||
<el-tooltip class="item" content="用于区分多组菜单" effect="dark" placement="right"> |
||||
<el-input v-model="menu.group" /> |
||||
</el-tooltip> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.menu.describe')" prop="describe"> |
||||
<el-input v-model="menu.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</el-card> |
||||
<el-card class="box-card" style="margin-top: -2rem;"> |
||||
<el-row> |
||||
<el-col :span="24" style="text-align: right"> |
||||
<el-button plain type="primary" @click="submit">{{ menu.id === '' ? this.$t('common.add') : |
||||
this.$t('common.edit') }} |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-card> |
||||
</el-col> |
||||
|
||||
<el-col :sm="10" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="resourceQueryParams.model.code" :placeholder="$t('table.resource.code')" class="filter-item search-item" |
||||
clearable |
||||
/> |
||||
<el-input |
||||
v-model="resourceQueryParams.model.name" :placeholder="$t('table.resource.name')" class="filter-item search-item" |
||||
clearable |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="resourceSearch">{{ $t('table.search') }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['resource:add','resource:delete']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item |
||||
v-has-permission="['resource:add']" :disabled="!menu.id" |
||||
@click.native="resourceAdd" |
||||
>{{ $t('table.add') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['resource:delete']" @click.native="resourceBatchDelete">{{ |
||||
$t('table.delete') }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="resourceTableKey" |
||||
ref="resourceTable" |
||||
v-loading="resourceLoading" |
||||
:data="resourceTableData.records" |
||||
border |
||||
fit |
||||
style="width: 100%;" |
||||
@selection-change="onResourceSelectChange" |
||||
@sort-change="resourceSortChange" |
||||
@filter-change="resourceFilterChange" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" /> |
||||
<el-table-column |
||||
:label="$t('table.resource.code')" :show-overflow-tooltip="true" align="center" |
||||
prop="code" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.resource.name')" :show-overflow-tooltip="true" align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" align="center" class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-hasPermission="['resource:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" |
||||
@click="resourceEdit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['resource:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="resourceSingleDelete(row)" |
||||
></i> |
||||
<el-link v-has-no-permission="['resource:update','resource:delete']" class="no-perm">{{ |
||||
$t('tips.noPermission') }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="resourceTableData.total>0" |
||||
:limit.sync="resourceQueryParams.size" |
||||
:page.sync="resourceQueryParams.current" |
||||
:total="Number(resourceTableData.total)" |
||||
@pagination="resourceFetch" |
||||
/> |
||||
</div> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
<Icons :dialog-visible="iconVisible" @choose="chooseIcon" @close="iconVisible = false" /> |
||||
<resource-edit |
||||
ref="resourceEdit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="resourceEditClose" @success="resourceEditSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import commonTree from '@/components/ceres/CommonTree.vue' |
||||
import Icons from './Icons' |
||||
import ResourceEdit from './Edit' |
||||
import Pagination from '@/components/Pagination' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import menuApi from '@/api/Menu.js' |
||||
import resourceApi from '@/api/Resource.js' |
||||
import { initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'MenuManage', |
||||
directives: { elDragDialog }, |
||||
components: { Icons, commonTree, Pagination, ResourceEdit }, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
iconVisible: false, |
||||
menuTree: [], |
||||
label: '', |
||||
menu: this.initMenu(), |
||||
resourceQueryParams: initQueryParams({ |
||||
model: { |
||||
menuId: null |
||||
} |
||||
}), |
||||
resourceTableKey: 0, |
||||
resourceLoading: false, |
||||
resourceSelection: [], |
||||
resourceTableData: { |
||||
total: 0 |
||||
}, |
||||
rules: { |
||||
label: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range2to10'), trigger: 'blur' } |
||||
], |
||||
path: [{ max: 255, message: this.$t('rules.noMoreThan100'), trigger: 'blur' }, |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
const isUrl = this.isUrl(this.menu.path) |
||||
|
||||
if (value === '/' || (!isUrl && value.endsWith('/'))) { |
||||
callback('请填写有效的路由地址') |
||||
} else { |
||||
callback() |
||||
} |
||||
}, trigger: 'blur' |
||||
}] |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
menuComponent() { |
||||
let comp = '' |
||||
if (this.menu.path && this.menu.path !== '/') { |
||||
const isUrl = this.isUrl(this.menu.path) |
||||
if (isUrl) { |
||||
comp = `跳转地址:${this.menu.path}` |
||||
} else { |
||||
// comp = `前端组件:src/views/ceres${this.menu.path}/Index.vue` |
||||
comp = `组件路径:src/views/${this.menu.component}.vue` |
||||
} |
||||
} else { |
||||
comp = `组件路径:src/views/ceres/Index.vue` |
||||
} |
||||
return comp |
||||
} |
||||
}, |
||||
watch: { |
||||
'menu.path': function () { |
||||
this.computedComponent() |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.initMenuTree() |
||||
}, |
||||
methods: { |
||||
isUrl(path) { |
||||
const urls = ['http://', '/http://', 'https://', '/https://', 'www.', '/www.'] |
||||
const urlIndex = urls.findIndex(item => { |
||||
return path.startsWith(item) |
||||
}) |
||||
return urlIndex >= 0 |
||||
}, |
||||
menuPath() { |
||||
const isUrl = this.isUrl(this.menu.path) |
||||
if (!isUrl && !this.menu.path.startsWith('/')) { |
||||
this.menu.path = '/' + this.menu.path |
||||
} else if (isUrl) { |
||||
if (this.menu.path.startsWith('/')) { |
||||
this.menu.path = this.menu.path.substr(1) |
||||
} |
||||
} |
||||
}, |
||||
computedComponent() { |
||||
const isUrl = this.isUrl(this.menu.path) |
||||
if (isUrl) { |
||||
this.menu.component = 'Layout' |
||||
} else { |
||||
if (this.menu.path) { |
||||
this.menu.component = `ceres${this.menu.path}/Index` |
||||
} else { |
||||
this.menu.component = `ceres/Index` |
||||
} |
||||
} |
||||
}, |
||||
initMenuTree() { |
||||
menuApi.allTree().then((response) => { |
||||
const res = response.data |
||||
this.menuTree = res.data |
||||
}) |
||||
}, |
||||
initMenu() { |
||||
return { |
||||
id: '', |
||||
label: '', |
||||
describe: '', |
||||
code: '', |
||||
isPublic: false, |
||||
path: '', |
||||
component: '', |
||||
isEnable: true, |
||||
sortValue: '', |
||||
parentId: 0, |
||||
icon: '', |
||||
group: '' |
||||
} |
||||
}, |
||||
nodeClick(data) { |
||||
this.menu = { ...data } |
||||
this.$refs.form.clearValidate() |
||||
|
||||
this.resourceQueryParams.model.menuId = data.id |
||||
this.resourceSearch() |
||||
}, |
||||
handleNumChange(val) { |
||||
this.menu.sortValue = val |
||||
}, |
||||
chooseIcons() { |
||||
this.iconVisible = true |
||||
}, |
||||
chooseIcon(icon) { |
||||
this.menu.icon = icon |
||||
this.iconVisible = false |
||||
}, |
||||
submit() { |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
this.menu.createTime = this.menu.updateTime = null |
||||
if (this.menu.id) { |
||||
this.update() |
||||
} else { |
||||
this.save() |
||||
} |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
save() { |
||||
console.log(this.menu.component) |
||||
menuApi.save(this.menu) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}, |
||||
update() { |
||||
console.log(this.menu) |
||||
menuApi.update(this.menu) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.initMenuTree() |
||||
this.label = '' |
||||
this.resetForm() |
||||
}, |
||||
search() { |
||||
this.$refs.menuTree.$refs.treeRef.filter(this.label) |
||||
}, |
||||
add() { |
||||
this.resetForm() |
||||
const checked = this.$refs.menuTree.$refs.treeRef.getCheckedKeys() |
||||
if (checked.length > 1) { |
||||
this.$message({ |
||||
message: this.$t('tips.onlyChooseOne'), |
||||
type: 'warning' |
||||
}) |
||||
} else if (checked.length > 0) { |
||||
this.menu.parentId = checked[0] |
||||
} else { |
||||
this.menu.parentId = 0 |
||||
} |
||||
this.resourceQueryParams.model.menuId = null |
||||
this.resourceReset() |
||||
}, |
||||
deleteMenu() { |
||||
const checked = this.$refs.menuTree.$refs.treeRef.getCheckedKeys() |
||||
if (checked.length === 0) { |
||||
this.$message({ |
||||
message: this.$t('tips.noNodeSelected'), |
||||
type: 'warning' |
||||
}) |
||||
} else { |
||||
this.$confirm(this.$t('tips.confirmDeleteNode'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
menuApi.delete({ ids: checked }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.reset() |
||||
this.resourceQueryParams.model.menuId = null |
||||
this.resourceReset() |
||||
}) |
||||
}).catch(() => { |
||||
this.$refs.menuTree.$refs.treeRef.setCheckedKeys([]) |
||||
}) |
||||
} |
||||
}, |
||||
resetForm() { |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.menu = this.initMenu() |
||||
}, |
||||
resourceAdd() { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.resourceEdit.setResource({ |
||||
menuId: this.menu.id |
||||
}) |
||||
}, |
||||
resourceEdit(row) { |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
row.menuId = this.menu.id |
||||
this.$refs.resourceEdit.setResource(row) |
||||
}, |
||||
resourceSingleDelete(row) { |
||||
this.$refs.resourceTable.clearSelection() |
||||
this.$refs.resourceTable.toggleRowSelection(row, true) |
||||
this.resourceBatchDelete() |
||||
}, |
||||
resourceBatchDelete() { |
||||
if (!this.resourceSelection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDeleteNode'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const ids = this.resourceSelection.map((item) => item.id) |
||||
resourceApi.delete({ ids: ids }).then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.resourceReset() |
||||
}) |
||||
}) |
||||
}, |
||||
resourceReset() { |
||||
this.resourceQueryParams = initQueryParams({ |
||||
model: { |
||||
menuId: this.resourceQueryParams.menuId |
||||
} |
||||
}) |
||||
this.$refs.resourceTable.clearSort() |
||||
this.$refs.resourceTable.clearFilter() |
||||
this.resourceSearch() |
||||
}, |
||||
resourceSearch() { |
||||
this.resourceFetch({ |
||||
...this.resourceQueryParams |
||||
}) |
||||
}, |
||||
resourceFetch(params = {}) { |
||||
if (this.resourceQueryParams.timeRange) { |
||||
this.resourceQueryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.resourceQueryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.resourceQueryParams.current = params.current ? params.current : this.resourceQueryParams.current |
||||
this.resourceQueryParams.size = params.size ? params.size : this.resourceQueryParams.size |
||||
|
||||
if (this.resourceQueryParams.model.menuId) { |
||||
this.resourceLoading = true |
||||
resourceApi.page(this.resourceQueryParams) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.resourceTableData = res.data |
||||
} |
||||
}) |
||||
.finally(() => this.resourceLoading = false) |
||||
} else { |
||||
this.resourceTableData = {} |
||||
} |
||||
}, |
||||
resourceSortChange(val) { |
||||
this.resourceQueryParams.sort = val.prop |
||||
this.resourceQueryParams.order = val.order |
||||
if (this.resourceQueryParams.sort) { |
||||
this.resourceSearch() |
||||
} |
||||
}, |
||||
resourceFilterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.resourceQueryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.resourceQueryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.resourceSearch() |
||||
}, |
||||
onResourceSelectChange(selection) { |
||||
this.resourceSelection = selection |
||||
}, |
||||
resourceEditClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
resourceEditSuccess() { |
||||
this.resourceSearch() |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.menu { |
||||
margin: 10px; |
||||
|
||||
.app-container { |
||||
margin: 0 0 10px 0 !important; |
||||
} |
||||
} |
||||
|
||||
.el-card.is-always-shadow { |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.el-card { |
||||
border-radius: 0; |
||||
border: none; |
||||
|
||||
.el-card__header { |
||||
padding: 10px 20px !important; |
||||
border-bottom: 1px solid #f1f1f1 !important; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,274 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :title="title" :type="type" |
||||
:visible.sync="isVisible" :width="width" |
||||
top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="role" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.role.code')" prop="code"> |
||||
<el-input v-model="role.code" :disabled="type==='edit'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.role.name')" prop="name"> |
||||
<el-input v-model="role.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.role.status')" prop="status"> |
||||
<el-radio-group v-model="role.status"> |
||||
<el-radio-button :label="true">{{ $t('common.status.valid') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.status.invalid') }}</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.role.describe')" prop="describe"> |
||||
<el-input v-model="role.describe" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.role.dsType')" prop="dsType"> |
||||
<el-radio-group v-model="role.dsType.code" @change="dsTypeChange"> |
||||
<el-radio-button v-for="(item, key, index) in enums.DataScopeType" :key="index" :label="key" :value="key"> |
||||
{{ item }} |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :hidden="orgHidden" :label="$t('table.role.orgList')" prop="orgList"> |
||||
<el-tree |
||||
ref="orgTree" |
||||
:check-strictly="true" |
||||
:data="orgList" |
||||
:default-checked-keys="role.orgList" |
||||
:default-expanded-keys="role.orgList" |
||||
:expand-on-click-node="false" |
||||
highlight-current |
||||
node-key="id" |
||||
show-checkbox |
||||
/> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import roleApi from '@/api/Role.js' |
||||
import orgApi from '@/api/Org.js' |
||||
|
||||
export default { |
||||
name: 'RoleEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
role: this.initRole(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
orgList: [], |
||||
orgHidden: true, |
||||
enums: { |
||||
DataScopeType: {} |
||||
}, |
||||
rules: { |
||||
name: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' }, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
if (!this.type === 'add' && value.trim().length > 0) { |
||||
roleApi.check(value) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.data) { |
||||
callback('编码重复') |
||||
} else { |
||||
callback() |
||||
} |
||||
}) |
||||
} else { |
||||
callback() |
||||
} |
||||
callback() |
||||
}, trigger: 'blur' |
||||
} |
||||
], |
||||
status: { required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
orgList: { |
||||
validator: (rule, value, callback) => { |
||||
if (this.role.dsType.code === 'CUSTOMIZE') { |
||||
if (this.$refs.orgTree.getCheckedKeys().length > 0) { |
||||
callback() |
||||
} else { |
||||
callback('请至少选择一个单位或部门') |
||||
} |
||||
} else { |
||||
callback() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
this.initOrg() |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initRole() { |
||||
return { |
||||
id: '', |
||||
code: '', |
||||
name: '', |
||||
orgList: [], |
||||
status: true, |
||||
describe: '', |
||||
dsType: { |
||||
code: 'SELF', |
||||
desc: '' |
||||
} |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
initOrg() { |
||||
orgApi.allTree({ status: true }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
|
||||
this.orgList = res.data |
||||
}) |
||||
}, |
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
setRole(val = {}) { |
||||
const vm = this |
||||
|
||||
if (val['enums']) { |
||||
vm.enums = val['enums'] |
||||
} |
||||
|
||||
if (val['row']) { |
||||
vm.role = { ...val['row'] } |
||||
|
||||
this.orgHidden = vm.role.dsType.code !== 'CUSTOMIZE' |
||||
if (!this.orgHidden) { |
||||
roleApi.getDetails(vm.role.id) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.role.orgList = res.data.orgList |
||||
this.$refs.orgTree.setCheckedKeys(res.data.orgList) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}, |
||||
close() { |
||||
this.$emit('close') |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.role = this.initRole() |
||||
this.orgHidden = true |
||||
this.$refs.orgTree.setCheckedKeys([]) |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
if (this.orgHidden && this.role.orgList) { |
||||
this.role.orgList.length = 0 |
||||
} else { |
||||
this.role.orgList = this.$refs.orgTree.getCheckedKeys() |
||||
} |
||||
|
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save() { |
||||
const vm = this |
||||
roleApi.save(this.role) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update() { |
||||
roleApi.update(this.role) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
dsTypeChange(value) { |
||||
this.orgHidden = value !== 'CUSTOMIZE' |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,530 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="queryParams.model.code" :placeholder="$t('table.role.code')" class="filter-item search-item" /> |
||||
<el-input v-model="queryParams.model.name" :placeholder="$t('table.role.name')" class="filter-item search-item" /> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['user:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="[ 'role:delete', 'role:export', 'role:import']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['role:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['role:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['role:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['role:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.role.code')" |
||||
align="center" |
||||
prop="code" |
||||
width="200px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.role.name')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.role.describe')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="dsTypeList" |
||||
column-key="dsType.code" |
||||
:label="$t('table.role.dsType')" |
||||
align="center" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.dsType ? scope.row.dsType.desc : '' }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
column-key="readonly" |
||||
:filters="[ |
||||
{ text: $t('common.yes'), value: true }, |
||||
{ text: $t('common.no'), value: false } |
||||
]" |
||||
:label="$t('table.role.readonly')" |
||||
align="center" |
||||
width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.readonly ? $t('common.yes') : $t('common.no') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
column-key="status" |
||||
:filters="[ |
||||
{ text: $t('common.status.valid'), value: true }, |
||||
{ text: $t('common.status.invalid'), value: false } |
||||
]" |
||||
:label="$t('table.role.status')" |
||||
class-name="status-col" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<el-tag :type="row.status | statusFilter">{{ |
||||
row.status ? $t("common.status.valid") : $t("common.status.invalid") |
||||
}} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
align="center" |
||||
column-key="operation" |
||||
class-name="small-padding fixed-width" |
||||
width="140px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['role:update']" |
||||
class="el-icon-edit table-operation" |
||||
style="color: #2db7f5;" |
||||
title="修改" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['role:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
title="删除" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['role:auth']" |
||||
class="el-icon-user table-operation" |
||||
style="color: #87d068;" |
||||
title="授权用户" |
||||
@click="authUser(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['role:config']" |
||||
class="el-icon-setting table-operation" |
||||
style="color: #E6A23C" |
||||
title="分配权限" |
||||
@click="authResource(row)" |
||||
></i> |
||||
|
||||
<!-- dropdown 有时候会有bug,不知道这么解决 --> |
||||
|
||||
<!-- <el-dropdown v-has-any-permission="['role:delete','role:auth','role:config']"> |
||||
<span class="el-dropdown-link"> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right" /> |
||||
</span> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item @click.native="singleDelete(row)" icon="el-icon-delete" v-hasPermission="['role:delete']">删除</el-dropdown-item> |
||||
<el-dropdown-item @click.native="authUser(row)" icon="el-icon-user" v-hasPermission="['role:auth']">授权</el-dropdown-item> |
||||
<el-dropdown-item @click.native="authResource(row)" icon="el-icon-setting" v-hasPermission="['role:config']">配置</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> --> |
||||
|
||||
<el-link |
||||
v-has-no-permission="[ |
||||
'role:update', |
||||
'role:delete', |
||||
'role:auth', |
||||
'role:config' |
||||
]" |
||||
class="no-perm" |
||||
>{{ $t("tips.noPermission") }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<role-edit |
||||
ref="edit" |
||||
:dialog-visible="dialog.isVisible" |
||||
:type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<user-role |
||||
ref="userRole" |
||||
:dialog-visible="userRoleDialog.isVisible" |
||||
@close="userRoleClose" |
||||
@success="userRoleSuccess" |
||||
/> |
||||
<role-authority |
||||
ref="roleAuthority" |
||||
:dialog-visible="roleAuthorityDialog.isVisible" |
||||
@close="roleAuthorityClose" |
||||
@success="roleAuthoritySuccess" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import RoleEdit from "./Edit" |
||||
import UserRole from "./UserRole" |
||||
import FileImport from "@/components/ceres/Import" |
||||
import RoleAuthority from "./RoleAuthority" |
||||
import roleApi from "@/api/Role.js" |
||||
import { convertEnum } from '@/utils/utils' |
||||
import { downloadFile, initEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "RoleManage", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, RoleEdit, UserRole, RoleAuthority, FileImport }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: "danger", |
||||
true: "success" |
||||
} |
||||
return map[status] || "success" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/role/import` |
||||
}, |
||||
userRoleDialog: { |
||||
isVisible: false |
||||
}, |
||||
roleAuthorityDialog: { |
||||
isVisible: false |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
dsType: { |
||||
code: null |
||||
} |
||||
} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { |
||||
DataScopeType: {} |
||||
}, |
||||
dicts: {} |
||||
} |
||||
}, |
||||
computed: { |
||||
dsTypeList() { |
||||
return convertEnum(this.enums.DataScopeType) |
||||
} |
||||
}, |
||||
mounted() { |
||||
initEnums('DataScopeType', this.enums) |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
userRoleClose() { |
||||
this.userRoleDialog.isVisible = false |
||||
}, |
||||
roleAuthorityClose() { |
||||
this.roleAuthorityDialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
userRoleSuccess() { |
||||
this.search() |
||||
}, |
||||
roleAuthoritySuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { |
||||
dsType: { |
||||
code: null |
||||
} |
||||
} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出角色数据' |
||||
roleApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出角色数据' |
||||
roleApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
roleApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = "add" |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setRole({ enums: this.enums }) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setRole({ row, enums: this.enums }) |
||||
this.dialog.type = "edit" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
roleApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
}, |
||||
authResource(row) { |
||||
this.roleAuthorityDialog.isVisible = true |
||||
this.$refs.roleAuthority.setRoleAuthority(row) |
||||
}, |
||||
authUser(row) { |
||||
this.userRoleDialog.isVisible = true |
||||
this.$refs.userRole.setUserRole(row) |
||||
} |
||||
} |
||||
} |
||||
|
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,398 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" |
||||
:title="title" |
||||
:visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" |
||||
:model="roleAuthority" |
||||
:rules="rules" |
||||
label-position="top" |
||||
label-width="100px" |
||||
> |
||||
<el-scrollbar style="height:800px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="8"> |
||||
<el-card class="box-card"> |
||||
<el-form-item label="菜单" prop="menuIdList"> |
||||
<div align="left" style="margin-left:24px;"> |
||||
<el-checkbox |
||||
v-model="checkedMenu" |
||||
:indeterminate="isIndeterminate" |
||||
@change="checkedAll" |
||||
/> |
||||
全选/反选 |
||||
</div> |
||||
<el-tree |
||||
ref="menuTree" |
||||
:check-strictly="true" |
||||
:data="menuTree" |
||||
:default-checked-keys="roleAuthority.menuIdList" |
||||
:default-expanded-keys="roleAuthority.menuIdList" |
||||
:disabled="disabled" |
||||
:expand-on-click-node="false" |
||||
default-expand-all |
||||
highlight-current |
||||
node-key="id" |
||||
show-checkbox |
||||
@check="checkMenu" |
||||
@node-click="nodeClick" |
||||
/> |
||||
</el-form-item> |
||||
</el-card> |
||||
</el-col> |
||||
<el-col :span="16"> |
||||
<el-card class="box-card"> |
||||
<el-form-item label="资源" prop="resourceIdList"> |
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" |
||||
style="width: 100%;" |
||||
@select="onSelect" |
||||
@select-all="onAllSelect" |
||||
> |
||||
<el-table-column |
||||
:reserve-selection="true" |
||||
align="center" |
||||
type="selection" |
||||
width="40px" |
||||
/> |
||||
<el-table-column |
||||
:label="$t('table.resource.code')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="code" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.resource.name')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-form-item> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
</el-scrollbar> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ |
||||
$t("common.cancel") |
||||
}} |
||||
</el-button> |
||||
<el-button |
||||
:disabled="disabled" |
||||
plain |
||||
type="primary" |
||||
@click="submitForm" |
||||
>{{ $t("common.confirm") }} |
||||
</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import roleApi from "@/api/Role.js" |
||||
import menuApi from "@/api/Menu.js" |
||||
import resourceApi from "@/api/Resource.js" |
||||
|
||||
export default { |
||||
name: "RoleAuthorityEdit", |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
roleAuthority: this.initRoleAuthority(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
menuTree: [], |
||||
resourceList: [], |
||||
// 回显的数据 |
||||
echoResourceIdList: [], |
||||
rules: {}, |
||||
tableKey: 0, |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
selection: [], |
||||
disabled: false, |
||||
isIndeterminate: false, |
||||
checkedMenu: false |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return "配置菜单资源" |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
this.initMenuTree() |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
allMenuIdList() { |
||||
const menuIdList = [] |
||||
this.getMenuIdList(this.menuTree, menuIdList) |
||||
return menuIdList |
||||
}, |
||||
getMenuIdList(menuList, menuIdList) { |
||||
if (menuList) { |
||||
menuList.forEach(item => { |
||||
menuIdList.push(item.id) |
||||
if (item.children && item.children.length > 0) { |
||||
this.getMenuIdList(item.children, menuIdList) |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
checkedAll() { |
||||
if (this.checkedMenu) { |
||||
// 全选 |
||||
this.$refs.menuTree.setCheckedKeys(this.allMenuIdList()) |
||||
this.isIndeterminate = false |
||||
} else { |
||||
// 取消选中 |
||||
this.$refs.menuTree.setCheckedKeys([]) |
||||
this.isIndeterminate = false |
||||
} |
||||
}, |
||||
nodeClick(data) { |
||||
const vm = this |
||||
vm.loading = true |
||||
|
||||
resourceApi |
||||
.page({ |
||||
current: 1, size: 10000, |
||||
model: { menuId: data.id } |
||||
}) |
||||
.then(response => { |
||||
const res = response.data |
||||
vm.tableData = res.data |
||||
vm.loading = false |
||||
vm.displayTable() |
||||
}) |
||||
}, |
||||
displayTable() { |
||||
const vm = this |
||||
vm.tableData.records.forEach(item => { |
||||
vm.roleAuthority.resourceIdList.forEach(resourceId => { |
||||
if (item.id === resourceId) { |
||||
vm.$refs.table.toggleRowSelection(item, true) |
||||
} |
||||
}) |
||||
}) |
||||
}, |
||||
onAllSelect(selection) { |
||||
this.onSelect(selection) |
||||
}, |
||||
onSelect(selection, row) { |
||||
this.mergeResourceIdList(selection, row) |
||||
// this.roleAuthority.resourceIdList = selection.map(item => item.id); |
||||
this.selection = selection |
||||
|
||||
// 根据右侧选中的资源,强制勾选左侧的 树状层级菜单 |
||||
const old = this.$refs.menuTree.getCheckedKeys() |
||||
const must = selection.map(item => item.menuId) |
||||
const newSelected = Array.from(new Set([...old, ...must])) |
||||
this.$refs.menuTree.setCheckedKeys(newSelected) |
||||
newSelected.forEach(item => { |
||||
this.selectedParent(item) |
||||
}) |
||||
}, |
||||
mergeResourceIdList(selection, row) { |
||||
// true就是选中,0或者false是取消选中 |
||||
let selected = true |
||||
if (row) { |
||||
selected = selection.length && selection.indexOf(row) !== -1 |
||||
} else { |
||||
selected = selection.length > 0 |
||||
} |
||||
|
||||
// 本次选中的 |
||||
const curResourceIdList = selection.map(item => item.id) |
||||
|
||||
const ridList = this.echoResourceIdList |
||||
if (!selected && row) { |
||||
var index = ridList.findIndex(item => { |
||||
if (item == row.id) { |
||||
return true |
||||
} |
||||
}) |
||||
ridList.splice(index, 1) |
||||
} |
||||
|
||||
// 本次选中的 + 回显的 然后去重 |
||||
this.roleAuthority.resourceIdList = [ |
||||
...new Set([...curResourceIdList, ...ridList]) |
||||
] |
||||
}, |
||||
|
||||
initMenuTree() { |
||||
menuApi.allTree().then(response => { |
||||
const res = response.data |
||||
this.menuTree = res.data |
||||
}) |
||||
}, |
||||
initRoleAuthority() { |
||||
return { |
||||
roleId: "", |
||||
menuIdList: [], |
||||
resourceIdList: [] |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return "90%" |
||||
} else if (this.screenWidth < 1400) { |
||||
return "45%" |
||||
} else { |
||||
return "1000px" |
||||
} |
||||
}, |
||||
setRoleAuthority(val) { |
||||
const vm = this |
||||
vm.roleAuthority.roleId = val.id |
||||
// vm.disabled = val.readonly |
||||
// 回显 |
||||
roleApi.findAuthorityIdByRoleId(val.id).then(response => { |
||||
const res = response.data |
||||
vm.roleAuthority.menuIdList = res.data.menuIdList |
||||
vm.roleAuthority.resourceIdList = res.data.resourceIdList |
||||
vm.echoResourceIdList = res.data.resourceIdList |
||||
vm.$refs.menuTree.setCheckedKeys(res.data.menuIdList) |
||||
res.data.menuIdList.forEach(item => { |
||||
vm.selectedParent(item) |
||||
}) |
||||
}) |
||||
}, |
||||
close() { |
||||
this.$emit("close") |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.roleAuthority = this.initRoleAuthority() |
||||
this.$refs.menuTree.setCheckedKeys([]) |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
|
||||
this.roleAuthority.menuIdList = vm.$refs.menuTree |
||||
.getHalfCheckedKeys() |
||||
.concat(vm.$refs.menuTree.getCheckedKeys()) |
||||
|
||||
// 勾选时, 实时计算出来 |
||||
// this.roleAuthority.resourceIdList = vm.selection.map(item => item.id); |
||||
|
||||
roleApi.saveRoleAuthority(this.roleAuthority).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t("tips.createSuccess"), |
||||
type: "success" |
||||
}) |
||||
vm.$emit("success") |
||||
} |
||||
}) |
||||
}, |
||||
checkMenu(data, node) { |
||||
if (node.checkedKeys.length === 0) { |
||||
// 取消 |
||||
this.checkedMenu = false |
||||
this.isIndeterminate = false |
||||
} else if (node.checkedKeys.length === this.allMenuIdList().length) { |
||||
// 全选 |
||||
this.checkedMenu = true |
||||
this.isIndeterminate = false |
||||
} else { |
||||
// 中立 |
||||
this.checkedMenu = false |
||||
this.isIndeterminate = true |
||||
} |
||||
|
||||
// 用于:父子节点严格互不关联时,父节点勾选变化时通知子节点同步变化,实现单向关联。 |
||||
const selected = node.checkedKeys.indexOf(data.id) // -1未选中 |
||||
// 选中 |
||||
if (selected !== -1) { |
||||
// 子节点只要被选中父节点就被选中 |
||||
this.selectedParent(data) |
||||
// 统一处理子节点为相同的勾选状态 |
||||
this.uniteChildSame(data, true) |
||||
} else { |
||||
// 未选中 处理子节点全部未选中 |
||||
if (data.children && data.children.length !== 0) { |
||||
this.uniteChildSame(data, false) |
||||
} |
||||
} |
||||
}, |
||||
// 统一处理子节点为相同的勾选状态 |
||||
uniteChildSame(data, isSelected) { |
||||
this.$refs.menuTree.setChecked(data.id, isSelected) |
||||
if (data.children) { |
||||
for (let i = 0; i < data.children.length; i++) { |
||||
this.uniteChildSame(data.children[i], isSelected) |
||||
} |
||||
} |
||||
}, |
||||
// 统一处理父节点为选中 |
||||
selectedParent(data) { |
||||
const currentNode = this.$refs.menuTree.getNode(data) |
||||
if (currentNode.parent.key !== undefined) { |
||||
this.$refs.menuTree.setChecked(currentNode.parent, true) |
||||
this.selectedParent(currentNode.parent) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,179 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :title="title" :visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="userRole" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item label="用户" prop="userIdList"> |
||||
<el-transfer |
||||
v-model="userRole.userIdList" |
||||
:data="userList" |
||||
:filter-method="filterMethod" |
||||
:props="{ |
||||
key: 'id', |
||||
label: 'name' |
||||
}" |
||||
:render-content="renderFunc" |
||||
:right-default-checked="userRole.userIdList" |
||||
:titles="['全部用户', '已选用户']" |
||||
filter-placeholder="用户名" |
||||
filterable |
||||
style="text-align: left; display: inline-block" |
||||
/> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button :disabled="disabled" plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import roleApi from '@/api/Role.js' |
||||
import userApi from '@/api/User.js' |
||||
|
||||
export default { |
||||
name: 'UserRoleEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
userRole: this.initUserRole(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
userList: [], |
||||
userIdList: [], |
||||
disabled: false, |
||||
rules: { |
||||
|
||||
}, |
||||
renderFunc (h, option) { |
||||
// return <span title='option.account - {option.name}'>{option.account} - {option.name}</span> |
||||
return h("span", { |
||||
"attrs": { |
||||
"title": option.account + " - " + option.name |
||||
} |
||||
}, [option.account, " - ", option.name]) |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return '分配角色成员' |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
this.initUserList() |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initUserRole () { |
||||
return { |
||||
roleId: '', |
||||
userIdList: [] |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
initUserList () { |
||||
userApi.page({ current: 1, size: 100000, model: { status: true }}) |
||||
.then((response) => { |
||||
const res = response.data |
||||
|
||||
this.userList = res.data.records |
||||
}).catch(() => { |
||||
this.$message({ |
||||
message: this.$t('tips.getDataFail'), |
||||
type: 'error' |
||||
}) |
||||
}) |
||||
}, |
||||
setUserRole (val) { |
||||
const vm = this |
||||
vm.userRole.roleId = val.id |
||||
// vm.disabled = val.readonly |
||||
roleApi.findUserIdByRoleId(val.id) |
||||
.then((response) => { |
||||
const res = response.data |
||||
vm.userRole.userIdList = res.data |
||||
}) |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.userRole = this.initUserRole() |
||||
this.disabled = false |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
console.log(this.userRole) |
||||
|
||||
roleApi.saveUserRole(this.userRole) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
filterMethod (query, item) { |
||||
return item.name.indexOf(query) > -1 || item.account.indexOf(query) > -1 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,393 @@
|
||||
<template> |
||||
<div class="area"> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="label" |
||||
:placeholder="$t('table.area.label')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-button |
||||
class="filter-item" |
||||
plain |
||||
type="primary" |
||||
@click="search" |
||||
>{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['area:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="[ 'area:delete', 'area:export']" |
||||
class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item |
||||
v-has-permission="['area:delete']" |
||||
@click.native="deleteArea" |
||||
>{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
|
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-tree |
||||
ref="areaTree" |
||||
:check-strictly="true" |
||||
:data="areaTree" |
||||
:filter-node-method="filterNode" |
||||
:load="loadTree" |
||||
highlight-current |
||||
node-key="id" |
||||
:lazy="true" |
||||
show-checkbox |
||||
@node-click="nodeClick" |
||||
/> |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div slot="header" class="clearfix"> |
||||
<span>{{ |
||||
area.id === "" ? this.$t("common.add") : this.$t("common.edit") |
||||
}}</span> |
||||
</div> |
||||
<div> |
||||
<el-form |
||||
ref="form" |
||||
:model="area" |
||||
:rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item |
||||
:hidden="true" |
||||
:label="$t('table.area.parentId')" |
||||
prop="parentId" |
||||
> |
||||
<el-tooltip |
||||
:content="$t('tips.topId')" |
||||
class="item" |
||||
effect="dark" |
||||
placement="top-start" |
||||
> |
||||
<el-input v-model="area.parentId" readonly /> |
||||
</el-tooltip> |
||||
</el-form-item> |
||||
<el-form-item |
||||
:label="$t('table.area.parentId')" |
||||
prop="parentLabel" |
||||
> |
||||
<el-input |
||||
v-model="area.parentLabel" |
||||
readonly |
||||
disabled="disabled" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.label')" prop="label"> |
||||
<el-input v-model="area.label" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.code')" prop="code"> |
||||
<el-input v-model="area.code" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.fullName')" prop="fullName"> |
||||
<el-input v-model="area.fullName" /> |
||||
</el-form-item> |
||||
<el-form-item |
||||
:label="$t('table.area.longitude')" |
||||
prop="longitude" |
||||
> |
||||
<el-input v-model="area.longitude" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.latitude')" prop="latitude"> |
||||
<el-input v-model="area.latitude" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.source')" prop="source"> |
||||
<el-input v-model="area.source" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.area.level')" prop="level"> |
||||
<el-radio-group |
||||
v-model="area.level.key" |
||||
border="true" |
||||
size="small" |
||||
> |
||||
<el-radio-button v-for="(item, key, index) in dicts.AREA_LEVEL" :key="index" :label="item" :value="key"> |
||||
{{ item }} |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
|
||||
<el-form-item |
||||
:label="$t('table.area.sortValue')" |
||||
prop="sortValue" |
||||
> |
||||
<el-input-number |
||||
v-model="area.sortValue" |
||||
:max="100" |
||||
:min="0" |
||||
@change="handleNumChange" |
||||
/> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</el-card> |
||||
<el-card class="box-card" style="margin-top: -2rem;"> |
||||
<el-row> |
||||
<el-col :span="24" style="text-align: right"> |
||||
<el-button plain type="primary" @click="submit">{{ |
||||
area.id === "" ? this.$t("common.add") : this.$t("common.edit") |
||||
}} |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import areaApi from "@/api/Area.js" |
||||
import { initDicts } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "AreaManager", |
||||
data() { |
||||
return { |
||||
label: "", |
||||
areaTree: [], |
||||
dicts: { AREA_LEVEL: {}}, |
||||
area: this.initArea(), |
||||
rules: { |
||||
label: [ |
||||
{ |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
min: 1, |
||||
max: 255, |
||||
message: this.$t("rules.range3to10"), |
||||
trigger: "blur" |
||||
} |
||||
], |
||||
code: [ |
||||
{ |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
min: 1, |
||||
max: 255, |
||||
message: this.$t("rules.range3to10"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
areaApi.check(value, this.area.id).then(response => { |
||||
const res = response.data |
||||
if (res.data) { |
||||
callback('编码重复') |
||||
} else { |
||||
callback() |
||||
} |
||||
}).catch(() => callback()) |
||||
}, |
||||
trigger: "blur" |
||||
} |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
initDicts('AREA_LEVEL', this.dicts) |
||||
}, |
||||
methods: { |
||||
initArea() { |
||||
return { |
||||
id: "", |
||||
code: "", |
||||
label: "", |
||||
parentId: 0, |
||||
parentLabel: "", |
||||
fullName: "", |
||||
longitude: "", |
||||
latitude: "", |
||||
source: "", |
||||
level: { |
||||
key: "PROVINCE" |
||||
}, |
||||
sortValue: 0 |
||||
} |
||||
}, |
||||
initAreaTree(parentId = 0) { |
||||
areaApi.query({ parentId: parentId }).then(response => { |
||||
const res = response.data |
||||
this.areaTree = res.data |
||||
}) |
||||
}, |
||||
loadTree(node, resolve) { |
||||
areaApi.query({ parentId: node.data.id }).then(response => { |
||||
const res = response.data |
||||
resolve(res.data) |
||||
}) |
||||
}, |
||||
handleNumChange(val) { |
||||
this.area.sortValue = val |
||||
}, |
||||
filterNode(value, data) { |
||||
if (!value) return true |
||||
return data.label.indexOf(value) !== -1 |
||||
}, |
||||
nodeClick(data) { |
||||
this.area = { ...data } |
||||
|
||||
const parent = this.$refs.areaTree.getNode(data.parentId) |
||||
if (parent) { |
||||
this.area.parentLabel = parent.label |
||||
} |
||||
|
||||
this.$refs.form.clearValidate() |
||||
}, |
||||
add() { |
||||
this.resetForm() |
||||
const checked = this.$refs.areaTree.getCheckedNodes() |
||||
if (checked.length > 1) { |
||||
this.$message({ |
||||
message: this.$t("tips.onlyChooseOne"), |
||||
type: "warning" |
||||
}) |
||||
} else if (checked.length > 0) { |
||||
this.area.parentId = checked[0].id |
||||
this.area.parentLabel = checked[0].label |
||||
} else { |
||||
this.area.parentId = 0 |
||||
this.area.parentLabel = "" |
||||
} |
||||
}, |
||||
deleteArea() { |
||||
const checked = this.$refs.areaTree.getCheckedKeys() |
||||
if (checked.length === 0) { |
||||
this.$message({ |
||||
message: this.$t("tips.noNodeSelected"), |
||||
type: "warning" |
||||
}) |
||||
} else { |
||||
this.$confirm( |
||||
this.$t("tips.confirmDeleteNode"), |
||||
this.$t("common.tips"), |
||||
{ |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
} |
||||
) |
||||
.then(() => { |
||||
areaApi.delete({ ids: checked }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}) |
||||
.catch(() => { |
||||
this.$refs.areaTree.setCheckedKeys([]) |
||||
}) |
||||
} |
||||
}, |
||||
search() { |
||||
this.$refs.areaTree.filter(this.label) |
||||
}, |
||||
reset() { |
||||
this.initAreaTree() |
||||
this.label = "" |
||||
this.resetForm() |
||||
}, |
||||
submit() { |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
if (this.area.id) { |
||||
this.update() |
||||
} else { |
||||
this.save() |
||||
} |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
save() { |
||||
areaApi.save({ ...this.area }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.createSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
|
||||
this.reset() |
||||
}) |
||||
}, |
||||
update() { |
||||
areaApi.update({ ...this.area }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.updateSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}, |
||||
resetForm() { |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.area = this.initArea() |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.area { |
||||
margin: 10px; |
||||
|
||||
.app-container { |
||||
margin: 0 0 10px 0 !important; |
||||
} |
||||
} |
||||
|
||||
.el-card.is-always-shadow { |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.el-card { |
||||
border-radius: 0; |
||||
border: none; |
||||
|
||||
.el-card__header { |
||||
padding: 10px 20px !important; |
||||
border-bottom: 1px solid #f1f1f1 !important; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,278 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.type" :placeholder="$t('table.dictionary.type')" size="small" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.name" :placeholder="$t('table.dictionary.name')" size="small" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-button |
||||
class="filter-item" plain type="primary" |
||||
size="small" |
||||
@click="search" |
||||
>{{ $t('table.search') }}</el-button> |
||||
<el-button |
||||
class="filter-item" plain type="warning" |
||||
size="small" |
||||
@click="reset" |
||||
>{{ $t('table.reset') }}</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['dict:delete','dict:export', 'dict:import']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button size="small"> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['dict:add']" @click.native="add"> |
||||
{{ $t('table.add') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['dict:delete']" @click.native="batchDelete"> |
||||
{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" size="mini" style="width: 100%;" |
||||
@filter-change="filterChange" |
||||
@row-click="rowClick" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column :label="$t('table.dictionary.type')" :show-overflow-tooltip="true" align="center" prop="type"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.type }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.dictionary.name')" :show-overflow-tooltip="true" align="center" prop="name"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.dictionary.describe')" :show-overflow-tooltip="true" align="center" |
||||
prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
column-key="status" |
||||
:filters="[{ text: $t('common.status.valid'), value: true }, { text: $t('common.status.invalid'), value: false }]" |
||||
:label="$t('table.dictionary.status')" |
||||
class-name="status-col" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<el-tag :type="row.status | statusFilter">{{ row.status ? $t('common.status.valid') : |
||||
$t('common.status.invalid') }} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" align="center" prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" align="center" class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-hasPermission="['dict:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['dict:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link v-has-no-permission="['dict:update','dict:delete']" class="no-perm">{{ $t('tips.noPermission') }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
<dictionary-edit |
||||
ref="edit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import DictionaryEdit from './Edit' |
||||
import dictionaryApi from '@/api/Dictionary.js' |
||||
import { initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'DictionaryManage', |
||||
components: { Pagination, DictionaryEdit }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: 'danger', |
||||
true: 'success' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
this.$emit('dictionaryClick', { id: -1 }) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const ids = [] |
||||
this.selection.forEach((u) => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
dictionaryApi.delete({ 'ids': ids }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setDictionary(false) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setDictionary(row) |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
dictionaryApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
rowClick(row) { |
||||
this.$emit('dictionaryClick', row) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,394 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div v-if="queryParams.dictionaryId === -1"> |
||||
<div class="my-code">点击字典查看详情</div> |
||||
</div> |
||||
<div v-else> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.code" :placeholder="$t('table.dictionaryItem.code')" size="small" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.name" :placeholder="$t('table.dictionaryItem.name')" size="small" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-button |
||||
class="filter-item" plain type="primary" |
||||
size="small" |
||||
@click="search" |
||||
>{{ $t('table.search') }}</el-button> |
||||
<el-button |
||||
class="filter-item" plain type="warning" |
||||
size="small" |
||||
@click="reset" |
||||
>{{ $t('table.reset') }}</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['dict:add','dict:delete','dict:export']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button size="small"> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['dict:add']" @click.native="add">{{ $t('table.add') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['dict:delete']" @click.native="batchDelete">{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['dict:export']" @click.native="exportExcel">{{ $t('table.export') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['dict:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['dict:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-table |
||||
:key="tableKey" ref="table" v-loading="loading" |
||||
:data="tableData.records" border fit |
||||
row-key="id" size="mini" style="width: 100%;" |
||||
@selection-change="onSelectChange" @sort-change="sortChange" @cell-click="cellClick" |
||||
@filter-change="filterChange" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.dictionaryItem.code')" :show-overflow-tooltip="true" align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.dictionaryItem.name')" :show-overflow-tooltip="true" align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.dictionaryItem.describe')" :show-overflow-tooltip="true" align="center" |
||||
prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
column-key="status" |
||||
:filter-multiple="false" |
||||
:filters="[{ text: $t('common.status.valid'), value: true }, { text: $t('common.status.invalid'), value: false }]" |
||||
:label="$t('table.dictionaryItem.status')" |
||||
class-name="status-col" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<el-tag :type="row.status | statusFilter">{{ row.status ? $t('common.status.valid') : |
||||
$t('common.status.invalid') }} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" align="center" prop="createTime" |
||||
sortable="custom" |
||||
width="160px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" column-key="operation" sortable="custom" |
||||
align="center" class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-hasPermission="['dict:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['dict:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link v-has-no-permission="['dict:update','dict:delete']" class="no-perm">{{ $t('tips.noPermission') }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
<dictionaryItem-edit |
||||
ref="edit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="editClose" @success="editSuccess" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import DictionaryItemEdit from './DictionaryItemEdit' |
||||
import dictionaryItemApi from '@/api/DictionaryItem.js' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'DictionaryItemManage', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, DictionaryItemEdit, FileImport }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: 'danger', |
||||
true: 'success' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/dictionaryItem/import` |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
dictionaryId: -1 |
||||
}, |
||||
sort: 'sortValue', |
||||
order: 'ascending' |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
dictionary: { |
||||
id: null, |
||||
code: '' |
||||
}, |
||||
tableData: { |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: {}, |
||||
mounted() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
methods: { |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { dictionaryId: this.dictionary.id } |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出字典数据' |
||||
dictionaryItemApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出字典数据' |
||||
dictionaryItemApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const ids = [] |
||||
this.selection.forEach((u) => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
dictionaryItemApi.delete({ 'ids': ids }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setDictionaryItem({ |
||||
id: null, |
||||
status: true, |
||||
dictionaryId: this.dictionary.id, |
||||
dictionaryType: this.dictionary.type |
||||
}) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setDictionaryItem(row) |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
dictionaryItemApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
}, |
||||
dictionaryClick(dictionary) { |
||||
this.queryParams.model.dictionaryId = dictionary.id |
||||
this.dictionary = dictionary |
||||
this.search() |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,191 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="dictionaryItem" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :hidden="true" :label="$t('table.dictionaryItem.dictionaryId')" prop="dictionaryId"> |
||||
<el-input v-model="dictionaryItem.dictionaryId" :disabled="type==='edit'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionaryItem.code')" prop="code"> |
||||
<el-input v-model="dictionaryItem.code" :disabled="type==='edit'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionaryItem.name')" prop="name"> |
||||
<el-input v-model="dictionaryItem.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionaryItem.status')" prop="status"> |
||||
<el-radio-group v-model="dictionaryItem.status"> |
||||
<el-radio :label="true">{{ $t('common.status.valid') }}</el-radio> |
||||
<el-radio :label="false">{{ $t('common.status.invalid') }}</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionaryItem.sortValue')" prop="sortValue"> |
||||
<el-input v-model="dictionaryItem.sortValue" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionaryItem.describe')" prop="describe"> |
||||
<el-input v-model="dictionaryItem.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import dictionaryItemApi from '@/api/DictionaryItem.js' |
||||
|
||||
export default { |
||||
name: 'DictionaryItemEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
dictionaryItem: this.initDictionaryItem(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
rules: { |
||||
dictionaryId: { required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
code: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 64, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
name: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 64, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
describe: [ |
||||
{ min: 1, max: 200, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
status: { required: true, message: this.$t('rules.require'), trigger: 'blur' } |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initDictionaryItem () { |
||||
return { |
||||
id: '', |
||||
dictionaryId: null, |
||||
dictionaryType: '', |
||||
name: '', |
||||
code: '', |
||||
status: true, |
||||
sortValue: 1, |
||||
describe: '' |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
setDictionaryItem (val) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.dictionaryItem = { ...val } |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.dictionaryItem = this.initDictionaryItem() |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
dictionaryItemApi.save(this.dictionaryItem) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
dictionaryItemApi.update(this.dictionaryItem) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,181 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="dictionary" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.dictionary.type')" prop="type"> |
||||
<el-input v-model="dictionary.type" :disabled="type==='edit'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionary.name')" prop="name"> |
||||
<el-input v-model="dictionary.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionary.status')" prop="status"> |
||||
<el-radio-group v-model="dictionary.status"> |
||||
<el-radio :label="true">{{ $t('common.status.valid') }}</el-radio> |
||||
<el-radio :label="false">{{ $t('common.status.invalid') }}</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.dictionary.describe')" prop="describe"> |
||||
<el-input v-model="dictionary.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import dictionaryApi from '@/api/Dictionary.js' |
||||
|
||||
export default { |
||||
name: 'DictionaryEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
dictionary: this.initDictionary(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
rules: { |
||||
type: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 64, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
name: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 64, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
describe: [ |
||||
{ min: 1, max: 200, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
status: { required: true, message: this.$t('rules.require'), trigger: 'blur' } |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initDictionary () { |
||||
return { |
||||
id: '', |
||||
name: '', |
||||
type: '', |
||||
status: true, |
||||
describe: '' |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
setDictionary (val) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.dictionary = { ...val } |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.dictionary = this.initDictionary() |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
dictionaryApi.save(this.dictionary) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
dictionaryApi.update(this.dictionary) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,62 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div slot="header" class="clearfix"> |
||||
<span>字典列表</span> |
||||
</div> |
||||
<dictionary ref="dictionary" @dictionaryClick="dictionaryClick" @resetItem="resetItem" /> |
||||
</el-card> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div slot="header" class="clearfix"> |
||||
<span>字典详情</span> |
||||
</div> |
||||
<dictionary-item ref="dictionaryItem" /> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Dictionary from './Dictionary' |
||||
import DictionaryItem from './DictionaryItem' |
||||
|
||||
export default { |
||||
name: 'DictionaryManage', |
||||
components: { Dictionary, DictionaryItem }, |
||||
filters: { |
||||
|
||||
}, |
||||
data () { |
||||
return { |
||||
|
||||
} |
||||
}, |
||||
computed: { |
||||
|
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
|
||||
}, |
||||
methods: { |
||||
dictionaryClick (row) { |
||||
this.$refs.dictionaryItem.dictionaryClick(row) |
||||
}, |
||||
resetItem () { |
||||
this.$refs.dictionaryItem.dictionaryClick({ id: -1 }) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.el-card /deep/ .el-card__body { |
||||
padding: 0px; |
||||
} |
||||
</style> |
@ -0,0 +1,184 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
:title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false"> |
||||
{{ $t("common.cancel") }} |
||||
</el-button> |
||||
<el-button plain type="primary" @click="submitForm"> |
||||
{{ $t("common.confirm") }} |
||||
</el-button> |
||||
</div> |
||||
<el-form |
||||
ref="form" :model="parameter" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.parameter.key')" prop="key"> |
||||
<el-input v-model="parameter.key" :disabled="type==='edit'" type="" placeholder="参数键" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.parameter.name')" prop="name"> |
||||
<el-input v-model="parameter.name" type="" placeholder="参数名称" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.parameter.value')" prop="value"> |
||||
<el-input v-model="parameter.value" type="" placeholder="参数值" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.parameter.describe')" prop="describe"> |
||||
<el-input v-model="parameter.describe" type="textarea" placeholder="描述" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.parameter.status')" prop="status"> |
||||
<el-radio-group v-model="parameter.status" size="medium"> |
||||
<el-radio-button :label="true">{{ $t("common.status.valid") }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t("common.status.invalid") }}</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.parameter.readonly')" prop="readonly"> |
||||
<el-radio-group v-model="parameter.readonly" size="medium"> |
||||
<el-radio-button :label="true">{{ $t("common.yes") }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t("common.no") }}</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import parameterApi from "@/api/Parameter.js" |
||||
|
||||
export default { |
||||
name: "ParameterEdit", |
||||
components: { }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: "add" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
parameter: this.initParameter(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
rules: { |
||||
|
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.$t("common." + this.type) |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initParameter() { |
||||
return { |
||||
id: "", |
||||
key: '', |
||||
name: '', |
||||
value: '', |
||||
describe: '', |
||||
status: true, |
||||
readonly: false |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return "90%" |
||||
} else if (this.screenWidth < 1400) { |
||||
return "45%" |
||||
} else { |
||||
return "800px" |
||||
} |
||||
}, |
||||
setParameter(val) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.parameter = { ...val } |
||||
} |
||||
}, |
||||
close() { |
||||
this.$emit("close") |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.parameter = this.initParameter() |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
if (vm.type === "edit") { |
||||
vm.update() |
||||
} else { |
||||
vm.save() |
||||
} |
||||
}, |
||||
save() { |
||||
const vm = this |
||||
parameterApi.save(this.parameter).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t("tips.createSuccess"), |
||||
type: "success" |
||||
}) |
||||
vm.$emit("success") |
||||
} |
||||
}) |
||||
}, |
||||
update() { |
||||
parameterApi.update(this.parameter).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t("tips.updateSuccess"), |
||||
type: "success" |
||||
}) |
||||
this.$emit("success") |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,418 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
|
||||
<el-input |
||||
v-model="queryParams.model.key" |
||||
:placeholder="$t('table.parameter.key')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.name" |
||||
:placeholder="$t('table.parameter.name')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.value" |
||||
:placeholder="$t('table.parameter.value')" |
||||
class="filter-item search-item" |
||||
/> |
||||
|
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['parameter:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['parameter:delete', 'parameter:export', 'parameter:import']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }}<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['parameter:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['parameter:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['parameter:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['parameter:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.parameter.key')" :show-overflow-tooltip="true" align="center" |
||||
prop="key" width="" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.key }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.parameter.name')" :show-overflow-tooltip="true" align="center" |
||||
prop="name" width="" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.parameter.value')" :show-overflow-tooltip="true" align="center" |
||||
prop="value" width="" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.value }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.parameter.describe')" :show-overflow-tooltip="true" align="center" |
||||
prop="describe" width="" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.parameter.status')" :show-overflow-tooltip="true" align="center" |
||||
:filter-multiple="false" column-key="status" |
||||
:filters="[{ text: $t('common.status.valid'), value: true },{ text: $t('common.status.invalid'), value: false }]" |
||||
prop="status" width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-tag slot :type="scope.row.status ? 'success' : 'danger'"> |
||||
{{ scope.row.status ? $t("common.status.valid") : $t("common.status.invalid") }} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.parameter.readonly')" :show-overflow-tooltip="true" align="center" |
||||
:filter-multiple="false" column-key="readonly" |
||||
:filters="[{ text: $t('common.yes'), value: 'true' }, { text: $t('common.no'), value: 'false' }]" |
||||
prop="readonly" width="70px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-tag slot :type="scope.row.readonly ? 'success' : 'danger'"> |
||||
{{ scope.row.readonly ? $t("common.yes") : $t("common.no") }} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" column-key="operation" align="center" |
||||
class-name="small-padding fixed-width" width="100px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['parameter:add']" class="el-icon-copy-document table-operation" :title="$t('common.delete')" |
||||
style="color: #2db7f5;" @click="copy(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['parameter:update']" class="el-icon-edit table-operation" :title="$t('common.delete')" |
||||
style="color: #2db7f5;" @click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['parameter:delete']" class="el-icon-delete table-operation" :title="$t('common.delete')" |
||||
style="color: #f50;" @click="singleDelete(row)" |
||||
></i> |
||||
<el-link v-has-no-permission="['parameter:update', 'parameter:add', 'parameter:delete']" class="no-perm"> |
||||
{{ $t("tips.noPermission") }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<parameter-edit |
||||
ref="edit" |
||||
:dialog-visible="dialog.isVisible" |
||||
:type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import ParameterEdit from "./Edit" |
||||
import parameterApi from "@/api/Parameter.js" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile, initDicts, initEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "ParameterManage", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, ParameterEdit, FileImport }, |
||||
filters: {}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/parameter/import` |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: {} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出参数数据' |
||||
parameterApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出参数数据' |
||||
parameterApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = this.selection.map(u => u.id) |
||||
this.delete(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
parameterApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = "add" |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setParameter(false) |
||||
}, |
||||
copy(row) { |
||||
this.$refs.edit.setParameter(row) |
||||
this.dialog.type = "copy" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setParameter(row) |
||||
this.dialog.type = "edit" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
parameterApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,218 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="application" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item v-show="type!=='add' " :label="$t('table.application.clientId')" prop="clientId"> |
||||
<el-input v-model="application.clientId" :disabled="type==='view' || type==='edit' " /> |
||||
</el-form-item> |
||||
<el-form-item v-show="type!=='add' " :label="$t('table.application.clientSecret')" prop="clientSecret"> |
||||
<el-input v-model="application.clientSecret" :disabled="type==='view' || type==='edit' " /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.name')" prop="name"> |
||||
<el-input v-model="application.name" :disabled="type==='view'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.website')" prop="website"> |
||||
<el-input v-model="application.website" :disabled="type==='view'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.icon')" prop="icon"> |
||||
<el-input v-model="application.icon" :disabled="type==='icon'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.appType')" prop="appType"> |
||||
<el-radio-group v-model="application.appType.code" border="true" size="small"> |
||||
<el-radio-button |
||||
v-for="(item, key, index) in enums.ApplicationAppTypeEnum" :key="index" :label="key" |
||||
:value="key" |
||||
>{{ item }} |
||||
</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.status')" prop="status"> |
||||
<el-radio-group v-model="application.status" border="true" size="small"> |
||||
<el-radio-button :label="true">{{ $t('common.status.valid') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.status.invalid') }}</el-radio-button> |
||||
</el-radio-group> |
||||
<aside class="tips">禁用:提示"请求地址,禁止访问!";</aside> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.application.describe')" prop="describe"> |
||||
<el-input v-model="application.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css' |
||||
import applicationApi from '@/api/Application.js' |
||||
import { initEnums } from '@/utils/commons.js' |
||||
|
||||
export default { |
||||
name: 'ApplicationEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
remoteApplicationLoading: false, |
||||
application: this.initApplication(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
orgList: [], |
||||
enums: { ApplicationAppTypeEnum: {}}, |
||||
applicationList: [], |
||||
rules: { |
||||
name: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
status: { required: true, message: this.$t('rules.require'), trigger: 'blur' } |
||||
|
||||
}, |
||||
serviceList: [ |
||||
{ id: "ceres-authority-server", name: "权限服务" }, |
||||
{ id: "ceres-file-server", name: "文件服务" }, |
||||
{ id: "ceres-msgs-server", name: "消息服务" }, |
||||
{ id: "ceres-demo-server", name: "演示服务" }, |
||||
{ id: "ceres-order-server", name: "订单服务" } |
||||
] |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
initEnums(['ApplicationAppTypeEnum'], this.enums) |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initApplication() { |
||||
return { |
||||
id: '', |
||||
clientId: '', |
||||
clientSecret: '', |
||||
website: '', |
||||
name: '', |
||||
icon: '', |
||||
appType: { code: 'SERVER' }, |
||||
describe: '', |
||||
status: true |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
setApplication(val, orgs) { |
||||
const vm = this |
||||
vm.orgList = orgs |
||||
if (val) { |
||||
vm.application = { ...val } |
||||
} |
||||
}, |
||||
close() { |
||||
this.$emit('close') |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.application = this.initApplication() |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save() { |
||||
const vm = this |
||||
applicationApi.save(this.application) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update() { |
||||
applicationApi.update(this.application) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.tips { |
||||
margin-bottom: 0; |
||||
padding: 0px 10px; |
||||
} |
||||
</style> |
@ -0,0 +1,394 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.clientId" :placeholder="$t('table.application.clientId')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.name" :placeholder="$t('table.application.name')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
:start-placeholder="$t('table.createTime')" |
||||
class="filter-item search-item date-range-item" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
type="datetimerange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
<el-button |
||||
v-has-permission="['application:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['application:delete','application:export']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['application:delete']" @click.native="batchDelete">{{ $t('table.delete') |
||||
}} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['application:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['application:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @cell-click="cellClick" |
||||
@filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.application.clientId')" column-key="clientId" :show-overflow-tooltip="true" |
||||
align="center" prop="clientId" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.clientId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.application.name')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.application.website')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" prop="website" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.website }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.application.appType')" :show-overflow-tooltip="true" align="center" |
||||
min-width="50px" prop="appType" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.appType ? scope.row.appType.desc : '' }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.application.status')" :show-overflow-tooltip="true" align="center" |
||||
prop="status" width="70px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-badge :type="scope.row.status ? 'success' :'danger'" class="status-item" is-dot /> |
||||
<span>{{ scope.row.status? $t('common.status.valid') : $t('common.status.invalid') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.application.describe')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.createTime')" :show-overflow-tooltip="true" sortable="custom" |
||||
align="center" |
||||
prop="className" width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" align="center" column-key="operation" |
||||
class-name="small-padding fixed-width" fixed="right" width="110px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-has-permission="['application:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-has-permission="['application:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
|
||||
<application-edit |
||||
ref="edit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import ApplicationEdit from './Edit' |
||||
import applicationApi from '@/api/Application.js' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
import { copy } from '@/utils/utils' |
||||
|
||||
export default { |
||||
name: 'Application', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, ApplicationEdit }, |
||||
filters: {}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
tableKey: 0, |
||||
loading: false, |
||||
queryParams: initQueryParams({ |
||||
model: {} |
||||
}), |
||||
selection: [], |
||||
tableData: { |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出应用数据' |
||||
applicationApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出应用数据' |
||||
applicationApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
applicationApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
const isPersist = this.selection.findIndex(item => item.isPersist) |
||||
if (isPersist > -1) { |
||||
this.$message({ |
||||
message: "不能删除内置数据", |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const logIds = this.selection.map(item => item.id) |
||||
this.delete(logIds) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(logIds) { |
||||
applicationApi.delete({ ids: logIds }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: {} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
closeDrawer(done) { |
||||
done() |
||||
this.currentRow = {} |
||||
}, |
||||
cellClick(row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
if (column['columnKey'] === "clientId") { |
||||
copy(row[column.property]) |
||||
this.$message({ |
||||
message: this.$t('tips.copySelected'), |
||||
type: 'success' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
}, |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
add() { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setApplication(false) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setApplication(row) |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
} |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.item { |
||||
margin-top: 7px; |
||||
} |
||||
|
||||
.box-item { |
||||
margin-top: 15px; |
||||
|
||||
aside { |
||||
word-wrap: break-word; |
||||
margin-top: 15px; |
||||
} |
||||
|
||||
pre { |
||||
white-space: pre-wrap; |
||||
font-size: 0.8em; |
||||
line-height: 1.5em; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,71 @@
|
||||
<template> |
||||
<el-tabs v-model="activeName" @tab-click="handleClick"> |
||||
<el-tab-pane label="权限服务" name="first"> |
||||
<i-frame ref="authorityDruid" :src="authorityDruid" @refresh="authorityRefresh" /> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="文件服务" name="second"> |
||||
<i-frame ref="fileDruid" :src="fileDruid" @refresh="fileRefresh" /> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="消息服务" name="third"> |
||||
<i-frame ref="msgsDruid" :src="msgsDruid" @refresh="msgsRefresh" /> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</template> |
||||
<script> |
||||
import iFrame from '@/components/iFrame' |
||||
import { druid } from '@/settings' |
||||
|
||||
export default { |
||||
components: { iFrame }, |
||||
data () { |
||||
return { |
||||
authorityDruid: '', |
||||
fileDruid: '', |
||||
msgsDruid: '', |
||||
activeName: 'first' |
||||
} |
||||
}, |
||||
computed: { |
||||
|
||||
}, |
||||
mounted () { |
||||
setTimeout(() => { |
||||
this.$notify.info({ |
||||
title: this.$t('common.tips'), |
||||
message: this.$t('tips.iframeGrant'), |
||||
duration: 5000 |
||||
}) |
||||
}, 1000) |
||||
|
||||
this.authorityDruid = this.druidUrl("authority") |
||||
this.$refs.authorityDruid.url = this.authorityDruid |
||||
|
||||
this.fileDruid = this.druidUrl("file") |
||||
this.$refs.fileDruid.url = this.fileDruid |
||||
|
||||
this.msgsDruid = this.druidUrl("msgs") |
||||
this.$refs.msgsDruid.url = this.msgsDruid |
||||
}, |
||||
methods: { |
||||
authorityRefresh (u) { |
||||
this.authorityDruid = u |
||||
}, |
||||
fileRefresh (u) { |
||||
this.fileDruid = u |
||||
}, |
||||
msgsRefresh (u) { |
||||
this.msgsDruid = u |
||||
}, |
||||
handleClick (tab, event) { |
||||
console.log(tab, event) |
||||
}, |
||||
druidUrl (service) { |
||||
if (druid[service]) { |
||||
return druid[service][process.env.NODE_ENV] |
||||
} else { |
||||
return service |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,433 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.account" |
||||
:placeholder="$t('table.loginLog.account')" class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.location" :placeholder="$t('table.loginLog.location')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.requestIp" |
||||
:placeholder="$t('table.loginLog.requestIp')" class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
:start-placeholder="$t('table.createTime')" |
||||
class="filter-item search-item date-range-item" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
type="datetimerange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['loginLog:delete', 'loginLog:export']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['loginLog:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['loginLog:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['loginLog:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
<el-dropdown v-has-any-permission="['loginLog:delete']" class="filter-item" trigger="click"> |
||||
<el-button> |
||||
清理日志 |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item @click.native="clear(1)"> |
||||
保留一个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(2)"> |
||||
保留三个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(3)"> |
||||
保留六个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(4)"> |
||||
保留一年 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(5)"> |
||||
保留一千条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(6)"> |
||||
保留一万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(7)"> |
||||
保留三万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(8)"> |
||||
保留十万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(9)"> |
||||
清空所有 |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.userName')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
min-width="80px" |
||||
prop="userName" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.userName }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.requestIp')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
min-width="80px" |
||||
prop="requestIp" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.requestIp }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.browser')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="browser" |
||||
width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.browser }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.browserVersion')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="browserVersion" |
||||
width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.browserVersion }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.loginLog.operatingSystem')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="operatingSystem" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.operatingSystem }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.location')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
min-width="150px" |
||||
prop="location" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.location }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.loginDate')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.loginLog.description')" |
||||
:show-overflow-tooltip="true" |
||||
align="left" |
||||
column-key="description" |
||||
prop="description" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span> |
||||
<el-badge |
||||
:type="scope.row.description && scope.row.description == '登录成功' ? 'success' : 'danger'" |
||||
class="item" is-dot |
||||
/> |
||||
{{ scope.row.description }} |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
column-key="operation" |
||||
align="center" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-has-permission="['loginLog:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
|
||||
<el-link v-has-no-permission="['loginLog:delete']" class="no-perm">{{ |
||||
$t("tips.noPermission") |
||||
}} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import loginLogApi from "@/api/LoginLog.js" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "LoginLog", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination }, |
||||
filters: {}, |
||||
data() { |
||||
return { |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
tableKey: 0, |
||||
loading: false, |
||||
queryParams: initQueryParams(), |
||||
selection: [], |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: {}, |
||||
dicts: {} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出登录日志数据' |
||||
loginLogApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出登录日志数据' |
||||
loginLogApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
loginLogApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
clear(type) { |
||||
this.$confirm('确认要清除日志吗?', this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
loginLogApi.clear({ type: type }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
|
||||
this.search() |
||||
}) |
||||
}) |
||||
.catch(() => { |
||||
}) |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const logIds = this.selection.map(item => item.id) |
||||
this.delete(logIds) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(logIds) { |
||||
loginLogApi.delete({ ids: logIds }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
|
||||
this.search() |
||||
}) |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams() |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.item { |
||||
margin-top: 7px; |
||||
} |
||||
</style> |
@ -0,0 +1,513 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.userName" :placeholder="$t('table.optLog.userName')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.requestIp" :placeholder="$t('table.optLog.requestIp')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
:start-placeholder="$t('table.createTime')" |
||||
class="filter-item search-item date-range-item" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
type="datetimerange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
<el-dropdown v-has-any-permission="['optLog:delete','optLog:export']" class="filter-item" trigger="click"> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['optLog:delete']" @click.native="batchDelete">{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['optLog:export']" @click.native="exportExcel">{{ $t('table.export') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['optLog:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
<el-dropdown v-has-any-permission="['optLog:delete']" class="filter-item" trigger="click"> |
||||
<el-button> |
||||
清理日志 |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item @click.native="clear(1)"> |
||||
保留一个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(2)"> |
||||
保留三个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(3)"> |
||||
保留六个月 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(4)"> |
||||
保留一年 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(5)"> |
||||
保留一千条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(6)"> |
||||
保留一万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(7)"> |
||||
保留三万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(8)"> |
||||
保留十万条 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click.native="clear(9)"> |
||||
清空所有 |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.optLog.userName')" :show-overflow-tooltip="true" align="center" |
||||
prop="userName" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.userName }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.optLog.requestUri')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" prop="requestUri" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.requestUri }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="httpMethodFilters" |
||||
:label="$t('table.optLog.httpMethod')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
column-key="httpMethod" |
||||
prop="httpMethod" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.httpMethod.desc }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.optLog.requestIp')" :show-overflow-tooltip="true" align="center" |
||||
prop="requestIp" width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.requestIp }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.optLog.description')" :show-overflow-tooltip="true" align="center" |
||||
min-width="100px" prop="description" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.description }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:filter-multiple="false" :filters="typeFilters" :label="$t('table.optLog.type')" |
||||
:show-overflow-tooltip="true" align="center" column-key="type" |
||||
prop="type" width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span> |
||||
<el-badge |
||||
:type="(scope.row.type && scope.row.type.code == 'OPT')? 'success':'danger' " class="item" |
||||
is-dot |
||||
/> |
||||
{{ scope.row.type.desc }} |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.optLog.actionMethod')" :show-overflow-tooltip="true" align="center" |
||||
min-width="120px" prop="actionMethod" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.classPath + '.' + scope.row.actionMethod }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.optLog.startTime')" :show-overflow-tooltip="true" align="center" |
||||
prop="startTime" sortable="custom" width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.startTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.optLog.consumingTime')" :show-overflow-tooltip="true" align="center" |
||||
prop="consumingTime" width="110px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<el-tag :type="row.consumingTime | timeFilter">{{ transTime(row.consumingTime) }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :formatter="uaForamt" label="终端 | 浏览器" prop="ua" width="120" /> |
||||
<el-table-column |
||||
:label="$t('table.operation')" column-key="operation" align="center" |
||||
class-name="small-padding fixed-width" |
||||
width="110px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-has-permission="['optLog:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<i |
||||
v-has-permission="['optLog:view']" class="el-icon-view table-operation" style="color: #87d068;" |
||||
@click="onView(row)" |
||||
></i> |
||||
<el-link v-has-no-permission="['optLog:delete','optLog:view']" class="no-perm">{{ $t('tips.noPermission') }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
|
||||
<el-drawer v-model="currentRow" :before-close="closeDrawer" :visible.sync="drawer" direction="rtl"> |
||||
<div slot="title" class="clearfix"> |
||||
<el-badge :type="(currentRow.type && currentRow.type.code == 'OPT')? 'success':'danger' " class="item" is-dot /> |
||||
{{ currentRow.type ? currentRow.type.desc : '' }} |
||||
{{ currentRow.requestUri }} |
||||
</div> |
||||
<el-scrollbar style="height: 100%;"> |
||||
<el-card class="box-card"> |
||||
<div class="box-item"> |
||||
<span class="field-label">执行方法:</span> |
||||
<aside>{{ currentRow.classPath + '.' + currentRow.actionMethod + '()' }}</aside> |
||||
</div> |
||||
|
||||
<div class="box-item"> |
||||
<span class="field-label">请求参数:</span> |
||||
<aside style>{{ currentRow.params }}</aside> |
||||
</div> |
||||
|
||||
<div class="box-item"> |
||||
<span class="field-label">响应信息:</span> |
||||
<aside style> |
||||
<pre style="white-space: pre-wrap;">{{ currentRow.result ? JSON.stringify(JSON.parse(currentRow.result), null, 4) : '' }}</pre> |
||||
</aside> |
||||
</div> |
||||
<div v-if="currentRow.type && currentRow.type['code']==='EX'" class="box-item"> |
||||
<span class="field-label">错误信息:</span> |
||||
<aside>{{ currentRow.exDetail }}</aside> |
||||
</div> |
||||
</el-card> |
||||
</el-scrollbar> |
||||
</el-drawer> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import { readUserAgent } from '@/utils/utils' |
||||
import optLogApi from '@/api/OptLog.js' |
||||
import { convertEnum } from '@/utils/utils' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import { downloadFile, initEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'OptLog', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination }, |
||||
filters: { |
||||
timeFilter(time) { |
||||
if (time < 500) { |
||||
return 'success' |
||||
} else if (time < 1000) { |
||||
return '' |
||||
} else if (time < 1500) { |
||||
return 'warning' |
||||
} else { |
||||
return 'danger' |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
tableKey: 0, |
||||
loading: false, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
type: { |
||||
key: null |
||||
}, |
||||
httpMethod: { |
||||
key: null |
||||
} |
||||
} |
||||
}), |
||||
selection: [], |
||||
tableData: {}, |
||||
enums: { |
||||
LogType: {}, |
||||
HttpMethod: {} |
||||
}, |
||||
drawer: false, |
||||
currentRow: {} |
||||
} |
||||
}, |
||||
computed: { |
||||
typeFilters() { |
||||
return convertEnum(this.enums.LogType) |
||||
}, |
||||
httpMethodFilters() { |
||||
return convertEnum(this.enums.HttpMethod) |
||||
} |
||||
}, |
||||
mounted() { |
||||
initEnums(['LogType', 'HttpMethod'], this.enums) |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出操作日志' |
||||
optLogApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出操作日志' |
||||
optLogApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
optLogApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
clear(type) { |
||||
this.$confirm('确认要清除日志吗?', this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
optLogApi.clear({ type: type }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
|
||||
this.search() |
||||
}) |
||||
}) |
||||
.catch(() => { |
||||
}) |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const logIds = this.selection.map(item => item.id) |
||||
this.delete(logIds) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(logIds) { |
||||
optLogApi.delete({ ids: logIds }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { |
||||
type: { |
||||
key: null |
||||
}, |
||||
httpMethod: { |
||||
key: null |
||||
} |
||||
} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
transTime(time) { |
||||
return `${time} ms` |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
}, |
||||
onView(row) { |
||||
this.currentRow = row |
||||
this.drawer = true |
||||
}, |
||||
closeDrawer(done) { |
||||
done() |
||||
this.currentRow = {} |
||||
}, |
||||
uaForamt(row) { |
||||
const ua = readUserAgent(row.ua) |
||||
return ua.terminal + ' | ' + ua.browser |
||||
} |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.item { |
||||
margin-top: 7px; |
||||
} |
||||
|
||||
.drawer-item { |
||||
margin-top: 6px; |
||||
} |
||||
|
||||
.box-item { |
||||
margin-top: 15px; |
||||
|
||||
aside { |
||||
word-wrap: break-word; |
||||
margin-top: 15px; |
||||
} |
||||
|
||||
pre { |
||||
white-space: pre-wrap; |
||||
font-size: 0.8em; |
||||
line-height: 1.5em; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,230 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="systemApi" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.systemApi.serviceId')" prop="serviceId"> |
||||
<el-select |
||||
v-model="systemApi.serviceId" :disabled="type==='view'" placeholder |
||||
style="width:100%" |
||||
value |
||||
> |
||||
<el-option v-for="item in serviceList" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.systemApi.code')" prop="code"> |
||||
<el-input v-model="systemApi.code" :disabled="type==='view' || type==='edit' " /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.systemApi.name')" prop="name"> |
||||
<el-input v-model="systemApi.name" :disabled="type==='view'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.systemApi.path')" prop="path"> |
||||
<el-input v-model="systemApi.path" :disabled="type==='view'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.systemApi.status')" prop="status"> |
||||
<el-radio-group v-model="systemApi.status" border="true" size="small"> |
||||
<el-radio-button :label="true">{{ $t('common.status.valid') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.status.invalid') }}</el-radio-button> |
||||
</el-radio-group> |
||||
<aside class="tips">禁用:提示"请求地址,禁止访问!";</aside> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.systemApi.isAuth')" prop="isAuth"> |
||||
<el-radio-group v-model="systemApi.isAuth" size="small"> |
||||
<el-radio-button :label="true">{{ $t('common.yes') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.no') }}</el-radio-button> |
||||
</el-radio-group> |
||||
<aside class="tips">是:未认证登录,提示"认证失败,请重新登录!";否: 不需要认证登录</aside> |
||||
</el-form-item> |
||||
<!-- <el-form-item :label="$t('table.systemApi.isOpen')" prop="isOpen"> |
||||
<el-radio-group size="small" v-model="systemApi.isOpen"> |
||||
<el-radio-button :label="true">{{ $t('common.yes') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.no') }}</el-radio-button> |
||||
</el-radio-group> |
||||
<aside class="tips">否:提示"请求地址,拒绝访问!"</aside> |
||||
</el-form-item>--> |
||||
<el-form-item :label="$t('table.systemApi.describe')" prop="describe"> |
||||
<el-input v-model="systemApi.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import Treeselect from '@riophae/vue-treeselect' |
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css' |
||||
import systemApiApi from '@/api/SystemApi.js' |
||||
|
||||
export default { |
||||
name: 'SystemApiEdit', |
||||
components: { Treeselect }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
remoteSystemApiLoading: false, |
||||
systemApi: this.initSystemApi(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
orgList: [], |
||||
systemApiList: [], |
||||
rules: { |
||||
name: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
status: { required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
serviceId: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 50, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
] |
||||
}, |
||||
serviceList: [ |
||||
{ id: "ceres-authority-server", name: "权限服务" }, |
||||
{ id: "ceres-file-server", name: "文件服务" }, |
||||
{ id: "ceres-msgs-server", name: "消息服务" }, |
||||
{ id: "ceres-demo-server", name: "演示服务" }, |
||||
{ id: "ceres-order-server", name: "订单服务" } |
||||
] |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initSystemApi () { |
||||
return { |
||||
id: '', |
||||
code: '', |
||||
describe: '', |
||||
requestMethod: '', |
||||
contentType: '', |
||||
serviceId: '', |
||||
path: '', |
||||
status: true, |
||||
isOpen: true, |
||||
isAuth: false |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
loadListOptions ({ callback }) { |
||||
callback() |
||||
}, |
||||
setSystemApi (val, orgs) { |
||||
const vm = this |
||||
vm.orgList = orgs |
||||
if (val) { |
||||
vm.systemApi = { ...val } |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.systemApi = this.initSystemApi() |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
systemApiApi.save(this.systemApi) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
systemApiApi.update(this.systemApi) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.tips { |
||||
margin-bottom: 0; |
||||
padding: 0px 10px; |
||||
} |
||||
</style> |
@ -0,0 +1,512 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.code" :placeholder="$t('table.systemApi.code')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.name" :placeholder="$t('table.systemApi.name')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.serviceId" :placeholder="$t('table.systemApi.serviceId')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
:start-placeholder="$t('table.createTime')" |
||||
class="filter-item search-item date-range-item" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
type="datetimerange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
<el-button |
||||
v-has-permission="['systemApi:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['systemApi:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="scan" |
||||
> |
||||
扫描接口 |
||||
</el-button> |
||||
<el-dropdown v-has-any-permission="['systemApi:delete','systemApi:export']" class="filter-item" trigger="click"> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['systemApi:delete']" @click.native="batchDelete"> |
||||
{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['systemApi:export']" @click.native="exportExcel"> |
||||
{{ $t('table.export') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['systemApi:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @cell-click="cellClick" |
||||
@filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column :label="$t('table.systemApi.code')" :show-overflow-tooltip="true" align="center" prop="code"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.name')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.describe')" :show-overflow-tooltip="true" align="left" |
||||
min-width="120px" prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.requestMethod')" :show-overflow-tooltip="true" align="left" |
||||
min-width="80px" prop="requestMethod" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.requestMethod }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.serviceId')" :show-overflow-tooltip="true" align="center" |
||||
min-width="180px" prop="serviceId" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.serviceId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.path')" :show-overflow-tooltip="true" align="left" |
||||
min-width="200px" |
||||
prop="path" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.path }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.status')" :show-overflow-tooltip="true" align="center" |
||||
prop="status" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-badge :type="scope.row.status ? 'success' :'danger'" class="status-item" is-dot /> |
||||
<span>{{ scope.row.status? $t('common.status.valid') : $t('common.status.invalid') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.isAuth')" :show-overflow-tooltip="true" align="center" |
||||
prop="isAuth" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.isAuth ? $t('common.yes') : $t('common.no') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.isOpen')" :show-overflow-tooltip="true" align="center" |
||||
prop="isOpen" |
||||
width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.isOpen? $t('common.yes') : $t('common.no') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.systemApi.isPersist')" :show-overflow-tooltip="true" align="center" |
||||
prop="isOpen" width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.isPersist? $t('common.yes') : $t('common.no') }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.createTime')" sortable="custom" :show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="className" width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" column-key="operation" align="center" |
||||
class-name="small-padding fixed-width" |
||||
fixed="right" width="110px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-has-permission="['systemApi:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-has-permission="['systemApi:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<i class="el-icon-view table-operation" style="color: #87d068;" @click="onView(row)"></i> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
|
||||
<el-drawer v-model="currentRow" :before-close="closeDrawer" :visible.sync="drawer" direction="rtl"> |
||||
<div slot="title" class="clearfix">{{ currentRow.path }}</div> |
||||
<el-scrollbar style="height: 100%;"> |
||||
<el-card class="box-card"> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.code') }}:</span> |
||||
<aside>{{ currentRow.code }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.name') }}:</span> |
||||
<aside style>{{ currentRow.name }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.describe') }}:</span> |
||||
<aside style>{{ currentRow.describe }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.requestMethod') }}:</span> |
||||
<aside style>{{ currentRow.requestMethod }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.contentType') }}:</span> |
||||
<aside style>{{ currentRow.contentType }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.serviceId') }}:</span> |
||||
<aside style>{{ currentRow.serviceId }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.path') }}:</span> |
||||
<aside style>{{ currentRow.path }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.status') }}:</span> |
||||
<aside style>{{ currentRow.status ? '是' : '否' }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.isPersist') }}:</span> |
||||
<aside style>{{ currentRow.isPersist ? '是' : '否' }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.isAuth') }}:</span> |
||||
<aside style>{{ currentRow.isAuth ? '是' : '否' }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.isOpen') }}:</span> |
||||
<aside style>{{ currentRow.isOpen ? '是' : '否' }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.isPersist') }}:</span> |
||||
<aside style>{{ currentRow.isPersist ? '是' : '否' }}</aside> |
||||
</div> |
||||
<div class="box-item"> |
||||
<span class="field-label">{{ $t('table.systemApi.className') }}:</span> |
||||
<aside style>{{ currentRow.className + '.' + currentRow.methodName }}</aside> |
||||
</div> |
||||
</el-card> |
||||
</el-scrollbar> |
||||
</el-drawer> |
||||
<system-api-edit |
||||
ref="edit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<system-api-scan |
||||
ref="scan" :dialog-visible="dialogScan.isVisible" :type="dialogScan.type" |
||||
@close="scanClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import SystemApiEdit from './Edit' |
||||
import SystemApiScan from './Scan' |
||||
import systemApiApi from '@/api/SystemApi.js' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'SystemApi', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, SystemApiEdit, SystemApiScan }, |
||||
filters: {}, |
||||
data() { |
||||
return { |
||||
dialogScan: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
tableKey: 0, |
||||
loading: false, |
||||
queryParams: initQueryParams({ |
||||
model: {} |
||||
}), |
||||
selection: [], |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
drawer: false, |
||||
currentRow: {} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出接口数据' |
||||
systemApiApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出接口数据' |
||||
systemApiApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
systemApiApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
const isPersist = this.selection.findIndex(item => item.isPersist) |
||||
if (isPersist > -1) { |
||||
this.$message({ |
||||
message: "不能删除内置数据", |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const logIds = this.selection.map(item => item.id) |
||||
this.delete(logIds) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(logIds) { |
||||
systemApiApi.delete({ ids: logIds }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = {} |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
onView(row) { |
||||
this.currentRow = row |
||||
this.drawer = true |
||||
}, |
||||
closeDrawer(done) { |
||||
done() |
||||
this.currentRow = {} |
||||
}, |
||||
cellClick(row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
|
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
}, |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
scanClose() { |
||||
this.dialogScan.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
add() { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setSystemApi(false) |
||||
}, |
||||
scan() { |
||||
this.dialogScan.type = 'add' |
||||
this.dialogScan.isVisible = true |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setSystemApi(row) |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.item { |
||||
margin-top: 7px; |
||||
} |
||||
|
||||
.drawer-item { |
||||
margin-top: 6px; |
||||
} |
||||
|
||||
.box-item { |
||||
margin-top: 15px; |
||||
|
||||
aside { |
||||
word-wrap: break-word; |
||||
margin-top: 15px; |
||||
} |
||||
|
||||
pre { |
||||
white-space: pre-wrap; |
||||
font-size: 0.8em; |
||||
line-height: 1.5em; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,127 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="systemApi" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
|
||||
<el-form-item :label="$t('table.systemApi.serviceId')" prop="serviceId"> |
||||
<el-select |
||||
v-model="systemApi.serviceId" :disabled="type==='view'" placeholder |
||||
style="width:100%" |
||||
value |
||||
> |
||||
<el-option v-for="item in serviceList" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
|
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import systemApiApi from '@/api/SystemApi.js' |
||||
|
||||
export default { |
||||
name: 'SystemApiScan', |
||||
components: { }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
rules: { |
||||
}, |
||||
systemApi: { |
||||
serviceId: 'authority' |
||||
}, |
||||
serviceList: [ |
||||
{ id: "authority", name: "权限服务" }, |
||||
{ id: "file", name: "文件服务" }, |
||||
{ id: "msgs", name: "消息服务" }, |
||||
{ id: "demo", name: "演示服务" }, |
||||
{ id: "order", name: "订单服务" } |
||||
] |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return '扫描Rest接口' |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.serviceId = 'authority' |
||||
}, |
||||
submitForm() { |
||||
systemApiApi.scan(this.systemApi.serviceId).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: "扫描成功,请稍后刷新数据", |
||||
type: 'success' |
||||
}) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.tips { |
||||
margin-bottom: 0; |
||||
padding: 0px 10px; |
||||
} |
||||
</style> |
@ -0,0 +1,188 @@
|
||||
<template> |
||||
<el-dialog |
||||
v-el-drag-dialog :close-on-click-modal="false" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
@dragDialog="handleDrag" |
||||
> |
||||
<el-form |
||||
ref="form" :model="attachment" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.attachment.bizId')" prop="bizId"> |
||||
<el-input v-model="attachment.bizId" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item :label="$t('table.attachment.bizType')" prop="bizType"> |
||||
<el-input v-model="attachment.bizType" /> |
||||
</el-form-item> |
||||
<el-form-item label="文件" prop="fileLength"> |
||||
<fileUpload |
||||
ref="fileRef" :accept-size="2*1024*1024" :auto-upload="false" |
||||
:limit="5" |
||||
@fileLengthVaild="fileLengthVaild" @setId="setIdAndSubmit" |
||||
> |
||||
<el-button slot="trigger" size="small" type="primary">选取文件</el-button> |
||||
<div slot="tip" class="el-upload__tip">文件不超过2MB</div> |
||||
</fileUpload> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button :disabled="disabled" plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import fileUpload from "@/components/ceres/fileUpload" |
||||
|
||||
export default { |
||||
name: 'AttachmentEdit', |
||||
directives: { elDragDialog, fileUpload }, |
||||
components: { fileUpload }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
accept: "image/jpeg, image/gif, image/png", |
||||
attachment: this.initAttachment(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
fileLength: 0, |
||||
disabled: false, |
||||
rules: { |
||||
bizType: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 0, max: 255, message: this.$t('rules.range0to255'), trigger: 'blur' } |
||||
], |
||||
bizId: { min: 0, max: 255, message: this.$t('rules.range0to255'), trigger: 'blur' }, |
||||
fileLength: { required: true, trigger: "change", |
||||
validator: (rule, value, callback) => { |
||||
const vm = this |
||||
if (vm.fileLength === 0) { |
||||
callback(new Error("请上传文件")) |
||||
} else if (vm.fileLength > 5) { |
||||
callback(new Error("一次性只能上传5个文件")) |
||||
} else { |
||||
callback() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.$t('common.upload') |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initAttachment () { |
||||
return { |
||||
id: '', |
||||
bizId: '', |
||||
bizType: '', |
||||
file: null, |
||||
isSingle: false |
||||
} |
||||
}, |
||||
handleDrag () { |
||||
console.log(`我被拖动了`) |
||||
}, |
||||
// 附件长度校验 |
||||
fileLengthVaild (data) { |
||||
const vm = this |
||||
vm.fileLength = data || 0 |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
setAttachment (val) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.attachment = { ...val } |
||||
} |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.attachment = this.initAttachment() |
||||
this.$refs.fileRef.init({ |
||||
id: "", |
||||
bizId: "", |
||||
bizType: "" |
||||
}) |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
vm.disabled = true |
||||
vm.$refs.fileRef.submitFile(this.attachment.id, this.attachment.bizId, this.attachment.bizType) |
||||
}, |
||||
setIdAndSubmit (isUploadCompleted) { |
||||
const vm = this |
||||
if (isUploadCompleted) { |
||||
vm.disabled = false |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,435 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.submittedFileName" |
||||
:placeholder="$t('table.attachment.submittedFileName')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['file:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="upload" |
||||
> |
||||
{{ $t("table.upload") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['file:delete', 'file:download']" |
||||
class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item |
||||
v-has-permission="['file:delete']" |
||||
@click.native="batchDelete" |
||||
>{{ $t("table.delete") }}</el-dropdown-item> |
||||
<el-dropdown-item |
||||
v-has-permission="['file:download']" |
||||
@click.native="batchDownload" |
||||
>{{ $t("table.download") }}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.attachment.submittedFileName')" |
||||
:show-overflow-tooltip="true" |
||||
align="left" |
||||
prop="submittedFileName" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<div class="hover-effect" @click="onView(scope.row)"> |
||||
<i :class="scope.row.icon" class="button-list"></i> |
||||
<span>{{ scope.row.submittedFileName }}</span> |
||||
</div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.attachment.dataType')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="dataType" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.dataType.desc }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.attachment.bizType')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.bizType }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.attachment.bizId')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="180px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.bizId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.attachment.size')" |
||||
align="center" |
||||
:show-overflow-tooltip="true" |
||||
width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ formatSize(scope.row) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
align="center" column-key="operation" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['file:download']" |
||||
class="el-icon-download table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDownload(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['file:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link |
||||
v-has-no-permission="['file:update', 'file:delete']" |
||||
class="no-perm" |
||||
>{{ $t("tips.noPermission") }}</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<attachment-edit |
||||
ref="edit" |
||||
:dialog-visible="dialog.isVisible" |
||||
:type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<el-dialog :visible.sync="dialogVisible"> |
||||
<img |
||||
v-if="dialogImageUrl" |
||||
:key="dialogImageUrl" |
||||
:src="dialogImageUrl" |
||||
alt="图片飞到火星了" |
||||
height="500px" |
||||
width="100%" |
||||
@error="errorImage()" |
||||
/> |
||||
<span v-else>图片飞到火星了~</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import AttachmentEdit from "./Edit" |
||||
import attachmentApi from "@/api/Attachment.js" |
||||
import { renderSize } from "@/utils/utils" |
||||
import { onlinePreview } from "@/settings" |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "AttachmentManage", |
||||
components: { Pagination, AttachmentEdit }, |
||||
filters: {}, |
||||
data() { |
||||
return { |
||||
dialogVisible: false, |
||||
dialogImageUrl: "", |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: {} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
records: [], |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
mounted() { |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
errorImage() { |
||||
const img = event.srcElement |
||||
img.src = require("@/assets/404_images/404_image.jpeg") |
||||
img.onerror = null // 防止闪图 |
||||
}, |
||||
formatSize(row) { |
||||
return renderSize(row.size) |
||||
}, |
||||
filterStatus(value, row) { |
||||
return row.status === value |
||||
}, |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: {} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
singleDownload(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDownload() |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDownload() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm("确认下载吗?", this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.download(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
download(ids) { |
||||
attachmentApi.download({ ids: ids }).then(response => { |
||||
downloadFile(response) |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
delete(ids) { |
||||
attachmentApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
onView(row) { |
||||
if (row.url) { |
||||
window.open(onlinePreview + encodeURIComponent(row.url)) |
||||
} |
||||
}, |
||||
upload() { |
||||
this.dialog.type = "upload" |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setAttachment(false) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setAttachment(row) |
||||
this.dialog.type = "edit" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
attachmentApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.file-breadcrumb { |
||||
margin: 10px 0px 20px; |
||||
} |
||||
.page { |
||||
text-align: center; |
||||
margin-top: 5px; |
||||
} |
||||
.button-list { |
||||
margin-right: 10px; |
||||
font-size: 20px !important; |
||||
color: #22a2ed; |
||||
vertical-align: middle; |
||||
} |
||||
.title { |
||||
color: #777; |
||||
font-size: 2em; |
||||
border-bottom: 1px solid #e5e5e5; |
||||
} |
||||
div{ |
||||
&.hover-effect { |
||||
cursor: pointer; |
||||
transition: background 0.3s; |
||||
|
||||
&:hover { |
||||
background: rgba(0, 0, 0, 0.025); |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,524 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.title" |
||||
:placeholder="$t('table.msgs.title')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.content" |
||||
:placeholder="$t('table.msgs.content')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<router-link :to="{ path: '/msgs/sendMsgs', query: { type: 'add' } }"> |
||||
<el-button v-has-permission="['msgs:add']" class="filter-item" plain type="danger"> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
</router-link> |
||||
<el-dropdown |
||||
v-has-any-permission="['msgs:delete', 'msgs:export']" |
||||
class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<!-- <router-link :to="{ path: '/msgs/sendMsgs', query: { type: 'add' } }">--> |
||||
<!-- <el-dropdown-item v-has-permission="['msgs:add']">--> |
||||
<!-- {{ $t("table.add") }}--> |
||||
<!-- </el-dropdown-item>--> |
||||
<!-- </router-link>--> |
||||
<el-dropdown-item v-has-permission="['msgs:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['msgs:mark']" @click.native="batchMark"> |
||||
标记已读 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['msgs:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['msgs:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['msgs:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.msgs.title')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="templateId" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.title }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.msgs.content')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="receiver" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.content }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.msgs.author')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.author }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="bizTypeFilters" |
||||
:label="$t('table.msgs.bizType')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
column-key="bizType.code" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.bizType ? scope.row.bizType.desc : "" }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="msgsCenterTypeFilters" |
||||
:label="$t('table.msgs.msgsCenterType')" |
||||
:show-overflow-tooltip="true" |
||||
class-name="status-col" |
||||
column-key="msgsCenterType.code" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ |
||||
scope.row.msgsCenterType |
||||
? scope.row.msgsCenterType.desc |
||||
: scope.row.msgsCenterType |
||||
}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="[ |
||||
{ text: '已读', value: 'true' }, |
||||
{ text: '未读', value: 'false' } |
||||
]" |
||||
:label="$t('table.msgs.isRead')" |
||||
align="center" |
||||
column-key="isRead" |
||||
prop="isRead" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span> |
||||
<el-tag slot :type="scope.row.isRead ? 'success' : 'danger'">{{ |
||||
scope.row.isRead ? "已读" : "未读" |
||||
}}</el-tag> |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
align="center" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
column-key="operation" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['msgs:view']" |
||||
class="el-icon-view table-operation" |
||||
style="color: #2db7f5;" |
||||
@click="view(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['msgs:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link |
||||
v-has-no-permission="['msgs:view', 'msgs:delete']" |
||||
class="no-perm" |
||||
>{{ $t("tips.noPermission") }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import msgsApi from "@/api/Msgs.js" |
||||
import { convertEnum } from "@/utils/utils" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile, initMsgsEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "MsgsList", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, FileImport }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
WAITING: "danger", |
||||
SUCCESS: "success", |
||||
FAIL: "error" |
||||
} |
||||
return map[status] || "success" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/msgs/msgsCenterInfo/import` |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
msgsCenterType: { code: null }, |
||||
bizType: { code: null } |
||||
} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { |
||||
MsgsCenterType: {}, |
||||
MsgsBizType: {} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
msgsCenterTypeFilters() { |
||||
return convertEnum(this.enums.MsgsCenterType) |
||||
}, |
||||
bizTypeFilters() { |
||||
return convertEnum(this.enums.MsgsBizType) |
||||
} |
||||
}, |
||||
watch: { |
||||
'$route'(to) { |
||||
if (to.path === '/msgs/myMsgs') { |
||||
this.fetch() |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
initMsgsEnums(['MsgsCenterType', 'MsgsBizType'], this.enums) |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
filterStatus(value, row) { |
||||
return row.status === value |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { |
||||
msgsCenterType: { code: null }, |
||||
bizType: { code: null } |
||||
} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出消息数据' |
||||
msgsApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出消息数据' |
||||
msgsApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
|
||||
delete(ids) { |
||||
msgsApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
batchMark() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm("确认全部标记为已读吗?", this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.mark(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
mark(ids, callback) { |
||||
msgsApi.mark({ msgCenterIds: ids }).then(response => { |
||||
const res = response.data |
||||
if (typeof callback === "function") { |
||||
callback(ids) |
||||
} |
||||
}) |
||||
}, |
||||
view(row) { |
||||
if (row.isRead) { |
||||
this.$router.push({ |
||||
path: "/msgs/sendMsgs", |
||||
query: { |
||||
id: row.id, |
||||
type: "view" |
||||
} |
||||
}) |
||||
} else { |
||||
this.mark([row.id], ids => { |
||||
this.$router.push({ |
||||
path: "/msgs/sendMsgs", |
||||
query: { |
||||
id: row.id, |
||||
type: "view" |
||||
} |
||||
}) |
||||
}) |
||||
} |
||||
}, |
||||
edit(row) { |
||||
this.$router.push({ |
||||
path: "/msgs/sendMsgs", |
||||
query: { |
||||
id: row.id, |
||||
type: "edit" |
||||
} |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
msgsApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick(row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,412 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form |
||||
ref="form" :model="msgsCenterInfo" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" status-icon |
||||
> |
||||
<el-row> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.title')" prop="msgsCenterInfoDTO.title"> |
||||
<el-input v-model="msgsCenterInfo.msgsCenterInfoDTO.title" :disabled="type==='view'" :maxlength="255" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.bizType')" prop="msgsCenterInfoDTO.bizType"> |
||||
<el-select |
||||
v-model="msgsCenterInfo.msgsCenterInfoDTO.bizType.code" :disabled="type==='view'" clearable |
||||
placeholder |
||||
style="width:100%" value |
||||
> |
||||
<el-option v-for="(item, key, index) in enums.MsgsBizType" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.bizId')" prop="msgsCenterInfoDTO.bizId"> |
||||
<el-input v-model="msgsCenterInfo.msgsCenterInfoDTO.bizId" :disabled="type==='view'" :maxlength="255" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.msgsCenterType')" prop="msgsCenterInfoDTO.msgsCenterType"> |
||||
<el-select |
||||
v-model="msgsCenterInfo.msgsCenterInfoDTO.msgsCenterType.code" :disabled="type==='view'" placeholder |
||||
style="width:100%" |
||||
value @change="msgsCenterTypeChange" |
||||
> |
||||
<el-option v-for="(item, key, index) in enums.MsgsCenterType" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item v-show="type!=='view'" label="接收类型" prop="msgsCenterInfoDTO.receiveType"> |
||||
<el-radio-group v-model="msgsCenterInfo.receiveType" :disabled="type==='view' || disabledReceiveType"> |
||||
<el-radio-button label="user">用户</el-radio-button> |
||||
<el-radio-button label="role">角色</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item v-if="msgsCenterInfo.receiveType==='user'" v-show="type!=='view'" label="接收用户" prop="userIdList"> |
||||
<el-select |
||||
v-model="msgsCenterInfo.userIdList" :disabled="type==='view' || disabledReceiveType" collapse-tags |
||||
multiple |
||||
placeholder style="width:100%" value |
||||
@change="userSelect" |
||||
> |
||||
<el-option v-for="item in allUserList" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-else v-show="type!=='view'" label="接收角色" prop="roleCodeList"> |
||||
<el-select |
||||
v-model="msgsCenterInfo.roleCodeList" :disabled="type==='view' || disabledReceiveType" collapse-tags |
||||
multiple |
||||
placeholder style="width:100%" value |
||||
@change="roleSelect" |
||||
> |
||||
<el-option v-for="item in allRoleList" :key="item.code" :label="item.name" :value="item.code" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<el-row> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.author')" prop="msgsCenterInfoDTO.author"> |
||||
<el-input v-model="msgsCenterInfo.msgsCenterInfoDTO.author" :disabled="type==='view'" :maxlength="255" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.handlerUrl')" prop="msgsCenterInfoDTO.handlerUrl"> |
||||
<el-input v-model="msgsCenterInfo.msgsCenterInfoDTO.handlerUrl" :disabled="type==='view'" :maxlength="255" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-form-item :label="$t('table.msgs.isSingleHandle')" prop="msgsCenterInfoDTO.isSingleHandle"> |
||||
<el-radio-group v-model="msgsCenterInfo.msgsCenterInfoDTO.isSingleHandle" :disabled="type==='view'"> |
||||
<el-radio-button :label="true">{{ $t('common.yes') }}</el-radio-button> |
||||
<el-radio-button :label="false">{{ $t('common.no') }}</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-form-item prop="msgsCenterInfoDTO.content" style="margin-bottom: 30px;"> |
||||
<Tinymce ref="content" v-model="msgsCenterInfo.msgsCenterInfoDTO.content" :height="400" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div class="dialog-footer"> |
||||
<el-button |
||||
v-show="type!=='view'" :disabled="disabled" plain |
||||
type="primary" |
||||
@click="submitForm(false)" |
||||
>发送</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import msgsApi from '@/api/Msgs.js' |
||||
import roleApi from '@/api/Role.js' |
||||
import userApi from '@/api/User.js' |
||||
import Tinymce from '@/components/Tinymce' |
||||
import { initMsgsEnums } from '@/utils/commons.js' |
||||
|
||||
export default { |
||||
name: 'MsgsEdit', |
||||
components: { Tinymce }, |
||||
filters: { |
||||
|
||||
}, |
||||
props: { |
||||
|
||||
}, |
||||
data () { |
||||
return { |
||||
allUserList: [], |
||||
allRoleList: [], |
||||
oldChooseUserIdList: [[]], |
||||
oldChooseRoleIdList: [[]], |
||||
dialog: { |
||||
isVisible: false |
||||
}, |
||||
type: 'add', |
||||
msgsCenterInfo: this.initMsgsCenterInfo(), |
||||
disabled: false, |
||||
disabledReceiveType: false, |
||||
enums: { |
||||
MsgsBizType: {}, |
||||
MsgsCenterType: {} |
||||
}, |
||||
rules: { |
||||
"msgsCenterInfoDTO.title": [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: "长度在 1 到 255 个字符", trigger: 'blur' } |
||||
], |
||||
"msgsCenterInfoDTO.content": [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 65535, message: "长度在 1 到 65535 个字符", trigger: 'blur' } |
||||
], |
||||
"msgsCenterInfoDTO.msgsCenterType": { required: true, message: this.$t('rules.require'), trigger: 'change' }, |
||||
"roleCodeList": { |
||||
validator: (rule, value, callback) => { |
||||
if (this.msgsCenterInfo.receiveType === 'role' && this.msgsCenterInfo.msgsCenterInfoDTO.msgsCenterType.code !== 'PUBLICITY' && this.msgsCenterInfo.roleCodeList.length <= 0) { |
||||
callback('请选择角色') |
||||
} else { |
||||
callback() |
||||
} |
||||
}, trigger: 'blur' |
||||
}, |
||||
"userIdList": { |
||||
validator: (rule, value, callback) => { |
||||
if (this.msgsCenterInfo.receiveType === 'user' && this.msgsCenterInfo.msgsCenterInfoDTO.msgsCenterType.code !== 'PUBLICITY' && this.msgsCenterInfo.userIdList.length <= 0) { |
||||
callback('请选择用户') |
||||
} else { |
||||
callback() |
||||
} |
||||
}, trigger: 'blur' |
||||
}, |
||||
"msgsCenterInfoDTO.handlerUrl": { min: 1, max: 255, message: "长度在 1 到 255 个字符", trigger: 'blur' } |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
|
||||
}, |
||||
watch: { |
||||
$route () { |
||||
if (this.$route.path === '/msgs/sendMsgs') { |
||||
this.loadMsgs() |
||||
this.loadUserList() |
||||
this.loadRoleList() |
||||
} |
||||
} |
||||
}, |
||||
mounted () { |
||||
this.loadMsgs() |
||||
this.loadUserList() |
||||
this.loadRoleList() |
||||
initMsgsEnums(['MsgsCenterType', 'MsgsBizType'], this.enums) |
||||
}, |
||||
methods: { |
||||
initMsgsCenterInfo () { |
||||
return { |
||||
userIdList: [], |
||||
roleCodeList: [], |
||||
receiveType: 'user', |
||||
msgsCenterInfoDTO: { |
||||
id: '', |
||||
bizId: '', |
||||
bizType: { |
||||
code: '' |
||||
}, |
||||
msgsCenterType: { |
||||
code: '' |
||||
}, |
||||
title: '', |
||||
content: '', |
||||
author: '', |
||||
handlerUrl: '', |
||||
handlerParams: '', |
||||
isSingleHandle: true |
||||
} |
||||
} |
||||
}, |
||||
loadMsgs () { |
||||
const type = this.$route.query.type |
||||
const id = this.$route.query.id |
||||
this.type = type |
||||
if (type === 'view') { |
||||
msgsApi.get(id) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.msgsCenterInfo.msgsCenterInfoDTO = res.data |
||||
if (this.msgsCenterInfo.msgsCenterInfoDTO.bizType === null) { |
||||
this.msgsCenterInfo.msgsCenterInfoDTO.bizType = { code: '' } |
||||
} |
||||
if (this.msgsCenterInfo.msgsCenterInfoDTO.msgsCenterType === null) { |
||||
this.msgsCenterInfo.msgsCenterInfoDTO.msgsCenterType = { code: '' } |
||||
} |
||||
} |
||||
}) |
||||
} else { |
||||
this.reset() |
||||
} |
||||
}, |
||||
loadUserList () { |
||||
userApi.page({ current: 1, size: 10000, model: { status: true }}) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
if (res.data.records.length > 0) { |
||||
this.allUserList = [...[{ id: '-1', name: '全选' }], ...res.data.records] |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
loadRoleList () { |
||||
roleApi.page({ current: 1, size: 10000, model: { status: true }}) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
if (res.data.records.length > 0) { |
||||
this.allRoleList = [...[{ code: '-1', name: '全选' }], ...res.data.records] |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
msgsCenterTypeChange (select) { |
||||
if (select === 'PUBLICITY') { |
||||
this.disabledReceiveType = true |
||||
} else { |
||||
this.disabledReceiveType = false |
||||
} |
||||
}, |
||||
userSelect (val) { |
||||
// 保留所有值 |
||||
const allValues = this.allUserList.map(item => item.id) |
||||
|
||||
// 用来储存上一次的值,可以进行对比 |
||||
const oldVal = this.oldChooseUserIdList.length === 1 ? [] : this.oldChooseUserIdList[1] |
||||
|
||||
// 若是全部选择 |
||||
if (val.includes('-1')) { |
||||
this.msgsCenterInfo.userIdList = allValues |
||||
} |
||||
|
||||
// 取消全部选中 上次有 当前没有 表示取消全选 |
||||
if (oldVal.includes('-1') && !val.includes('-1')) { |
||||
this.msgsCenterInfo.userIdList = [] |
||||
} |
||||
|
||||
// 点击非全部选中 需要排除全部选中 以及 当前点击的选项 |
||||
// 新老数据都有全部选中 |
||||
if (oldVal.includes('-1') && val.includes('-1')) { |
||||
const index = val.indexOf('-1') |
||||
val.splice(index, 1) // 排除全选选项 |
||||
this.msgsCenterInfo.userIdList = val |
||||
} |
||||
|
||||
// 全选未选 但是其他选项全部选上 则全选选上 上次和当前 都没有全选 |
||||
if (!oldVal.includes('-1') && !val.includes('-1')) { |
||||
if (val.length === allValues.length - 1) { |
||||
this.msgsCenterInfo.userIdList = ['-1'].concat(val) |
||||
} |
||||
} |
||||
|
||||
// 储存当前最后的结果 作为下次的老数据 |
||||
this.oldChooseUserIdList[1] = this.msgsCenterInfo.userIdList |
||||
}, |
||||
roleSelect (val) { |
||||
// 保留所有值 |
||||
const allValues = this.allRoleList.map(item => item.code) |
||||
|
||||
// 用来储存上一次的值,可以进行对比 |
||||
const oldVal = this.oldChooseRoleIdList.length === 1 ? [] : this.oldChooseRoleIdList[1] |
||||
|
||||
// 若是全部选择 |
||||
if (val.includes('-1')) { |
||||
this.msgsCenterInfo.roleCodeList = allValues |
||||
} |
||||
|
||||
// 取消全部选中 上次有 当前没有 表示取消全选 |
||||
if (oldVal.includes('-1') && !val.includes('-1')) { |
||||
this.msgsCenterInfo.roleCodeList = [] |
||||
} |
||||
|
||||
// 点击非全部选中 需要排除全部选中 以及 当前点击的选项 |
||||
// 新老数据都有全部选中 |
||||
if (oldVal.includes('-1') && val.includes('-1')) { |
||||
const index = val.indexOf('-1') |
||||
val.splice(index, 1) // 排除全选选项 |
||||
this.msgsCenterInfo.roleCodeList = val |
||||
} |
||||
|
||||
// 全选未选 但是其他选项全部选上 则全选选上 上次和当前 都没有全选 |
||||
if (!oldVal.includes('-1') && !val.includes('-1')) { |
||||
if (val.length === allValues.length - 1) { |
||||
this.msgsCenterInfo.roleCodeList = ['-1'].concat(val) |
||||
} |
||||
} |
||||
|
||||
// 储存当前最后的结果 作为下次的老数据 |
||||
this.oldChooseRoleIdList[1] = this.msgsCenterInfo.roleCodeList |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.msgsCenterInfo = this.initMsgsCenterInfo() |
||||
this.disabledReceiveType = false |
||||
|
||||
// 这里报错 |
||||
// this.$nextTick(() => |
||||
// this.$refs.content.setContent('') |
||||
// ) |
||||
|
||||
// 设置设置的时间短了 也报错 |
||||
setTimeout(() => { |
||||
this.$refs.content.setContent('') |
||||
}, 1000) |
||||
}, |
||||
submitForm (draft) { |
||||
const vm = this |
||||
console.log(vm.msgsCenterInfo) |
||||
|
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit(draft) |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit (draft) { |
||||
const vm = this |
||||
if (vm.type === 'edit') { |
||||
vm.update() |
||||
} else { |
||||
vm.save() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
vm.disabled = true |
||||
msgsApi.save(vm.msgsCenterInfo) |
||||
.then((response) => { |
||||
vm.disabled = false |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.reset() |
||||
vm.$router.push('/msgs/myMsgs') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
const vm = this |
||||
vm.disabled = true |
||||
msgsApi.update(vm.msgs) |
||||
.then((response) => { |
||||
vm.disabled = false |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.reset() |
||||
vm.$router.push('/msgs/myMsgs') |
||||
} |
||||
}) |
||||
} |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,507 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form |
||||
ref="form" :model="smsTask" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" status-icon |
||||
> |
||||
<el-row> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item :label="$t('table.smsTask.templateId')" prop="templateId"> |
||||
<el-select |
||||
v-model="smsTask.templateId" :disabled="type==='view'" :multiple="false" |
||||
filterable |
||||
placeholder="请输入关键词" style="width:300px;" @change="changeTemplate" |
||||
> |
||||
<el-option v-for="item in smsTemplateList" :key="item.id" :label="item.name + '('+item.customCode+')'" :value="item.id" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item v-show="type==='view'" :label="$t('table.smsTask.status')" prop="status"> |
||||
<el-tag :disabled="type==='view'" :type="smsTask.status | statusFilter">{{ smsTask.status.desc }}</el-tag> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-form-item :label="$t('table.smsTask.receiver')" prop="receiver"> |
||||
<el-tag |
||||
v-for="tag in receiverList" :key="tag" :closable="type!=='view'" |
||||
:disable-transitions="false" |
||||
@close="handleClose(tag)" |
||||
>{{ tag }}</el-tag> |
||||
<el-input |
||||
v-if="receiverVisible" ref="saveTagInput" v-model="receiver" |
||||
:disabled="type==='view'" |
||||
class="input-new-tag" @blur="handleInputConfirm" @keyup.enter.native="handleInputConfirm" |
||||
/> |
||||
<el-button v-else :disabled="type==='view'" class="button-new-tag" @click="showInput">添加</el-button> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTask.topic')" prop="topic"> |
||||
<el-input v-model="smsTask.topic" :disabled="type==='view'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTask.content')" prop="content2"> |
||||
<el-row class="message"> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item v-for="(item, key, index) in smsTask.templateParam" :key="index" :label="key" prop="content"> |
||||
<el-input :disabled="type==='view'" :value="item" maxlength="255" @input="(value)=>{templateCode(value,key,index)}" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item label="预览:"> |
||||
<div class="article" v-html="smsTask.content"></div> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-row> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item label="定时发送" prop="sendTime"> |
||||
<el-radio-group v-model="timing" :disabled="type==='view'" size="medium"> |
||||
<el-radio-button :label="false">否</el-radio-button> |
||||
<el-radio-button :label="true">是</el-radio-button> |
||||
</el-radio-group> |
||||
<el-date-picker |
||||
v-show="timing" |
||||
v-model="smsTask.sendTime" |
||||
:disabled="type==='view'" |
||||
:picker-options="pickerOptions" |
||||
align="right" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
placeholder="选择发送时间" |
||||
style="margin-left:20px" |
||||
type="datetime" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24" style="margin-top: 10px;"> |
||||
<el-form-item v-show="type==='view'" label="是否草稿" prop="draft"> |
||||
<el-radio-group v-model="smsTask.draft" :disabled="type==='view'" size="medium"> |
||||
<el-radio-button :label="false">否</el-radio-button> |
||||
<el-radio-button :label="true">是</el-radio-button> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<div class="dialog-footer"> |
||||
<el-button |
||||
v-show="type!=='view'" :disabled="disabled" plain |
||||
type="primary" |
||||
@click="submitForm(false)" |
||||
>立即发送</el-button> |
||||
<el-button |
||||
v-show="type!=='view'" :disabled="disabled" plain |
||||
type="warning" |
||||
@click="submitForm(true)" |
||||
>存草稿</el-button> |
||||
</div> |
||||
<aside v-show="type!=='view'" class="tips"> |
||||
模板提示: |
||||
<p>1.长度不超过500字,单条短信超过70字后,按67字/条分多条计费;</p> |
||||
<p>2.短信模板内容不能包含【】符号。</p> |
||||
</aside> |
||||
<div v-show="type==='view'"> |
||||
<send-status-index ref="statusList" :dialog-visible="dialog.isVisible" /> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import smsTemplateApi from '@/api/SmsTemplate.js' |
||||
import smsTaskApi from '@/api/SmsTask.js' |
||||
import { validMobile } from '@/utils/my-validate' |
||||
import SendStatusIndex from './SendStatusIndex' |
||||
|
||||
export default { |
||||
name: 'SmsTaskEdit', |
||||
components: { SendStatusIndex }, |
||||
filters: { |
||||
statusFilter (status) { |
||||
const map = { |
||||
WAITING: 'danger', |
||||
SUCCESS: 'success', |
||||
FAIL: 'error' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
props: { |
||||
|
||||
}, |
||||
data () { |
||||
return { |
||||
dialog: { |
||||
isVisible: false |
||||
}, |
||||
type: 'add', |
||||
smsTask: this.initSmsTask(), |
||||
smsTemplateList: [], |
||||
receiverList: [], |
||||
receiverVisible: false, |
||||
receiver: '', |
||||
timing: false, |
||||
disabled: false, |
||||
smsTemplate: '', |
||||
content: '', |
||||
rules: { |
||||
topic: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' } |
||||
], |
||||
templateId: { required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
sendTime: { |
||||
validator: (rule, value, callback) => { |
||||
const vm = this |
||||
if (vm.timing) { |
||||
if (vm.smsTask.sendTime) { |
||||
callback() |
||||
} else { |
||||
callback('请选择发送日期') |
||||
} |
||||
} else { |
||||
callback() |
||||
} |
||||
}, trigger: 'change' |
||||
} |
||||
}, |
||||
pickerOptions: { |
||||
shortcuts: [{ |
||||
text: '一小时后', |
||||
onClick (picker) { |
||||
const date = new Date() |
||||
date.setTime(date.getTime() + 3600 * 1000 * 1) |
||||
picker.$emit('pick', date) |
||||
} |
||||
}, { |
||||
text: '明天', |
||||
onClick (picker) { |
||||
const date = new Date() |
||||
date.setTime(date.getTime() + 3600 * 1000 * 24) |
||||
picker.$emit('pick', date) |
||||
} |
||||
}, { |
||||
text: '一周后', |
||||
onClick (picker) { |
||||
const date = new Date() |
||||
date.setTime(date.getTime() + 3600 * 1000 * 24 * 7) |
||||
picker.$emit('pick', date) |
||||
} |
||||
}] |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
|
||||
}, |
||||
watch: { |
||||
$route () { |
||||
if (this.$route.path === '/sms/manage/edit') { |
||||
this.initSmsTemplateList() |
||||
this.loadSendStatus() |
||||
} |
||||
} |
||||
}, |
||||
mounted () { |
||||
// 在vue的mount阶段执行的函数都是顺序执行,不会阻塞的,所以如果希望mount阶段的函数也是阻塞的,需要额外写一个async函数,然后把需要同步执行的函数写到里面,然后在mount阶段调用这个额外写的函数 |
||||
this.initSmsTemplateList() |
||||
this.loadSendStatus() |
||||
}, |
||||
methods: { |
||||
loadSendStatus () { |
||||
const type = this.$route.query.type |
||||
const id = this.$route.query.id |
||||
if (type === 'view') { |
||||
this.$refs.statusList.setTaskId(id) |
||||
} |
||||
}, |
||||
async loadSmsTask () { |
||||
const type = this.$route.query.type |
||||
const id = this.$route.query.id |
||||
this.type = type |
||||
if (type) { // 切换到别的页面时,无需重置表单 |
||||
// this.smsTask = this.initSmsTask() |
||||
this.reset() |
||||
} |
||||
if (type === 'view') { |
||||
this.disabled = true |
||||
} else { |
||||
this.disabled = false |
||||
} |
||||
|
||||
if (id) { |
||||
await smsTaskApi.get(id) |
||||
.then(response => { |
||||
const res = response.data |
||||
this.smsTask = { ...this.smsTask, ...res.data } |
||||
if (type !== 'edit') { |
||||
this.smsTask.id = '' |
||||
} |
||||
this.changeTemplate(this.smsTask.templateId) |
||||
this.receiverList = this.smsTask.receiver.split(",") |
||||
|
||||
if (this.smsTask.templateParams) { |
||||
this.smsTask.templateParam = JSON.parse(this.smsTask.templateParams) |
||||
} |
||||
this.smsTask.content = res.data.content |
||||
console.log('查询') |
||||
if (this.smsTask.sendTime) { |
||||
this.timing = true |
||||
} else { |
||||
this.timing = false |
||||
} |
||||
|
||||
this.smsTemplate = this.smsTemplateList.find(item => item.id === this.smsTask.templateId) |
||||
}) |
||||
} |
||||
}, |
||||
changeTemplate (id) { |
||||
const vm = this |
||||
// vm.preSearch() |
||||
if (id) { |
||||
// 遍历模板添加文本框 |
||||
for (const item of vm.smsTemplateList) { |
||||
if (item.id === id) { |
||||
let templateParam = {} |
||||
if (typeof (item.templateParams) === 'string') { |
||||
templateParam = JSON.parse(item.templateParams) |
||||
} else { |
||||
templateParam = item.templateParams |
||||
} |
||||
|
||||
for (const prop in templateParam) { |
||||
templateParam[prop] = '' |
||||
} |
||||
vm.smsTemplate = item |
||||
if (vm.type !== 'view') { |
||||
console.log('赋值') |
||||
vm.smsTask.templateParam = templateParam |
||||
// vm.smsTask.content = item.content |
||||
this.content = item.content |
||||
} |
||||
break |
||||
} |
||||
} |
||||
vm.changeContent() |
||||
} |
||||
}, |
||||
// 模板文本框输入内容 |
||||
templateCode (val, key) { |
||||
const vm = this |
||||
vm.smsTask.templateParam[key] = val |
||||
vm.changeContent() |
||||
}, |
||||
// 短信内容处理 |
||||
changeContent () { |
||||
const vm = this |
||||
if (!vm.smsTemplate) { |
||||
return |
||||
} |
||||
const type = vm.smsTemplate.providerType.code |
||||
let content = vm.smsTemplate.content |
||||
|
||||
for (const key in vm.smsTask.templateParam) { |
||||
let strs = '' |
||||
if (type == "TENCENT") { |
||||
strs = '{' + key + '}' |
||||
} else { |
||||
strs = '${' + key + '}' |
||||
} |
||||
if (vm.smsTask.templateParam[key]) { |
||||
content = content.replace(strs, vm.smsTask.templateParam[key]) |
||||
} |
||||
} |
||||
if (vm.type !== 'view') { |
||||
console.log('赋值') |
||||
vm.smsTask.content = content |
||||
} |
||||
}, |
||||
async initSmsTemplateList () { |
||||
await smsTemplateApi.page({ current: 1, size: 10000, model: {}}) |
||||
.then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.smsTemplateList = res.data.records |
||||
} |
||||
}) |
||||
await this.loadSmsTask() // 顺序不能变 |
||||
}, |
||||
initSmsTask () { |
||||
return { |
||||
templateId: '', |
||||
receiver: '', |
||||
topic: '', |
||||
templateParam: {}, |
||||
sendTime: null, |
||||
content: '', |
||||
draft: false, |
||||
status: { |
||||
code: '', |
||||
desc: '' |
||||
} |
||||
} |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.smsTask = this.initSmsTask() |
||||
this.receiverList = [] |
||||
}, |
||||
submitForm (draft) { |
||||
const vm = this |
||||
if (vm.smsTask.templateParam && Object.keys(vm.smsTask.templateParam).length > 0) { |
||||
let flag = false |
||||
for (const key in vm.smsTask.templateParam) { |
||||
if (!vm.smsTask.templateParam[key]) { |
||||
flag = true |
||||
break |
||||
} |
||||
} |
||||
if (flag) { |
||||
vm.$message({ |
||||
message: '发送内容不能为空', |
||||
type: 'error' |
||||
}) |
||||
return |
||||
} |
||||
} else { |
||||
vm.$message({ |
||||
message: '发送内容不能为空', |
||||
type: 'error' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit(draft) |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit (draft) { |
||||
const vm = this |
||||
vm.smsTask.draft = draft |
||||
vm.smsTask.receiver = vm.receiverList.join(',') |
||||
if (!vm.timing) { |
||||
vm.smsTask.sendTime = null |
||||
} |
||||
if (vm.type === 'edit') { |
||||
vm.update() |
||||
} else { |
||||
vm.save() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
vm.disabled = true |
||||
smsTaskApi.save(vm.smsTask) |
||||
.then((response) => { |
||||
vm.disabled = false |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.reset() |
||||
vm.$router.push('/sms/manage') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
const vm = this |
||||
vm.disabled = true |
||||
smsTaskApi.update(vm.smsTask) |
||||
.then((response) => { |
||||
vm.disabled = false |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.reset() |
||||
vm.$router.push('/sms/manage') |
||||
} |
||||
}) |
||||
}, |
||||
handleClose (tag) { |
||||
this.receiverList.splice(this.receiverList.indexOf(tag), 1) |
||||
}, |
||||
showInput () { |
||||
this.receiverVisible = true |
||||
this.$nextTick(() => { |
||||
this.$refs.saveTagInput.$refs.input.focus() |
||||
}) |
||||
}, |
||||
handleInputConfirm () { |
||||
const vm = this |
||||
// 正则校验 |
||||
const inputValue = vm.receiver |
||||
if (inputValue) { |
||||
if (!validMobile(inputValue)) { |
||||
this.$message({ |
||||
message: '该手机号不合法', |
||||
type: 'error' |
||||
}) |
||||
vm.$refs.saveTagInput.focus() |
||||
return |
||||
} |
||||
|
||||
if (this.receiverList.indexOf(inputValue) === -1) { |
||||
vm.receiverList.push(inputValue) |
||||
vm.receiverVisible = false |
||||
vm.receiver = '' |
||||
} else { |
||||
this.$message({ |
||||
message: '该账号已经存在', |
||||
type: 'error' |
||||
}) |
||||
vm.$refs.saveTagInput.focus() |
||||
} |
||||
} else { |
||||
this.receiverVisible = false |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.el-tag { |
||||
margin-right: 10px; |
||||
} |
||||
.button-new-tag { |
||||
margin-left: 10px; |
||||
height: 32px; |
||||
line-height: 30px; |
||||
padding-top: 0; |
||||
padding-bottom: 0; |
||||
} |
||||
.input-new-tag { |
||||
width: 120px; |
||||
vertical-align: bottom; |
||||
} |
||||
.message { |
||||
border: 1px solid #ddd; |
||||
padding-bottom: 10px; |
||||
} |
||||
aside { |
||||
margin-top: 10px; |
||||
margin-bottom: 0; |
||||
} |
||||
.tips { |
||||
border: 1px solid #ddd; |
||||
margin-left: 18px; |
||||
} |
||||
.tips p { |
||||
text-indent: 20px; |
||||
padding: 0; |
||||
margin: 0px; |
||||
} |
||||
.article { |
||||
font-size: 12px; |
||||
height: auto; |
||||
} |
||||
</style> |
@ -0,0 +1,431 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.templateId" :placeholder="$t('table.smsTask.templateId')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.topic" :placeholder="$t('table.smsTask.topic')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.content" :placeholder="$t('table.smsTask.content')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
<router-link :to="{path:'/sms/manage/edit',query: {type: 'add'}}"> |
||||
<el-button v-has-permission="['sms:manage:add']" class="filter-item" plain type="danger"> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
</router-link> |
||||
<el-dropdown v-has-any-permission="['sms:manage:delete','sms:manage:export']" class="filter-item" trigger="click"> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['sms:manage:delete']" @click.native="batchDelete">{{ $t('table.delete') |
||||
}} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:manage:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:manage:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:manage:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.smsTask.templateId')" :show-overflow-tooltip="true" align="center" |
||||
prop="templateId" width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.templateId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.smsTask.receiver')" :show-overflow-tooltip="true" align="center" |
||||
prop="receiver" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.receiver }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTask.topic')" :show-overflow-tooltip="true" align="center" width="100px"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.topic }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTask.content')" :show-overflow-tooltip="true" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.content }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" :filters="statusFilters" :label="$t('table.smsTask.status')" |
||||
:show-overflow-tooltip="true" class-name="status-col" column-key="status" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span v-if="scope.row.sendTime"> |
||||
<el-tooltip :content="'发送时间: '+ scope.row.sendTime" class="item" effect="dark" placement="top"> |
||||
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status.desc }}</el-tag> |
||||
</el-tooltip> |
||||
</span> |
||||
<span v-else> |
||||
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status.desc }}</el-tag> |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="[{ text: $t('common.yes'), value: 'true' }, { text: $t('common.no'), value: 'false' }]" |
||||
:label="$t('table.smsTask.draft')" |
||||
align="center" |
||||
column-key="draft" |
||||
prop="draft" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span> |
||||
<el-tag slot :type="scope.row.draft?'danger':'success'">{{ scope.row.draft ? '是' : '否' }}</el-tag> |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" align="center" sortable="custom" |
||||
prop="createTime" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" align="center" column-key="operation" |
||||
class-name="small-padding fixed-width" width="100px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i |
||||
v-hasPermission="['sms:manage:view']" class="el-icon-view table-operation" style="color: #2db7f5;" |
||||
@click="view(row)" |
||||
></i> |
||||
<i |
||||
v-show="row.draft" v-hasPermission="['sms:manage:update']" class="el-icon-edit table-operation" |
||||
style="color: #2db7f5;" @click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['sms:manage:add']" class="el-icon-copy-document table-operation" style="color: #909399;" |
||||
@click="copy(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['sms:manage:delete']" class="el-icon-delete table-operation" style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link |
||||
v-has-no-permission="['sms:manage:update','sms:manage:delete','sms:manage:add','sms:manage:view']" |
||||
class="no-perm" |
||||
> |
||||
{{ $t('tips.noPermission') }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import smsTaskApi from '@/api/SmsTask.js' |
||||
import { convertEnum } from '@/utils/utils' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile, initMsgsEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'StationManage', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, FileImport }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
WAITING: 'danger', |
||||
SUCCESS: 'success', |
||||
FAIL: 'error' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/msgs/smsTask/import` |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({}), |
||||
selection: [], |
||||
// 以下已修改 |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { |
||||
TaskStatus: {} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
statusFilters() { |
||||
return convertEnum(this.enums.TaskStatus) |
||||
} |
||||
}, |
||||
watch: { |
||||
'$route'(to) { |
||||
if (to.path === '/sms/manage') { |
||||
this.fetch() |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
initMsgsEnums(['TaskStatus'], this.enums) |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
smsTaskApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
smsTaskApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const ids = [] |
||||
this.selection.forEach((u) => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
smsTaskApi.delete({ 'ids': ids }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
copy(row) { |
||||
this.$router.push({ |
||||
path: '/sms/manage/edit', |
||||
query: { |
||||
id: row.id, |
||||
type: 'copy' |
||||
} |
||||
}) |
||||
}, |
||||
view(row) { |
||||
this.$router.push({ |
||||
path: '/sms/manage/edit', |
||||
query: { |
||||
id: row.id, |
||||
type: 'view' |
||||
} |
||||
}) |
||||
}, |
||||
edit(row) { |
||||
this.$router.push({ |
||||
path: '/sms/manage/edit', |
||||
query: { |
||||
id: row.id, |
||||
type: 'edit' |
||||
} |
||||
}) |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
smsTaskApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,249 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.receiver" :placeholder="$t('table.smsSendStatus.receiver')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input |
||||
v-model="queryParams.model.bizId" :placeholder="$t('table.smsSendStatus.bizId')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-input v-model="queryParams.model.ext" :placeholder="$t('table.smsSendStatus.ext')" class="filter-item search-item" /> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.smsSendStatus.receiver')" :show-overflow-tooltip="true" align="center" |
||||
prop="receiver" width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.receiver }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="sendStatusFilters" |
||||
:label="$t('table.smsSendStatus.sendStatus')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
column-key="sendStatus" |
||||
prop="sendStatus" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.sendStatus.desc }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
:label="$t('table.smsSendStatus.bizId')" :show-overflow-tooltip="true" align="center" |
||||
prop="bizId" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.bizId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.smsSendStatus.ext')" :show-overflow-tooltip="true" align="center" |
||||
prop="ext" |
||||
width="150px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.ext }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.smsSendStatus.code')" :show-overflow-tooltip="true" align="center" |
||||
prop="code" |
||||
width="120px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.code }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsSendStatus.message')" :show-overflow-tooltip="true" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.message }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsSendStatus.fee')" align="center" width="80px"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.fee }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" align="center" prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" @pagination="fetch" |
||||
/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import smsSendStatusApi from '@/api/SmsSendStatus.js' |
||||
import { convertEnum } from '@/utils/utils' |
||||
import { initMsgsEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'SmsSendStatusManage', |
||||
components: { Pagination }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: 'danger', |
||||
true: 'success' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: { taskId: 0 } |
||||
}), |
||||
selection: [], |
||||
// 以下已修改 |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { SendStatus: {}} |
||||
|
||||
} |
||||
}, |
||||
computed: { |
||||
sendStatusFilters() { |
||||
return convertEnum(this.enums.SendStatus) |
||||
}, |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
// this.close() |
||||
// this.reset() |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
initMsgsEnums('SendStatus', this.enums) |
||||
}, |
||||
methods: { |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
setTaskId(taskId) { |
||||
this.queryParams.model.taskId = taskId |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
const taskId = this.queryParams.model.taskId |
||||
this.queryParams = initQueryParams({ |
||||
model: { taskId: taskId } |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
smsSendStatusApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,238 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" :close-on-press-escape="true" :title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" :width="width" top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" :model="smsTemplate" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.smsTemplate.providerType')" prop="providerType"> |
||||
<el-select v-model="smsTemplate.providerType.code" placeholder style="width:100%" value> |
||||
<el-option v-for="(item, key, index) in enums.ProviderType" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.appId')" prop="appId"> |
||||
<el-input v-model="smsTemplate.appId" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.appSecret')" prop="appSecret"> |
||||
<el-input v-model="smsTemplate.appSecret" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.url')" prop="url"> |
||||
<el-input v-model="smsTemplate.url" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.customCode')" prop="customCode"> |
||||
<el-input v-model="smsTemplate.customCode" :disabled="type === 'edit'" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.name')" prop="name"> |
||||
<el-input v-model="smsTemplate.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.content')" prop="content"> |
||||
<el-input v-model="smsTemplate.content" /> |
||||
<aside> |
||||
百度云:使用 ${xx} 作为占位符 |
||||
<br /> |
||||
阿里云:使用 ${xx} 作为占位符 |
||||
<br /> |
||||
腾讯云:使用 {xx} 作为占位符 |
||||
</aside> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.templateCode')" prop="templateCode"> |
||||
<el-input v-model="smsTemplate.templateCode" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.signName')" prop="signName"> |
||||
<el-input v-model="smsTemplate.signName" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.smsTemplate.templateDescribe')" prop="templateDescribe"> |
||||
<el-input v-model="smsTemplate.templateDescribe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ $t('common.cancel') }}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import smsTemplateApi from '@/api/SmsTemplate.js' |
||||
|
||||
export default { |
||||
name: 'SmsTemplateEdit', |
||||
components: {}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'add' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
smsTemplate: this.initSmsTemplate(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
enums: { |
||||
ProviderType: {} |
||||
}, |
||||
rules: { |
||||
providerType: [{ required: true, message: this.$t('rules.require'), trigger: 'change' }], |
||||
appId: [{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' }], |
||||
appSecret: [{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range4to10'), trigger: 'blur' }], |
||||
customCode: [ |
||||
{ min: 0, max: 20, message: this.$t('rules.range4to10'), trigger: 'blur' }, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
if (this.type === 'add' && value.trim() !== '') { |
||||
smsTemplateApi.check(value) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.data) { |
||||
callback('自定义编码重复') |
||||
} else { |
||||
callback() |
||||
} |
||||
}) |
||||
} else { |
||||
callback() |
||||
} |
||||
}, trigger: 'blur' |
||||
} |
||||
], |
||||
content: { required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
templateCode: { required: true, message: this.$t('rules.require'), trigger: 'blur' } |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title () { |
||||
return this.type === 'add' ? this.$t('common.add') : this.$t('common.edit') |
||||
} |
||||
}, |
||||
watch: { |
||||
|
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initSmsTemplate () { |
||||
return { |
||||
id: '', |
||||
providerType: { code: '' }, |
||||
appId: '', |
||||
appSecret: '', |
||||
url: '', |
||||
customCode: '', |
||||
name: '', |
||||
content: '', |
||||
templateParams: '', |
||||
templateCode: '', |
||||
signName: '', |
||||
templateDescribe: '' |
||||
} |
||||
}, |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return '90%' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '45%' |
||||
} else { |
||||
return '800px' |
||||
} |
||||
}, |
||||
loadListOptions ({ callback }) { |
||||
callback() |
||||
}, |
||||
setSmsTemplate (val = {}) { |
||||
const vm = this |
||||
if (val['row']) { |
||||
vm.smsTemplate = { ...val['row'] } |
||||
} |
||||
vm.enums = val['enums'] |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
}, |
||||
reset () { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.smsTemplate = this.initSmsTemplate() |
||||
}, |
||||
submitForm () { |
||||
const vm = this |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit () { |
||||
const vm = this |
||||
if (vm.type === 'add') { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save () { |
||||
const vm = this |
||||
smsTemplateApi.save(this.smsTemplate) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
vm.$emit('success') |
||||
} |
||||
}) |
||||
}, |
||||
update () { |
||||
smsTemplateApi.update(this.smsTemplate) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
this.$emit('success') |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
aside { |
||||
margin-top: 10px; |
||||
margin-bottom: 0; |
||||
} |
||||
</style> |
@ -0,0 +1,401 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="queryParams.model.appId" :placeholder="$t('table.smsTemplate.appId')" size="small" class="filter-item search-item" /> |
||||
<el-input v-model="queryParams.model.customCode" :placeholder="$t('table.smsTemplate.customCode')" size="small" class="filter-item search-item" /> |
||||
<el-input v-model="queryParams.model.name" :placeholder="$t('table.smsTemplate.name')" size="small" class="filter-item search-item" /> |
||||
<el-input v-model="queryParams.model.templateCode" :placeholder="$t('table.smsTemplate.templateCode')" size="small" class="filter-item search-item" /> |
||||
<el-input v-model="queryParams.model.signName" :placeholder="$t('table.smsTemplate.signName')" size="small" class="filter-item search-item" /> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
size="small" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button |
||||
size="small" class="filter-item" plain |
||||
type="primary" |
||||
@click="search" |
||||
>{{ $t('table.search') }}</el-button> |
||||
<el-button |
||||
size="small" class="filter-item" plain |
||||
type="warning" |
||||
@click="reset" |
||||
>{{ $t('table.reset') }}</el-button> |
||||
<el-button |
||||
v-has-permission="['sms:template:add']" size="small" class="filter-item" |
||||
plain |
||||
type="danger" @click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown v-has-any-permission="['sms:template:delete','sms:template:export']" class="filter-item" trigger="click"> |
||||
<el-button size="small"> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['sms:template:delete']" @click.native="batchDelete">{{ $t('table.delete') }}</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:template:export']" @click.native="exportExcel">{{ $t('table.export') }}</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:template:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['sms:template:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" /> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="providerTypeFilters" |
||||
column-key="providerType" |
||||
:label="$t('table.smsTemplate.providerType')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="providerType" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.providerType.desc }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.appId')" :show-overflow-tooltip="true" align="center" prop="appId"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.appId }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.appSecret')" :show-overflow-tooltip="true" align="center" prop="appSecret"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.appSecret }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.smsTemplate.name')" :show-overflow-tooltip="true" align="center" |
||||
prop="name" |
||||
width="150px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.customCode')" :show-overflow-tooltip="true" align="center" prop="customCode"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.customCode }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.templateCode')" align="center" width="150px"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.templateCode }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.signName')" align="center" width="150px"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.signName }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('table.smsTemplate.templateDescribe')" align="center" width="150px"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.templateDescribe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" align="center" prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" align="center" column-key="operation" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{row}"> |
||||
<i v-hasPermission="['sms:template:update']" class="el-icon-edit table-operation" style="color: #2db7f5;" @click="edit(row)"></i> |
||||
<i v-hasPermission="['sms:template:delete']" class="el-icon-delete table-operation" style="color: #f50;" @click="singleDelete(row)"></i> |
||||
<el-link v-has-no-permission="['sms:template:update','sms:template:delete']" class="no-perm">{{ $t('tips.noPermission') }}</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total>0" :limit.sync="queryParams.size" :page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<sms-template-edit |
||||
ref="edit" :dialog-visible="dialog.isVisible" :type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import SmsTemplateEdit from './Edit' |
||||
import smsTemplateApi from '@/api/SmsTemplate.js' |
||||
import { convertEnum } from '@/utils/utils' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile, initDicts, initMsgsEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'SmsTemplateManage', |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, SmsTemplateEdit, FileImport }, |
||||
filters: { |
||||
statusFilter (status) { |
||||
const map = { |
||||
false: 'danger', |
||||
true: 'success' |
||||
} |
||||
return map[status] || 'success' |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: 'add' |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/msgs/smsTemplate/import` |
||||
}, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: {} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { |
||||
ProviderType: {} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
providerTypeFilters () { |
||||
return convertEnum(this.enums.ProviderType) |
||||
} |
||||
}, |
||||
mounted () { |
||||
initMsgsEnums(['ProviderType'], this.enums) |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
editClose () { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess () { |
||||
this.search() |
||||
}, |
||||
onSelectChange (selection) { |
||||
this.selection = selection |
||||
}, |
||||
search () { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset () { |
||||
this.queryParams = initQueryParams({ |
||||
model: {} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
smsTemplateApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
smsTemplateApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete (row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete () { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t('tips.noDataSelected'), |
||||
type: 'warning' |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t('tips.confirmDelete'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
const ids = [] |
||||
this.selection.forEach((u) => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}).catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections () { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete (ids) { |
||||
smsTemplateApi.delete({ ids: ids }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add () { |
||||
this.dialog.type = 'add' |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setSmsTemplate({ enums: this.enums }) |
||||
}, |
||||
edit (row) { |
||||
this.$refs.edit.setSmsTemplate({ row, enums: this.enums }) |
||||
this.dialog.type = 'edit' |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch (params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
smsTemplateApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
@ -0,0 +1,343 @@
|
||||
<template> |
||||
<div class="org"> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="label" :placeholder="$t('table.org.label')" class="filter-item search-item" /> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t('table.search') }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t('table.reset') }}</el-button> |
||||
<el-button |
||||
v-has-permission="['org:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
>{{ |
||||
$t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['org:delete','org:export', 'org:import']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t('table.more') }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['org:delete']" @click.native="deleteOrg">{{ $t('table.delete') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['org:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['org:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['org:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
<el-tree |
||||
ref="orgTree" :check-strictly="true" :data="orgTree" |
||||
:filter-node-method="filterNode" |
||||
default-expand-all highlight-current node-key="id" |
||||
show-checkbox @node-click="nodeClick" |
||||
/> |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<el-card class="box-card"> |
||||
<div slot="header" class="clearfix"> |
||||
<span>{{ org.id === '' ? this.$t('common.add') : this.$t('common.edit') }}</span> |
||||
</div> |
||||
<div> |
||||
<el-form |
||||
ref="form" :model="org" :rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.org.parentId')" prop="parentId"> |
||||
<el-tooltip :content="$t('tips.topId')" class="item" effect="dark" placement="top-start"> |
||||
<el-input v-model="org.parentId" readonly /> |
||||
</el-tooltip> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.org.label')" prop="label"> |
||||
<el-input v-model="org.label" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.org.abbreviation')" prop="abbreviation"> |
||||
<el-input v-model="org.abbreviation" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.org.describe')" prop="describe"> |
||||
<el-input v-model="org.describe" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.org.status')" prop="status"> |
||||
<el-radio-group v-model="org.status"> |
||||
<el-radio :label="true">{{ $t('common.status.valid') }}</el-radio> |
||||
<el-radio :label="false">{{ $t('common.status.invalid') }}</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.org.sortValue')" prop="sortValue"> |
||||
<el-input-number v-model="org.sortValue" :max="100" :min="0" @change="handleNumChange" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</el-card> |
||||
<el-card class="box-card" style="margin-top: -2rem;"> |
||||
<el-row> |
||||
<el-col :span="24" style="text-align: right"> |
||||
<el-button plain type="primary" @click="submit">{{ org.id === '' ? this.$t('common.add') : |
||||
this.$t('common.edit') }} |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import orgApi from '@/api/Org.js' |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import { downloadFile } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: 'OrgManager', |
||||
directives: { elDragDialog }, |
||||
components: { FileImport }, |
||||
data() { |
||||
return { |
||||
label: '', |
||||
orgTree: [], |
||||
org: this.initOrg(), |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/org/import` |
||||
}, |
||||
rules: { |
||||
label: [ |
||||
{ required: true, message: this.$t('rules.require'), trigger: 'blur' }, |
||||
{ min: 1, max: 255, message: this.$t('rules.range3to10'), trigger: 'blur' } |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.initOrgTree() |
||||
}, |
||||
methods: { |
||||
initOrg() { |
||||
return { |
||||
id: '', |
||||
abbreviation: '', |
||||
label: '', |
||||
parentId: 0, |
||||
status: true, |
||||
describe: '', |
||||
sortValue: 0 |
||||
} |
||||
}, |
||||
initOrgTree() { |
||||
orgApi.allTree({}) |
||||
.then((response) => { |
||||
const res = response.data |
||||
this.orgTree = res.data |
||||
}) |
||||
}, |
||||
exportExcelPreview() { |
||||
const queryParams = { |
||||
model: {}, |
||||
map: { |
||||
fileName: '导出组织数据' |
||||
}, |
||||
size: 10000 |
||||
} |
||||
orgApi.preview(queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
const queryParams = { |
||||
model: {}, |
||||
map: { |
||||
fileName: '导出组织数据' |
||||
}, |
||||
size: 10000 |
||||
} |
||||
orgApi.export(queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.initOrgTree() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
handleNumChange(val) { |
||||
this.org.sortValue = val |
||||
}, |
||||
filterNode(value, data) { |
||||
if (!value) return true |
||||
return data.label.indexOf(value) !== -1 |
||||
}, |
||||
nodeClick(data) { |
||||
this.org = { ...data } |
||||
this.$refs.form.clearValidate() |
||||
}, |
||||
add() { |
||||
this.resetForm() |
||||
const checked = this.$refs.orgTree.getCheckedKeys() |
||||
if (checked.length > 1) { |
||||
this.$message({ |
||||
message: this.$t('tips.onlyChooseOne'), |
||||
type: 'warning' |
||||
}) |
||||
} else if (checked.length > 0) { |
||||
this.org.parentId = checked[0] |
||||
} else { |
||||
this.org.parentId = 0 |
||||
} |
||||
}, |
||||
deleteOrg() { |
||||
const checked = this.$refs.orgTree.getCheckedKeys() |
||||
if (checked.length === 0) { |
||||
this.$message({ |
||||
message: this.$t('tips.noNodeSelected'), |
||||
type: 'warning' |
||||
}) |
||||
} else { |
||||
this.$confirm(this.$t('tips.confirmDeleteNode'), this.$t('common.tips'), { |
||||
confirmButtonText: this.$t('common.confirm'), |
||||
cancelButtonText: this.$t('common.cancel'), |
||||
type: 'warning' |
||||
}).then(() => { |
||||
orgApi.delete({ ids: checked }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.deleteSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}).catch(() => { |
||||
this.$refs.orgTree.setCheckedKeys([]) |
||||
}) |
||||
} |
||||
}, |
||||
search() { |
||||
this.$refs.orgTree.filter(this.label) |
||||
}, |
||||
reset() { |
||||
this.initOrgTree() |
||||
this.label = '' |
||||
this.resetForm() |
||||
}, |
||||
submit() { |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
if (this.org.id) { |
||||
this.update() |
||||
} else { |
||||
this.save() |
||||
} |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
save() { |
||||
orgApi.save({ ...this.org }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.createSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
|
||||
this.reset() |
||||
}) |
||||
}, |
||||
update() { |
||||
orgApi.update({ ...this.org }) |
||||
.then((response) => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t('tips.updateSuccess'), |
||||
type: 'success' |
||||
}) |
||||
} |
||||
this.reset() |
||||
}) |
||||
}, |
||||
resetForm() { |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.org = this.initOrg() |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.org { |
||||
margin: 10px; |
||||
|
||||
.app-container { |
||||
margin: 0 0 10px 0 !important; |
||||
} |
||||
} |
||||
|
||||
.el-card.is-always-shadow { |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.el-card { |
||||
border-radius: 0; |
||||
border: none; |
||||
|
||||
.el-card__header { |
||||
padding: 10px 20px !important; |
||||
border-bottom: 1px solid #f1f1f1 !important; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,232 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
:title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" |
||||
:model="station" |
||||
:rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.station.name')" prop="name"> |
||||
<el-input v-model="station.name" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.station.orgId')" prop="orgId"> |
||||
<treeselect |
||||
v-model="station.org.key" |
||||
:clear-value-text="$t('common.clear')" |
||||
:load-options="loadListOptions" |
||||
:multiple="false" |
||||
:options="orgList" |
||||
:searchable="true" |
||||
placeholder=" " |
||||
style="width:100%" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.station.status')" prop="status"> |
||||
<el-radio-group v-model="station.status"> |
||||
<el-radio :label="true">{{ $t("common.status.valid") }}</el-radio> |
||||
<el-radio :label="false">{{ $t("common.status.invalid") }}</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.station.describe')" prop="describe"> |
||||
<el-input v-model="station.describe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ |
||||
$t("common.cancel") |
||||
}}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ |
||||
$t("common.confirm") |
||||
}}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import Treeselect from "@riophae/vue-treeselect" |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
||||
import stationApi from "@/api/Station.js" |
||||
|
||||
export default { |
||||
name: "StationEdit", |
||||
components: { Treeselect }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: "add" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
remoteStationLoading: false, |
||||
station: this.initStation(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
orgList: [], |
||||
stationList: [], |
||||
rules: { |
||||
name: [ |
||||
{ |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
min: 1, |
||||
max: 255, |
||||
message: this.$t("rules.range4to10"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
if (!this.station.id) { |
||||
// this.$get(`system/user/check/${value}`).then((r) => { |
||||
// if (!r.data) { |
||||
// callback(this.$t('rules.usernameExist')) |
||||
// } else { |
||||
// callback() |
||||
// } |
||||
// }) |
||||
} else { |
||||
// callback() |
||||
} |
||||
callback() |
||||
}, |
||||
trigger: "blur" |
||||
} |
||||
], |
||||
status: { |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.type === "add" |
||||
? this.$t("common.add") |
||||
: this.$t("common.edit") |
||||
} |
||||
}, |
||||
watch: {}, |
||||
mounted() { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initStation() { |
||||
return { |
||||
id: "", |
||||
name: "", |
||||
org: { |
||||
key: null, |
||||
data: null |
||||
}, |
||||
status: true, |
||||
describe: "" |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return "90%" |
||||
} else if (this.screenWidth < 1400) { |
||||
return "45%" |
||||
} else { |
||||
return "800px" |
||||
} |
||||
}, |
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
setStation(val, orgs) { |
||||
const vm = this |
||||
vm.orgList = orgs |
||||
if (val) { |
||||
vm.station = { ...val } |
||||
} |
||||
}, |
||||
close() { |
||||
this.$emit("close") |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.station = this.initStation() |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
if (vm.type === "add") { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save() { |
||||
const vm = this |
||||
stationApi.save(this.station).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t("tips.createSuccess"), |
||||
type: "success" |
||||
}) |
||||
vm.$emit("success") |
||||
} |
||||
}) |
||||
}, |
||||
update() { |
||||
stationApi.update(this.station).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t("tips.updateSuccess"), |
||||
type: "success" |
||||
}) |
||||
this.$emit("success") |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,453 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.name" :placeholder="$t('table.station.name')" |
||||
class="filter-item search-item" |
||||
/> |
||||
<treeselect |
||||
v-model="queryParams.model.orgId.key" |
||||
:clear-value-text="$t('common.clear')" |
||||
:load-options="loadListOptions" |
||||
:multiple="false" |
||||
:options="orgList" |
||||
:placeholder="$t('table.station.orgId')" |
||||
:searchable="true" |
||||
class="filter-item search-item" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search">{{ $t("table.search") }}</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset">{{ $t("table.reset") }}</el-button> |
||||
<el-button |
||||
v-has-permission="['station:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="['station:delete','station:export','station:import']" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['station:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['station:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['station:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['station:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.station.name')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.station.describe')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="describe" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.describe }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.station.orgId')" |
||||
align="center" |
||||
:show-overflow-tooltip="true" |
||||
width="180px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span> |
||||
{{ scope.row.org.data ? scope.row.org.data.label : scope.row.org.key }} |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
column-key="status" |
||||
:filters="[ |
||||
{ text: $t('common.status.valid'), value: true }, |
||||
{ text: $t('common.status.invalid'), value: false } |
||||
]" |
||||
:label="$t('table.station.status')" |
||||
class-name="status-col" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<el-tag :type="row.status | statusFilter">{{ |
||||
row.status ? $t("common.status.valid") : $t("common.status.invalid") |
||||
}} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
align="center" |
||||
column-key="operation" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['station:update']" |
||||
class="el-icon-edit table-operation" |
||||
style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['station:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link |
||||
v-has-no-permission="['station:update', 'station:delete']" |
||||
class="no-perm" |
||||
>{{ $t("tips.noPermission") }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<station-edit |
||||
ref="edit" |
||||
:dialog-visible="dialog.isVisible" |
||||
:type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" |
||||
:type="fileImport.type" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Treeselect from "@riophae/vue-treeselect" |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import Pagination from "@/components/Pagination" |
||||
import StationEdit from "./Edit" |
||||
import stationApi from "@/api/Station.js" |
||||
import orgApi from "@/api/Org.js" |
||||
import { downloadFile, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "StationManage", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, StationEdit, Treeselect, FileImport }, |
||||
filters: { |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: "danger", |
||||
true: "success" |
||||
} |
||||
return map[status] || "success" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/station/import` |
||||
}, |
||||
tableKey: 0, |
||||
orgList: [], |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
orgId: { |
||||
key: null |
||||
} |
||||
} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
} |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: { |
||||
$route() { |
||||
if (this.$route.path === "/user/station") { |
||||
this.initOrg() |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.initOrg() |
||||
this.fetch() |
||||
}, |
||||
methods: { |
||||
initOrg() { |
||||
orgApi |
||||
.allTree({ status: true }) |
||||
.then(response => { |
||||
const res = response.data |
||||
this.orgList = res.data |
||||
}) |
||||
.catch(() => { |
||||
this.$message({ |
||||
message: this.$t("tips.getDataFail"), |
||||
type: "error" |
||||
}) |
||||
}) |
||||
}, |
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { |
||||
orgId: { key: null } |
||||
} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出岗位数据' |
||||
stationApi.preview({ ...this.queryParams, ...{ size: 10000 }}).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出岗位数据' |
||||
stationApi.export({ ...this.queryParams, ...{ size: 10000 }}).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
this.delete(ids) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
stationApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = "add" |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setStation(false, this.orgList) |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setStation(row, this.orgList) |
||||
this.dialog.type = "edit" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
stationApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
|
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,427 @@
|
||||
<template> |
||||
<el-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
:title="title" |
||||
:type="type" |
||||
:visible.sync="isVisible" |
||||
:width="width" |
||||
top="50px" |
||||
> |
||||
<el-form |
||||
ref="form" |
||||
:model="user" |
||||
:rules="rules" |
||||
label-position="right" |
||||
label-width="100px" |
||||
> |
||||
<el-form-item :label="$t('table.user.account')" prop="account"> |
||||
<el-input |
||||
v-model="user.account" |
||||
:readonly="type === 'add' ? false : 'readonly'" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.name')" prop="name"> |
||||
<el-input v-model="user.name" /> |
||||
</el-form-item> |
||||
<el-form-item |
||||
v-show="type === 'add'" |
||||
:label="$t('table.user.password')" |
||||
prop="password" |
||||
> |
||||
<el-tooltip |
||||
:content="$t('tips.defaultPassword')" |
||||
class="item" |
||||
effect="dark" |
||||
placement="top-start" |
||||
> |
||||
<el-input type="password" value="123456" /> |
||||
</el-tooltip> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.avatar')" prop="avatar"> |
||||
<imgUpload |
||||
ref="imgFileRef" |
||||
:accept="accept" |
||||
:accept-size="2 * 1024 * 1024" |
||||
:auto-upload="true" |
||||
:data="user.avatar" |
||||
:file-list="imgFileList" |
||||
:show-file-list="false" |
||||
list-type="picture-card" |
||||
@setId="setIdAndSubmit" |
||||
> |
||||
<i class="el-icon-plus"></i> |
||||
</imgUpload> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.orgId')" prop="orgId"> |
||||
<treeselect |
||||
v-model="user.org.key" |
||||
:clear-value-text="$t('common.clear')" |
||||
:load-options="loadListOptions" |
||||
:multiple="false" |
||||
:options="orgList" |
||||
:searchable="true" |
||||
placeholder=" " |
||||
style="width:100%" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.stationId')" prop="stationId"> |
||||
<el-select |
||||
v-model="user.station.key" |
||||
:loading="remoteStationLoading" |
||||
:multiple="false" |
||||
filterable |
||||
placeholder="请输入关键词" |
||||
> |
||||
<el-option |
||||
v-for="item in stationList" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:value="item.id" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.email')" prop="email"> |
||||
<el-input v-model="user.email" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.mobile')" prop="mobile"> |
||||
<el-input v-model="user.mobile" /> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.sex')" prop="sex"> |
||||
<el-select v-model="user.sex.code" placeholder style="width:100%" value> |
||||
<el-option |
||||
v-for="(item, key, index) in enums.Sex" :key="index" :label="item" |
||||
:value="key" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.nation')" prop="nation"> |
||||
<el-select v-model="user.nation.key" style="width:100%" :placeholder="$t('table.user.nation')" value> |
||||
<el-option v-for="(item, key, index) in dicts.NATION" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.education')" prop="education"> |
||||
<el-select v-model="user.education.key" style="width:100%" :placeholder="$t('table.user.education')" value> |
||||
<el-option v-for="(item, key, index) in dicts.EDUCATION" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.positionStatus')" prop="positionStatus"> |
||||
<el-select v-model="user.positionStatus.key" style="width:100%" :placeholder="$t('table.user.positionStatus')" value> |
||||
<el-option v-for="(item, key, index) in dicts.POSITION_STATUS" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.status')" prop="status"> |
||||
<el-radio-group v-model="user.status"> |
||||
<el-radio :label="true">{{ $t("common.status.valid") }}</el-radio> |
||||
<el-radio :label="false">{{ $t("common.status.invalid") }}</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
<el-form-item :label="$t('table.user.workDescribe')" prop="workDescribe"> |
||||
<el-input v-model="user.workDescribe" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button plain type="warning" @click="isVisible = false">{{ |
||||
$t("common.cancel") |
||||
}}</el-button> |
||||
<el-button plain type="primary" @click="submitForm">{{ |
||||
$t("common.confirm") |
||||
}}</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</template> |
||||
<script> |
||||
import { validMobile } from "@/utils/my-validate" |
||||
import Treeselect from "@riophae/vue-treeselect" |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
||||
import imgUpload from "@/components/ceres/imgUpload" |
||||
import userApi from "@/api/User.js" |
||||
import stationApi from "@/api/Station.js" |
||||
|
||||
export default { |
||||
name: "UserEdit", |
||||
components: { Treeselect, imgUpload }, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: "add" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
accept: "image/jpeg, image/gif, image/png", |
||||
remoteStationLoading: false, |
||||
user: this.initUser(), |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
orgList: [], |
||||
stationList: [], |
||||
imgFileList: [], |
||||
imgFileData: { |
||||
bizId: "", |
||||
bizType: "USER_AVATAR" |
||||
}, |
||||
// 图片文件总数 |
||||
imgFileTotal: 0, |
||||
// 上传成功数 |
||||
successNum: 0, |
||||
enums: { |
||||
Sex: {} |
||||
}, |
||||
dicts: { |
||||
NATION: {}, |
||||
POSITION_STATUS: {}, |
||||
EDUCATION: {} |
||||
}, |
||||
rules: { |
||||
account: [ |
||||
{ |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
min: 1, |
||||
max: 255, |
||||
message: this.$t("rules.range4to10"), |
||||
trigger: "blur" |
||||
}, |
||||
{ |
||||
validator: (rule, value, callback) => { |
||||
if (!this.user.id) { |
||||
callback() |
||||
} else { |
||||
callback() |
||||
} |
||||
}, |
||||
trigger: "blur" |
||||
} |
||||
], |
||||
email: { |
||||
type: "email", |
||||
message: this.$t("rules.email"), |
||||
trigger: "blur" |
||||
}, |
||||
mobile: { |
||||
validator: (rule, value, callback) => { |
||||
if (value !== "" && !validMobile(value)) { |
||||
callback(this.$t("rules.mobile")) |
||||
} else { |
||||
callback() |
||||
} |
||||
}, |
||||
trigger: "blur" |
||||
}, |
||||
sex: { |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "change" |
||||
}, |
||||
status: { |
||||
required: true, |
||||
message: this.$t("rules.require"), |
||||
trigger: "blur" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get() { |
||||
return this.dialogVisible |
||||
}, |
||||
set() { |
||||
this.close() |
||||
this.reset() |
||||
} |
||||
}, |
||||
title() { |
||||
return this.type === "add" |
||||
? this.$t("common.add") |
||||
: this.$t("common.edit") |
||||
} |
||||
}, |
||||
watch: { |
||||
// 监听deptId |
||||
"user.org.key": "orgSelect" |
||||
}, |
||||
mounted() { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
myAvatar(avatar) { |
||||
if (!avatar) { |
||||
return require(`@/assets/avatar/default.jpg`) |
||||
} else { |
||||
if (avatar.startsWith("http://") || avatar.startsWith("https://")) { |
||||
return avatar |
||||
} else { |
||||
return require(`@/assets/avatar/${avatar}`) |
||||
} |
||||
} |
||||
}, |
||||
initUser() { |
||||
return { |
||||
id: "", |
||||
account: "", |
||||
name: "", |
||||
org: { |
||||
key: null |
||||
}, |
||||
station: { key: null }, |
||||
email: "", |
||||
mobile: "", |
||||
sex: { |
||||
code: "N" |
||||
}, |
||||
nation: { |
||||
key: "" |
||||
}, |
||||
education: { |
||||
key: "" |
||||
}, |
||||
positionStatus: { |
||||
key: "" |
||||
}, |
||||
status: true, |
||||
avatar: "", |
||||
workDescribe: "", |
||||
password: "123456" |
||||
} |
||||
}, |
||||
initWidth() { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 991) { |
||||
return "90%" |
||||
} else if (this.screenWidth < 1400) { |
||||
return "45%" |
||||
} else { |
||||
return "800px" |
||||
} |
||||
}, |
||||
|
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
orgSelect(node) { |
||||
this.loadStation(node) |
||||
}, |
||||
loadStation(orgId) { |
||||
this.user.station.key = null |
||||
if (orgId) { |
||||
stationApi.page({ |
||||
size: 10000, |
||||
model: { orgId: { key: orgId }, status: true } |
||||
}).then(response => { |
||||
const res = response.data |
||||
this.stationList = res.data.records |
||||
}) |
||||
} else { |
||||
this.stationList = [] |
||||
} |
||||
}, |
||||
setIdAndSubmit(bizId, url) { |
||||
const vm = this |
||||
vm.successNum += 1 |
||||
vm.imgFileData.bizId = bizId |
||||
vm.user.avatar = url |
||||
vm.user.id = bizId |
||||
|
||||
if (vm.successNum === vm.imgFileTotal) { |
||||
vm.$store.state.hasLoading = false |
||||
} |
||||
}, |
||||
setUser(val, orgs, dicts, enums) { |
||||
const vm = this |
||||
if (val) { |
||||
vm.user = { ...val } |
||||
} |
||||
vm.dicts = dicts |
||||
vm.enums = enums |
||||
|
||||
vm.orgList = orgs |
||||
vm.imgFileData.bizId = vm.user["id"] |
||||
vm.$nextTick(() => { |
||||
vm.$refs.imgFileRef.init({ |
||||
bizId: vm.user["id"], |
||||
bizType: vm.imgFileData.bizType, |
||||
imageUrl: vm.myAvatar(vm.user["avatar"]), |
||||
isSingle: true, |
||||
isDetail: false |
||||
}) |
||||
}) |
||||
}, |
||||
close() { |
||||
this.$emit("close") |
||||
}, |
||||
reset() { |
||||
// 先清除校验,再清除表单,不然有奇怪的bug |
||||
this.$refs.form.clearValidate() |
||||
this.$refs.form.resetFields() |
||||
this.user = this.initUser() |
||||
this.imgFileData.bizId = "" |
||||
this.$refs.imgFileRef.init({ |
||||
bizId: "", |
||||
bizType: "", |
||||
imageUrl: "", |
||||
isSingle: true, |
||||
isDetail: false |
||||
}) |
||||
}, |
||||
submitForm() { |
||||
const vm = this |
||||
this.$refs.form.validate(valid => { |
||||
if (valid) { |
||||
vm.editSubmit() |
||||
} else { |
||||
return false |
||||
} |
||||
}) |
||||
}, |
||||
editSubmit() { |
||||
const vm = this |
||||
if (vm.type === "add") { |
||||
vm.save() |
||||
} else { |
||||
vm.update() |
||||
} |
||||
}, |
||||
save() { |
||||
const vm = this |
||||
userApi.save(this.user).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
vm.isVisible = false |
||||
vm.$message({ |
||||
message: vm.$t("tips.createSuccess"), |
||||
type: "success" |
||||
}) |
||||
vm.$emit("success") |
||||
} |
||||
}) |
||||
}, |
||||
update() { |
||||
userApi.update(this.user).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.isVisible = false |
||||
this.$message({ |
||||
message: this.$t("tips.updateSuccess"), |
||||
type: "success" |
||||
}) |
||||
this.$emit("success") |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,705 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input |
||||
v-model="queryParams.model.account" |
||||
:placeholder="$t('table.user.account')" class="filter-item search-item" clearable |
||||
/> |
||||
<el-select |
||||
v-model="queryParams.model.nation.key" clearable :placeholder="$t('table.user.nation')" |
||||
class="filter-item search-item" |
||||
> |
||||
<el-option v-for="(item, key, index) in dicts.NATION" :key="index" :label="item" :value="key" /> |
||||
</el-select> |
||||
<treeselect |
||||
v-model="queryParams.model.org.key" |
||||
clearable |
||||
:clear-value-text="$t('common.clear')" |
||||
:load-options="loadListOptions" |
||||
:multiple="false" |
||||
:options="orgList" |
||||
:searchable="true" |
||||
class="filter-item search-item" |
||||
placeholder="组织" |
||||
/> |
||||
<el-date-picker |
||||
v-model="queryParams.timeRange" |
||||
:range-separator="null" |
||||
class="filter-item search-item date-range-item" |
||||
end-placeholder="结束日期" |
||||
format="yyyy-MM-dd HH:mm:ss" |
||||
start-placeholder="开始日期" |
||||
type="daterange" |
||||
value-format="yyyy-MM-dd HH:mm:ss" |
||||
/> |
||||
<el-button class="filter-item" plain type="primary" @click="search"> |
||||
{{ $t("table.search") }} |
||||
</el-button> |
||||
<el-button class="filter-item" plain type="warning" @click="reset"> |
||||
{{ $t("table.reset") }} |
||||
</el-button> |
||||
<el-button |
||||
v-has-permission="['user:add']" class="filter-item" plain |
||||
type="danger" |
||||
@click="add" |
||||
> |
||||
{{ $t("table.add") }} |
||||
</el-button> |
||||
<el-dropdown |
||||
v-has-any-permission="[ |
||||
'user:delete', |
||||
'user:rest', |
||||
'user:export', |
||||
'user:import', |
||||
]" class="filter-item" |
||||
trigger="click" |
||||
> |
||||
<el-button> |
||||
{{ $t("table.more") }} |
||||
<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item v-has-permission="['user:delete']" @click.native="batchDelete"> |
||||
{{ $t("table.delete") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['user:reset']" @click.native="resetPassword"> |
||||
{{ $t("table.resetPassword") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['user:export']" @click.native="exportExcel"> |
||||
{{ $t("table.export") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['user:export']" @click.native="exportExcelPreview"> |
||||
{{ $t("table.exportPreview") }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-has-permission="['user:import']" @click.native="importExcel"> |
||||
{{ $t("table.import") }} |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
|
||||
<el-table |
||||
:key="tableKey" |
||||
ref="table" |
||||
v-loading="loading" |
||||
:data="tableData.records" |
||||
border |
||||
fit |
||||
row-key="id" style="width: 100%;" @filter-change="filterChange" |
||||
@selection-change="onSelectChange" |
||||
@sort-change="sortChange" |
||||
@cell-click="cellClick" |
||||
> |
||||
<el-table-column align="center" type="selection" width="40px" :reserve-selection="true" /> |
||||
<el-table-column |
||||
:label="$t('table.user.avatar')" |
||||
align="center" |
||||
prop="avatar" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-avatar |
||||
:key="scope.row.avatar" |
||||
:src="myAvatar(scope.row.avatar)" |
||||
fit="fill" |
||||
> |
||||
<el-avatar>{{ scope.row.name | userAvatarFilter }}</el-avatar> |
||||
</el-avatar> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.account')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="account" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.account }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.name')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
prop="name" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.name }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="sexList" |
||||
column-key="sex.code" |
||||
:label="$t('table.user.sex')" |
||||
class-name="status-col" |
||||
prop="sex.desc" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<el-tag :type="row.sex ? row.sex['code'] :'' | sexFilter">{{ row.sex ? row.sex.desc : '' }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.email')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.email }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.nation')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.nation['data'] ? scope.row.nation['data'] : scope.row.nation['key'] }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="educationList" |
||||
column-key="education.key" |
||||
:label="$t('table.user.education')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="80px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.education['data'] ? scope.row.education['data'] : scope.row.education['key'] }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
:filters="positionStatusList" |
||||
column-key="positionStatus.key" |
||||
:label="$t('table.user.positionStatus')" |
||||
:show-overflow-tooltip="true" |
||||
align="center" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.positionStatus['data'] ? scope.row.positionStatus['data'] : scope.row.positionStatus['key'] }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.orgId')" |
||||
align="center" |
||||
:show-overflow-tooltip="true" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ |
||||
scope.row.org["data"] ? scope.row.org.data.label : scope.row.org.key |
||||
}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.stationId')" |
||||
align="center" |
||||
:show-overflow-tooltip="true" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ |
||||
scope.row.station["data"] |
||||
? scope.row.station.data |
||||
: scope.row.station.key |
||||
}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:filter-multiple="false" |
||||
column-key="status" |
||||
:filters="[ |
||||
{ text: $t('common.status.valid'), value: true }, |
||||
{ text: $t('common.status.invalid'), value: false } |
||||
]" |
||||
:label="$t('table.user.status')" |
||||
class-name="status-col" |
||||
width="70px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<el-tag :type="row.status | statusFilter">{{ |
||||
row.status ? $t("common.status.valid") : $t("common.status.invalid") |
||||
}} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.user.createTime')" |
||||
align="center" |
||||
prop="createTime" |
||||
sortable="custom" |
||||
width="170px" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.createTime }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
:label="$t('table.operation')" |
||||
align="center" |
||||
column-key="operation" |
||||
class-name="small-padding fixed-width" |
||||
width="100px" |
||||
> |
||||
<template slot-scope="{ row }"> |
||||
<i |
||||
v-hasPermission="['user:view']" |
||||
class="el-icon-view table-operation" |
||||
style="color: #87d068;" |
||||
@click="view(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['user:update']" |
||||
class="el-icon-edit table-operation" |
||||
style="color: #2db7f5;" |
||||
@click="edit(row)" |
||||
></i> |
||||
<i |
||||
v-hasPermission="['user:delete']" |
||||
class="el-icon-delete table-operation" |
||||
style="color: #f50;" |
||||
@click="singleDelete(row)" |
||||
></i> |
||||
<el-link |
||||
v-has-no-permission="['user:view', 'user:update', 'user:delete']" |
||||
class="no-perm" |
||||
>{{ $t("tips.noPermission") }} |
||||
</el-link> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="queryParams.size" |
||||
:page.sync="queryParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="fetch" |
||||
/> |
||||
<user-edit |
||||
ref="edit" |
||||
:dialog-visible="dialog.isVisible" |
||||
:type="dialog.type" |
||||
@close="editClose" |
||||
@success="editSuccess" |
||||
/> |
||||
<user-view |
||||
ref="view" |
||||
:dialog-visible="userViewVisible" |
||||
@close="viewClose" |
||||
/> |
||||
<file-import |
||||
ref="import" |
||||
:dialog-visible="fileImport.isVisible" :type="fileImport.type" |
||||
:export-error-url="fileImport.exportErrorUrl" :action="fileImport.action" |
||||
accept=".xls,.xlsx" |
||||
@close="importClose" |
||||
@success="importSuccess" |
||||
/> |
||||
<el-dialog |
||||
v-el-drag-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="true" |
||||
title="预览" |
||||
width="80%" |
||||
top="50px" |
||||
:visible.sync="preview.isVisible" |
||||
> |
||||
<el-scrollbar> |
||||
<div v-html="preview.context"></div> |
||||
</el-scrollbar> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from "@/components/Pagination" |
||||
import Treeselect from "@riophae/vue-treeselect" |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
||||
import elDragDialog from '@/directive/el-drag-dialog' |
||||
import FileImport from "@/components/ceres/Import" |
||||
import UserEdit from "./Edit" |
||||
import UserView from "./View" |
||||
import userApi from "@/api/User.js" |
||||
import orgApi from "@/api/Org.js" |
||||
import { convertEnum } from '@/utils/utils' |
||||
import { downloadFile, initDicts, initEnums, initQueryParams } from '@/utils/commons' |
||||
|
||||
export default { |
||||
name: "UserManage", |
||||
directives: { elDragDialog }, |
||||
components: { Pagination, UserEdit, UserView, Treeselect, FileImport }, |
||||
filters: { |
||||
userAvatarFilter(name) { |
||||
return name.charAt(0) |
||||
}, |
||||
sexFilter(status) { |
||||
const map = { |
||||
W: "success", |
||||
M: "danger", |
||||
N: "info" |
||||
} |
||||
return map[status] || "info" |
||||
}, |
||||
statusFilter(status) { |
||||
const map = { |
||||
false: "danger", |
||||
true: "success" |
||||
} |
||||
return map[status] || "success" |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
orgList: [], |
||||
dialog: { |
||||
isVisible: false, |
||||
type: "add" |
||||
}, |
||||
preview: { |
||||
isVisible: false, |
||||
context: '' |
||||
}, |
||||
fileImport: { |
||||
isVisible: false, |
||||
type: "import", |
||||
action: `${process.env.VUE_APP_BASE_API}/authority/user/import`, |
||||
exportErrorUrl: `/authority/user/exportError` |
||||
}, |
||||
userViewVisible: false, |
||||
tableKey: 0, |
||||
queryParams: initQueryParams({ |
||||
model: { |
||||
nation: { |
||||
key: '' |
||||
}, |
||||
education: { |
||||
key: '' |
||||
}, |
||||
positionStatus: { |
||||
key: '' |
||||
}, |
||||
org: { |
||||
key: null |
||||
}, |
||||
station: { |
||||
key: null |
||||
}, |
||||
sex: { |
||||
code: '' |
||||
} |
||||
} |
||||
}), |
||||
selection: [], |
||||
loading: false, |
||||
tableData: { |
||||
total: 0 |
||||
}, |
||||
enums: { |
||||
Sex: {} |
||||
}, |
||||
dicts: { |
||||
NATION: {}, |
||||
POSITION_STATUS: {}, |
||||
EDUCATION: {} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
currentUser() { |
||||
return this.$store.state.account.user |
||||
}, |
||||
sexList() { |
||||
return convertEnum(this.enums.Sex) |
||||
}, |
||||
nationList() { |
||||
return convertEnum(this.dicts.NATION) |
||||
}, |
||||
educationList() { |
||||
return convertEnum(this.dicts.EDUCATION) |
||||
}, |
||||
positionStatusList() { |
||||
return convertEnum(this.dicts.POSITION_STATUS) |
||||
} |
||||
}, |
||||
watch: { |
||||
$route() { |
||||
if (this.$route.path === "/user/user") { |
||||
this.initOrg() |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
initEnums('Sex', this.enums) |
||||
initDicts(['NATION', 'POSITION_STATUS', 'EDUCATION'], this.dicts) |
||||
this.fetch() |
||||
this.initOrg() |
||||
}, |
||||
methods: { |
||||
initOrg() { |
||||
orgApi.allTree({ status: true }).then(response => { |
||||
const res = response.data |
||||
this.orgList = res.data |
||||
}) |
||||
}, |
||||
myAvatar(avatar) { |
||||
if (!avatar) { |
||||
return require(`@/assets/avatar/default.jpg`) |
||||
} else { |
||||
if (avatar.startsWith("http://") || avatar.startsWith("https://")) { |
||||
return avatar |
||||
} else { |
||||
return require(`@/assets/avatar/${avatar}`) |
||||
} |
||||
} |
||||
}, |
||||
viewClose() { |
||||
this.userViewVisible = false |
||||
}, |
||||
editClose() { |
||||
this.dialog.isVisible = false |
||||
}, |
||||
editSuccess() { |
||||
this.search() |
||||
}, |
||||
onSelectChange(selection) { |
||||
this.selection = selection |
||||
}, |
||||
loadListOptions({ callback }) { |
||||
callback() |
||||
}, |
||||
search() { |
||||
this.fetch({ |
||||
...this.queryParams |
||||
}) |
||||
}, |
||||
reset() { |
||||
this.queryParams = initQueryParams({ |
||||
model: { |
||||
nation: { |
||||
key: '' |
||||
}, |
||||
education: { |
||||
key: '' |
||||
}, |
||||
positionStatus: { |
||||
key: '' |
||||
}, |
||||
org: { |
||||
key: null |
||||
}, |
||||
station: { |
||||
key: null |
||||
}, |
||||
sex: { |
||||
code: '' |
||||
} |
||||
} |
||||
}) |
||||
this.$refs.table.clearSort() |
||||
this.$refs.table.clearFilter() |
||||
this.search() |
||||
}, |
||||
exportExcelPreview() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
userApi.preview(this.queryParams).then(response => { |
||||
const res = response.data |
||||
this.preview.isVisible = true |
||||
this.preview.context = res.data |
||||
}) |
||||
}, |
||||
exportExcel() { |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
this.queryParams.map.fileName = '导出用户数据' |
||||
userApi.export(this.queryParams).then(response => { |
||||
downloadFile(response) |
||||
}) |
||||
}, |
||||
importExcel() { |
||||
this.fileImport.type = "upload" |
||||
this.fileImport.isVisible = true |
||||
this.$refs.import.setModel(false) |
||||
}, |
||||
importSuccess() { |
||||
this.search() |
||||
}, |
||||
importClose() { |
||||
this.fileImport.isVisible = false |
||||
}, |
||||
resetPassword() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
this.$confirm( |
||||
this.$t("tips.confirmRestPassword"), |
||||
this.$t("common.tips"), |
||||
{ |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
} |
||||
) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
ids.push(u.id) |
||||
}) |
||||
userApi.reset({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.resetPasswordSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.clearSelections() |
||||
}) |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
singleDelete(row) { |
||||
this.$refs.table.clearSelection() |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
this.batchDelete() |
||||
}, |
||||
batchDelete() { |
||||
if (!this.selection.length) { |
||||
this.$message({ |
||||
message: this.$t("tips.noDataSelected"), |
||||
type: "warning" |
||||
}) |
||||
return |
||||
} |
||||
let contain = false |
||||
this.$confirm(this.$t("tips.confirmDelete"), this.$t("common.tips"), { |
||||
confirmButtonText: this.$t("common.confirm"), |
||||
cancelButtonText: this.$t("common.cancel"), |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
const ids = [] |
||||
this.selection.forEach(u => { |
||||
if (u.id === this.currentUser.id) { |
||||
contain = true |
||||
return |
||||
} |
||||
ids.push(u.id) |
||||
}) |
||||
if (contain) { |
||||
this.$message({ |
||||
message: this.$t("tips.containCurrentUser"), |
||||
type: "warning" |
||||
}) |
||||
this.clearSelections() |
||||
} else { |
||||
this.delete(ids) |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
this.clearSelections() |
||||
}) |
||||
}, |
||||
clearSelections() { |
||||
this.$refs.table.clearSelection() |
||||
}, |
||||
delete(ids) { |
||||
userApi.delete({ ids: ids }).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.$message({ |
||||
message: this.$t("tips.deleteSuccess"), |
||||
type: "success" |
||||
}) |
||||
} |
||||
this.search() |
||||
}) |
||||
}, |
||||
add() { |
||||
this.dialog.type = "add" |
||||
this.dialog.isVisible = true |
||||
this.$refs.edit.setUser(false, this.orgList, this.dicts, this.enums) |
||||
}, |
||||
view(row) { |
||||
this.$refs.view.setUser(row, this.orgList, this.dicts, this.enums) |
||||
this.userViewVisible = true |
||||
}, |
||||
edit(row) { |
||||
this.$refs.edit.setUser(row, this.orgList, this.dicts, this.enums) |
||||
this.dialog.type = "edit" |
||||
this.dialog.isVisible = true |
||||
}, |
||||
fetch(params = {}) { |
||||
this.loading = true |
||||
if (this.queryParams.timeRange) { |
||||
this.queryParams.map.createTime_st = this.queryParams.timeRange[0] |
||||
this.queryParams.map.createTime_ed = this.queryParams.timeRange[1] |
||||
} |
||||
|
||||
this.queryParams.current = params.current ? params.current : this.queryParams.current |
||||
this.queryParams.size = params.size ? params.size : this.queryParams.size |
||||
|
||||
userApi.page(this.queryParams).then(response => { |
||||
const res = response.data |
||||
if (res.isSuccess) { |
||||
this.tableData = res.data |
||||
} |
||||
}).finally(() => this.loading = false) |
||||
}, |
||||
sortChange(val) { |
||||
this.queryParams.sort = val.prop |
||||
this.queryParams.order = val.order |
||||
if (this.queryParams.sort) { |
||||
this.search() |
||||
} |
||||
}, |
||||
filterChange(filters) { |
||||
for (const key in filters) { |
||||
if (key.includes('.')) { |
||||
const val = {} |
||||
val[key.split('.')[1]] = filters[key][0] |
||||
this.queryParams.model[key.split('.')[0]] = val |
||||
} else { |
||||
this.queryParams.model[key] = filters[key][0] |
||||
} |
||||
} |
||||
this.search() |
||||
}, |
||||
cellClick (row, column) { |
||||
if (column['columnKey'] === "operation") { |
||||
return |
||||
} |
||||
let flag = false |
||||
this.selection.forEach((item) => { |
||||
if (item.id === row.id) { |
||||
flag = true |
||||
this.$refs.table.toggleRowSelection(row) |
||||
} |
||||
}) |
||||
if (!flag) { |
||||
this.$refs.table.toggleRowSelection(row, true) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,222 @@
|
||||
<template> |
||||
<el-dialog :title="$t('common.view')" :visible.sync="isVisible" :width="width" class="user-view"> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="24" :xs="24"> |
||||
<div class="img-wrapper"> |
||||
<el-avatar :key="user.avatar" :src="user.avatar" fit="fill"> |
||||
<el-avatar>{{ user.name | userAvatarFilter }}</el-avatar> |
||||
</el-avatar> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-user"></i> |
||||
<span>{{ $t('table.user.account') +':' }}</span> |
||||
{{ user.account }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-suitcase"></i> |
||||
<span>{{ $t('table.user.name') +':' }}</span> |
||||
{{ user.name }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-user"></i> |
||||
<span>{{ $t('table.user.email') +':' }}</span> |
||||
{{ user.email }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-suitcase"></i> |
||||
<span>{{ $t('table.user.mobile') +':' }}</span> |
||||
{{ user.mobile }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-trophy"></i> |
||||
<span>{{ $t('table.user.orgId') +':' }}</span> |
||||
{{ user.orgId }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-phone-outline"></i> |
||||
<span>{{ $t('table.user.stationId') +':' }}</span> |
||||
{{ user.stationId }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-star-off"></i> |
||||
<span>{{ $t('table.user.sex') +':' }}</span> |
||||
{{ user.sex.desc }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-bangzhu"></i> |
||||
<span>{{ $t('table.user.status') +':' }}</span> |
||||
{{ user.status ? $t('common.status.valid') : $t('common.status.invalid') }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-time"></i> |
||||
<span>{{ $t('table.user.createTime') +':' }}</span> |
||||
{{ user.createTime }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-brush"></i> |
||||
<span>{{ $t('table.user.updateTime') +':' }}</span> |
||||
{{ user.updateTime }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-date"></i> |
||||
<span>{{ $t('table.user.lastLoginTime') +':' }}</span> |
||||
{{ user.lastLoginTime ? user.lastLoginTime: $t('tips.neverLogin') }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-date"></i> |
||||
<span>{{ $t('table.user.passwordExpireTime') +':' }}</span> |
||||
{{ user.passwordExpireTime }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-date"></i> |
||||
<span>{{ $t('table.user.passwordErrorLastTime') +':' }}</span> |
||||
{{ user.passwordErrorLastTime }} |
||||
</div> |
||||
</el-col> |
||||
<el-col :sm="12" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-date"></i> |
||||
<span>{{ $t('table.user.passwordErrorNum') +':' }}</span> |
||||
{{ user.passwordErrorNum }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="10"> |
||||
<el-col :sm="24" :xs="24"> |
||||
<div class="view-item"> |
||||
<i class="el-icon-document"></i> |
||||
<span>{{ $t('table.user.workDescribe') +':' }}</span> |
||||
{{ user.workDescribe ? user.workDescribe: $t('tips.nothing') }} |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: 'UserView', |
||||
filters: { |
||||
userAvatarFilter (name) { |
||||
return name ? name.charAt(0) : '无' |
||||
} |
||||
}, |
||||
props: { |
||||
dialogVisible: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
screenWidth: 0, |
||||
width: this.initWidth(), |
||||
user: { |
||||
sex: { |
||||
desc: '' |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
isVisible: { |
||||
get () { |
||||
return this.dialogVisible |
||||
}, |
||||
set () { |
||||
this.close() |
||||
} |
||||
} |
||||
}, |
||||
mounted () { |
||||
window.onresize = () => { |
||||
return (() => { |
||||
this.width = this.initWidth() |
||||
})() |
||||
} |
||||
}, |
||||
methods: { |
||||
initWidth () { |
||||
this.screenWidth = document.body.clientWidth |
||||
if (this.screenWidth < 550) { |
||||
return '95%' |
||||
} else if (this.screenWidth < 990) { |
||||
return '580px' |
||||
} else if (this.screenWidth < 1400) { |
||||
return '600px' |
||||
} else { |
||||
return '650px' |
||||
} |
||||
}, |
||||
setUser (val) { |
||||
this.user = { ...val } |
||||
}, |
||||
close () { |
||||
this.$emit('close') |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.user-view { |
||||
.img-wrapper { |
||||
text-align: center; |
||||
margin-top: -1.5rem; |
||||
margin-bottom: 10px; |
||||
img { |
||||
width: 4rem; |
||||
border-radius: 50%; |
||||
} |
||||
} |
||||
.view-item { |
||||
margin: 7px; |
||||
i { |
||||
font-size: 0.97rem; |
||||
} |
||||
span { |
||||
margin-left: 5px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,235 @@
|
||||
<template> |
||||
<div class="overview_page"> |
||||
<div class="total_info"> |
||||
<ul> |
||||
<li v-for="(item,index) in totalList" :key="index"> |
||||
<p>{{ item.value }}</p> |
||||
<p> |
||||
{{ item.name }} |
||||
<i class="el-icon-warning-outline icon" :title="item.tips"></i> |
||||
</p> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="toolbar"> |
||||
<el-form |
||||
:inline="true" |
||||
:model="formParams" |
||||
> |
||||
<el-form-item label="商家名称"> |
||||
<el-input v-model="formParams.model.tenantName" size="mini" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="商家编码"> |
||||
<el-input v-model="formParams.model.tenantCode" size="mini" /> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button |
||||
type="primary" |
||||
size="mini" |
||||
@click="query" |
||||
> |
||||
查询 |
||||
</el-button> |
||||
<el-button |
||||
plain |
||||
size="mini" |
||||
@click="reset" |
||||
> |
||||
重置 |
||||
</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
<el-table |
||||
:data="tableData.records" |
||||
border |
||||
style="width: 100%" |
||||
> |
||||
<el-table-column |
||||
prop="tenantName" |
||||
label="商家名称" |
||||
/> |
||||
<el-table-column |
||||
prop="tenantCode" |
||||
label="商家编码" |
||||
/> |
||||
<el-table-column |
||||
:formatter="getPrice" |
||||
prop="incomeAmount" |
||||
label="营收总额" |
||||
/> |
||||
<el-table-column |
||||
:formatter="getPrice" |
||||
prop="freezesAmount" |
||||
label="冻结金额" |
||||
/> |
||||
<el-table-column |
||||
:formatter="getPrice" |
||||
prop="withdrawAmount" |
||||
label="已提金额" |
||||
/> |
||||
<el-table-column |
||||
:formatter="getPrice" |
||||
prop="refundAmount" |
||||
label="已退款金额" |
||||
/> |
||||
</el-table> |
||||
<pagination |
||||
v-show="tableData.total > 0" |
||||
:limit.sync="formParams.size" |
||||
:page.sync="formParams.current" |
||||
:total="Number(tableData.total)" |
||||
@pagination="query" |
||||
/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' |
||||
import Finance from '@/api/Finance' |
||||
export default { |
||||
components: { |
||||
Pagination |
||||
}, |
||||
data() { |
||||
return { |
||||
formParams: { |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": { |
||||
"canWithdrawAmount": 0, |
||||
"freezesAmount": 0, |
||||
"incomeAmount": 0, |
||||
"refundAmount": 0, |
||||
"tenantCode": "", |
||||
"tenantName": "", |
||||
"withdrawAmount": 0 |
||||
}, |
||||
"order": "descending", |
||||
"size": 10, |
||||
"sort": "id" |
||||
}, |
||||
totalList: [ |
||||
{ name: '营收总额', value: 0, field: 'incomeAmount', tips: '所有商家支付成功的订单总金额' }, |
||||
{ name: '冻结总金额', value: 0, field: 'freezesAmount', tips: '所有商家交易尚未完成仍在冻结中的金额' }, |
||||
{ name: '可提现金额', value: 0, field: 'canWithdrawAmount', tips: '所有商家可以提现但尚未提现的的金额' }, |
||||
{ name: '已提金额', value: 0, field: 'withdrawAmount', tips: '所有商家的售后订单中产生退款并退款成功的总金额' }, |
||||
{ name: '已退款金额', value: 0, field: 'refundAmount', tips: '' } |
||||
], |
||||
tableData: {} |
||||
} |
||||
}, |
||||
created() { |
||||
this.getDayList() |
||||
this.getSummary() |
||||
}, |
||||
methods: { |
||||
async getDayList() { |
||||
const res = await Finance.getDayList(this.formParams) |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
this.tableData = resData.data |
||||
} |
||||
}, |
||||
async getSummary() { |
||||
const res = await Finance.getSummary() |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
const o = resData.data |
||||
this.totalList.map(item => { |
||||
item.value = o[item.field] / 100 || 0 |
||||
}) |
||||
} |
||||
}, |
||||
query() { |
||||
this.getDayList() |
||||
}, |
||||
getPrice(item, row, value) { |
||||
return value / 100 |
||||
}, |
||||
reset() { |
||||
this.formParams = { |
||||
"current": 1, |
||||
"map": {}, |
||||
"model": { |
||||
"canWithdrawAmount": 0, |
||||
"freezesAmount": 0, |
||||
"incomeAmount": 0, |
||||
"refundAmount": 0, |
||||
"tenantCode": "", |
||||
"tenantName": "", |
||||
"withdrawAmount": 0 |
||||
}, |
||||
"order": "descending", |
||||
"size": 10, |
||||
"sort": "id" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.overview_page { |
||||
margin-top: 20px; |
||||
padding: 20px; |
||||
background-color: #fff; |
||||
height: calc(100% -20px); |
||||
.total_info { |
||||
border-bottom: 1px solid #E0E5EB; |
||||
margin-bottom: 20px; |
||||
ul { |
||||
overflow: hidden; |
||||
display: flex; |
||||
list-style: none; |
||||
li { |
||||
flex: 2.4; |
||||
text-align: center; |
||||
padding: 20px 0; |
||||
p { |
||||
margin: 0; |
||||
&:nth-child(1) { |
||||
font-weight: 600; |
||||
font-size: 30px; |
||||
color: #ffae11; |
||||
margin-bottom: 20px; |
||||
} |
||||
&:nth-child(2) { |
||||
font-size: 18px; |
||||
.icon { |
||||
&:hover { |
||||
cursor: pointer; |
||||
} |
||||
color: red; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .el-table { |
||||
th { |
||||
background: #EEF3FF; |
||||
color:#333333; |
||||
font-size:16px; |
||||
font-weight: 400; |
||||
border-color: #E0E5EB; |
||||
text-align: center; |
||||
} |
||||
td { |
||||
font-size: 14px; |
||||
text-align: center; |
||||
color: #666666; |
||||
} |
||||
|
||||
.cell { |
||||
text-align: center; |
||||
white-space: pre-line;/*保留换行符*/ |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,320 @@
|
||||
<template> |
||||
<div class="empower_page"> |
||||
<div class="top_btn"> |
||||
菜单赋权 |
||||
<el-button type="primary" class="save_btn" :loading="loading" @click="save">保存</el-button> |
||||
</div> |
||||
<div class="empower_content"> |
||||
<!-- <div class="item"> |
||||
<div class="top_box"> |
||||
平台菜单 |
||||
<el-select v-model="type" placeholder="请选择"> |
||||
<el-option |
||||
v-for="item in options" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</div> |
||||
<div class="menu_tree"> |
||||
<el-tree |
||||
ref="platFormTree" |
||||
:data="platFormMenu" |
||||
show-checkbox |
||||
default-expand-all |
||||
node-key="id" |
||||
highlight-current |
||||
:props="defaultProps" |
||||
/> |
||||
</div> |
||||
</div> --> |
||||
|
||||
<!-- <div class="item"> |
||||
<div class="btn_list"> |
||||
<p @click="empower"> |
||||
<img :src="right" alt="" /> |
||||
</p> |
||||
<p @click="recycleMenu"> |
||||
<img :src="left" alt="" /> |
||||
</p> |
||||
</div> |
||||
</div> --> |
||||
|
||||
<div class="item"> |
||||
<div class="top_box"> |
||||
<el-form inline label-width="100px"> |
||||
<el-form-item class="select_type"> |
||||
<el-select v-model="type" placeholder="请选择"> |
||||
<el-option |
||||
v-for="item in options" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item v-if="type" label="商家编号"> |
||||
<el-col :span="15"> |
||||
<el-input v-model="form.tenantCode" placeholder="请输入商家编号" /> |
||||
</el-col> |
||||
<el-col :span="6"> |
||||
<el-button @click="getSpecialMerchantMenu">搜索</el-button> |
||||
</el-col> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
<div class="menu_tree"> |
||||
<el-checkbox v-model="checked" @change="changeCheck">全选</el-checkbox> |
||||
<el-tree |
||||
ref="merchantTree" |
||||
:data="form.menuList" |
||||
show-checkbox |
||||
default-expand-all |
||||
node-key="id" |
||||
highlight-current |
||||
:props="defaultProps" |
||||
@check-change="checkChange" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Menu from '@/api/Menu' |
||||
export default { |
||||
data() { |
||||
return { |
||||
checked: false, |
||||
loading: false, |
||||
options: [ |
||||
{ label: '同步所有商家', value: 0 }, |
||||
{ label: '同步指定商家', value: 1 } |
||||
], |
||||
type: 0, |
||||
tenantCode: '', |
||||
defaultProps: { |
||||
children: 'children', |
||||
label: 'label' |
||||
}, |
||||
platFormMenu: [], |
||||
mechantMenu: [], |
||||
selected: [], |
||||
form: { |
||||
menuList: [], |
||||
tenantCode: null |
||||
}, |
||||
allKeys: [] |
||||
|
||||
} |
||||
}, |
||||
computed: { |
||||
left () { |
||||
return require('@/assets/menu-left.png') |
||||
}, |
||||
right () { |
||||
return require('@/assets/menu-right.png') |
||||
} |
||||
}, |
||||
created() { |
||||
// this.getPlatformMenu() |
||||
this.getAllMerchanMenu() |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
changeCheck(v) { |
||||
if (v) { |
||||
this.$refs.merchantTree.setCheckedKeys(this.allKeys) |
||||
} else { |
||||
this.$refs.merchantTree.setCheckedKeys([]) |
||||
} |
||||
}, |
||||
async getPlatformMenu() { |
||||
const res = await Menu.getPlatformMenu() |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
this.platFormMenu = resData.data |
||||
} |
||||
}, |
||||
async getAllMerchanMenu() { |
||||
const res = await Menu.getAllMerchanMenu() |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
const t = resData.data |
||||
this.changeTreeData(t) |
||||
this.form.menuList = t |
||||
this.getSelected(t) |
||||
this.$nextTick(() => { |
||||
this.setCheckedNodes() |
||||
}) |
||||
} |
||||
}, |
||||
changeTreeData(data) { |
||||
if (data && data.length) { |
||||
data.map(item => { |
||||
if (item.children && item.children.length && (item.children.findIndex(k => k.isSync === 0) > -1)) { |
||||
item.isSync = 0 |
||||
} |
||||
}) |
||||
} |
||||
}, |
||||
// 获取指定商家的菜单 |
||||
async getSpecialMerchantMenu() { |
||||
const res = await Menu.getSpecialMerchantMenu(this.form.tenantCode) |
||||
const resData = res.data |
||||
if (resData.code === 0) { |
||||
this.form.menuList = resData.data |
||||
} |
||||
}, |
||||
save() { |
||||
this.loading = true |
||||
Menu.saveMenu(this.form).then(res => { |
||||
this.loading = false |
||||
if (res.data.code === 0) { |
||||
this.$message.success('菜单同步成功') |
||||
} |
||||
}) |
||||
}, |
||||
getSelected(data) { |
||||
const t = [] |
||||
const arr = [] |
||||
if (data && data.length) { |
||||
data.forEach(item => { |
||||
if (item.isSync) { |
||||
t.push(item.id) |
||||
} |
||||
arr.push(item.id) |
||||
if (item.children && item.children.length) { |
||||
item.children.forEach(ob => { |
||||
if (ob.isSync) { |
||||
t.push(ob.id) |
||||
} |
||||
arr.push(ob.id) |
||||
}) |
||||
} |
||||
}) |
||||
} |
||||
this.selected = t |
||||
this.allKeys = arr |
||||
if (t.length === arr.length) { |
||||
this.checked = true |
||||
} |
||||
}, |
||||
setCheckedNodes() { |
||||
if (this.selected.length) { |
||||
this.$refs.merchantTree.setCheckedKeys(this.selected) |
||||
} |
||||
}, |
||||
checkChange(a, b, c, d) { |
||||
a.isSync = b ? 1 : 0 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='less' scoped> |
||||
.empower_page { |
||||
min-height: 500px; |
||||
margin-top:20px; |
||||
padding: 20px; |
||||
background-color: #ffffff; |
||||
|
||||
.top_btn { |
||||
height: 50px; |
||||
font-size: 20px; |
||||
line-height: 50px; |
||||
margin-bottom: 20px; |
||||
border-bottom: 1px #E0E5EB solid; |
||||
.save_btn { |
||||
float: right; |
||||
} |
||||
} |
||||
|
||||
.empower_content { |
||||
// overflow: hidden; |
||||
.item { |
||||
min-height: 700px; |
||||
// float: left; |
||||
box-sizing: border-box; |
||||
&:nth-child(1), &:nth-child(3) { |
||||
// width:calc(50% - 75px); |
||||
width: 50%; |
||||
margin: 20px auto; |
||||
background:rgba(255,255,255,1); |
||||
box-shadow:0px 0px 10px 0px rgba(51,51,51,0.15); |
||||
// border: 1px #E0E5EB solid; |
||||
border-radius:4px; |
||||
.top_box { |
||||
height: 60px; |
||||
line-height: 60px; |
||||
font-size: 18px; |
||||
border-radius: 4px 4px 0 0; |
||||
background-color: #F7F7F7; |
||||
padding: 0 10px; |
||||
} |
||||
.menu_tree { |
||||
padding: 0 20px; |
||||
} |
||||
} |
||||
|
||||
&:nth-child(2) { |
||||
width: 150px; |
||||
height: 100%; |
||||
position: relative; |
||||
.btn_list { |
||||
height: 150px; |
||||
width: 40px; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
margin-top: -75px; |
||||
margin-left: -20px; |
||||
p { |
||||
height: 60px; |
||||
text-align: center; |
||||
background-color: #EEEEEE; |
||||
border-radius:4px; |
||||
padding-top: 18px; |
||||
img { |
||||
width:24px; |
||||
height:24px; |
||||
} |
||||
&:hover { |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.select_type { |
||||
float: left; |
||||
} |
||||
|
||||
/deep/.el-form { |
||||
overflow: hidden; |
||||
} |
||||
|
||||
/deep/.el-form-item { |
||||
float: right; |
||||
} |
||||
|
||||
/deep/.select_type { |
||||
float: left; |
||||
} |
||||
/deep/.el-form-item__content { |
||||
line-height: 60px !important; |
||||
} |
||||
/deep/ label { |
||||
font-weight: 400; |
||||
} |
||||
/deep/.el-col-6 { |
||||
margin-left: 10px; |
||||
} |
||||
</style> |
Loading…
Reference in new issue