From 7c906b4acf785180132f91db5d70c3a29fa85cd3 Mon Sep 17 00:00:00 2001 From: 马宇豪 <978517621@qq.com> Date: 星期三, 21 六月 2023 09:39:13 +0800 Subject: [PATCH] 新增页面和配置,对接口 --- src/util/validate.js | 6 src/views/Admin/Report.vue | 72 + src/components/Home/QuickNavigation.vue | 119 +++ src/views/Admin/msgRecord.vue | 70 - config/env.production.js | 2 src/views/Admin/components/msgDetailMod.vue | 191 +++++ src/assets/style/themeColor.less | 1 src/components/Home/Review.vue | 84 ++ src/views/Admin/history.vue | 59 + src/util/AntDesign.js | 4 src/api/list.js | 9 src/views/Admin/notice.vue | 154 +++- config/env.development.js | 2 src/views/Admin/msgReview.vue | 69 + src/layout/menuSider.vue | 17 src/views/Admin/components/userMod.vue | 4 src/components/Home/Projecting.vue | 123 ++- src/views/Admin/callRecord.vue | 34 src/views/Admin/release.vue | 61 + src/util/request.js | 24 src/views/Admin/components/sameLevelMod.vue | 1 src/router/index.js | 8 /dev/null | 54 - src/views/Admin/components/msgEditMod.vue | 223 +++++- src/views/Admin/list.vue | 82 + src/layout/menu/index.js | 264 ++++++- src/views/Admin/HomeDefault.vue | 16 src/views/Admin/massSend.vue | 43 src/views/Admin/sameLevel.vue | 18 src/views/Admin/userManage.vue | 17 src/views/Admin/components/callListMod.vue | 21 src/views/Home.vue | 25 src/components/Home/Dynamic.vue | 65 + 33 files changed, 1,399 insertions(+), 543 deletions(-) diff --git a/config/env.development.js b/config/env.development.js index 5d13ab3..9441e3b 100644 --- a/config/env.development.js +++ b/config/env.development.js @@ -1,5 +1,5 @@ module.exports = { NODE_ENV: "development", baseUrl: 'http://192.168.0.38:8086', - // baseUrl: '121.239.169.30:33306', + // baseUrl: 'http://121.239.169.30:13001', } \ No newline at end of file diff --git a/config/env.production.js b/config/env.production.js index 07f4c05..1ee261b 100644 --- a/config/env.production.js +++ b/config/env.production.js @@ -1,4 +1,4 @@ module.exports = { NODE_ENV: "production", - baseUrl: '121.239.169.30:33306', + baseUrl: 'http://121.239.169.30:13001', } \ No newline at end of file diff --git a/src/api/list.js b/src/api/list.js index 806dd84..1b9fef7 100644 --- a/src/api/list.js +++ b/src/api/list.js @@ -62,5 +62,10 @@ }) } - - +// 删除文件 +export function deleteFile(id){ + return request({ + url: '/attachment/delete/' + id, + method: 'get' + }) +} \ No newline at end of file diff --git a/src/assets/style/themeColor.less b/src/assets/style/themeColor.less index a7a9ba5..f219243 100644 --- a/src/assets/style/themeColor.less +++ b/src/assets/style/themeColor.less @@ -1,6 +1,7 @@ @base: #1890ff; @link: #1890ff; @success: #52c41a; +@green: #87d068; @warning: #faad14; @danger: #f5222d; @blackText: rgba(0,0,0,.65); diff --git a/src/components/Home/Dynamic.vue b/src/components/Home/Dynamic.vue index e3784ed..7fc8b45 100644 --- a/src/components/Home/Dynamic.vue +++ b/src/components/Home/Dynamic.vue @@ -3,51 +3,60 @@ <a-list item-layout="horizontal" :data-source="lists"> <a-list-item slot="renderItem" slot-scope="item"> <a-list-item-meta - :description="item.created | filterTime" + :description="item.responseTime | filterTime" > - <a slot="title" href="#">{{ item.title }}</a> + <a slot="title" href="#" @click="openDetails(item.warnInfoId)">{{ item.publishingUnit }} 发布了 {{item.title}}</a> <a-avatar slot="avatar" - src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" + :src="userImg" /> </a-list-item-meta> </a-list-item> </a-list> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> </a-card> </template> <script> +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; +import {getResponseRecord} from "@/api/list"; + export default { name: "Dynamic", + components: { msgDetailMod }, data() { return { - lists: [ - { - title: "阿勒泰地区莽村 李有田 在 20230301大风红色预警提示 进行了“已安排部署”叫应。", - created: '2023-03-1 12:12:12' - }, - { - title: "李宏伟 在 20230301大风红色预警提示 进行了“已安排部署”叫应。", - created: '2023-03-12 12:12:12' - }, - { - title: "李宏伟 在 20230301大风红色预警提示 进行了“已安排部署”叫应。", - created: '2023-03-12 12:12:12' - }, - { - title: "李宏伟 在 20230301大风红色预警提示 进行了“已安排部署”叫应。", - created: '2023-03-12 12:12:12' - }, - { - title: "阿勒泰地区莽村 李有田 在 20230311大风红色预警工作通知 进行了“已安排部署”叫应。", - created: '2023-03-12 12:12:12' - }, - { - title: "木木 在 20230301大风红色预警提示 进行了“已安排部署”叫应。", - created: '2023-03-12 12:12:12' + search:{ + pageIndex: 1, + pageSize: 6, + searchParams:{ + emergType: null, + startTime: '', + endTime: '' } - ], + }, + lists: [], + userImg: require('@/assets/user.png') }; }, + created() { + this.getData() + }, + methods: { + async getData(){ + const t = this + const res = await getResponseRecord(this.search) + if(res.data.code == 100){ + t.lists = res.data.data + }else{ + this.$message.error(res.data.msg) + } + }, + openDetails(id){ + const t = this + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true + } + } }; </script> diff --git a/src/components/Home/Projecting.vue b/src/components/Home/Projecting.vue index 84dba18..6f4557b 100644 --- a/src/components/Home/Projecting.vue +++ b/src/components/Home/Projecting.vue @@ -1,69 +1,89 @@ <template> <a-card title="近期通知" class="projecting"> - <a slot="extra" href="#" style="color: rgb(19, 194, 194)">全部通知</a> - <a-card-grid style="width:33.33%;text-align:center" v-for="(item, index) in lists" :key="'projecting' + index"> + <a slot="extra" href="release" class="tapBtn">全部通知</a> + <a-card-grid style="width:33.33%;text-align:center" v-for="(item, index) in lists" :key="'projecting' + index" @click="openDetails(item.id)"> <div class="title"> - <img :src="item.img" :alt="item.title"> - <span>{{ item.title }}</span> + <img :src="img" :alt="item.title"> + <span>{{ getRiskName(item.disasterType)}} {{getLevelName(item.warningLevel)}}</span> </div> <p>{{ item.content }}</p> <div class="project-item"> - <b>{{ item.name }}</b> - <span>{{ item.created | filterTime }}</span> + <b>{{ item.publishingUnit }}</b> + <span>{{ item.publishingTime | filterTime }}</span> </div> </a-card-grid> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> </a-card> </template> <script> +import {getPublishRecord} from "@/api/list"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; export default { name: 'projecting', + components: { msgDetailMod }, data () { return { - lists: [ - { - img: require('@/assets/user.png'), - title: '气象 红色预警',//显示灾害种类和对应颜色级别 - content: '根据中央气象台消息,全疆近日气温将……', - name: '自治区', - created: '2020-10-12 12:12:12' - }, - { - img: require('@/assets/user.png'), - title: '气象 红色预警', - content: '今日阿勒泰地区将持续低温,请各单位……', - name: '阿勒泰地区', - created: '2021-08-21 12:12:12' - }, - { - img: require('@/assets/user.png'), - title: '气象 黄色预警', - content: '根据中央气象台消息,全疆近日气温将……', - name: '自治区', - created: '2022-10-12 12:12:12' - }, - { - img: require('@/assets/user.png'), - title: '气象 红色预警', - content: '根据中央气象台消息,全疆近日气温将……', - name: '自治区', - created: '2022-08-21 12:12:12' - }, - { - img: require('@/assets/user.png'), - title: '气象 红色预警', - content: '根据中央气象台消息,全疆近日气温将……', - name: '自治区', - created: '2022-10-12 12:12:12' - }, - { - img: require('@/assets/user.png'), - title: '气象 红色预警', - content: '根据中央气象台消息,全疆近日气温将……', - name: '自治区', - created: '2022-08-25 12:12:12' + search:{ + pageIndex: 1, + pageSize: 6, + searchParams:{ + emergType: null, + startTime: '', + endTime: '' } + }, + lists: [], + img: require('@/assets/user.png'), + riskOptions: [ + {name: '地震',value: 1}, + {name: '洪涝',value: 2}, + {name: '气象',value: 3}, + {name: '泥石流',value: 4}, + {name: '水旱',value: 5}, + {name: '森林草原火灾',value: 6} + ], + levelOptions: [ + {name: '红色预警',value: 1}, + {name: '橙色预警',value: 2}, + {name: '黄色预警',value: 3}, + {name: '蓝色预警',value: 4} ] + // lists: [ + // { + // img: require('@/assets/user.png'), + // title: '气象 红色预警',//显示灾害种类和对应颜色级别 + // content: '根据中央气象台消息,全疆近日气温将……', + // name: '自治区', + // created: '2020-10-12 12:12:12' + // } + // ] + } + }, + created() { + this.getData() + }, + methods:{ + async getData(){ + const t = this + const res = await getPublishRecord(t.search) + if(res.data.code == 100){ + t.lists = res.data.data + }else{ + this.$message.error(res.data.msg) + } + }, + getRiskName(disasterType){ + return this.riskOptions.find(i => i.value === disasterType)?.name; + }, + + getLevelName(warningLevel){ + return this.levelOptions.find(i => i.value === warningLevel)?.name; + }, + openDetails(id){ + const t = this + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true } } } @@ -71,6 +91,13 @@ <style lang="less" scoped> .projecting { + .tapBtn{ + color: #333; + &:hover{ + color: @link; + } + } + .title { text-align: left; margin-bottom: 10px; diff --git a/src/components/Home/QuickNavigation.vue b/src/components/Home/QuickNavigation.vue index 86ebd58..ef920be 100644 --- a/src/components/Home/QuickNavigation.vue +++ b/src/components/Home/QuickNavigation.vue @@ -1,17 +1,103 @@ <template> <a-card title="快捷操作" class="quick"> - <a style="color:blue">待叫应(1)</a> - <a >待审核</a> - <a>发布通知</a> - <a>查看统计</a> - <a>用户管理</a> + <a-tooltip overlayClassName="tip"> + <template #title v-if="toResponse == 0"> + 暂无待叫应信息 + </template> + <a :class="toResponse>0?'resColor':''" @click="toRes" v-if="userinfo.role.id == 3 && userinfo.unittype !==1">待叫应<span v-if="toResponse > 0">({{toResponse}})</span></a> + </a-tooltip> + + <a-tooltip overlayClassName="tip"> + <template #title v-if="toReview == 0"> + 暂无待审核信息 + </template> + <a :class="toReview>0?'resColor':''" @click="toRev" v-if="userinfo.role.id == 2">待审核<span v-if="toReview > 0">({{toReview}})</span></a> + </a-tooltip> + <a href="massSend" v-if="userinfo.role.id == 3">发布通知</a> + <a>查看统计</a> + <a href="user" v-if="userinfo.role.id == 3">用户管理</a> <!-- <a-button><a-icon type="plus" />添加</a-button> --> </a-card> </template> <script> +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; +import {getMsgRecord, getResponseRecord} from "@/api/list"; +import {getUserInfo} from "@/util/storage"; +import {getReviewRecord} from "@/api/review"; + export default { - name: 'quick-navigation' + name: 'quick-navigation', + data() { + return { + userinfo: getUserInfo(), + toResponse: null, + toReview: null, + }; + }, + created() { + const t = this + t.getResData() + t.getReviewData() + }, + methods: { + async getResData(){ + const t = this + const res = await getMsgRecord({ + pageIndex: 1, + pageSize: 10, + searchParams:{ + responseStatus: 1, + startTime: '', + endTime: '' + } + }) + if(res.data.code == 100){ + t.toResponse = res.data.total + }else{ + this.$message.error(res.data.msg) + } + }, + + async getReviewData(){ + const t = this + const res = await getReviewRecord({ + pageIndex: 1, + pageSize: 10, + searchParams:{ + reviewStatus: 1, + startTime: '', + endTime: '' + } + }) + if(res.data.code == 100){ + t.toReview = res.data.total + }else{ + this.$message.error(res.data.msg) + } + }, + + toRes(){ + if(this.toResponse>0){ + this.$router.push({ + name: 'list', + query: { + type: 1 + } + }) + } + }, + toRev(){ + if(this.toReview>0){ + this.$router.push({ + name: 'msgReview', + query: { + type: 1 + } + }) + } + } + } } </script> @@ -19,10 +105,31 @@ .quick { a { display: inline-block; + text-align: center; width: 25%; font-size: 14px; margin-bottom: 13px; color: #333; + + &:hover{ + color: @link; + } + } + .resColor{ + color: @danger; } } </style> +<style lang="less"> +.tip{ + .ant-tooltip-inner { + // 这里是框框 + color: #333; + background-color: #fff!important; + } + .ant-tooltip-arrow::before { + // 这里是小三角形 + background-color: #fff!important; + } +} +</style> \ No newline at end of file diff --git a/src/components/Home/Review.vue b/src/components/Home/Review.vue new file mode 100644 index 0000000..fd70f71 --- /dev/null +++ b/src/components/Home/Review.vue @@ -0,0 +1,84 @@ +<template> + <a-card title="最新审核记录"> + <a slot="extra" href="msgReview" class="tapBtn">更多记录</a> + <a-list item-layout="horizontal" :data-source="lists"> + <a-list-item slot="renderItem" slot-scope="item"> + <a-list-item-meta + :description="item.gmtReviewSubmit | filterTime" + > + <a slot="title" v-if="item.reviewStatus == 1" href="#" @click="openDetails(item.id)">{{item.title}} <span class="orange">未审核</span></a> + <a slot="title" v-if="item.reviewStatus == 2" href="#" @click="openDetails(item.id)">{{item.title}} <span class="blue">已审核</span></a> + <a slot="title" v-if="item.reviewStatus == 3" href="#" @click="openDetails(item.id)">{{item.title}} <span class="red">审核已驳回</span></a> + <a-avatar + slot="avatar" + :src="userImg" + /> + </a-list-item-meta> + </a-list-item> + </a-list> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> + </a-card> +</template> + +<script> +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; +import {getResponseRecord} from "@/api/list"; +import {getReviewRecord} from "@/api/review"; + +export default { + name: "Dynamic", + components: { msgDetailMod }, + data() { + return { + search:{ + pageIndex: 1, + pageSize: 10, + searchParams:{ + reviewStatus: null, + startTime: '', + endTime: '' + } + }, + lists: [], + userImg: require('@/assets/user.png') + }; + }, + created() { + this.getData() + }, + methods: { + async getData(){ + const t = this + const res = await getReviewRecord(this.search) + if(res.data.code == 100){ + t.lists = res.data.data + }else{ + this.$message.error(res.data.msg) + } + }, + openDetails(id){ + const t = this + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true + } + } +}; +</script> +<style lang="less" scoped> +.tapBtn{ + color: #333; + &:hover{ + color: @link; + } +} +.blue{ + color: @base; +} + +.orange{ + color: @warning; +} +.red{ + color: @danger; +} +</style> \ No newline at end of file diff --git a/src/layout/menu/index.js b/src/layout/menu/index.js index 44cb324..f1e46de 100644 --- a/src/layout/menu/index.js +++ b/src/layout/menu/index.js @@ -1,12 +1,13 @@ -const menuData = [{ +const menu = { + adminMenu: [{ MenuTitle: "首页", Icon: "home", MenuID: "1", Children: [{ - MenuID: "11", - MenuTitle: "控制面板", - MenuPath: "/home", - }, + MenuID: "11", + MenuTitle: "控制面板", + MenuPath: "/home", + }, { MenuID: "18", MenuTitle: "实时气象", @@ -29,79 +30,214 @@ } ], }, - { - MenuTitle: "预警信息管理", - Icon: "mail", - MenuID: "2", - Children: [{ + { + MenuTitle: "预警信息管理", + Icon: "mail", + MenuID: "2", + Children: [{ MenuID: "21", MenuTitle: "信息编辑", MenuPath: "/notice", }, - { - MenuID: "22", - MenuTitle: "信息审核", - MenuPath: "/msgReview", - }, - { - MenuID: "23", - MenuTitle: "信息发布", - MenuPath: "/report", - }, - { - MenuID: "24", - MenuTitle: "历史信息", - MenuPath: "/history", - }, - { - MenuID: "25", - MenuTitle: "叫应记录", - MenuPath: "/callRecord", - }, - ], - }, - { - MenuTitle: "短信管理", - Icon: "message", - MenuID: "3", - Children: [{ + { + MenuID: "22", + MenuTitle: "信息审核", + MenuPath: "/msgReview", + }, + { + MenuID: "23", + MenuTitle: "信息发布", + MenuPath: "/report", + }, + { + MenuID: "24", + MenuTitle: "历史信息", + MenuPath: "/history", + }, + { + MenuID: "25", + MenuTitle: "叫应记录", + MenuPath: "/callRecord", + }, + ], + }, + { + MenuTitle: "短信管理", + Icon: "message", + MenuID: "3", + Children: [{ MenuID: "31", MenuTitle: "常规群发", MenuPath: "/massSend", }, - { - MenuID: "32", - MenuTitle: "短信记录", - MenuPath: "/msgRecord", - }, - { - MenuID: "33", - MenuTitle: "平级接收人管理", - MenuPath: "/samelevel", - }, - ], - }, - { - MenuTitle: "设置", - Icon: "setting", - MenuID: "4", - Children: [{ + { + MenuID: "32", + MenuTitle: "短信记录", + MenuPath: "/msgRecord", + }, + { + MenuID: "33", + MenuTitle: "平级接收人管理", + MenuPath: "/samelevel", + }, + ], + }, + { + MenuTitle: "设置", + Icon: "setting", + MenuID: "4", + Children: [{ MenuID: "41", MenuTitle: "用户管理", MenuPath: "/user", }, + { + MenuID: "42", + MenuTitle: "短信平台设置", + MenuPath: "/smsSetting", + }, + // { + // MenuID: "43", + // MenuTitle: "菜单权限", + // MenuPath: "/menu", + // }, + ], + }, + ], + leaderMenu: [{ + MenuTitle: "首页", + Icon: "home", + MenuID: "1", + Children: [{ + MenuID: "11", + MenuTitle: "控制面板", + MenuPath: "/home", + }, { - MenuID: "42", - MenuTitle: "短信平台设置", - MenuPath: "/smsSetting", + MenuID: "18", + MenuTitle: "实时气象", + MenuPath: "/wendy", }, - // { - // MenuID: "43", - // MenuTitle: "菜单权限", - // MenuPath: "/menu", - // }, + { + MenuID: "13", + MenuTitle: "数据统计", + MenuPath: "/audit" + } ], }, -] + { + MenuTitle: "预警信息管理", + Icon: "mail", + MenuID: "2", + Children: [ + { + MenuID: "22", + MenuTitle: "信息审核", + MenuPath: "/msgReview", + }, + ], + } + ], + workerMenu: [{ + MenuTitle: "首页", + Icon: "home", + MenuID: "1", + Children: [{ + MenuID: "11", + MenuTitle: "控制面板", + MenuPath: "/home", + }, + { + MenuID: "18", + MenuTitle: "实时气象", + MenuPath: "/wendy", + }, + { + MenuID: "12", + MenuTitle: "我收到的", + MenuPath: "/list" + }, + { + MenuID: "14", + MenuTitle: "我发布的", + MenuPath: "/release" + }, + { + MenuID: "13", + MenuTitle: "数据统计", + MenuPath: "/audit" + } + ], + }, + { + MenuTitle: "预警信息管理", + Icon: "mail", + MenuID: "2", + Children: [{ + MenuID: "21", + MenuTitle: "信息编辑", + MenuPath: "/notice", + }, + { + MenuID: "23", + MenuTitle: "信息发布", + MenuPath: "/report", + }, + { + MenuID: "24", + MenuTitle: "历史信息", + MenuPath: "/history", + }, + { + MenuID: "25", + MenuTitle: "叫应记录", + MenuPath: "/callRecord", + }, + ], + }, + { + MenuTitle: "短信管理", + Icon: "message", + MenuID: "3", + Children: [{ + MenuID: "31", + MenuTitle: "常规群发", + MenuPath: "/massSend", + }, + { + MenuID: "32", + MenuTitle: "短信记录", + MenuPath: "/msgRecord", + }, + { + MenuID: "33", + MenuTitle: "平级接收人管理", + MenuPath: "/samelevel", + }, + ], + }, + { + MenuTitle: "设置", + Icon: "setting", + MenuID: "4", + Children: [{ + MenuID: "41", + MenuTitle: "用户管理", + MenuPath: "/user", + }, + { + MenuID: "42", + MenuTitle: "短信平台设置", + MenuPath: "/smsSetting", + }, + // { + // MenuID: "43", + // MenuTitle: "菜单权限", + // MenuPath: "/menu", + // }, + ], + }, + ] +} -export default menuData; \ No newline at end of file +export default menu; \ No newline at end of file diff --git a/src/layout/menuSider.vue b/src/layout/menuSider.vue index 53b9b33..656f81e 100644 --- a/src/layout/menuSider.vue +++ b/src/layout/menuSider.vue @@ -21,15 +21,28 @@ </template> <script> -import menuData from './menu' +import menu from './menu' +import { getUserInfo } from "@/util/storage"; export default { name: "menu-sider", data() { return { - navData: menuData, + userInfo: {}, + navData: [], openKeys: ['1','2','3','4'] }; }, + created() { + const t = this + t.userInfo = getUserInfo() + if(t.userInfo.role.id == 1){ + t.navData = menu.adminMenu + }else if(t.userInfo.role.id == 3){ + t.navData = menu.workerMenu + }else{ + t.navData = menu.leaderMenu + } + }, methods: { onOpenChange(openKeys) { if (openKeys.length !== 0) { diff --git a/src/router/index.js b/src/router/index.js index 8cbbfaa..d03f95e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -41,12 +41,6 @@ component: () => import('@/views/Admin/list'), }, { - path: '/details', - name: 'detail', - meta: { title: '信息详情' }, - component: () => import('@/views/Admin/Details'), - }, - { path: '/audit', name: 'audit', meta: { title: '数据统计' }, @@ -60,7 +54,7 @@ }, { path: '/msgReview', - name: '/msgReview', + name: 'msgReview', meta: { title: '信息审核' }, component: () => import('@/views/Admin/msgReview'), }, diff --git a/src/util/AntDesign.js b/src/util/AntDesign.js index 2c484ef..68899f4 100644 --- a/src/util/AntDesign.js +++ b/src/util/AntDesign.js @@ -28,6 +28,6 @@ Cascader, Pagination, FormModel, - message + Upload, } from "ant-design-vue"; -Vue.use(Alert).use(Pagination).use(Tag).use(Switch).use(FormModel).use(Modal).use(Cascader).use(TreeSelect).use(Button).use(Layout).use(Menu).use(Icon).use(Form).use(Input).use(Tabs).use(Checkbox).use(Row).use(Col).use(Avatar).use(Divider).use(Card).use(List).use(Tooltip).use(Dropdown).use(Select).use(Radio).use(DatePicker).use(Table); +Vue.use(Alert).use(Pagination).use(Upload).use(Tag).use(Switch).use(FormModel).use(Modal).use(Cascader).use(TreeSelect).use(Button).use(Layout).use(Menu).use(Icon).use(Form).use(Input).use(Tabs).use(Checkbox).use(Row).use(Col).use(Avatar).use(Divider).use(Card).use(List).use(Tooltip).use(Dropdown).use(Select).use(Radio).use(DatePicker).use(Table); diff --git a/src/util/request.js b/src/util/request.js index 2fb29a4..74f0b2f 100644 --- a/src/util/request.js +++ b/src/util/request.js @@ -36,25 +36,23 @@ (response) => { // 对响应数据做点什么 if (response.data.code && response.data.code === 401) { - message.error('用户不存在'); - loginOut() - .then(() => { - Session.clear(); - window.location.href = '/'; - }); - // useLoginApi() - // .signOut() - // .then(() => { - // Session.clear(); - // window.location.href = '/'; - // }); + // message.error('用户不存在') + setTimeout(()=>{ + loginOut() + .then(() => { + Session.clear(); + window.location.href = '/'; + }); + },2000) } else if (response.data.code && response.data.code === 405) { - message.error('token失效'); + message.error('token失效') + setTimeout(()=>{ loginOut() .then(() => { Session.clear(); window.location.href = '/'; }); + },2000) } return Promise.resolve(response); }, diff --git a/src/util/validate.js b/src/util/validate.js index 3338c7f..60c609b 100644 --- a/src/util/validate.js +++ b/src/util/validate.js @@ -215,6 +215,12 @@ else return true; } +// 简单校验手机号(十一位数字则通过) +export function verifySimplePhone(val) { + var regex = /^\d{11}$/; // 正则表达式,\d 匹配数字,{11} 表示匹配11次 + return regex.test(val); +} + /** * 国内电话号码 * @param val 当前值字符串 diff --git a/src/views/Admin/Details.vue b/src/views/Admin/Details.vue deleted file mode 100644 index 76e1adf..0000000 --- a/src/views/Admin/Details.vue +++ /dev/null @@ -1,54 +0,0 @@ -<template> - <div class="inner"> - <h2>标题:{{title}}</h2> - <p><b>类别:</b>{{category}}</p> - <p><b>级别:</b><a-tag :color="level === '黄色' ? 'yellow' :level === '橙色'? 'orange':level === '红色'?'red':'blue'"> - {{ level }} - </a-tag></p> - <p><b>发布单位:</b>{{department}}</p> - <p><b>短信内容:</b><i>{{smsmessage}}</i></p> - <p><b>附件内容:</b><a :href=attachment.url><a-icon type="link" /> {{attachment.title}}</a></p> - <p><b>响应状态:</b> - <span v-if="receipt=='待叫应'" - style='background-color:blue;padding:5px;color:#fff;border-radius: 5px;'>{{receipt}}</span> - <span v-else-if="receipt=='已叫应'" - style='background-color:limegreen;padding:5px;color:#2a2a2a;border-radius: 5px;'>{{receipt}}</span> - <span v-else style='background-color:red;padding:5px;color:#fff;border-radius: 5px;'>{{receipt}} - </span></p> - </div> -</template> - -<script> - export default{ - data(){ - return{ - key: 1, - id:1001, - time: '2023年5月3日 15:30', - department: '自治区预警中心', - category: '气象', - level: '黄色', - title: '标题:全疆(地区)高温橙色预警', - attachment: { - title:'中央气象台2023年5月3日报告', - url:'http://www.baidu.com' - }, - smsmessage: '【自然灾害预警提示】中央气象台2023年5月3日报告,我省南部将持续高温天气,请各部门注意采取相应措施。发布单位:自治区预警中心', - receipt: '已叫应' - } - } - } -</script> - -<style scoped> -p{ - font-size:16px; -} -i{ - background-color: aliceblue; - padding: 2px 5px; -} -.inner{ - padding:25px 25px; -} -</style> \ No newline at end of file diff --git a/src/views/Admin/HomeDefault.vue b/src/views/Admin/HomeDefault.vue index f3a24e2..2d308e2 100644 --- a/src/views/Admin/HomeDefault.vue +++ b/src/views/Admin/HomeDefault.vue @@ -6,8 +6,8 @@ <div class="content-left"> <img src="./../../assets/user.png" alt=""> <div class="user"> - <h2>{{ dateTime}},{{userName}},欢迎使用自治区自然灾害综合风险预警发布及响应联动系统</h2> - <p>自治区预警中心干部 工作人员</p> + <h2>{{ dateTime}},{{userInfo.realName}},欢迎使用自治区自然灾害综合风险预警发布及响应联动系统</h2> + <p>{{userInfo.company}} {{userInfo.role.roleName}}</p> </div> </div> <div class="content-right"> @@ -29,9 +29,12 @@ </div> </div> <div class="home-default-content"> - <div class="left"> + <div class="left" v-if="userInfo.role.id == 1 || userInfo.role.id == 3"> <Projecting /> <Dynamic style="margin-top: 20px"/> + </div> + <div class="left" v-if="userInfo.role.id == 2"> + <Review /> </div> <div class="right"> <QuickNavigation /> @@ -45,27 +48,30 @@ <script> import Projecting from '@/components/Home/Projecting' import Dynamic from '@/components/Home/Dynamic' +import Review from '@/components/Home/Review' import QuickNavigation from '@/components/Home/QuickNavigation' import IndexEcharts from '@/components/Home/IndexEcharts' import Team from '@/components/Home/Team' import Cookies from "js-cookie"; +import {getUserInfo} from "@/util/storage"; export default { name: 'home-default', components: { Projecting, Dynamic, + Review, QuickNavigation, IndexEcharts, Team }, data() { return { - userName: '' + userInfo: getUserInfo() }; }, created() { - this.userName = JSON.parse(Cookies.get('userInfo')).realName + }, computed: { dateTime () { diff --git a/src/views/Admin/Report.vue b/src/views/Admin/Report.vue index d90fbd7..0ef6c22 100644 --- a/src/views/Admin/Report.vue +++ b/src/views/Admin/Report.vue @@ -45,9 +45,11 @@ <template #disasterType="text"> {{ getRiskName(text) }} </template> - <template #attachment="text"> - <span v-if="text==='无'">无</span> - <a v-else><b><a-icon type="paper-clip" /> {{text}}</b></a> + <template #attachment="attachment"> + <span v-if="attachment===null|| attachment===[]">无</span> + <div v-else> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in attachment" :key="index"><a-icon type="paper-clip"/>{{item.attachmentName}}</a-button> + </div> </template > <template #reviewStatus="reviewStatus"> <a-tag @@ -58,7 +60,7 @@ </template> <template #operation="text, record, index"> <a-button type="primary" v-if="record.reviewStatus == 2" @click="confirmPost(record.id)">确认发布</a-button> - <a-button type="link" v-if="record.reviewStatus == 2 || record.reviewStatus == 3" @click="openMod('view',record)">查看信息详情</a-button> + <a-button type="link" @click="openMod('view',record)">查看信息详情</a-button> <a-button class="del" type="link" @click="delData(record.id)">删除</a-button> </template> </a-table> @@ -73,6 +75,9 @@ import msgEditMod from '@/views/Admin/components/msgEditMod' import {delRecipient} from "@/api/user"; import {deleteMsg, publishMsg} from "@/api/send"; +import Cookies from "js-cookie"; +import axios from "axios"; +import {getUserInfo} from "@/util/storage"; export default { name: 'msgReview', @@ -143,6 +148,7 @@ scopedSlots: { customRender: 'attachment' }, + width: '15%' }, { title: '审核情况', @@ -160,6 +166,11 @@ }, ], data: [] + } + }, + mounted() { + if(getUserInfo().role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') } }, created() { @@ -209,14 +220,15 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - let res = await publishMsg(id) - if(res.data.code == 100){ - t.$message.success('信息发布成功'); - t.getData() - }else{ - t.$message.warning(res.data.msg); - } + onOk() { + publishMsg(id).then(res=>{ + if(res.data.code == 100){ + t.$message.success('信息发布成功'); + t.getData() + }else{ + t.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); @@ -232,14 +244,15 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - let res = await deleteMsg(id) - if(res.data.code == 100){ - t.$message.success('信息删除成功'); - t.getData() - }else{ - t.$message.warning(res.data.msg); - } + onOk() { + deleteMsg(id).then(res=>{ + if(res.data.code == 100){ + t.$message.success('信息删除成功'); + t.getData() + }else{ + t.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); @@ -247,6 +260,25 @@ }); }, + viewFile(item){ + const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachment,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachmentName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + openMod(type,data){ const t = this getReviewDetail(data.id).then(res=>{ diff --git a/src/views/Admin/callRecord.vue b/src/views/Admin/callRecord.vue index 7615f63..1b8e387 100644 --- a/src/views/Admin/callRecord.vue +++ b/src/views/Admin/callRecord.vue @@ -36,7 +36,7 @@ <!-- 表格实体部分--> <div class="table-cont"> - <a-table :columns="columns" :data-source="data" bordered :pagination="pagination"> + <a-table :columns="columns" :data-source="data" bordered :pagination="pagination" :rowKey="record=>record.id"> <template #index="text,record,index"> {{ index + 1 }} </template> @@ -53,18 +53,18 @@ </a-tag> </template > <template #operation="text, record, index"> -<!-- <a-button type="primary">叫应列表</a-button>--> - <a-button type="link" @click="openMod('view',record)">查看详情</a-button> + <a-button type="link" @click="openDetails(record.warnInfoId)">查看详情</a-button> </template> </a-table> - <msg-edit-mod ref="msgEdit" @refresh="getData"></msg-edit-mod> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> </div> </div> </template> <script> import {getHistoryRecord, getMsgRecord, getPublishRecord, getResponseRecord} from "@/api/list"; -import msgEditMod from "@/views/Admin/components/msgEditMod"; -import {getReviewDetailByWorker} from "@/api/review"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; +import {getUserInfo} from "@/util/storage"; + const columns = [{ title: '序号', dataIndex: 'index', @@ -128,7 +128,7 @@ ]; export default { name: 'release', - components: { msgEditMod }, + components: { msgDetailMod }, data() { return { search:{ @@ -170,6 +170,11 @@ ] } }, + mounted() { + if(getUserInfo().role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') + } + }, created() { const t = this t.getData() @@ -186,19 +191,10 @@ } }, - openMod(type,data){ + openDetails(id){ const t = this - getReviewDetailByWorker(data.warnInfoId).then(res=>{ - if(res.data.code == 100){ - if(res.data.data){ - t.$refs.msgEdit.openMod(type,res.data.data) - }else{ - t.$message.error('查询信息详情失败') - } - }else{ - this.$message.error(res.data.msg) - } - }) + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true }, onPageChange(page, pageSize) { diff --git a/src/views/Admin/components/callListMod.vue b/src/views/Admin/components/callListMod.vue index 7b4e630..10b3bec 100644 --- a/src/views/Admin/components/callListMod.vue +++ b/src/views/Admin/components/callListMod.vue @@ -23,6 +23,11 @@ {{ unittype==1?'省级':unittype==2?'地(市、州)级':unittype==3?'区县级':unittype==4?'村(乡、镇)级':'管理员' }} </a-tag> </template > + <template #responseStatus="text"> + <a-tag :color="text === 3 ? 'red' :text === 2? 'green':text === 1?'orange':'blue'"> + {{text == 1 ? '待叫应' : text == 2 ?'已叫应':text == 3 ?'超时未叫应' : ''}} + </a-tag> + </template> </a-table> </a-modal> </template> @@ -62,18 +67,12 @@ { title: '接收人单位', dataIndex: 'receiveUnit', - width: '20%', - scopedSlots: { - customRender: 'receiveUnit' - } + width: '20%' }, { title: '接收人', dataIndex: 'recipienterName', - width: '20%', - scopedSlots: { - customRender: 'recipienterName' - } + width: '20%' }, { title: '级别', @@ -84,11 +83,11 @@ }, }, { - title: '叫应时间', - dataIndex: 'responseTime', + title: '叫应状态', + dataIndex: 'responseStatus', width: '15%', scopedSlots: { - customRender: 'responseTime' + customRender: 'responseStatus' } //设置定制化表格数据 } ] diff --git a/src/views/Admin/components/msgDetailMod.vue b/src/views/Admin/components/msgDetailMod.vue new file mode 100644 index 0000000..b55b369 --- /dev/null +++ b/src/views/Admin/components/msgDetailMod.vue @@ -0,0 +1,191 @@ +<template> + <a-modal + title="信息详情" + centered + :visible="visible" + :confirm-loading="confirmLoading" + width="50%" + cancelText="取消" + okText="确认" + @ok="handleCancel" + @cancel="handleCancel" + :afterClose="clearMod" + > + <div class="detail-mod"> + <a-row :gutter="24" v-if="details.title"><a-col :span="4">标题</a-col><a-col class="noBorder" :span="14" style="font-size: 24px;font-weight: bolder">{{details.title}}</a-col></a-row> + <a-row :gutter="24" v-if="details.emergType"><a-col :span="4">紧急类型</a-col> + <a-col :span="14" class="noBorder"> + <a-tag :color="details.emergType == 1? 'red': 'blue'" style="font-size: 18px;padding: 5px 15px"> + {{ details.emergType == 1?'紧急':details.emergType == 2?'常规':''}} + </a-tag> + </a-col> + </a-row> + <a-row :gutter="24" v-if="details.disasterType"><a-col :span="4">灾种类型</a-col><a-col :span="14">{{ getRiskName(details.disasterType)}}</a-col></a-row> + <a-row :gutter="24" v-if="details.warningLevel"><a-col :span="4">预警级别</a-col> + <a-col :span="14" class="noBorder"> + <a-tag :color="details.warningLevel == 1? 'red': details.warningLevel == 2?'orange':details.warningLevel == 3?'yellow':'blue'" style="font-size: 18px;padding: 5px 15px"> + {{ getLevelName(details.warningLevel)}} + </a-tag> + </a-col> + </a-row> + <a-row :gutter="24" v-if="details.publishingUnit"><a-col :span="4">发布单位</a-col><a-col :span="14">{{details.publishingUnit}}</a-col></a-row> + <a-row :gutter="24" v-if="details.content"><a-col :span="4">信息内容</a-col><a-col :span="14">{{details.content}}</a-col></a-row> + <a-row :gutter="24" v-if="details.acceptingUnitIds && details.acceptingUnitIds.length>0"> + <a-col :span="4">接收人</a-col> + <a-col :span="20"> + <div v-for="(item,index) in details.acceptingUnitIds" :key="index" class="table"> + <div style="width: 20%"> + {{item.recipienterName}} + </div> + <div style="width: 20%"> + {{item.recipienterPhone}} + </div> + <div style="width: 60%"> + {{item.receiveUnit}} + </div> + </div> + </a-col> + </a-row> + <a-row :gutter="24" v-if="details.attachments && details.attachments.length > 0"><a-col :span="4">附件内容</a-col> + <a-col :span="14" class="noBorder"> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in details.attachments" :key="index"><a-icon type="paper-clip"/>{{item.attachementName}}</a-button> + </a-col> + </a-row> + </div> + </a-modal> +</template> + +<script> +import {getReviewDetailByWorker} from "@/api/review"; +import axios from "axios"; +import Cookies from "js-cookie"; +export default { + name: 'msgDetailMod', + data () { + return { + visible: false, + confirmLoading: false, + details: {}, + riskOptions: [ + {name: '地震',value: 1}, + {name: '洪涝',value: 2}, + {name: '气象',value: 3}, + {name: '泥石流',value: 4}, + {name: '水旱',value: 5}, + {name: '森林草原火灾',value: 6} + ], + levelOptions: [ + {name: '红色预警',value: 1}, + {name: '橙色预警',value: 2}, + {name: '黄色预警',value: 3}, + {name: '蓝色预警',value: 4} + ] + } + }, + created() { + const t = this + }, + methods:{ + clearMod(){ + + }, + + async getDetails(id){ + const t = this + const res = await getReviewDetailByWorker(id) + if(res.data.code == 100){ + if(res.data.data){ + t.details = res.data.data + }else{ + t.$message.error('查询信息详情失败') + } + }else{ + this.$message.error(res.data.msg) + } + }, + + viewFile(item){ + const t = this + const { baseUrl } = require('../../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachement,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachementName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + + handleOk(e) { + const t = this + t.confirmLoading = true; + }, + handleCancel(e) { + const t = this + t.visible = false; + }, + onChange(value) { + console.log(value); + }, + + getRiskName(disasterType){ + return this.riskOptions.find(i => i.value === disasterType)?.name; + }, + getLevelName(warningLevel){ + return this.levelOptions.find(i => i.value === warningLevel)?.name; + } + + } +} +</script> + +<style lang="less" scoped> +.detail-mod{ + font-size: 16px; + + .ant-row{ + margin-bottom: 24px; + display: flex; + align-items: center; + + &:first-of-type{ + margin-bottom: 12px; + } + + .ant-col{ + &:first-of-type{ + text-align: right; + } + + &:last-of-type{ + border: 1px solid #d9d9d9; + padding: 5px 10px; + } + } + + .noBorder{ + border: none !important; + padding: 5px 10px; + } + + .table{ + display: flex; + align-items: center; + border-bottom: 1px solid @blackBorder; + &:last-of-type{ + border-bottom: none; + } + &>div{ + padding: 5px 10px; + } + } + } +} +</style> diff --git a/src/views/Admin/components/msgEditMod.vue b/src/views/Admin/components/msgEditMod.vue index 4a69812..fd3139a 100644 --- a/src/views/Admin/components/msgEditMod.vue +++ b/src/views/Admin/components/msgEditMod.vue @@ -59,7 +59,23 @@ </a-form-model-item> <a-row> <a-col :span="12"> - <a-button>上传附件</a-button> + <a-upload + :disabled="disable" + :action="uploadUrl" + :file-list="fileList" + @change="fileChange" + :headers="header" + accept=".doc, .docx, .word, .pdf, .zip, .xlsx, .rar" + :data="{module: 'naturalDisasterPath'}" + @download="downloadFile" + :remove="(file)=>{removeFile(file)}" + :showUploadList="{ + showRemoveIcon: true, + showDownloadIcon: true + }" + > + <a-button> <a-icon type="upload" />上传附件</a-button> + </a-upload> </a-col> <a-col :span="12" style="display: flex;align-items: center;justify-content: right"> <b style="margin-bottom: 24px">超时设置:</b> @@ -102,7 +118,7 @@ </a-col> <a-col :span="12"> <b style="margin-bottom: 6px">平级接收人选择:</b> - <a-form-model-item prop="recipient"> + <a-form-model-item> <a-select mode="multiple" placeholder="选择平级接收单位" v-model="form.recipient" @change="handle" :disabled="disable"> <a-select-option v-for="item in filteredOptions" :key="item.id" :value="item.id"> {{ item.recipientName }} @@ -126,7 +142,7 @@ <b style="margin-bottom: 6px">选择审批领导:</b> <a-form-model-item prop="reviewId"> <a-select show-search v-model="form.reviewId" placeholder="请选择审批领导"> - <a-select-option v-for="(item,index) in leaders" :value="item.id" :key="index">{{item.name}}</a-select-option> + <a-select-option v-for="(item,index) in leaders" :value="item.id" :key="index">{{item.realName}}</a-select-option> </a-select> </a-form-model-item> </a-col> @@ -142,9 +158,8 @@ <h2>短信预览</h2> <div class="mobile"> <div class="mesg"> - <P>【{{form.title}}】{{form.content}}。发布单位:{{form.publishingUnit}}</P> + <P>【自然灾害风险预警提示】{{form.content}}<br>发布单位:{{form.publishingUnit}}</P> </div> - </div> </div> </a-form-model> @@ -152,11 +167,13 @@ </template> <script> -import {getAreaWithUserIfo, getPeerRecipient, getLeaders} from '@/api/user' +import {getAreaWithUserIfo, getPeerRecipient, getLeaders, delRecipient} from '@/api/user' import {getUserInfo} from "@/util/storage"; import Cookies from "js-cookie"; import {massSend, msgSend} from "@/api/send"; import {postReview} from "@/api/review"; +import axios from "axios"; +import {deleteFile} from "@/api/list"; export default { name: "msgEditMod", data() { @@ -217,16 +234,26 @@ timeout: [{ required: true, message: '请输入超时时间', trigger: 'blur'}], receiver: [{ required: true, message: '请选择接收单位', trigger: 'change'}], reviewId: [{ required: true, message: '请选择审批人', trigger: 'change'}], - recipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] + // recipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] // acceptingUnitIds: [{ required: true, message: '请选择接收单位', trigger: 'change'}], // peerRecipientIds: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] - } + }, + uploadUrl: '', + fileList: [], + header: { + uid: null, + tk: Cookies.get('resTk') + }, + delList: [] }; }, components: {}, created() { const t = this + const { baseUrl } = require('../../../../config/env.' + process.env.NODE_ENV) + t.uploadUrl= baseUrl + '/attachment/upload/detail' t.userInfo = getUserInfo() + t.header.uid = t.userInfo.uid t.form.districtId = t.userInfo.districtId t.form.publishingUnit = t.userInfo.company t.getSameLevel() @@ -236,31 +263,62 @@ methods: { openMod(type,data){ const t = this - for(let i in data){ - if(t.isValidKey(i,t.form)){ - t.form[i] = data[i] - } - } - const arr = data.acceptingUnitIds.map((i)=>{return { - value: i.districtId - }}) - t.form.receiver = JSON.parse(JSON.stringify(arr)).filter( - (item, index) => JSON.parse(JSON.stringify(arr)).findIndex(obj => obj.value === item.value) === index - ) - t.form.recipient = data.peerRecipientIds.map(i=>i.recipienterId) t.form.acceptingUnitIds = [] t.form.peerRecipientIds = [] - if(type == 'review') { - t.title = '信息审核' - t.disable = false - }else if(type == 'view'){ - t.title = '信息详情' - t.disable = true + if(type == 'review' || type == 'view') { + for(let i in data){ + if(t.isValidKey(i,t.form)){ + t.form[i] = data[i] + } + } + if(data.attachments && data.attachments.length>0){ + t.fileList = data.attachments.map((i)=>{ + return { + uid: i.id, + name: i.attachementName, + status: 'done', + url: i.attachement + } + }) + }else{ + t.fileList = [] + } + const arr = data.acceptingUnitIds.map((i)=>{return { + value: i.districtId + }}) + t.form.receiver = JSON.parse(JSON.stringify(arr)).filter( + (item, index) => JSON.parse(JSON.stringify(arr)).findIndex(obj => obj.value === item.value) === index + ) + t.form.recipient = data.peerRecipientIds.map(i=>i.recipienterId) + if(type == 'review'){ + t.title = '信息审核' + t.disable = false + }else{ + t.title = '信息详情' + t.disable = true + } }else{ + t.form.title = data.title + t.form.emergType = data.emergType + t.form.disasterType = data.disasterType + t.form.warningLevel = data.warningLevel + t.form.content = data.content + t.form.timeout = data.timeout + if(data.attachments && data.attachments.length>0){ + t.fileList = data.attachments.map((i)=>{ + return { + uid: i.id, + name: i.attachementName, + status: 'done', + url: i.attachement + } + }) + }else{ + t.fileList = [] + } t.title = '信息转发' t.getLeaders() t.disable = false - } t.visible = true }, @@ -276,7 +334,7 @@ if(res.data.data){ t.filteredOptions = res.data.data }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -289,13 +347,13 @@ let res = await getAreaWithUserIfo() if(res.data.code == 100){ if(res.data.data){ - const treeD = [] + // const treeD = [] t.userTitTree(res.data.data) - treeD.push(t.findNodeById(res.data.data,t.userInfo.districtId)) - t.areaUsers = treeD + // treeD.push(t.findNodeById(res.data.data,t.userInfo.districtId)) + t.areaUsers = t.findNodeById(res.data.data,t.userInfo.districtId).children t.unittype = this.findNodeById(this.areaUsers,t.userInfo.districtId)?.type }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -310,7 +368,7 @@ if(res.data.data){ t.leaders = res.data.data }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -334,12 +392,54 @@ } }, + fileChange(info) { + let fileList = [...info.fileList]; + // 2. read from response and show file link + fileList = fileList.map(file => { + if(file.status == 'done'){ + if (file.response) { + const res = file.response + if(res.code == 100){ + this.$message.success('文件上传成功') + }else{ + this.$message.error('文件上传失败') + } + // Component will show file.url as link + file.url = res.data.fileUrl + } + } + return file; + }); + this.fileList = fileList; + }, + + removeFile(file){ + this.delList.push(file.uid) + }, + + async deleteFile(){ + const t = this + for(let i of t.delList){ + const res = await deleteFile(i) + if(res.data.code == 100){ + console.log('文件删除成功') + }else{ + t.$message.error(res.data.msg) + } + } + }, + confirmSend(status){ this.$refs.ruleForm.validate(valid => { if (valid) { this.form.acceptingUnitIds = [] this.form.peerRecipientIds = [] + this.form.attachments = [] const aList = this.form.receiver.map(item=>this.findNodeById(this.areaUsers,item.value)?.users) + if(aList.includes(null)){ + this.$message.error('选择接收单位时存在无用户的单位') + return + } const newAList = [].concat(...aList) for(let i of newAList){ const {realName,...data} = i @@ -347,11 +447,24 @@ const obj = { recipienterId, recipienterName, recipienterPhone, receiveUnit,...rest} this.form.acceptingUnitIds.push(obj) } - const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) - for(let i of bList){ - const {id:recipienterId,recipientName: recipienterName,phone: recipienterPhone, company: receiveUnit,...rest} = i - const obj = {recipienterId, recipienterName,recipienterPhone,receiveUnit,unittype:this.unittype,...rest} - this.form.peerRecipientIds.push(obj) + if(this.form.recipient.length>0){ + const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) + for(let i of bList){ + const {id:recipienterId,recipientName: recipienterName,phone: recipienterPhone, company: receiveUnit,...rest} = i + const obj = {recipienterId, recipienterName,recipienterPhone,receiveUnit,unittype:this.unittype,...rest} + this.form.peerRecipientIds.push(obj) + } + } + if(this.fileList.length == 0){ + this.form.attachments = [] + }else{ + this.form.attachments = this.fileList.map((i)=>{ + if(i.response){ + return i.response.data.id + }else{ + return i.uid + } + }) } if(status == 2 || status == 3){ const {receiver,recipient,reviewId,...data} = this.form @@ -359,31 +472,56 @@ postReview(data).then( res =>{ if(res.data.code == 100){ this.$message.success('审核已提交') - this.$emit('refresh') - this.visible = false + this.deleteFile() }else{ this.$message.error(res.data.msg) } + this.visible = false + this.$emit('refresh') this.$refs.ruleForm.clearValidate() this.$refs.ruleForm.resetFields() + this.delList = [] + this.fileList = [] }) }else{ const {receiver,recipient,id,...data} = this.form msgSend(data).then( res =>{ if(res.data.code == 100){ this.$message.success('信息已提交审核') + this.deleteFile() }else{ this.$message.error(res.data.msg) } - this.$emit('refresh') this.visible = false + this.$emit('refresh') this.$refs.ruleForm.clearValidate() this.$refs.ruleForm.resetFields() + this.delList = [] + this.fileList = [] }) } }else{ console.log('error submit!!'); return false; + } + }) + }, + + downloadFile(file){ + const t = this + const { baseUrl } = require('../../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + file.url,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", file.name); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') } }) }, @@ -432,6 +570,7 @@ userTitTree(treeData) { for(const node of treeData){ if(node.users){ + node.users = node.users.filter(i=>i.roleId == 3) node.users = node.users.map((i)=>{ return{ ...i, @@ -439,7 +578,7 @@ districtId: node.id } }) - node.name = node.name + '('+node.users.map(i=>i.name +' '+ i.phone).join(',')+')' + node.name = node.name + '('+node.users.map(i=>i.realName +' '+ i.phone).join(',')+')' } if(node.children){ this.userTitTree(node.children) diff --git a/src/views/Admin/components/sameLevelMod.vue b/src/views/Admin/components/sameLevelMod.vue index a86fd14..210a5dd 100644 --- a/src/views/Admin/components/sameLevelMod.vue +++ b/src/views/Admin/components/sameLevelMod.vue @@ -132,7 +132,6 @@ if (valid) { if(this.title == '新增用户'){ const { id,...data } = this.form - console.log(data,'data') addRecipient(data).then((res)=>{ if(res.data.code == 100){ this.$message.success('新增平级接收人成功') diff --git a/src/views/Admin/components/userMod.vue b/src/views/Admin/components/userMod.vue index 499ef98..4428956 100644 --- a/src/views/Admin/components/userMod.vue +++ b/src/views/Admin/components/userMod.vue @@ -81,7 +81,7 @@ <script> import {addUser, updateUser} from '@/api/user' -import {verifyPasswordPowerful, verifyPhone} from "@/util/validate"; +import {verifyPasswordPowerful, verifyPhone, verifySimplePhone} from "@/util/validate"; export default { name: 'userMod', props: ['unitType'], @@ -101,7 +101,7 @@ if(value === ''){ callback(new Error('请输入手机号')) }else{ - if(!verifyPhone(value)){ + if(!verifySimplePhone(value)){ callback(new Error('手机号格式有误')) }else{ callback() diff --git a/src/views/Admin/history.vue b/src/views/Admin/history.vue index 1e91970..d16edc6 100644 --- a/src/views/Admin/history.vue +++ b/src/views/Admin/history.vue @@ -54,8 +54,11 @@ {{ getLevelName(text) }} </a-tag> </template> - <template #attachment="text"> - <a><b><a-icon type="paper-clip" /></b></a> + <template #attachment="attachment"> + <span v-if="attachment===null|| attachment.length == 0">无</span> + <div v-else> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in attachment" :key="index"><a-icon type="paper-clip"/>{{item.attachmentName}}</a-button> + </div> </template > <template #responseSituation="text"> <a-tag :color="text === 3 ? 'red' :text === 2? 'green':text === 1?'orange':'blue'"> @@ -64,19 +67,22 @@ </template> <template #operation="text, record, index"> <a-button type="primary" @click="openList(record.id)">叫应列表</a-button> - <a-button type="link" @click="openMod('view',record)">查看详情</a-button> + <a-button type="link" @click="openDetails(record.id)">查看详情</a-button> </template> </a-table> - <msg-edit-mod ref="msgEdit" @refresh="getData"></msg-edit-mod> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> <call-list-mod ref="callList" @refresh="getData"></call-list-mod> </div> </div> </template> <script> import {getHistoryRecord, getMsgRecord, getPublishRecord} from "@/api/list"; -import msgEditMod from "@/views/Admin/components/msgEditMod"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; import callListMod from "@/views/Admin/components/callListMod"; import {getReviewDetailByWorker} from "@/api/review"; +import axios from "axios"; +import Cookies from "js-cookie"; +import {getUserInfo} from "@/util/storage"; const columns = [{ title: '序号', dataIndex: 'index', @@ -122,7 +128,7 @@ { title: '附件', dataIndex: 'attachment', - width: '6%', + width: '15%', scopedSlots: { customRender: 'attachment' }, @@ -145,7 +151,7 @@ ]; export default { name: 'release', - components: { msgEditMod, callListMod }, + components: { msgDetailMod, callListMod }, data() { return { search:{ @@ -187,6 +193,11 @@ ] } }, + mounted() { + if(getUserInfo().role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') + } + }, created() { const t = this t.getData() @@ -208,19 +219,10 @@ t.$refs.callList.openMod(id) }, - openMod(type,data){ + openDetails(id){ const t = this - getReviewDetailByWorker(data.id).then(res=>{ - if(res.data.code == 100){ - if(res.data.data){ - t.$refs.msgEdit.openMod(type,res.data.data) - }else{ - t.$message.error('查询信息详情失败') - } - }else{ - this.$message.error(res.data.msg) - } - }) + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true }, onPageChange(page, pageSize) { @@ -238,6 +240,25 @@ } }, + viewFile(item){ + const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachment,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachmentName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + timeOk(value) { console.log('onOk: ', value); }, diff --git a/src/views/Admin/list.vue b/src/views/Admin/list.vue index 8a45500..f88ec4a 100644 --- a/src/views/Admin/list.vue +++ b/src/views/Admin/list.vue @@ -38,7 +38,7 @@ </a-row> <!-- 表格实体部分--> <div class="table-cont"> - <a-table :columns="columns" :data-source="data" bordered :pagination="pagination"> + <a-table :columns="columns" :data-source="data" bordered :pagination="pagination" :rowKey="record=>record.id"> <template #index="text,record,index"> {{index + 1}} </template> @@ -53,8 +53,11 @@ {{ getLevelName(text) }} </a-tag> </template> - <template #attachment="text"> - <a><b><a-icon type="paper-clip" /> {{text}}</b></a> + <template #attachment="attachment"> + <span v-if="attachment===null|| attachment===[]">无</span> + <div v-else> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in attachment" :key="index"><a-icon type="paper-clip"/>{{item.attachmentName}}</a-button> + </div> </template > <template #responseStatus="text"> <a-tag :color="text === 3 ? 'red' :text === 2? 'green':text === 1?'orange':'blue'"> @@ -75,11 +78,12 @@ <template #operation="text, record, index"> <a-button type="primary" v-if="record.responseStatus == 1" style="margin-right: 12px" @click="confirmResponce(record.id)">确认已收到</a-button> <a-button type="primary" @click="openMod('repost',record)">转发</a-button> - <a-button type="link" @click="openMod('view',record)">查看详情</a-button> + <a-button type="link" @click="openDetails(record,record.warnInfoId)">查看详情</a-button> </template> </a-table> </div> <msg-edit-mod ref="msgEdit" @refresh="getData"></msg-edit-mod> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> <!-- 对话框 --> <!-- <a-modal title="回执" --> <!-- okText="确认已安排部署"--> @@ -94,14 +98,19 @@ <script> import {getMsgRecord, readById, responseMsg} from "@/api/list"; import msgEditMod from "@/views/Admin/components/msgEditMod"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; import {publishMsg} from "@/api/send"; import {getReviewDetail, getReviewDetailByWorker} from "@/api/review"; +import axios from "axios"; +import Cookies from "js-cookie"; +import {getUserInfo} from "@/util/storage"; export default { name: 'list', - components: { msgEditMod }, + components: { msgEditMod, msgDetailMod }, data() { return { + userInfo: getUserInfo(), search:{ pageIndex: 1, pageSize: 10, @@ -116,7 +125,6 @@ { title: '序号', dataIndex: 'index', - width: '5%', scopedSlots: { customRender: 'index' }, @@ -124,7 +132,6 @@ { title: '发布时间', dataIndex: 'publishingTime', - width: '15%', scopedSlots: { customRender: 'publishingTime' }, //设置定制化表格数据 @@ -132,12 +139,10 @@ { title: '发布单位', dataIndex: 'publishingUnit', - width: '12%', }, { title: '灾种', dataIndex: 'disasterType', - width: '8%', scopedSlots: { customRender: 'disasterType' } @@ -148,17 +153,15 @@ scopedSlots: { customRender: 'warningLevel' }, //设置定制化表格数据 - width: '8%', }, { title: '信息标题', dataIndex: 'title', - width: '16%', }, { title: '附件', dataIndex: 'attachment', - width: '6%', + width: '15%', scopedSlots: { customRender: 'attachment' }, @@ -166,7 +169,6 @@ { title: '叫应状态', dataIndex: 'responseStatus', - width: '10%', scopedSlots: { customRender: 'responseStatus' }, //设置定制化表格数据 @@ -174,6 +176,7 @@ { title: '操作', dataIndex: 'operation', + width: '15%', scopedSlots: { customRender: 'operation' }, @@ -211,8 +214,16 @@ ] }; }, + mounted() { + if(this.userInfo.role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') + } + }, created() { const t = this + if(t.$route.query){ + t.search.searchParams.responseStatus = t.$route.query.type + } t.getData() }, methods: { @@ -242,6 +253,25 @@ } }, + viewFile(item){ + const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachment,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachmentName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + resetSearch(){ const t = this t.search = { @@ -265,14 +295,15 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - let res = await responseMsg(id) - if(res.data.code == 100){ - t.$message.success('信息叫应成功'); - t.getData() - }else{ - t.$message.warning(res.data.msg); - } + onOk() { + responseMsg(id).then(res=>{ + if(res.data.code == 100){ + t.$message.success('信息叫应成功'); + t.getData() + }else{ + t.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); @@ -285,7 +316,6 @@ getReviewDetailByWorker(data.warnInfoId).then(res=>{ if(res.data.code == 100){ if(res.data.data){ - t.read(data.id) t.$refs.msgEdit.openMod(type,res.data.data) }else{ t.$message.error('查询信息详情失败') @@ -296,11 +326,19 @@ }) }, + openDetails(data,id){ + const t = this + t.read(data.id) + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true + }, + async read(id){ const t = this const res = await readById(id) if(res.data.code == 100){ console.log('已读') + t.getData() }else{ t.$message.error('设置已读出错') } diff --git a/src/views/Admin/massSend.vue b/src/views/Admin/massSend.vue index 3e2d999..2bc3f52 100644 --- a/src/views/Admin/massSend.vue +++ b/src/views/Admin/massSend.vue @@ -1,5 +1,13 @@ <template> <div class="inner"> + <a-alert + message="管理员身份无法进行短信群发操作" + banner + closable + v-if="userInfo.role.id === 1" + type="error" + style="margin-bottom: 12px" + /> <h2>预警信息发布</h2> <a-form-model ref="ruleForm" :model="form" :rules="rules" :wrapper-col="wrapperCol"> <div class="left"> @@ -96,7 +104,7 @@ <div> <b>平级接收人选择:</b> </div> - <a-form-model-item prop="recipient"> + <a-form-model-item> <a-select mode="multiple" placeholder="选择平级接收单位" v-model="form.recipient" @change="handle"> <a-select-option v-for="item in filteredOptions" :key="item.id" :value="item.id"> {{ item.recipientName }} @@ -122,7 +130,7 @@ <!-- </a-select>--> <!-- </div>--> <div style="display: flex;justify-content: right"> - <a-button type="primary" style="width: 250px;" @click="confirmSend()"> + <a-button type="primary" style="width: 250px;" @click="confirmSend()" :disabled="userInfo.role.id==1?true:false"> 确认发送 </a-button> </div> @@ -149,7 +157,7 @@ name: "massSend", data() { return { - userInfo: {}, + userInfo: getUserInfo(), department: '自治区自然灾害综合监测预警中心', filteredOptions:[], wrapperCol: { span: 24 }, @@ -193,7 +201,7 @@ warningLevel: [{ required: true, message: '请选择预警级别', trigger: 'change'}], content: [{ required: true, message: '请输入信息内容', trigger: 'blur'}], receiver: [{ required: true, message: '请选择接收单位', trigger: 'change'}], - recipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] + // recipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] // verticalRecipient: [{ required: true, message: '请选择接收单位', trigger: 'change'}], // horizontalRecipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] } @@ -202,7 +210,6 @@ components: {}, created() { const t = this - t.userInfo = getUserInfo() t.form.publishingUnit = t.userInfo.company t.getSameLevel() t.getAreaUsers() @@ -218,7 +225,7 @@ if(res.data.data){ t.filteredOptions = res.data.data }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -235,8 +242,9 @@ t.userTitTree(res.data.data) treeD.push(t.findNodeById(res.data.data,t.userInfo.districtId)) t.areaUsers = treeD + console.log(t.areaUsers,t.unittype,'696969') }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -271,18 +279,25 @@ this.form.verticalRecipient = [] this.form.horizontalRecipient = [] const aList = this.form.receiver.map(item=>this.findNodeById(this.areaUsers,item.value)?.users) + if(aList.includes(null)){ + this.$message.error('选择接收单位时存在无用户的单位') + return + } const newAList = [].concat(...aList) for(let i of newAList){ - const {realName,...data} = i + const {realName,id,...data} = i const {company: recipientUnit,...rest} = data const obj = {recipientUnit,recipientType:1,...rest} this.form.verticalRecipient.push(obj) } - const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) - for(let i of bList){ - const {recipientName: name, company: recipientUnit,...rest} = i - const obj = {name,recipientUnit,recipientType:2,...rest} - this.form.horizontalRecipient.push(obj) + if(this.form.recipient.length>0){ + const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) + for(let i of bList){ + const {recipientName: name, company: recipientUnit,...rest} = i + const obj = {name,recipientUnit,recipientType:2,...rest} + const {id,...noId} = obj + this.form.horizontalRecipient.push(noId) + } } const {receiver,recipient,...data} = this.form massSend(data).then( res =>{ @@ -372,7 +387,7 @@ userTitTree(treeData) { for(const node of treeData){ if(node.users){ - node.name = node.name + '('+node.users.map(i=>i.name +' '+ i.phone).join(',')+')' + node.name = node.name + '('+node.users.map(i=>i.realName +' '+ i.phone).join(',')+')' } if(node.children){ this.userTitTree(node.children) diff --git a/src/views/Admin/msgRecord.vue b/src/views/Admin/msgRecord.vue index 3cf0327..87c3624 100644 --- a/src/views/Admin/msgRecord.vue +++ b/src/views/Admin/msgRecord.vue @@ -42,54 +42,31 @@ </a-card> </div> </div> - <a-pagination v-model="search.pageIndex" :total="total" :show-total="total => `共 ${total} 条数据`" show-less-items/> - <a-modal v-model="visible" width="40%" title="短信详情" @ok="handleOk" cancelText="取消" okText="确认" centered> - <div class="detail-mod"> - <a-row :gutter="24"><a-col :span="4" style="text-align: right">{{ details.emergType == 1?'紧急':details.emergType == 2?'常规':'' }}</a-col></a-row> - <a-row :gutter="24"><a-col :span="4" style="text-align: right">发送时间</a-col><a-col :span="14" style="border: 1px solid #d9d9d9;padding: 5px 10px !important;">{{details.gmtCreate}}</a-col></a-row> - <a-row :gutter="24"><a-col :span="4" style="text-align: right">灾种类型</a-col><a-col :span="14" style="border: 1px solid #d9d9d9;padding: 5px 10px !important;">{{ getRiskName(details.disasterType)}}</a-col></a-row> - <a-row :gutter="24"><a-col :span="4" style="text-align: right">预警级别</a-col><a-col :span="14" style="border: 1px solid #d9d9d9;padding: 5px 10px !important;">{{ getLevelName(details.warningLevel)}}</a-col></a-row> - <a-row :gutter="24"><a-col :span="4" style="text-align: right">信息内容</a-col><a-col :span="14" style="border: 1px solid #d9d9d9;padding: 5px 10px !important;">{{details.content}}</a-col></a-row> - <a-row :gutter="24"> - <a-col :span="4" style="text-align: right">接收人</a-col> - <a-col :span="20" style="border: 1px solid #d9d9d9;padding: 0 !important;"> - <div v-for="(item,index) in details.recipients" :key="index" class="table"> - <div style="width: 20%"> - {{item.name}} - </div> - <div style="width: 20%"> - {{item.phone}} - </div> - <div style="width: 60%"> - {{item.recipientUnit}} - </div> - </div> - </a-col> - </a-row> - </div> - </a-modal> + <a-pagination class="pageItem" v-model="search.pageIndex" :total="total" :defaultPageSize="search.pageSize" @change="onPageChange" :show-total="total => `共 ${total} 条数据`"/> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> </div> </template> <script> import {getUser} from '@/api/user' import {getMassRecord} from "@/api/send"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; export default { name: 'msgRecord', - components: {}, + components: {msgDetailMod}, data () { return { search:{ pageIndex: 1, - pageSize: 10, + pageSize: 5, searchParams:{ startTime: '', endTime: '' } }, timeRange: [], - total: 0, + total: null, msg: [], visible: false, details: {}, @@ -119,7 +96,7 @@ const res = await getMassRecord(this.search) if(res.data.code == 200){ t.msg = res.data.data - t.pagination.total = res.data.total + t.total = res.data.total }else{ this.$message.error(res.data.msg) } @@ -139,6 +116,12 @@ t.getData() }, + onPageChange(page, pageSize) { + const t= this + t.search.pageIndex = page + t.getData() + }, + timeChange(value, dateString) { const t = this if(dateString){ @@ -151,8 +134,8 @@ }, viewDetails(item){ const t = this - t.details = item - t.visible = true + t.$refs.msgDetail.details = item + t.$refs.msgDetail.visible = true }, getRiskName(disasterType){ @@ -203,29 +186,6 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - } - } - } - } -} -.detail-mod{ - font-size: 16px; - - .ant-row{ - margin-bottom: 24px; - - .table{ - display: flex; - align-items: center; - border-bottom: 1px solid @blackBorder; - &:last-of-type{ - border-bottom: none; - } - &>div{ - border-right: 1px solid @blackBorder; - padding: 5px 10px; - &:last-of-type{ - border-right: none; } } } diff --git a/src/views/Admin/msgReview.vue b/src/views/Admin/msgReview.vue index 011ba5d..f12dfe5 100644 --- a/src/views/Admin/msgReview.vue +++ b/src/views/Admin/msgReview.vue @@ -38,16 +38,18 @@ </a-row> <div class="table-cont"> - <a-table :columns="columns" :data-source="data" bordered :rowKey="record=>record.id"> + <a-table :columns="columns" :data-source="data" bordered :rowKey="record=>record.id" :pagination="pagination"> <template #index="text,record,index"> {{ index+1 }} </template> <template #disasterType="text"> {{ getRiskName(text) }} </template> - <template #attachment="text"> - <span v-if="text==='无'">无</span> - <a v-else><b><a-icon type="paper-clip" /> {{text}}</b></a> + <template #attachment="attachment"> + <span v-if="attachment===null|| attachment===[]">无</span> + <div v-else> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in attachment" :key="index"><a-icon type="paper-clip"/>{{item.attachmentName}}</a-button> + </div> </template > <template #reviewStatus="reviewStatus"> <a-tag @@ -57,12 +59,13 @@ </a-tag> </template> <template #operation="text, record, index"> - <a-button type="link" v-if="record.reviewStatus == 2 || record.reviewStatus == 3" @click="openMod('view',record)">查看信息详情</a-button> + <a-button type="link" v-if="record.reviewStatus == 2 || record.reviewStatus == 3" @click="openDetails(record.id)">查看信息详情</a-button> <a-button type="primary" v-if="record.reviewStatus == 1" @click="openMod('review',record)">查看并审核</a-button> </template> </a-table> </div> <msg-edit-mod ref="msgEdit" @refresh="getData"></msg-edit-mod> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> </div> </template> @@ -70,12 +73,17 @@ import {getReviewDetail, getReviewRecord} from "@/api/review"; import msgEditMod from '@/views/Admin/components/msgEditMod' +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; +import axios from "axios"; +import Cookies from "js-cookie"; +import {getUserInfo} from "@/util/storage"; export default { name: 'msgReview', - components: { msgEditMod }, + components: { msgEditMod, msgDetailMod }, data () { return { + userInfo: getUserInfo(), search:{ pageIndex: 1, pageSize: 10, @@ -94,6 +102,14 @@ {name: '水旱',value: 5}, {name: '森林草原火灾',value: 6} ], + pagination: { + current: 1, + defaultCurrent: 1, + defaultPageSize: 10, + total: 0, + onChange: ( page, pageSize ) => this.onPageChange(page,pageSize), + showTotal: total => `共 ${total} 条` + }, columns: [ { title: '序号', @@ -132,6 +148,7 @@ scopedSlots: { customRender: 'attachment' }, + width: '15%' }, { title: '审核情况', @@ -151,8 +168,16 @@ data: [] } }, + mounted() { + if(getUserInfo().role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') + } + }, created() { const t = this + if(t.$route.query){ + t.search.searchParams.reviewStatus = t.$route.query.type + } t.getData() }, methods:{ @@ -190,6 +215,32 @@ } }, + onPageChange(page, pageSize) { + const t= this + t.pagination.current = page + t.search.pageIndex = page + t.getData() + }, + + viewFile(item){ + const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachment,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachmentName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + openMod(type,data){ const t = this getReviewDetail(data.id).then(res=>{ @@ -201,6 +252,12 @@ }) }, + openDetails(id){ + const t = this + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true + }, + onOk(value) { console.log('onOk: ', value); }, diff --git a/src/views/Admin/notice.vue b/src/views/Admin/notice.vue index aa3a28d..1511dac 100644 --- a/src/views/Admin/notice.vue +++ b/src/views/Admin/notice.vue @@ -1,5 +1,13 @@ <template> <div class="inner"> + <a-alert + message="管理员身份无法进行信息编辑操作" + banner + closable + v-if="userInfo.role.id === 1" + type="error" + style="margin-bottom: 12px" + /> <h2>预警信息发布</h2> <a-form-model ref="ruleForm" :model="form" :rules="rules" :wrapper-col="wrapperCol"> <div class="left"> @@ -52,7 +60,17 @@ </a-form-model-item> <a-row> <a-col :span="12"> - <a-button>上传附件</a-button> + <a-upload + :action="uploadUrl" + :file-list="fileList" + @change="fileChange" + :headers="header" + accept=".doc, .docx, .word, .pdf, .zip, .xlsx, .rar" + :data="{module: 'naturalDisasterPath'}" + :remove="(file)=>{removeFile(file)}" + > + <a-button> <a-icon type="upload" />上传附件</a-button> + </a-upload> </a-col> <a-col :span="12" style="display: flex;align-items: center;justify-content: right"> <b style="margin-bottom: 24px">超时设置:</b> @@ -108,25 +126,23 @@ <b style="margin-bottom: 6px">选择审批领导:</b> <a-form-model-item prop="reviewId"> <a-select show-search v-model="form.reviewId" placeholder="请选择审批领导" style="width: 300px"> - <a-select-option v-for="(item,index) in leaders" :value="item.id" :key="index">{{item.name}}</a-select-option> + <a-select-option v-for="(item,index) in leaders" :value="item.id" :key="index">{{item.realName}}</a-select-option> </a-select> </a-form-model-item> </a-col> <a-col :span="12" style="text-align: right"> - <a-button type="primary" style="width: 250px;" @click="confirmSend()"> + <a-button type="primary" style="width: 250px;" @click="confirmSend()" :disabled="userInfo.role.id==1?true:false"> 确认并提交审核 </a-button> </a-col> </a-row> </div> - <div class="right"> <h2>短信预览</h2> <div class="mobile"> <div class="mesg"> - <P>【{{form.title}}】{{form.content}}。发布单位:{{form.publishingUnit}}</P> + <P>【自然灾害风险预警提示】{{form.content}}<br>发布单位:{{form.publishingUnit}}</P> </div> - </div> </div> </a-form-model> @@ -137,7 +153,9 @@ import {getAreaWithUserIfo, getPeerRecipient, getLeaders} from '@/api/user' import {getUserInfo} from "@/util/storage"; import Cookies from "js-cookie"; + import axios from "axios"; import {massSend, msgSend} from "@/api/send"; +import {deleteFile} from "@/api/list"; export default { name: "notice", data() { @@ -197,13 +215,23 @@ recipient: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] // acceptingUnitIds: [{ required: true, message: '请选择接收单位', trigger: 'change'}], // peerRecipientIds: [{ required: true, message: '请选择平级接收人', trigger: 'change'}] - } + }, + uploadUrl: '', + fileList: [], + header: { + uid: null, + tk: Cookies.get('resTk') + }, + delList: [] }; }, components: {}, created() { const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + t.uploadUrl= baseUrl + '/attachment/upload/detail' t.userInfo = getUserInfo() + t.header.uid = t.userInfo.uid t.form.districtId = t.userInfo.districtId t.form.publishingUnit = t.userInfo.company t.getSameLevel() @@ -220,7 +248,7 @@ if(res.data.data){ t.filteredOptions = res.data.data }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -233,14 +261,14 @@ let res = await getAreaWithUserIfo() if(res.data.code == 100){ if(res.data.data){ - const treeD = [] + // const treeD = [] t.userTitTree(res.data.data) - const obj = t.findNodeById(res.data.data,t.userInfo.districtId) - treeD.push(t.removeNodesWithoutUsers(obj)) - t.areaUsers = treeD + // treeD.push(t.findNodeById(res.data.data,t.userInfo.districtId)) + console.log(res.data.data) + t.areaUsers = t.findNodeById(res.data.data,t.userInfo.districtId).children t.unittype = this.findNodeById(this.areaUsers,t.userInfo.districtId)?.type }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -255,7 +283,7 @@ if(res.data.data){ t.leaders = res.data.data }else{ - this.$message.warning('暂无数据'); + console.log('暂无数据') } }else{ this.$message.warning(res.data.msg); @@ -279,34 +307,79 @@ } }, + fileChange(info) { + let fileList = [...info.fileList]; + // 2. read from response and show file link + fileList = fileList.map(file => { + if(file.status == 'done'){ + if (file.response) { + const res = file.response + if(res.code == 100){ + this.$message.success('文件上传成功') + }else{ + this.$message.error('文件上传失败') + } + // Component will show file.url as link + file.url = res.data.fileUrl + } + } + return file; + }); + this.fileList = fileList; + }, + + removeFile(file){ + this.delList.push(file.uid) + }, + + async deleteFile(){ + const t = this + for(let i of t.delList){ + const res = await deleteFile(i) + if(res.data.code == 100){ + console.log('文件删除成功') + }else{ + t.$message.error(res.data.msg) + } + } + }, + confirmSend(){ this.$refs.ruleForm.validate(valid => { if (valid) { this.form.acceptingUnitIds = [] this.form.peerRecipientIds = [] const aList = this.form.receiver.map(item=>this.findNodeById(this.areaUsers,item.value)?.users) - console.log(aList,'a') + if(aList.includes(null)){ + this.$message.error('选择接收单位时存在无用户的单位') + return + } const newAList = [].concat(...aList) - console.log(newAList,'b') for(let i of newAList){ const {realName,...data} = i const {id:recipienterId,name: recipienterName,phone: recipienterPhone,company: receiveUnit,...rest} = data const obj = { recipienterId, recipienterName, recipienterPhone, receiveUnit,...rest} this.form.acceptingUnitIds.push(obj) } - const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) - for(let i of bList){ - const {id:recipienterId,recipientName: recipienterName,phone: recipienterPhone, company: receiveUnit,...rest} = i - const obj = {recipienterId, recipienterName,recipienterPhone,receiveUnit,unittype:this.unittype,...rest} - this.form.peerRecipientIds.push(obj) + if(this.form.recipient.length>0){ + const bList = this.form.recipient.map(item => this.filteredOptions.find(i=>i.id == item)) + for(let i of bList){ + const {id:recipienterId,recipientName: recipienterName,phone: recipienterPhone, company: receiveUnit,...rest} = i + const obj = {recipienterId, recipienterName,recipienterPhone,receiveUnit,unittype:this.unittype,...rest} + this.form.peerRecipientIds.push(obj) + } } + this.form.attachments = this.fileList.map(i=>i.response.data.id) const {receiver,recipient,id,...data} = this.form msgSend(data).then( res =>{ if(res.data.code == 100){ + this.deleteFile() this.$message.success('信息已提交审核') }else{ this.$message.error(res.data.msg) } + this.fileList = [] + this.delList = [] this.$refs.ruleForm.clearValidate() this.$refs.ruleForm.resetFields() }) @@ -353,6 +426,7 @@ userTitTree(treeData) { for(const node of treeData){ if(node.users){ + node.users = node.users.filter(i=>i.roleId == 3) node.users = node.users.map((i)=>{ return{ ...i, @@ -360,7 +434,7 @@ districtId: node.id } }) - node.name = node.name + '('+node.users.map(i=>i.name +' '+ i.phone).join(',')+')' + node.name = node.name + '('+node.users.map(i=>i.realName +' '+ i.phone).join(',')+')' } if(node.children){ this.userTitTree(node.children) @@ -369,15 +443,15 @@ return treeData }, // 将users为null的节点删除 - removeNodesWithoutUsers(node) { - if (node.users === null) { - return null; // 返回 null 表示删除节点 - } - if (node.children && node.children.length > 0) { - node.children = node.children.map(child => this.removeNodesWithoutUsers(child)).filter(Boolean); - } - return node; - }, + // removeNodesWithoutUsers(node) { + // if (node.users === null && node.children === null) { + // return null; // 返回 null 表示删除节点 + // } + // if (node.children && node.children.length > 0) { + // node.children = node.children.map(child => this.removeNodesWithoutUsers(child)).filter(Boolean); + // } + // return node; + // }, onSearch() { console.log(...arguments); @@ -395,24 +469,6 @@ handleLevel(selectedItems) { // this.selectedItems = selectedItems; }, - - onChange(){ - console.log(this.value) - }, - handleChange(value) { - console.log(`selected ${value}`); - }, - handleBlur() { - console.log('blur'); - }, - handleFocus() { - console.log('focus'); - }, - filterOption(input, option) { - return ( - option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 - ); - }, }, } </script> diff --git a/src/views/Admin/release.vue b/src/views/Admin/release.vue index 162678b..3a7589a 100644 --- a/src/views/Admin/release.vue +++ b/src/views/Admin/release.vue @@ -36,7 +36,7 @@ <!-- 表格实体部分--> <div class="table-cont"> - <a-table :columns="columns" :data-source="data" bordered :pagination="pagination"> + <a-table :columns="columns" :data-source="data" bordered :pagination="pagination" :rowKey="record=>record.id"> <template #index="text,record,index"> {{ index + 1 }} </template> @@ -54,8 +54,11 @@ {{ getLevelName(text) }} </a-tag> </template> - <template #attachment="text"> - <a><b><a-icon type="paper-clip"/></b></a> + <template #attachment="attachment"> + <span v-if="attachment===null|| attachment===[]">无</span> + <div v-else> + <a-button @click="viewFile(item)" type="link" v-for="(item,index) in attachment" :key="index"><a-icon type="paper-clip"/>{{item.attachmentName}}</a-button> + </div> </template > <template #responseSituation="text"> <a-tag :color="text === 3 ? 'red' :text === 2? 'green':text === 1?'orange':'blue'"> @@ -64,10 +67,10 @@ </template> <template #operation="text, record, index"> <a-button type="primary" @click="openList(record.id)">叫应列表</a-button> - <a-button type="link" @click="openMod('view',record)">查看详情</a-button> + <a-button type="link" @click="openDetails(record.id)">查看详情</a-button> </template> </a-table> - <msg-edit-mod ref="msgEdit" @refresh="getData"></msg-edit-mod> + <msg-detail-mod ref="msgDetail"></msg-detail-mod> <call-list-mod ref="callList" @refresh="getData"></call-list-mod> </div> <!-- 对话框 --> @@ -80,9 +83,12 @@ </template> <script> import {getMsgRecord, getPublishRecord} from "@/api/list"; -import msgEditMod from "@/views/Admin/components/msgEditMod"; +import msgDetailMod from "@/views/Admin/components/msgDetailMod"; import callListMod from "@/views/Admin/components/callListMod"; import {getReviewDetailByWorker} from "@/api/review"; +import axios from "axios"; +import Cookies from "js-cookie"; +import {getUserInfo} from "@/util/storage"; const columns = [{ title: '序号', dataIndex: 'index', @@ -128,7 +134,7 @@ { title: '附件', dataIndex: 'attachment', - width: '6%', + width: '15%', scopedSlots: { customRender: 'attachment' }, @@ -151,7 +157,7 @@ ]; export default { name: 'release', - components: { msgEditMod, callListMod }, + components: { msgDetailMod, callListMod }, data() { return { search:{ @@ -193,6 +199,11 @@ ] } }, + mounted() { + if(getUserInfo().role.id == 1){ + this.columns = this.columns.filter(i=>i.dataIndex !== 'operation') + } + }, created() { const t = this t.getData() @@ -214,19 +225,10 @@ t.$refs.callList.openMod(id) }, - openMod(type,data){ + openDetails(id){ const t = this - getReviewDetailByWorker(data.id).then(res=>{ - if(res.data.code == 100){ - if(res.data.data){ - t.$refs.msgEdit.openMod(type,res.data.data) - }else{ - t.$message.error('查询信息详情失败') - } - }else{ - this.$message.error(res.data.msg) - } - }) + t.$refs.msgDetail.getDetails(id) + t.$refs.msgDetail.visible = true }, onPageChange(page, pageSize) { @@ -244,6 +246,25 @@ } }, + viewFile(item){ + const t = this + const { baseUrl } = require('../../../config/env.' + process.env.NODE_ENV) + axios.get(baseUrl + item.attachment,{headers:{'Content-Type': 'application/json','tk': `${Cookies.get('resTk')}`,'uid':`${Cookies.get('resUid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", item.attachmentName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) + }, + timeOk(value) { console.log('onOk: ', value); }, diff --git a/src/views/Admin/sameLevel.vue b/src/views/Admin/sameLevel.vue index 09231d2..23317e6 100644 --- a/src/views/Admin/sameLevel.vue +++ b/src/views/Admin/sameLevel.vue @@ -119,7 +119,6 @@ }, created() { const t = this - console.log(getUserInfo(),'id') t.unittype = getUserInfo().unittype t.districtId = getUserInfo().districtId t.getUserList() @@ -189,14 +188,15 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - let res = await delRecipient(row.id) - if(res.data.code == 100){ - t.$message.success('删除用户信息成功'); - t.getUserList() - }else{ - t.$message.warning(res.data.msg); - } + onOk() { + delRecipient(row.id).then(res=>{ + if(res.data.code == 100){ + t.$message.success('删除用户信息成功'); + t.getUserList() + }else{ + t.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); diff --git a/src/views/Admin/userManage.vue b/src/views/Admin/userManage.vue index 7c24e36..585a1d8 100644 --- a/src/views/Admin/userManage.vue +++ b/src/views/Admin/userManage.vue @@ -215,14 +215,15 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - let res = await delUser(row.id) - if(res.data.code == 100){ - t.$message.success('删除用户信息成功'); - t.getUserList() - }else{ - t.$message.warning(res.data.msg); - } + onOk() { + delUser(row.id).then(res=>{ + if(res.data.code == 100){ + t.$message.success('删除用户信息成功'); + t.getUserList() + }else{ + t.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); diff --git a/src/views/Home.vue b/src/views/Home.vue index abcedf0..e62029e 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -57,7 +57,7 @@ name: "Home", data() { return { - userInfo: {}, + userInfo: getUserInfo(), collapsed: false, //返回logo图片或表述 pageList: [], activePage: '', @@ -70,8 +70,6 @@ pwdMod }, created() { - this.userInfo = getUserInfo() - // this.getDistrictInfo() const route = this.$route if (this.pageList.findIndex(item => item.path === route.path) === -1) { this.pageList.push(this.createPage(route)) @@ -122,16 +120,17 @@ cancelText: '取消', okText: '确认', centered: true, - async onOk() { - const res = await loginOut() - if (res.data.code === 100) { - Session.clear(); // 清除缓存/token等 - // 使用 reload 时,不需要调用 resetRoute() 重置路由 - t.$router.push('/') - // window.location.reload(); - } else { - this.$message.warning(res.data.msg); - } + onOk() { + loginOut().then(res=>{ + if (res.data.code === 100) { + Session.clear(); // 清除缓存/token等 + // 使用 reload 时,不需要调用 resetRoute() 重置路由 + t.$router.push('/') + // window.location.reload(); + } else { + this.$message.warning(res.data.msg); + } + }) }, onCancel() { console.log('Cancel'); -- Gitblit v1.9.2