马宇豪
2023-06-21 7c906b4acf785180132f91db5d70c3a29fa85cd3
新增页面和配置,对接口
已修改30个文件
已添加2个文件
已删除1个文件
1942 ■■■■ 文件已修改
config/env.development.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/env.production.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/list.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/themeColor.less 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Home/Dynamic.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Home/Projecting.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Home/QuickNavigation.vue 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Home/Review.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/menu/index.js 264 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/menuSider.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/AntDesign.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/request.js 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/validate.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/Details.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/HomeDefault.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/Report.vue 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/callRecord.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/callListMod.vue 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/msgDetailMod.vue 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/msgEditMod.vue 223 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/sameLevelMod.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/userMod.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/history.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/list.vue 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/massSend.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/msgRecord.vue 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/msgReview.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/notice.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/release.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/sameLevel.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/userManage.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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',
}
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',
}
src/api/list.js
@@ -62,5 +62,10 @@
    })
}
// 删除文件
export function deleteFile(id){
    return request({
        url: '/attachment/delete/' + id,
        method: 'get'
    })
}
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);
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>
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;
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>
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>
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;
export default menu;
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) {
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'),
        },
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);
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);
    },
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 当前值字符串
src/views/Admin/Details.vue
文件已删除
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 () {
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=>{
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) {
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'
          } //设置定制化表格数据
        }
      ]
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>
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)
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('新增平级接收人成功')
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()
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);
    },
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('设置已读出错')
        }
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)
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;
        }
      }
    }
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);
    },
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>
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);
      },
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');
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');
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');