马宇豪
2023-06-05 daa4b6c11281722578fa4e03ad690401d7c0ea4d
新增页面和配置
已修改11个文件
已添加20个文件
已删除5个文件
23151 ■■■■■ 文件已修改
config/env.development.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/env.production.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 19918 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/user.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/theme.css 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/themeColor.less 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/menu/index.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/AntDesign.js 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/request.js 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/storage.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/util/validate.js 368 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/History.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/List.vue 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/Release.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/Report.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/Response.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/UserManage.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/callRecord.vue 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/pwdMod.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/sameLevelMod.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/components/userMod.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/list.vue 283 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/menuManage.vue 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/msgRecord.vue 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/release.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/sameLevel.vue 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Admin/userManage.vue 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/SameLevel.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/env.development.js
对比新文件
@@ -0,0 +1,4 @@
module.exports = {
    NODE_ENV: "development",
    baseUrl: 'http://192.168.0.38:8086',
}
config/env.production.js
对比新文件
@@ -0,0 +1,4 @@
module.exports = {
    NODE_ENV: "production",
    baseUrl: 'http://192.168.0.38:8086',
}
package-lock.json
文件太大
package.json
@@ -8,11 +8,16 @@
  },
  "dependencies": {
    "ant-design-vue": "^1.7.7",
    "axios": "^1.4.0",
    "core-js": "^3.6.5",
    "echarts": "^5.1.2",
    "js-cookie": "^3.0.5",
    "json-bigint": "^1.0.0",
    "moment": "^2.29.1",
    "quill-image-resize-module": "^3.0.0",
    "style-resources-loader": "^1.5.0",
    "vue": "^2.6.11",
    "vue-cli-plugin-style-resources-loader": "^0.1.5",
    "vue-quill-editor": "^3.0.6",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
src/App.vue
@@ -16,7 +16,9 @@
}
.inner{
    background-color: #fff;padding: 20px 10px;
    height: 100vh;
    height: 88vh;
  overflow: hidden;
  overflow-y: scroll;
}
.ftright{
    float:right;
src/api/login.js
对比新文件
@@ -0,0 +1,17 @@
//将拦截器整体导入
import request from '@/util/request'//导入已经写好的拦截器
export function Login(data){
    return request({
        url:'/account/auth/login',
        method:'post',
        data: data,
    })
}
export function getMenuAdmin(){
    return request({
        url:'/sys/menu/get/u',
        method:'get',
    })
}
src/api/user.js
对比新文件
@@ -0,0 +1,18 @@
//将拦截器整体导入
import request from '@/util/request'//导入已经写好的拦截器
export function getUser(data){
    return request({
        url:'/account/user/find/user/list',
        method:'post',
        data:data,
    })
}
export function addUser(data){
    return request({
        url:'/account/user/add',
        method:'post',
        data: data,
    })
}
src/assets/style/theme.css
对比新文件
@@ -0,0 +1,3 @@
.mid-input{
    width: 200px !important;
}
src/assets/style/themeColor.less
对比新文件
@@ -0,0 +1,6 @@
@base: #1890ff;
@link: #1890ff;
@success: #52c41a;
@warning: #faad14;
@danger: #f5222d;
@blackText: rgba(0,0,0,.65);
src/layout/menu/index.js
@@ -51,7 +51,7 @@
            {
                MenuID: "23",
                MenuTitle: "叫应记录",
                MenuPath: "/responses",
                MenuPath: "/callRecord",
            },
        ],
    },
@@ -67,7 +67,7 @@
            {
                MenuID: "32",
                MenuTitle: "短信记录",
                MenuPath: "/",
                MenuPath: "/msgRecord",
            },
            {
                MenuID: "33",
@@ -90,11 +90,11 @@
                MenuTitle: "短信平台设置",
                MenuPath: "/smssetting",
            },
            {
                MenuID: "43",
                MenuTitle: "菜单权限",
                MenuPath: "/munu",
            },
            // {
            //     MenuID: "43",
            //     MenuTitle: "菜单权限",
            //     MenuPath: "/menu",
            // },
        ],
    },
]
src/main.js
@@ -5,6 +5,7 @@
import './util/AntDesign'
import 'ant-design-vue/dist/antd.css'
import moment from 'moment'
//设置组件默认中文
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
src/router/index.js
@@ -32,13 +32,13 @@
        path: '/release',
        name: 'release',
        meta: { title: '我发布的' },
        component: () => import('@/views/Admin/Release'),
        component: () => import('@/views/Admin/release'),
      },
      {
        path: '/list',
        name: 'list',
        meta: { title: '我收到的' },
        component: () => import('@/views/Admin/List'),
        component: () => import('@/views/Admin/list'),
      },
      {
        path: '/details',
@@ -71,23 +71,35 @@
        component: () => import('@/views/Admin/History'),
      },
      {
        path: '/responses',
        name: 'response',
        path: '/callRecord',
        name: 'callRecord',
        meta: { title: '叫应记录' },
        component: () => import('@/views/Admin/Response'),
        component: () => import('@/views/Admin/callRecord'),
      },
        {
            path: '/msgRecord',
            name: 'msgRecord',
            meta: { title: '短信记录' },
            component: () => import('@/views/Admin/msgRecord'),
        },
      {
        path: '/samelevel',
        name: 'samelevel',
        meta: { title: '叫应记录' },
        component: () => import('@/views/SameLevel'),
        meta: { title: '平级接收人管理' },
        component: () => import('@/views/Admin/sameLevel'),
      },
      {
        path: '/user',
        name: 'user',
        meta: { title: '管理' },
        component: () => import('@/views/Admin/UserManage'),
        meta: { title: '用户管理' },
        component: () => import('@/views/Admin/userManage'),
      },
        {
            path: '/menu',
            name: 'menu',
            meta: { title: '菜单管理' },
            component: () => import('@/views/Admin/menuManage'),
        },
    ]
  },
];
@@ -97,10 +109,10 @@
  base: process.env.BASE_URL,
  routes,
});
// 全局后置钩子
router.afterEach((to) => {
  // 设置title
  document.title = to.meta.title;
// 全局后置钩子
router.afterEach((to) => {
  // 设置title
  document.title = to.meta.title;
});
export default router;
src/util/AntDesign.js
@@ -17,35 +17,18 @@
  Tooltip,
  Dropdown,
  Select,
  Switch,
  Radio,
  DatePicker,
  Table,
  Tag,
  Modal,
  TreeSelect,
  Alert
  Alert,
  Cascader,
  Pagination,
  FormModel,
  message
} from "ant-design-vue";
Vue.use(Alert);
Vue.use(TreeSelect);
Vue.use(Button);
Vue.use(Layout);
Vue.use(Menu);
Vue.use(Icon);
Vue.use(Form);
Vue.use(Input);
Vue.use(Tabs);
Vue.use(Checkbox);
Vue.use(Row);
Vue.use(Col);
Vue.use(Avatar);
Vue.use(Divider);
Vue.use(Card);
Vue.use(List);
Vue.use(Tooltip);
Vue.use(Dropdown);
Vue.use(Select);
Vue.use(Radio);
Vue.use(DatePicker);
Vue.use(Table);
Vue.use(Tag);
Vue.use(Modal);
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.prototype.$message = message;
src/util/request.js
对比新文件
@@ -0,0 +1,78 @@
import axios from "axios";//原生的axios
import Cookies from 'js-cookie';
import { Session } from '@/util/storage';
//用来拦截用的
axios.defaults.headers.post["Content-Type"] = "application/json;charset=utf-8";
//创建一个单例
const { baseUrl } = require('../../config/env.' + process.env.NODE_ENV)
const http= axios.create({
    baseURL: baseUrl,
    timeout: 5000,//响应时间
    // headers:{"Content-Type":"application/json;charset=utf-8"},
})
//拦截器  -请求拦截
http.interceptors.request.use(config=>{
    // 部分接口需要token
    let token = Cookies.get('resTk')
    let uid = Cookies.get('resUid')
    if(token){
        config.headers.tk = token;
        config.headers.uid = uid
        // config.headers ={
        // 'token':token
        // }
    }
    return config;
},err=>{
    return Promise.reject(err)
})
//拦截器  -响应拦截
http.interceptors.response.use(
    (response) => {
        // 对响应数据做点什么
        if (response.data.code && response.data.code === 'A0213') {
            this.$message.error('用户uid不存在');
            // useLoginApi()
            //     .signOut()
            //     .then(() => {
            //         Session.clear();
            //         window.location.href = '/';
            //     });
        } else if (response.data.code && response.data.code === 405) {
            this.$message.error('token失效');
            // useLoginApi()
            //     .signOut()
            //     .then(() => {
            //         Session.clear();
            //         window.location.href = '/';
            //     });
        }
        return Promise.resolve(response);
    },
    (error) => {
        // 对响应错误做点什么
        if (error.message.indexOf('timeout') != -1) {
            this.$message.error('网络超时');
            setTimeout(() => {
                Session.clear();
                window.location.href = '/';
            }, 1000);
        } else if (error.message == 'Network Error') {
            this.$message.error('网络连接错误');
            setTimeout(() => {
                Session.clear();
                window.location.href = '/';
            }, 1000);
        } else {
            if (error.response.data) this.$message.error(error.response.data.error);
            else this.$message.error('接口路径找不到');
        }
        return Promise.reject(error);
    }
);
//整体导出
export default http;
src/util/storage.js
对比新文件
@@ -0,0 +1,59 @@
import Cookies from 'js-cookie';
/**
 * window.localStorage 浏览器永久缓存
 * @method set 设置永久缓存
 * @method get 获取永久缓存
 * @method remove 移除永久缓存
 * @method clear 移除全部永久缓存
 */
export const Local = {
    // 设置永久缓存
    set(key, val) {
        window.localStorage.setItem(key, JSON.stringify(val));
    },
    // 获取永久缓存
    get(key) {
        let json = window.localStorage.getItem(key);
        return JSON.parse(json);
    },
    // 移除永久缓存
    remove(key) {
        window.localStorage.removeItem(key);
    },
    // 移除全部永久缓存
    clear() {
        window.localStorage.clear();
    },
};
/**
 * window.sessionStorage 浏览器临时缓存
 * @method set 设置临时缓存
 * @method get 获取临时缓存
 * @method remove 移除临时缓存
 * @method clear 移除全部临时缓存
 */
export const Session = {
    // 设置临时缓存
    set(key, val) {
        if (key === 'token') return Cookies.set(key, val);
        window.sessionStorage.setItem(key, JSON.stringify(val));
    },
    // 获取临时缓存
    get(key) {
        if (key === 'token') return Cookies.get(key);
        let json = window.sessionStorage.getItem(key);
        return JSON.parse(json);
    },
    // 移除临时缓存
    remove(key) {
        if (key === 'token') return Cookies.remove(key);
        window.sessionStorage.removeItem(key);
    },
    // 移除全部临时缓存
    clear() {
        Cookies.remove('token');
        window.sessionStorage.clear();
    },
};
src/util/validate.js
对比新文件
@@ -0,0 +1,368 @@
/**
 * 2020.11.29 lyt 整理
 * 工具类集合,适用于平时开发
 * 新增多行注释信息,鼠标放到方法名即可查看
 */
/**
 * 验证百分比(不可以小数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberPercentage(val){
    // 匹配空格
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 只能是数字和小数点,不能是其他输入
    v = v.replace(/[^\d]/g, '');
    // 不能以0开始
    v = v.replace(/^0/g, '');
    // 数字超过100,赋值成最大值100
    v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
    // 返回结果
    return v;
}
/**
 * 验证百分比(可以小数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberPercentageFloat(val) {
    let v = verifyNumberIntegerAndFloat(val);
    // 数字超过100,赋值成最大值100
    v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
    // 超过100之后不给再输入值
    v = v.replace(/^100\.$/, '100');
    // 返回结果
    return v;
}
/**
 * 小数或整数(不可以负数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberIntegerAndFloat(val) {
    // 匹配空格
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 只能是数字和小数点,不能是其他输入
    v = v.replace(/[^\d.]/g, '');
    // 以0开始只能输入一个
    v = v.replace(/^0{2}$/g, '0');
    // 保证第一位只能是数字,不能是点
    v = v.replace(/^\./g, '');
    // 小数只能出现1位
    v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
    // 小数点后面保留2位
    v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
    // 返回结果
    return v;
}
/**
 * 0到9
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyString(val) {
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 只能是数字和小数点,不能是其他输入
    v = v.replace(/[^\d.]/g, '');
    // 以0开始只能输入一个
    v = v.replace(/^\./g, '');
    // 小数只能出现1位
    v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
    // 小数点后面保留2位
    v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
    // 返回结果
    return v;
}
/**
 * 正整数验证
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifiyNumberInteger(val) {
    // 匹配空格
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
    v = v.replace(/[\.]*/g, '');
    // 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
    v = v.replace(/(^0[\d]*)$/g, '0');
    // 首位是0,只能出现一次
    v = v.replace(/^0\d$/g, '0');
    // 只匹配数字
    v = v.replace(/[^\d]/g, '');
    // 返回结果
    return v;
}
/**
 * 去掉中文及空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyCnAndSpace(val) {
    // 匹配中文与空格
    let v = val.replace(/[\u4e00-\u9fa5\s]+/g, '');
    // 匹配空格
    v = v.replace(/(^\s*)|(\s*$)/g, '');
    // 返回结果
    return v;
}
/**
 * 去掉英文及空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyEnAndSpace(val) {
    // 匹配英文与空格
    let v = val.replace(/[a-zA-Z]+/g, '');
    // 匹配空格
    v = v.replace(/(^\s*)|(\s*$)/g, '');
    // 返回结果
    return v;
}
/**
 * 禁止输入空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyAndSpace(val) {
    // 匹配空格
    let v = val.replace(/(^\s*)|(\s*$)/g, '');
    // 返回结果
    return v;
}
/**
 * 金额用 `,` 区分开
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberComma(val) {
    // 调用小数或整数(不可以负数)方法
    let v = verifyNumberIntegerAndFloat(val);
    // 字符串转成数组
    v = v.toString().split('.');
    // \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符
    v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    // 数组转字符串
    v = v.join('.');
    // 返回结果
    return v;
}
/**
 * 匹配文字变色(搜索时)
 * @param val 当前值字符串
 * @param text 要处理的字符串值
 * @param color 搜索到时字体高亮颜色
 * @returns 返回处理后的字符串
 */
export function verifyTextColor(val, text = '', color = 'red') {
    // 返回内容,添加颜色
    let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`);
    // 返回结果
    return v;
}
/**
 * 数字转中文大写
 * @param val 当前值字符串
 * @param unit 默认:仟佰拾亿仟佰拾万仟佰拾元角分
 * @returns 返回处理后的字符串
 */
export function verifyNumberCnUppercase(val, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
    // 当前内容字符串添加 2个0,为什么??
    val += '00';
    // 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1
    let lookup = val.indexOf('.');
    // substring:不包含结束下标内容,substr:包含结束下标内容
    if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);
    // 根据内容 val 的长度,截取返回对应大写
    unit = unit.substr(unit.length - val.length);
    // 循环截取拼接大写
    for (let i = 0; i < val.length; i++) {
        v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
    }
    // 正则处理
    v = v
        .replace(/零角零分$/, '整')
        .replace(/零[仟佰拾]/g, '零')
        .replace(/零{2,}/g, '零')
        .replace(/零([亿|万])/g, '$1')
        .replace(/零+元/, '元')
        .replace(/亿零{0,3}万/, '亿')
        .replace(/^元/, '零元');
    // 返回结果
    return v;
}
/**
 * 手机号码
 * @param val 当前值字符串
 * @returns 返回 true: 手机号码正确
 */
export function verifyPhone(val) {
    // false: 手机号码不正确
    if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0|1,5-9]))\d{8}$/.test(val)) return false;
    // true: 手机号码正确
    else return true;
}
/**
 * 国内电话号码
 * @param val 当前值字符串
 * @returns 返回 true: 国内电话号码正确
 */
export function verifyTelPhone(val) {
    // false: 国内电话号码不正确
    if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false;
    // true: 国内电话号码正确
    else return true;
}
/**
 * 登录账号 (字母开头,允许5-16字节,允许字母数字下划线)
 * @param val 当前值字符串
 * @returns 返回 true: 登录账号正确
 */
export function verifyAccount(val) {
    // false: 登录账号不正确
    if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false;
    // true: 登录账号正确
    else return true;
}
/**
 * 密码 (以字母开头,长度在6~16之间,只能包含字母、数字和下划线)
 * @param val 当前值字符串
 * @returns 返回 true: 密码正确
 */
export function verifyPassword(val) {
    // false: 密码不正确
    if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false;
    // true: 密码正确
    else return true;
}
/**
 * 强密码 (字母+数字+特殊字符,长度在6-16之间)
 * @param val 当前值字符串
 * @returns 返回 true: 强密码正确
 */
export function verifyPasswordPowerful(val) {
    // false: 强密码不正确
    if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) return false;
    // true: 强密码正确
    else return true;
}
/**
 * 密码强度
 * @param val 当前值字符串
 * @description 弱:纯数字,纯字母,纯特殊字符
 * @description 中:字母+数字,字母+特殊字符,数字+特殊字符
 * @description 强:字母+数字+特殊字符
 * @returns 返回处理后的字符串:弱、中、强
 */
export function verifyPasswordStrength(val) {
    let v = '';
    // 弱:纯数字,纯字母,纯特殊字符
    if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱';
    // 中:字母+数字,字母+特殊字符,数字+特殊字符
    if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中';
    // 强:字母+数字+特殊字符
    if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '强';
    // 返回结果
    return v;
}
/**
 * IP地址
 * @param val 当前值字符串
 * @returns 返回 true: IP地址正确
 */
export function verifyIPAddress(val) {
    // false: IP地址不正确
    if (!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(val)) return false;
    // true: IP地址正确
    else return true;
}
/**
 * 邮箱
 * @param val 当前值字符串
 * @returns 返回 true: 邮箱正确
 */
export function verifyEmail(val) {
    // false: 邮箱不正确
    if (!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)) return false;
    // true: 邮箱正确
    else return true;
}
/**
 * 身份证
 * @param val 当前值字符串
 * @returns 返回 true: 身份证正确
 */
export function verifyIdCard(val) {
    // false: 身份证不正确
    if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false;
    // true: 身份证正确
    else return true;
}
/**
 * 姓名
 * @param val 当前值字符串
 * @returns 返回 true: 姓名正确
 */
export function verifyFullName(val) {
    // false: 姓名不正确
    if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false;
    // true: 姓名正确
    else return true;
}
/**
 * 邮政编码
 * @param val 当前值字符串
 * @returns 返回 true: 邮政编码正确
 */
export function verifyPostalCode(val) {
    // false: 邮政编码不正确
    if (!/^[1-9][0-9]{5}$/.test(val)) return false;
    // true: 邮政编码正确
    else return true;
}
/**
 * url 处理
 * @param val 当前值字符串
 * @returns 返回 true: url 正确
 */
export function verifyUrl(val) {
    // false: url不正确
    if (!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(val)) return false;
    // true: url正确
    else return true;
}
/**
 * 车牌号
 * @param val 当前值字符串
 * @returns 返回 true:车牌号正确
 */
export function verifyCarNum(val) {
    // false: 车牌号不正确
    if (!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(val)) return false;
    // true:车牌号正确
    else return true;
}
src/views/Admin/History.vue
@@ -17,7 +17,7 @@
            </a-radio-button>
        </a-radio-group>
        <div style="float:right">
            时间区间筛选:<a-range-picker :placeholder="['开始时间', '结束时间']" @change="onChange" />
            时间区间筛选:<a-range-picker :placeholder="['开始时间', '结束时间']"/>
        </div>
        <br /><br />
        <!-- 表格实体部分-->
src/views/Admin/List.vue
文件已删除
src/views/Admin/Release.vue
文件已删除
src/views/Admin/Report.vue
@@ -12,7 +12,7 @@
          </a-radio-button>
      </a-radio-group>
      <div style="float:right">
          时间区间筛选:<a-range-picker :placeholder="['开始时间', '结束时间']" @change="onChange" />
          时间区间筛选:<a-range-picker :placeholder="['开始时间', '结束时间']"/>
      </div>
      <br/><br/>
      <!-- 表格实体部分-->
src/views/Admin/Response.vue
文件已删除
src/views/Admin/UserManage.vue
文件已删除
src/views/Admin/callRecord.vue
对比新文件
@@ -0,0 +1,200 @@
<template>
  <div class="inner">
    <div class="table-cont">
      <a-table :columns="columns" :data-source="tableData" :pagination="pagination" :rowKey="record=>record.id" bordered>
        <template #level="level">
          <a-tag
              :key="level"
              :color="level === 1 ? 'pink' : level === 2 ? 'blue' : 'green'"
          >
            {{ level==1?'省级':level==2?'地(市、州)级':level==3?'区县级':'村(乡、镇)级' }}
          </a-tag>
        </template>
        <template #actions="actions,row">
          <a-button type="link" @click="viewData()">查看</a-button>
        </template>
      </a-table>
    </div>
    <a-modal
        title="信息详情"
        :visible="visible"
        @ok="handleOk"
        @cancel="handleCancel"
        cancelText="取消" okText="确认"
        width="50%"
    >
      <a-row class="tit">
        <a-col :span="4" style="text-align: right;padding-right: 8px">标题</a-col>
        <a-col :span="14">信息详情标题</a-col>
      </a-row>
      <a-form-model :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :colon="false">
        <a-form-model-item label="类别">
          <a-input readonly v-model="form.type"/>
        </a-form-model-item>
        <a-form-model-item label="级别">
          <a-tag color="yellow">黄色</a-tag>
        </a-form-model-item>
        <a-form-model-item label="发布单位">
          <a-input readonly v-model="form.dep"/>
        </a-form-model-item>
        <a-form-model-item label="短信内容">
          <a-input readonly type="textarea" v-model="form.content"/>
        </a-form-model-item>
        <a-form-model-item label="附件内容">
          <a><b><a-icon type="paper-clip"/>附件</b></a>
        </a-form-model-item>
      </a-form-model>
    </a-modal>
  </div>
</template>
<script>
import {getUser} from '@/api/user'
export default {
  name: 'callRecord',
  components: {},
  data () {
    return {
      visible: false,
      form: {},
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      columns:[
        {
          title: '叫应时间',
          dataIndex: 'callTime',
          key: 'callTime'
        },
        {
          title: '预警信息',
          dataIndex: 'warnings',
          key: 'warnings'
        },
        {
          title: '接收人单位',
          dataIndex: 'depName',
          key: 'depName'
        },
        {
          title: '接收人',
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: '级别',
          dataIndex: 'level',
          key: 'level',
          scopedSlots: { customRender: 'level' }
        },
        {
          title: '操作',
          dataIndex: 'actions',
          key: 'actions',
          scopedSlots: { customRender: 'actions' }
        }
      ],
      tableData: [
        {
          id: 1,
          callTime: '2023-06-02',
          warnings: '666666',
          name: '黄公子',
          level: 1
        },
        {
          id: 2,
          callTime: '2023-06-02',
          warnings: '666666',
          name: '黄公子',
          level: 2
        },
        {
          id: 3,
          callTime: '2023-06-02',
          warnings: '666666',
          name: '黄公子',
          level: 4
        },
      ],
      pagination: {
        current: 1,
        defaultCurrent: 1,
        defaultPageSize: 10,
        total: 11,
        onChange: ( page, pageSize ) => this.onPageChange(page,pageSize)
      },
      areaData: [
        {
          value: 1,
          label: '江苏省',
          children: [
            {
              value: 11,
              label: '苏州市',
              children: [
                {
                  value: 111,
                  label: '工业园区',
                },
              ],
            },
          ],
        },
        {
          value: 2,
          label: '新疆维吾尔自治区',
          children: [
            {
              value: 21,
              label: '乌鲁木齐市',
              children: [
                {
                  value: 211,
                  label: '国泰新华',
                },
              ],
            },
          ],
        },
      ]
    }
  },
  created() {
    const t = this
  },
  methods:{
    async getUserList(){
      const t = this
      const res = await getUser(t.search)
    },
    viewData(){
      const t = this
      t.visible = true
    },
    onPageChange(page, pageSize) {
      const t= this
      t.pagination.current = page
    },
    handleOk(e) {
      this.visible = false
    },
    handleCancel(e) {
      this.visible = false;
    },
  }
}
</script>
<style lang="less" scoped>
  .tit{
    font-size: 18px;
    font-weight: bolder;
    color: @blackText;
    margin-bottom: 24px;
  }
</style>
src/views/Admin/components/pwdMod.vue
对比新文件
@@ -0,0 +1,103 @@
<template>
  <a-modal
      title="重置密码"
      :visible="visible"
      :confirm-loading="confirmLoading"
      width="50%"
      cancelText="取消"
      okText="确认"
      @ok="onSubmit"
      @cancel="handleCancel"
      :afterClose="clearMod"
  >
    <a-form-model ref="ruleForm" :rules="rules" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :colon="false">
      <a-form-model-item label="请输入新密码" prop="newPwd">
        <a-input v-model="form.newPwd"/>
      </a-form-model-item>
      <a-form-model-item label="确认密码" prop="checkPwd">
        <a-input v-model="form.checkPwd"/>
      </a-form-model-item>
    </a-form-model>
  </a-modal>
</template>
<script>
import {verifyPasswordPowerful, verifyPhone, verifyTelPhone} from "@/util/validate";
export default {
  name: 'pwdMod',
  data () {
    let validatePwd = (rule, value, callback)=>{
      if(value === ''){
        callback(new Error('请输入密码'))
      }else{
        if(!verifyPasswordPowerful(value)){
          callback(new Error('密码须包含字母、数字、特殊字符(不包括下划线),长度在6-16之间'))
        }else{
          callback()
        }
      }
    }
    let validatePwd2 = (rule, value, callback)=>{
      if(value === ''){
        callback(new Error('请再次输入密码'))
      }else if(value !== this.form.newPwd){
        callback(new Error('两次输入密码不同'))
      }else{
        callback()
      }
    }
    return {
      visible: false,
      confirmLoading: false,
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      form: {
        id: null,
        newPwd: '',
        checkPwd: ''
      },
      rules: {
        newPwd: [{ required: true, validator: validatePwd, trigger: 'blur'}],
        checkPwd: [{ required: true, validator: validatePwd2, trigger: 'blur'}]
      }
    }
  },
  created() {
    const t = this
  },
  methods:{
    clearMod(){
      this.$refs.ruleForm.clearValidate()
    },
    onSubmit() {
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          alert('submit!');
          this.visible = false
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    handleOk(e) {
      const t = this
      t.confirmLoading = true;
    },
    handleCancel(e) {
      const t = this
      t.visible = false;
    },
    onChange(value) {
      console.log(value);
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/views/Admin/components/sameLevelMod.vue
对比新文件
@@ -0,0 +1,137 @@
<template>
  <a-modal
      :title="title"
      :visible="visible"
      :confirm-loading="confirmLoading"
      width="50%"
      cancelText="取消"
      okText="确认"
      @ok="onSubmit"
      @cancel="handleCancel"
      :afterClose="clearMod"
  >
    <a-form-model ref="ruleForm" :rules="rules" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :colon="false">
      <a-form-model-item label="姓名或称呼" prop="name">
        <a-input v-model="form.name"/>
      </a-form-model-item>
      <a-form-model-item label="单位名称(备注)" prop="depName">
        <a-input v-model="form.depName"/>
      </a-form-model-item>
      <a-form-model-item label="手机号码" prop="phone">
        <a-input v-model="form.phone"/>
      </a-form-model-item>
      <a-form-model-item label="选择级别" prop="level">
        <a-select v-model="form.level" placeholder="监管级别">
          <a-select-option :value="1">
            省级
          </a-select-option>
          <a-select-option :value="2">
            地(市、州)级
          </a-select-option>
          <a-select-option :value="3">
            区县级
          </a-select-option>
          <a-select-option :value="4">
            村(乡、镇)级
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item label="所属地区" prop="area">
        <a-tree-select
            v-model="form.area"
            style="width: 100%"
            :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
            :tree-data="areaData"
            placeholder="行政区划"
        >
        </a-tree-select>
      </a-form-model-item>
    </a-form-model>
  </a-modal>
</template>
<script>
import { addUser } from '@/api/user'
export default {
  name: 'userMod',
  data () {
    return {
      title: '新增用户',
      visible: false,
      confirmLoading: false,
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      areaData: [],
      unitName: '',
      form: {
        name: '',
        depName: '',
        phone: '',
        level: null,
        area: null
      },
      rules: {
        name: [{ required: true, message: '请输入姓名', trigger: 'blur'}],
        phone: [{ required: true, message: '请输入手机号', trigger: 'blur'}],
        depName: [{ required: true, message: '请输入单位名称', trigger: 'blur'}],
        level: [{ required: true, message: '请选择监管级别', trigger: 'change'}],
        area: [{ required: true, message: '请选择行政区划', trigger: 'change'}]
      }
    }
  },
  created() {
    const t = this
  },
  methods:{
    openDialog(type,data){
      const t = this
      if(type == 'add'){
        t.title = '新增用户'
        t.form = {
          name: '',
          depName: '',
          phone: '',
          level: null,
          area: null
        }
      }else{
        t.title = '编辑用户'
        t.form = data
      }
      t.visible = true
    },
    clearMod(){
      this.$refs.ruleForm.clearValidate()
    },
    onSubmit() {
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          alert('submit!');
          this.visible = false
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    handleOk(e) {
      const t = this
      t.confirmLoading = true;
    },
    handleCancel(e) {
      const t = this
      t.visible = false;
    },
    onChange(value) {
      console.log(value);
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/views/Admin/components/userMod.vue
对比新文件
@@ -0,0 +1,175 @@
<template>
  <a-modal
      :title="title"
      :visible="visible"
      :confirm-loading="confirmLoading"
      width="50%"
      cancelText="取消"
      okText="确认"
      @ok="onSubmit"
      @cancel="handleCancel"
      :afterClose="clearMod"
  >
    <a-form-model ref="ruleForm" :rules="rules" :model="form" :label-col="labelCol" :wrapper-col="wrapperCol" :colon="false">
      <a-form-model-item label="姓名" prop="name">
        <a-input v-model="form.name"/>
      </a-form-model-item>
      <a-form-model-item label="手机号码" prop="phone">
        <a-input v-model="form.phone"/>
      </a-form-model-item>
      <a-form-model-item label="用户名" prop="userName">
        <a-input v-model="form.userName"/>
      </a-form-model-item>
      <a-form-model-item label="密码" v-if="title== '新增用户'" prop="password">
        <a-input v-model="form.password"/>
      </a-form-model-item>
      <a-form-model-item label="重复密码" v-if="title== '新增用户'" prop="rePassword">
        <a-input v-model="form.rePassword"/>
      </a-form-model-item>
      <a-form-model-item label="性别" prop="sex">
        <a-radio-group v-model="form.sex" :default-value="0" button-style="solid">
          <a-radio-button :value="0">男</a-radio-button>
          <a-radio-button :value="1">女</a-radio-button>
        </a-radio-group>
      </a-form-model-item>
      <a-form-model-item label="选择级别" prop="level">
        <a-select v-model="form.level" placeholder="监管级别">
          <a-select-option :value="1">
            省级
          </a-select-option>
          <a-select-option :value="2">
            地(市、州)级
          </a-select-option>
          <a-select-option :value="3">
            区县级
          </a-select-option>
          <a-select-option :value="4">
            村(乡、镇)级
          </a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item label="所属地区" prop="area">
<!--        <a-cascader v-model="form.area" :options="areaData" expandTrigger="hover" changeOnSelect placeholder="请选择" @change="onChange"/>-->
        <a-tree-select
            v-model="form.area"
            style="width: 100%"
            :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
            :tree-data="areaData"
            placeholder="行政区划"
        >
        </a-tree-select>
      </a-form-model-item>
      <a-form-model-item label="所属单位">
        <a-input v-model="unitName"/>
      </a-form-model-item>
      <a-form-model-item label="角色" prop="role">
        <a-select v-model="form.role" placeholder="角色">
          <a-select-option :value="1">
            领导
          </a-select-option>
          <a-select-option :value="2">
            公司人员
          </a-select-option>
        </a-select>
      </a-form-model-item>
    </a-form-model>
  </a-modal>
</template>
<script>
import { addUser } from '@/api/user'
export default {
  name: 'userMod',
  data () {
    return {
      title: '新增用户',
      visible: false,
      confirmLoading: false,
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      areaData: [],
      unitName: '',
      form: {
        name: '',
        phone: '',
        userName: '',
        password: '',
        rePassword: '',
        sex: null,
        level: null,
        area: null,
        role: null
      },
      rules: {
        name: [{ required: true, message: '请输入姓名', trigger: 'blur'}],
        phone: [{ required: true, message: '请输入手机号', trigger: 'blur'}],
        userName: [{ required: true, message: '请输入用户名', trigger: 'blur'}],
        password: [{ required: true, message: '请输入密码', trigger: 'blur'}],
        rePassword: [{ required: true, message: '请再次输入密码', trigger: 'blur'}],
        sex: [{ required: true, message: '请选择性别', trigger: 'change'}],
        level: [{ required: true, message: '请选择监管级别', trigger: 'change'}],
        area: [{ required: true, message: '请选择行政区划', trigger: 'change'}],
        role: [{ required: true, message: '请选择角色', trigger: 'change'}]
      }
    }
  },
  created() {
    const t = this
  },
  methods:{
    openDialog(type,data){
      const t = this
      if(type == 'add'){
        t.title = '新增用户'
        t.form = {
          name: '',
          phone: '',
          userName: '',
          password: '',
          rePassword: '',
          sex: undefined,
          level: undefined,
          area: undefined,
          role: undefined
        }
      }else{
        t.title = '编辑用户'
        t.form = data
      }
      t.visible = true
    },
    clearMod(){
      this.$refs.ruleForm.clearValidate()
    },
    onSubmit() {
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          alert('submit!');
          this.visible = false
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    handleOk(e) {
      const t = this
      t.confirmLoading = true;
    },
    handleCancel(e) {
      const t = this
      t.visible = false;
    },
    onChange(value) {
      console.log(value);
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/views/Admin/list.vue
对比新文件
@@ -0,0 +1,283 @@
<template>
    <div class="inner">
    <a-row type="flex" justify="space-between" style="margin-bottom: 20px">
      <a-col :span="8">
        <a-radio-group v-model="category">
          <a-radio-button value="default">
            全部
          </a-radio-button>
          <a-radio-button value="1">
            待叫应
          </a-radio-button>
          <a-radio-button value="2">
            已叫应
          </a-radio-button>
          <a-radio-button value="3">
            超时未叫应
          </a-radio-button>
        </a-radio-group>
      </a-col>
      <a-col :span="16">
        <a-row type="flex" justify="end" :gutter="12">
          <a-col :span="8">
            <a-range-picker
                format="YYYY-MM-DD"
                :placeholder="['开始时间', '结束时间']"
                @change="onChange"
                @ok="onOk"
                style="width: 100%"
            />
          </a-col>
          <a-col :span="4">
            <a-button type="primary">查询</a-button>
            <a-button style="margin-left: 12px">重置</a-button>
          </a-col>
        </a-row>
      </a-col>
    </a-row>
        <!-- 表格实体部分-->
    <div class="table-cont">
      <a-table :columns="columns" :data-source="data" bordered>
        <template slot="time" slot-scope="text,record">
          <a v-if="!record.readed" style="color:red">[未读]</a>{{text}}
        </template>
        <span slot="level" slot-scope="text">
          <a-tag :color="text === '黄色' ? 'yellow' :text === '橙色'? 'orange':text === '红色'?'red':'blue'">
            {{ text }}
          </a-tag>
        </span>
        <template slot="attachment" slot-scope="text">
          <span v-if="text==='无'">无</span>
          <a v-else><b><a-icon type="paper-clip" /> {{text}}</b></a>
        </template >
        <template slot="receipt" slot-scope="text">
          <span v-if="text=='待叫应'"
            style='background-color:blue;padding:5px;color:#fff;border-radius: 5px;'>{{text}}</span>
          <span v-else-if="text=='已叫应'"
            style='background-color:limegreen;padding:5px;color:#2a2a2a;border-radius: 5px;'>{{text}}</span>
          <span v-else style='background-color:red;padding:5px;color:#fff;border-radius: 5px;'>{{text}}
          </span>
        </template>
        <template slot="operation" slot-scope="text, record, index">
          <div class="editable-row-operations">
            <div v-if="record.receipt==='待叫应'">
              <a @click="showModal" style="color:orangered"><a-icon type="notification" />
                确认已收到</a>&nbsp;&nbsp;
            </div>
            <br />
            <router-link :to="{path:'/torelease'}">转发</router-link>&nbsp;&nbsp;
            <router-link :to="{path:'/details',query: {id: record.id}}">查看详情</router-link>
          </div>
        </template>
      </a-table>
    </div>
        <!-- 对话框 -->
        <a-modal title="回执"
        okText="确认已安排部署"
        cancelText="取消"
        :visible="visible" :confirm-loading="confirmLoading" @ok="handleOk"
            @cancel="handleCancel">
            <p>{{ ModalText }}</p>
        </a-modal>
    </div>
</template>
<script>
    const columns = [{
            title: '序号',
            dataIndex: 'key',
            width: '5%',
        },
        {
            title: '发布时间',
            dataIndex: 'time',
            width: '15%',
            scopedSlots: {
                customRender: 'time'
            }, //设置定制化表格数据
        },
        {
            title: '发布单位',
            dataIndex: 'department',
            width: '12%',
        },
        {
            title: '类别',
            dataIndex: 'category',
            width: '8%',
        },
        {
            title: '级别',
            dataIndex: 'level',
            scopedSlots: {
                customRender: 'level'
            }, //设置定制化表格数据
            width: '8%',
        },
        {
            title: '信息标题',
            dataIndex: 'title',
            width: '16%',
        },
        {
            title: '附件',
            dataIndex: 'attachment',
            width: '6%',
            scopedSlots: {
                customRender: 'attachment'
            },
        },
        {
            title: '叫应状态',
            dataIndex: 'receipt',
            width: '10%',
            scopedSlots: {
                customRender: 'receipt'
            }, //设置定制化表格数据
        },
        {
            title: '操作',
            dataIndex: 'operation',
            scopedSlots: {
                customRender: 'operation'
            },
        },
    ];
    const data = [{
            key: 1,
            id:1001,
            readed:false,
            time: '2023年5月3日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '黄色',
            title: '全疆高温红色预警',
            attachment: '1',
            receipt: '待叫应'
        },
        {
            key: 2,
            readed:true,
            id:1002,
            time: '2023年5月2日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '橙色',
            title: '全疆高温红色预警',
            attachment: '1',
            receipt: '已叫应'
        },
        {
            key: 3,
            readed:true,
            id:1003,
            time: '2023年5月1日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '橙色',
            title: '全疆高温红色预警',
            attachment: '1',
            receipt: '已叫应'
        },
        {
            key: 4,
            readed:true,
            id:1004,
            time: '2023年5月1日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '橙色',
            title: '全疆高温红色预警',
            attachment: '2',
            receipt: '超时未叫应'
        },
        {
            key: 5,
            readed:true,
            id:1005,
            time: '2023年4月21日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '橙色',
            title: '全疆高温红色预警',
            attachment: '无',
            receipt: '已叫应'
        },
        {
            key: 6,
            readed:true,
            id:1006,
            time: '2023年4月21日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '橙色',
            title: '全疆高温红色预警',
            attachment: '1',
            receipt: '已叫应'
        },
        {
            key: 7,
            readed:true,
            id:1007,
            time: '2023年1月21日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '红色',
            title: '全疆低温红色预警',
            attachment: '1',
            receipt: '已叫应'
        },
    ];
    export default {
        data() {
            this.cacheData = data.map(item => ({
                ...item
            }));
            return {
                data,
                columns,
                editingKey: '',
                category: 'default',
                ModalText: '确认已经安排部署?',
                visible: false,
                confirmLoading: false,
            };
        },
        methods: {
            handleChange(value) {
                console.log(`Selected: ${value}`);
            },
            popupScroll() {
                console.log('popupScroll');
            },
            onChange(date, dateString) {
                console.log(date, dateString);
            },
      onOk(value) {
        console.log('onOk: ', value);
      },
            //叫应回执时间
            showModal() {
                this.visible = true;
            },
            handleOk(e) {
                this.ModalText = '正在提交您的叫应状态...';
                this.confirmLoading = true;
                setTimeout(() => {
                    this.visible = false;
                    this.confirmLoading = false;
                }, 2000);
            },
            handleCancel(e) {
                this.visible = false;
            },
        },
    };
</script>
<style>
</style>
src/views/Admin/menuManage.vue
对比新文件
@@ -0,0 +1,204 @@
<template>
  <div class="inner">
    <a-row type="flex" justify="space-between" style="margin-bottom: 20px">
      <a-col :span="4">
        <a-button type="primary" @click="editData('add',{})">新增菜单</a-button>
      </a-col>
      <a-col :span="20">
        <a-row type="flex" justify="end" :gutter="12">
          <a-col :span="4">
            <a-input v-model="search.searchParams.name" placeholder="菜单名称" style="width: 100%"/>
          </a-col>
          <a-col :span="4">
            <a-button type="primary" @click="getUserList">查询</a-button>
            <a-button style="margin-left: 12px" @click="resetSearch">重置</a-button>
          </a-col>
        </a-row>
      </a-col>
    </a-row>
    <div class="table-cont">
      <a-table
          :columns="columns"
          :data-source="tableData"
          :rowKey="record=>record.id" bordered
      >
        <template #type="type">
          <a-tag color="pink">
            {{type}}
          </a-tag>
        </template>
<!--        <template v-slot="type">-->
<!--          <a-tag color="pink">-->
<!--            {{type}}-->
<!--          </a-tag>-->
<!--        </template>-->
        <template #action="text, row">
          <a-button type="link" @click="editData('edit',row)">编辑</a-button>
          <a-button type="link" class="delBtn">删除</a-button>
        </template>
      </a-table>
    </div>
    <user-mod ref="userMod" @refrech="getUserList"></user-mod>
    <pwd-mod ref="pwdMod" @refrech="getUserList"></pwd-mod>
  </div>
</template>
<script>
import {getUser} from '@/api/user'
import userMod from "@/views/Admin/components/userMod"
import pwdMod from "@/views/Admin/components/pwdMod";
export default {
  name: 'user',
  components: {
    userMod,
    pwdMod
  },
  data () {
    return {
      areaVal: [],
      search:{
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          name: ''
        }
      },
      columns:[
        {
          title: '菜单名称',
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: '路由路径',
          dataIndex: 'route',
          key: 'route'
        },
        {
          title: '组件路径',
          dataIndex: 'path',
          key: 'path'
        },
        {
          title: '类型',
          dataIndex: 'type',
          key: 'type',
          scopedSlots: { customRender: 'type' },
        },
        {
          title: '操作',
          key: 'action',
          scopedSlots: { customRender: 'action' },
        },
      ],
      tableData: [
        {
          id: 1,
          name: '首页',
          route: '/index',
          path: '/index',
          type: 1,
          children: [
            {
              id: 2,
              name: '控制面板',
              route: '/panel',
              path: '/panel',
              type: 2
            },
            {
              id: 3,
              name: '实时气象',
              route: '/weather',
              path: '/weather',
              type: 1
            }
          ]
        },
        {
          id: 4,
          name: '预警信息管理',
          route: '/warning',
          path: '/warning',
          type: 1,
          children: [
            {
              id: 5,
              name: '信息编辑',
              route: '/msgEdit',
              path: '/msgEdit',
              type: 1
            },
            {
              id: 6,
              name: '信息审核',
              route: '/msgReview',
              path: '/msgReview',
              type: 1
            }
          ]
        },
      ],
      pagination: {
        current: 1,
        defaultCurrent: 1,
        defaultPageSize: 10,
        total: 11,
        onChange: ( page, pageSize ) => this.onPageChange(page,pageSize)
      }
    }
  },
  created() {
    const t = this
    t.getUserList()
  },
  methods:{
    async getUserList(){
      const t = this
      const res = await getUser(t.search)
    },
    resetSearch(){
      const t = this
      t.areaVal = []
      t.search = {
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          realName: '',
          districtId: null,
          unittype: undefined
        }
      }
      t.getUserList()
    },
    editData(type,data){
      const t = this
      t.$refs.userMod.openDialog(type,data)
      t.$refs.userMod.areaData = t.areaData
    },
    editPwd(record){
      const t = this
      t.$refs.pwdMod.form.id = record.id
      t.$refs.pwdMod.visible = true
    },
    onPageChange(page, pageSize) {
      const t= this
      t.pagination.current = page
    },
    onChange(value) {
      const t = this
      t.search.searchParams.districtId = value[value.length - 1]
    },
  }
}
</script>
<style lang="less" scoped>
.delBtn{
  color: @danger
}
</style>
src/views/Admin/msgRecord.vue
对比新文件
@@ -0,0 +1,142 @@
<template>
  <div class="inner">
    <a-row type="flex" :gutter="12" style="margin-bottom: 20px">
      <a-col :span="6">
        <a-range-picker
            format="YYYY-MM-DD"
            :placeholder="['开始时间', '结束时间']"
            @change="onChange"
            @ok="onOk"
            style="width: 100%"
        />
      </a-col>
      <a-col :span="4">
        <a-button type="primary">查询</a-button>
        <a-button style="margin-left: 12px">重置</a-button>
      </a-col>
    </a-row>
    <div class="table-cont">
      <div class="msg">
        <a-card hoverable class="msg-item" v-for="item in msg" :key="item.id">
          <template #title>
            <div class="tit">
              发送时间:<span>{{item.time}}</span>
            </div>
            <a-divider type="vertical" />
            <div class="tit">
              任务ID:<span>{{item.id}}</span>
            </div>
          </template>
          <p>
            {{item.content}}
          </p>
          <template #actions>
            <div>
              接收号码:<span>{{item.phone.join(',')}}</span>
            </div>
            <div>
              <a-button type="primary" @click="viewDetails">查看详情</a-button>
            </div>
          </template>
        </a-card>
      </div>
    </div>
    <a-modal v-model="visible" width="50%" title="短信详情" @ok="handleOk" cancelText="取消" okText="确认">
      短信详情
    </a-modal>
  </div>
</template>
<script>
import {getUser} from '@/api/user'
export default {
  name: 'msgRecord',
  components: {},
  data () {
    return {
      msg: [
        {
          time: '2023-05-30',
          id: '1201',
          content: '第一条短信',
          phone: ['15261806176','15261806176','15261806176','15261806176','15261806176','15261806176','15261806176','15261806176','15261806176']
        },
        {
          time: '2023-05-30',
          id: '1202',
          content: '第二条短信',
          phone: ['15261806176','15261806176','15261806176','15261806176','15261806176']
        },
        {
          time: '2023-05-30',
          id: '1203',
          content: '第三条短信',
          phone: ['15261806176','15261806176','15261806176','15261806176','15261806176']
        }
      ],
      visible: false
    }
  },
  created() {
    const t = this
  },
  methods:{
    onChange(value, dateString) {
      console.log('Selected Time: ', value);
      console.log('Formatted Selected Time: ', dateString);
    },
    onOk(value) {
      console.log('onOk: ', value);
    },
    viewDetails(){
      const t = this
      t.visible = true
    },
    handleOk(e) {
      console.log(e);
      this.visible = false;
    }
  }
}
</script>
<style lang="less" scoped>
.msg{
  width: 100%;
  margin-bottom: 12px;
  .msg-item{
    width: 100%;
    margin-bottom: 24px;
    /deep/ .ant-card-head-title{
      display: flex;
      align-items: center;
      .tit{
        width: 50%;
      }
    }
    /deep/ .ant-card-actions{
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 24px;
      li{
        width: 10% !important;
      }
      &>li:first-of-type{
        width: 90% !important;
        div{
          color: #333;
          text-align: left;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }
  }
}
</style>
src/views/Admin/release.vue
对比新文件
@@ -0,0 +1,192 @@
<template>
  <div class="inner">
    <a-row type="flex" justify="space-between" style="margin-bottom: 20px">
      <a-col :span="8">
        <a-radio-group v-model="category">
          <a-radio-button value="default">
            全部
          </a-radio-button>
          <a-radio-button value="1">
            紧临
          </a-radio-button>
          <a-radio-button value="2">
            常规
          </a-radio-button>
        </a-radio-group>
      </a-col>
      <a-col :span="16">
        <a-row type="flex" justify="end" :gutter="12">
          <a-col :span="8">
            <a-range-picker
                format="YYYY-MM-DD"
                :placeholder="['开始时间', '结束时间']"
                @change="onChange"
                @ok="onOk"
                style="width: 100%"
            />
          </a-col>
          <a-col :span="4">
            <a-button type="primary">查询</a-button>
            <a-button style="margin-left: 12px">重置</a-button>
          </a-col>
        </a-row>
      </a-col>
    </a-row>
      <!-- 表格实体部分-->
    <div class="table-cont">
      <a-table :columns="columns" :data-source="data" bordered>
        <template #level="text">
          <a-tag :color="text === '黄色' ? 'yellow' :text === '橙色'? 'orange':text === '红色'?'red':'blue'">
            {{ text }}
          </a-tag>
        </template>
        <template #attachment="text">
          <span v-if="text==='无'">无</span>
          <a v-else><b><a-icon type="paper-clip" /> {{text}}</b></a>
        </template >
        <template #operation="text, record, index">
          <div class="editable-row-operations">
          <a @click="showModal" style="color:orangered">
            叫应列表</a>&nbsp;&nbsp;
            <router-link :to="{path:'/details',query: {id: record.id}}">信息详情</router-link>
          </div>
        </template>
      </a-table>
    </div>
      <!-- 对话框 -->
      <a-modal title="查看叫应详情"
      okText="确认"
      cancelText="关闭"
      :visible="visible" :confirm-loading="confirmLoading" @ok="handleOk" @cancel="handleOk">
      </a-modal>
  </div>
</template>
<script>
    const columns = [{
            title: '序号',
            dataIndex: 'key',
            width: '8%',
        },
        {
            title: '发布时间',
            dataIndex: 'time',
            width: '15%',
            scopedSlots: {
                customRender: 'time'
            }, //设置定制化表格数据
        },
        {
            title: '发布单位',
            dataIndex: 'department',
            width: '12%',
        },
        {
            title: '类别',
            dataIndex: 'category',
            width: '8%',
        },
        {
            title: '级别',
            dataIndex: 'level',
            scopedSlots: {
                customRender: 'level'
            }, //设置定制化表格数据
            width: '8%',
        },
        {
            title: '信息标题',
            dataIndex: 'title',
            width: '16%',
        },
        {
            title: '附件',
            dataIndex: 'attachment',
            width: '6%',
            scopedSlots: {
                customRender: 'attachment'
            },
        },
        {
            title: '叫应情况',
            dataIndex: 'receipt',
            width: '10%',
            scopedSlots: {
                customRender: 'receipt'
            }, //设置定制化表格数据
        },
        {
            title: '操作',
            dataIndex: 'operation',
            scopedSlots: {
                customRender: 'operation'
            },
        },
    ];
    const data = [{
            key: 1,
            id:1001,
            readed:false,
            time: '2023年5月3日 15:30',
            department: '自治区预警中心',
            category: '气象',
            level: '黄色',
            title: '全疆高温红色预警',
            attachment: '1',
            receipt: '部分叫应'
        },
        {
                key: 2,
                id:1002,
                readed:false,
                time: '2023年5月3日 15:30',
                department: '自治区预警中心',
                category: '气象',
                level: '黄色',
                title: '全疆高温红色预警',
                attachment: '1',
                receipt: '全部叫应'
            },{
                key: 3,
                id:1003,
                readed:false,
                time: '2023年5月3日 15:30',
                department: '自治区预警中心',
                category: '气象',
                level: '黄色',
                title: '全疆高温红色预警',
                attachment: '1',
                receipt: '均未叫应'
            }]
    export default {
        data() {
            return {
                category: 'default',
                data,
                columns,
                visible: false,
                confirmLoading: false,
            }
        },
        methods: {
      onChange(value, dateString) {
        console.log('Selected Time: ', value);
        console.log('Formatted Selected Time: ', dateString);
      },
      onOk(value) {
        console.log('onOk: ', value);
      },
            //弹出层
            showModal() {
                this.visible = true;
            },
            handleOk(e) {
                this.visible = false;
            },
        }
        }
</script>
src/views/Admin/sameLevel.vue
对比新文件
@@ -0,0 +1,219 @@
<template>
  <div class="inner">
    <a-row type="flex" justify="space-between" style="margin-bottom: 20px">
      <a-col :span="4">
        <a-button type="primary" @click="editData('add',{})">新增用户</a-button>
      </a-col>
      <a-col :span="20">
        <a-row type="flex" justify="end" :gutter="12">
          <a-col :span="4">
            <a-cascader :options="areaData" v-model="areaVal" placeholder="行政规划" expandTrigger="hover" changeOnSelect @change="onChange" style="width: 100%"/>
          </a-col>
          <a-col :span="4">
            <a-button type="primary" @click="getUserList">查询</a-button>
            <a-button style="margin-left: 12px" @click="resetSearch">重置</a-button>
          </a-col>
        </a-row>
      </a-col>
    </a-row>
    <div class="table-cont">
      <a-table :columns="columns" :data-source="tableData" :pagination="pagination" :rowKey="record=>record.name" bordered>
        <template #levels="level">
          <a-tag
            :color="level === 1 ? 'pink' : level === 2 ? 'blue' : 'green'"
          >
            {{ level === 1 ? '省级' : level === 2 ? '地(市、州)级' : level === 3 ? '区县级' : '村(乡、镇)级' }}
          </a-tag>
        </template>
        <template #area="area">
          {{findAreaById(areaData,area)}}
        </template>
        <template #action="action,row">
          <a-button type="link" @click="editData('edit',row)">编辑</a-button>
          <a-button type="link" class="delBtn">删除</a-button>
        </template>
      </a-table>
    </div>
    <same-level-mod ref="sameLevelMod" @refrech="getUserList"></same-level-mod>
  </div>
</template>
<script>
import {getUser} from '@/api/user'
import sameLevelMod from "@/views/Admin/components/sameLevelMod"
export default {
  name: 'sameLevel',
  components: {
    sameLevelMod
  },
  data () {
    return {
      areaVal: [],
      search:{
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          districtId: null
        }
      },
      columns:[
        {
          title: '单位名称',
          dataIndex: 'depName',
          key: 'depName'
        },
        {
          title: '接收人姓名',
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: '手机号码',
          dataIndex: 'phone',
          key: 'phone'
        },
        {
          title: '级别',
          dataIndex: 'level',
          key: 'level',
          scopedSlots: { customRender: 'levels' }
        },
        {
          title: '行政区划',
          dataIndex: 'area',
          key: 'area',
          scopedSlots: { customRender: 'area' }
        },
        {
          title: '操作',
          key: 'action',
          scopedSlots: { customRender: 'action' }
        },
      ],
      tableData: [
        {
          depName: '阿勒泰地区自然资源局',
          name: 'John Brown',
          phone: '15261806177',
          level: 1,
          area: 111
        },
        {
          depName: '阿勒泰地区公安局',
          name: 'Jim Green',
          phone: '15261806178',
          level: 2,
          area: 211
        },
        {
          depName: '阿勒泰地区自然资源局',
          name: 'Joe Black',
          phone: '15261806176',
          level: 3,
          area: 11
        },
      ],
      pagination: {
        current: 1,
        defaultCurrent: 1,
        defaultPageSize: 10,
        total: 11,
        onChange: ( page, pageSize ) => this.onPageChange(page,pageSize)
      },
      areaData: [
        {
          value: 1,
          label: '江苏省',
          children: [
            {
              value: 11,
              label: '苏州市',
              children: [
                {
                  value: 111,
                  label: '工业园区',
                },
              ],
            },
          ],
        },
        {
          value: 2,
          label: '新疆维吾尔自治区',
          children: [
            {
              value: 21,
              label: '乌鲁木齐市',
              children: [
                {
                  value: 211,
                  label: '国泰新华',
                },
              ],
            },
          ],
        },
      ]
    }
  },
  created() {
    const t = this
    t.getUserList()
  },
  methods:{
    async getUserList(){
      const t = this
      const res = await getUser(t.search)
    },
    resetSearch(){
      const t = this
      t.areaVal = []
      t.search = {
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          districtId: null
        }
      }
      t.getUserList()
    },
    editData(type,data){
      const t = this
      t.$refs.sameLevelMod.openDialog(type,data)
      t.$refs.sameLevelMod.areaData = t.areaData
    },
    onPageChange(page, pageSize) {
      const t= this
      t.pagination.current = page
    },
    onChange(value) {
      const t = this
      t.search.searchParams.districtId = value[value.length - 1]
    },
    findAreaById(data,value) {
      for (const node of data) {
        if (node.value === value) {
          return node.label;
        }
        if (node.children) {
          const foundLabel = this.findAreaById(node.children, value);
          if (foundLabel) {
            return foundLabel;
          }
        }
      }
      return null;
    }
  }
}
</script>
<style lang="less" scoped>
.delBtn{
  color: @danger
}
</style>
src/views/Admin/userManage.vue
对比新文件
@@ -0,0 +1,284 @@
<template>
  <div class="inner">
    <a-row type="flex" justify="space-between" style="margin-bottom: 20px">
      <a-col :span="4">
        <a-button type="primary" @click="editData('add',{})">新增用户</a-button>
      </a-col>
      <a-col :span="20">
        <a-row type="flex" justify="end" :gutter="12">
          <a-col :span="4">
            <a-cascader :options="areaData" v-model="areaVal" placeholder="行政规划" expandTrigger="hover" changeOnSelect @change="onChange" style="width: 100%"/>
          </a-col>
          <a-col :span="4">
            <a-select v-model="search.searchParams.unittype" placeholder="监管层级" style="width: 100%">
              <a-select-option :value="1">
                省级
              </a-select-option>
              <a-select-option :value="2">
                地(市、州)级
              </a-select-option>
              <a-select-option :value="3">
                区县级
              </a-select-option>
              <a-select-option :value="4">
                村(乡、镇)级
              </a-select-option>
            </a-select>
          </a-col>
          <a-col :span="4">
            <a-input v-model="search.searchParams.realName" placeholder="姓名" style="width: 100%"/>
          </a-col>
          <a-col :span="4">
            <a-button type="primary" @click="getUserList">查询</a-button>
            <a-button style="margin-left: 12px" @click="resetSearch">重置</a-button>
          </a-col>
        </a-row>
      </a-col>
    </a-row>
    <div class="table-cont">
      <a-table :columns="columns" :data-source="tableData" :pagination="pagination" :rowKey="record=>record.id" bordered>
        <template #sex="sex">
          {{ sex == 0?'男':'女' }}
        </template>
        <template #level="level">
          <a-tag
              :key="level"
              :color="level === 1 ? 'pink' : level === 2 ? 'blue' : 'green'"
          >
            {{ level==1?'省级':level==2?'地(市、州)级':level==3?'区县级':'村(乡、镇)级' }}
          </a-tag>
        </template>
        <template #area="area">
          {{findAreaById(areaData,area)}}
        </template>
        <template #role="role">
          {{ role == 1?'领导':'工作人员'}}
        </template>
        <template #action="action,row">
          <a-button type="link" @click="editData('edit',row)">编辑</a-button>
          <a-button type="link" class="delBtn">删除</a-button>
          <a-button type="link" @click="editPwd(row)">重置密码</a-button>
        </template>
      </a-table>
    </div>
    <user-mod ref="userMod" @refrech="getUserList"></user-mod>
    <pwd-mod ref="pwdMod" @refrech="getUserList"></pwd-mod>
  </div>
</template>
<script>
import {getUser} from '@/api/user'
import userMod from "@/views/Admin/components/userMod"
import pwdMod from "@/views/Admin/components/pwdMod";
export default {
  name: 'user',
  components: {
    userMod,
    pwdMod
  },
  data () {
    return {
      areaVal: [],
      search:{
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          realName: '',
          districtId: null,
          unittype: undefined
        }
      },
      columns:[
        {
          title: '用户ID',
          dataIndex: 'id',
          key: 'id'
        },
        {
          title: '姓名',
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: '手机号码',
          dataIndex: 'phone',
          key: 'phone'
        },
        {
          title: '用户名',
          dataIndex: 'userName',
          key: 'userName'
        },
        {
          title: '性别',
          dataIndex: 'sex',
          key: 'sex',
          scopedSlots: { customRender: 'sex' },
        },
        {
          title: '级别',
          dataIndex: 'level',
          key: 'level',
          scopedSlots: { customRender: 'level' }
        },
        {
          title: '行政区划',
          dataIndex: 'area',
          key: 'area',
          scopedSlots: { customRender: 'area' }
        },
        {
          title: '角色',
          dataIndex: 'role',
          key: 'role',
          scopedSlots: { customRender: 'role' },
        },
        {
          title: '操作',
          key: 'action',
          scopedSlots: { customRender: 'action' },
        },
      ],
      tableData: [
        {
          id: 1,
          name: 'John Brown',
          phone: '15261806177',
          userName: 'JBrown',
          sex: 0,
          level: 1,
          area: 111,
          role: 1
        },
        {
          id: 2,
          name: 'Jim Green',
          phone: '15261806178',
          userName: 'JGreen',
          sex: 1,
          level: 2,
          area: 211,
          role: 2
        },
        {
          id: 3,
          name: 'Joe Black',
          phone: '15261806176',
          userName: 'JBlack',
          sex: 0,
          level: 3,
          area: 11,
          role: 1
        },
      ],
      pagination: {
        current: 1,
        defaultCurrent: 1,
        defaultPageSize: 10,
        total: 11,
        onChange: ( page, pageSize ) => this.onPageChange(page,pageSize)
      },
      areaData: [
        {
          value: 1,
          label: '江苏省',
          children: [
            {
              value: 11,
              label: '苏州市',
              children: [
                {
                  value: 111,
                  label: '工业园区',
                },
              ],
            },
          ],
        },
        {
          value: 2,
          label: '新疆维吾尔自治区',
          children: [
            {
              value: 21,
              label: '乌鲁木齐市',
              children: [
                {
                  value: 211,
                  label: '国泰新华',
                },
              ],
            },
          ],
        },
      ]
    }
  },
  created() {
    const t = this
    t.getUserList()
  },
  methods:{
    async getUserList(){
      const t = this
      const res = await getUser(t.search)
    },
    resetSearch(){
      const t = this
      t.areaVal = []
      t.search = {
        pageIndex: 1,
        pageSize: 10,
        searchParams:{
          realName: '',
          districtId: null,
          unittype: undefined
        }
      }
      t.getUserList()
    },
    editData(type,data){
      const t = this
      t.$refs.userMod.openDialog(type,data)
      t.$refs.userMod.areaData = t.areaData
    },
    editPwd(record){
      const t = this
      t.$refs.pwdMod.form.id = record.id
      t.$refs.pwdMod.visible = true
    },
    onPageChange(page, pageSize) {
      const t= this
      t.pagination.current = page
    },
    onChange(value) {
      const t = this
      t.search.searchParams.districtId = value[value.length - 1]
    },
    findAreaById(data,value) {
      for (const node of data) {
        if (node.value === value) {
          return node.label;
        }
        if (node.children) {
          const foundLabel = this.findAreaById(node.children, value);
          if (foundLabel) {
            return foundLabel;
          }
        }
      }
      return null;
    }
  }
}
</script>
<style lang="less" scoped>
.delBtn{
  color: @danger
}
</style>
src/views/Home.vue
@@ -8,10 +8,10 @@
            <a-layout>
                <a-layout-header style="background: #fff; padding: 0">
                    <a-icon class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'"
                        @click="() => (collapsed = !collapsed)" />
                        @click="() => (collapsed = !collapsed)"/>
                    <a-dropdown>
                        <a class="ant-dropdown-link" @click="e => e.preventDefault()">
                            您好,李静 <a-icon type="down" />
                            您好,李静 <a-icon type="down"/>
                        </a>
                        <a-menu slot="overlay">
                            <a-menu-item>
@@ -25,7 +25,6 @@
                            </a-menu-item>
                        </a-menu>
                    </a-dropdown>
                </a-layout-header>
                <TabsHeader :pageList="pageList" :activePage="activePage" @change="changePage" @close="remove" />
                <a-layout-content :style="{
@@ -38,9 +37,9 @@
            </a-layout>
        </a-layout>
        <center style="textAlign: center;margin-left: 5%;margin-top:50px;">
            技术支持:中国科学院
        </center>
<!--        <center style="textAlign: center;margin-left: 5%;margin-top:50px;">-->
<!--            技术支持:中国科学院-->
<!--        </center>-->
    </div>
</template>
@@ -92,9 +91,9 @@
                }
            }
        },
        methods: {
            logout(){
                this.$router.push('/')
        methods: {
            logout(){
                this.$router.push('/')
            },
            changePage(key) {
                this.activePage = key
src/views/Login.vue
@@ -6,55 +6,77 @@
    </div>
  <div class="login">
    <a-form
    <a-form-model
      layout="horizontal"
      :form="form"
      @submit="handleSubmit"
      :model="form"
      ref="ruleForm"
      :rules="rules"
      class="login-form"
    >
      <a-tabs default-active-key="1" @change="callback">
        <a-tab-pane key="1" tab="用户名登录">
          <a-form-item>
            <a-input
              placeholder="请输入用户"
              size="large"
            >
              <a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)" />
            </a-input>
          </a-form-item>
          <a-form-item>
            <a-input-password
              type="password"
              placeholder="请输入密码"
              size="large"
            >
              <a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
            </a-input-password>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane key="2" tab="验证码登录" force-render>
          <a-form-item>
            <a-input
              placeholder="手机号"
              size="large"
            >
              <a-icon slot="prefix" type="mobile" style="color:rgba(0,0,0,.25)" />
            </a-input>
          </a-form-item>
          <a-form-item>
            <a-row :gutter="8">
              <a-col :span="17">
                <a-input placeholder="验证码">
                  <a-icon slot="prefix" type="mobile" style="color:rgba(0,0,0,.25)" />
                </a-input>
              </a-col>
              <a-col :span="7">
                <a-button style="width: 100%">获取验证码</a-button>
              </a-col>
            </a-row>
          </a-form-item>
        </a-tab-pane>
      </a-tabs>
      <a-form-model-item ref="name" prop="name">
        <a-input
            placeholder="请输入用户"
            size="large"
            v-model="form.name"
        >
          <a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)" />
        </a-input>
      </a-form-model-item>
      <a-form-model-item ref="pwd" prop="pwd">
        <a-input-password
            type="password"
            placeholder="请输入密码"
            size="large"
            v-model="form.pwd"
        >
          <a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
        </a-input-password>
      </a-form-model-item>
<!--      <a-tabs default-active-key="1" @change="callback">-->
<!--        <a-tab-pane key="1" tab="用户名登录">-->
<!--          <a-form-item>-->
<!--            <a-input-->
<!--              placeholder="请输入用户"-->
<!--              size="large"-->
<!--              v-model="form.name"-->
<!--            >-->
<!--              <a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)" />-->
<!--            </a-input>-->
<!--          </a-form-item>-->
<!--          <a-form-item>-->
<!--            <a-input-password-->
<!--              type="password"-->
<!--              placeholder="请输入密码"-->
<!--              size="large"-->
<!--              v-model="form.pwd"-->
<!--            >-->
<!--              <a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />-->
<!--            </a-input-password>-->
<!--          </a-form-item>-->
<!--        </a-tab-pane>-->
<!--        <a-tab-pane key="2" tab="验证码登录" force-render>-->
<!--          <a-form-item>-->
<!--            <a-input-->
<!--              placeholder="手机号"-->
<!--              size="large"-->
<!--            >-->
<!--              <a-icon slot="prefix" type="mobile" style="color:rgba(0,0,0,.25)" />-->
<!--            </a-input>-->
<!--          </a-form-item>-->
<!--          <a-form-item>-->
<!--            <a-row :gutter="8">-->
<!--              <a-col :span="17">-->
<!--                <a-input placeholder="验证码">-->
<!--                  <a-icon slot="prefix" type="mobile" style="color:rgba(0,0,0,.25)" />-->
<!--                </a-input>-->
<!--              </a-col>-->
<!--              <a-col :span="7">-->
<!--                <a-button style="width: 100%">获取验证码</a-button>-->
<!--              </a-col>-->
<!--            </a-row>-->
<!--          </a-form-item>-->
<!--        </a-tab-pane>-->
<!--      </a-tabs>-->
      <div style="margin-bottom: 20px">
        <a-checkbox :checked="true" style="color:#fff;">自动登录</a-checkbox>
        <a style="float: right">忘记密码</a>
@@ -65,43 +87,61 @@
          html-type="submit"
          style="width: 100%"
          size="large"
          @click="handleSubmit"
        >
          登录
        </a-button>
      </a-form-item>
      <center><p>技术支持:中国科学院</p></center>
    </a-form>
    </a-form-model>
  </div>
  </div>
</template>
<script>
import { Login, getMenuAdmin } from "@/api/login";
import Cookies from 'js-cookie';
export default {
  name: "login",
  data() {
    return {
      // hasErrors,
      form: this.$form.createForm(this),
      // form: this.$form.createForm(this),
      form: {
        name: '',
        pwd: ''
      },
      rules: {
        name: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
        pwd: [{ required: true, message: '请输入用户密码', trigger: 'blur' }]
      },
      menu: []
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.form.validateFields();
    });
    // this.$nextTick(() => {
    //   this.form.validateFields();
    // });
  },
  methods: {
    handleSubmit(e) {
      e.preventDefault();
      this.form.validateFields((err, values) => {
        if (!err) {
          console.log("Received values of form: ", values);
          this.$router.push({ name: "default" });
    handleSubmit() {
      this.$refs.ruleForm.validate(async (valid) => {
        if (valid) {
          const res = await Login(this.form)
          if (res.data.code === 100) {
            Cookies.set('resTk', res.data.data.tk);
            Cookies.set('resUid', res.data.data.uid);
          } else {
            console.log(res.data.msg)
            this.$message.warning(res.data.msg);
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    callback(key) {
      console.log(key);
    },
    }
  },
};
</script>
src/views/SameLevel.vue
文件已删除
vue.config.js
对比新文件
@@ -0,0 +1,13 @@
const path = require("path");
module.exports = {
    pluginOptions: {
        "style-resources-loader": {
            preProcessor: "less",
            patterns: [
                // 自己对应文件路径,全局变量路径,不能使用路径别名
                path.resolve(__dirname, "./src/assets/style/themeColor.less"),
            ],
        },
    },
};