From 88d7869b422a1070a0ea8efd22613997e9dbe2fe Mon Sep 17 00:00:00 2001
From: zhouwenxuan <1175765986@qq.com>
Date: 星期三, 29 十一月 2023 10:04:52 +0800
Subject: [PATCH] 后台管理页面、菜单配置

---
 src/views/safetyReview/baseSet/evaluateType/index.vue                           |   82 ++
 src/layout/components/Sidebar/menu.js                                           |   84 ++
 src/api/backManage/notice.js                                                    |    8 
 src/views/safetyReview/notice/components/noticeDialog.vue                       |  150 ++++
 src/components/Editor/index.vue                                                 |    4 
 src/views/safetyReview/userManage/superviseUsers/index.vue                      |   91 ++
 src/views/safetyReview/baseSet/business/components/businessDialog.vue           |   87 ++
 src/layout/components/Sidebar/Logo.vue                                          |   14 
 src/views/safetyReview/userManage/expertUsers/index.vue                         |  169 ++++
 src/layout/components/Sidebar/index.vue                                         |   19 
 src/views/components/loginForm.vue                                              |    6 
 src/views/safetyReview/baseSet/area/index.vue                                   |   92 ++
 src/views/safetyReview/userManage/superviseUsers/components/superviseDialog.vue |  195 +++++
 src/store/modules/user.js                                                       |    3 
 src/views/safetyReview/law/components/lawDialog.vue                             |  183 +++++
 src/router/index.js                                                             |  143 ++++
 src/components/Breadcrumb/index.vue                                             |    4 
 src/views/safetyReview/baseSet/business/index.vue                               |   82 ++
 src/views/safetyReview/law/law.vue                                              |   87 ++
 src/api/backManage/area.js                                                      |    8 
 src/views/safetyReview/userManage/institutionUsers/index.vue                    |   96 ++
 src/views/safetyReview/baseSet/evaluateType/components/typeDialog.vue           |  100 ++
 src/views/safetyReview/notice/notice.vue                                        |   84 ++
 src/views/safetyReview/institution/institution.vue                              |   79 ++
 src/views/safetyReview/baseSet/area/components/areaDialog.vue                   |  118 +++
 25 files changed, 1,975 insertions(+), 13 deletions(-)

diff --git a/src/api/backManage/area.js b/src/api/backManage/area.js
new file mode 100644
index 0000000..9dc7b47
--- /dev/null
+++ b/src/api/backManage/area.js
@@ -0,0 +1,8 @@
+import request from '@/utils/request'
+
+export function getArea() {
+    return request({
+        url: 'api/system/region/regionTree',
+        method: 'get'
+    })
+}
diff --git a/src/api/backManage/notice.js b/src/api/backManage/notice.js
new file mode 100644
index 0000000..014c25e
--- /dev/null
+++ b/src/api/backManage/notice.js
@@ -0,0 +1,8 @@
+import request from '@/utils/request'
+
+export function getNoticeList() {
+    return request({
+        url: 'api/system/notice/noticeList',
+        method: 'get'
+    })
+}
diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue
index 489cba1..5ad8e1e 100644
--- a/src/components/Breadcrumb/index.vue
+++ b/src/components/Breadcrumb/index.vue
@@ -20,7 +20,7 @@
   const first = matched[0]
   // 判断是否为首页
   if (!isDashboard(first)) {
-    matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched)
+    // matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched)
   }
 
   levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
@@ -63,4 +63,4 @@
     cursor: text;
   }
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue
index 0a696f2..bb8b869 100644
--- a/src/components/Editor/index.vue
+++ b/src/components/Editor/index.vue
@@ -90,7 +90,7 @@
       ["link", "image", "video"]                      // 链接、图片、视频
     ],
   },
-  placeholder: "请输入内容",
+  placeholder: props.readOnly ? "" : "请输入内容",
   readOnly: props.readOnly
 });
 
@@ -108,7 +108,7 @@
 const content = ref("");
 watch(() => props.modelValue, (v) => {
   if (v !== content.value) {
-    content.value = v === undefined ? "<p></p>" : v;
+    content.value = (v === undefined || v === "") ? "<p></p>" : v;
   }
 }, { immediate: true });
 
diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue
index 67582d0..6b29184 100644
--- a/src/layout/components/Sidebar/Logo.vue
+++ b/src/layout/components/Sidebar/Logo.vue
@@ -1,11 +1,11 @@
 <template>
   <div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
     <transition name="sidebarLogoFade">
-      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
+      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" :to="firstPage">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
         <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
       </router-link>
-      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
+      <router-link v-else key="expand" class="sidebar-logo-link" :to="firstPage">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
         <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
       </router-link>
@@ -17,14 +17,20 @@
 import variables from '@/assets/styles/variables.module.scss'
 import logo from '@/assets/logo/logo.png'
 import useSettingsStore from '@/store/modules/settings'
-
+import {onMounted, ref} from "vue";
+import Cookies from "js-cookie";
 defineProps({
   collapse: {
     type: Boolean,
     required: true
   }
 })
+const firstPage = ref("");
+onMounted(() => {
+    const routers = JSON.parse(Cookies.get('routers')) ;
+    firstPage.value = routers[0].path;
 
+});
 const title = import.meta.env.VITE_APP_TITLE;
 const settingsStore = useSettingsStore();
 const sideTheme = computed(() => settingsStore.sideTheme);
@@ -78,4 +84,4 @@
     }
   }
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
index 9b14dfc..e7245e5 100644
--- a/src/layout/components/Sidebar/index.vue
+++ b/src/layout/components/Sidebar/index.vue
@@ -30,13 +30,28 @@
 import useAppStore from '@/store/modules/app'
 import useSettingsStore from '@/store/modules/settings'
 import usePermissionStore from '@/store/modules/permission'
-
+import {onMounted, ref} from "vue";
+import Cookies from "js-cookie";
+import menu from "./menu"
 const route = useRoute();
 const appStore = useAppStore()
 const settingsStore = useSettingsStore()
 const permissionStore = usePermissionStore()
+// const sidebarRouters =  computed(() => permissionStore.sidebarRouters);
+const sidebarRouters = ref([])
+onMounted(() => {
+    getMenu();
+});
+const getMenu = () => {
+    const userInfo = JSON.parse(Cookies.get('userInfo'))
+    if(userInfo.identity === 0) {
+        sidebarRouters.value =  menu.adminMenu
+        Cookies.set('routers',JSON.stringify(sidebarRouters.value))
+    }
+}
 
-const sidebarRouters =  computed(() => permissionStore.sidebarRouters);
+
+
 const showLogo = computed(() => settingsStore.sidebarLogo);
 const sideTheme = computed(() => settingsStore.sideTheme);
 const theme = computed(() => settingsStore.theme);
diff --git a/src/layout/components/Sidebar/menu.js b/src/layout/components/Sidebar/menu.js
new file mode 100644
index 0000000..e0c6940
--- /dev/null
+++ b/src/layout/components/Sidebar/menu.js
@@ -0,0 +1,84 @@
+import Layout from '@/layout'
+const menu = {
+    adminMenu: [
+        {
+            path: '/institution',
+            name: 'Institution',
+            meta: { title: '机构公示',icon: 'form',affix: true }
+        },
+        {
+            path: '/notice',
+            name: 'Notice',
+            meta: { title: '公告发布',icon: 'form', affix: true }
+        },
+        {
+            path: '/law',
+            name: 'Law',
+            meta: { title: '法律法规',icon: 'form', affix: true }
+        },
+        {
+            path: '/userManage',
+            redirect: '/userManage/supervise',
+            meta: { title: '用户管理',icon: 'form'},
+            children: [
+                {
+                    path: 'supervise',
+                    name: 'supervise',
+                    meta: { title: '监管用户管理',icon: 'form'}
+                },
+                {
+                    path: 'institutionUser',
+                    name: 'institutionUser',
+                    meta: { title: '机构用户管理',icon: 'form'}
+                },
+                {
+                    path: 'expertUsers',
+                    name: 'expertUsers',
+                    meta: { title: '专家用户管理',icon: 'form'}
+                }
+            ]
+        },
+        {
+            path: '/expertManage',
+            redirect: '/userManage/supervise',
+            meta: { title: '厅专家库管理',icon: 'form'},
+            children: [
+                {
+                    path: 'expert',
+                    name: 'expert',
+                    meta: { title: '厅专家库',icon: 'form'}
+                },
+                {
+                    path: 'record',
+                    name: 'record',
+                    meta: { title: '专家申请记录',icon: 'form'}
+                }
+            ]
+        },
+        {
+            path: '/baseSet',
+            redirect: '/baseSet/evaluate',
+            meta: { title: '基础设置',icon: 'form'},
+            children: [
+                {
+                    path: 'evaluate',
+                    name: 'evaluate',
+                    meta: { title: '评价类型管理',icon: 'form'}
+                },
+                {
+                    path: 'business',
+                    name: 'business',
+                    meta: { title: '业务范围',icon: 'form'}
+                },
+                {
+                    path: 'area',
+                    name: 'area',
+                    meta: { title: '地区维护',icon: 'form'}
+                }
+
+            ]
+        },
+
+    ]
+}
+export default menu;
diff --git a/src/router/index.js b/src/router/index.js
index 1814798..4d25555 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -52,6 +52,27 @@
     component: () => import('@/views/error/401'),
     hidden: true
   },
+
+  {
+    path: '/expertUser',
+    component: () => import('@/views/safetyReview/userManage/expertUsers/index.vue'),
+    hidden: true
+  },
+  {
+    path: '/evaluate',
+    component: () => import('@/views/safetyReview/baseSet/evaluateType/index.vue'),
+    hidden: true
+  },
+  {
+    path: '/business',
+    component: () => import('@/views/safetyReview/baseSet/business/index.vue'),
+    hidden: true
+  },
+  {
+    path: '/area',
+    component: () => import('@/views/safetyReview/baseSet/area/index.vue'),
+    hidden: true
+  },
   {
     path: '',
     component: Layout,
@@ -61,11 +82,131 @@
         path: '/index',
         component: () => import('@/views/index'),
         name: 'Index',
-        meta: { title: '首页', icon: 'dashboard', affix: true }
+        meta: { title: '首页',icon: 'form', affix: true }
       }
     ]
   },
   {
+    path: '/institution',
+    component: Layout,
+    redirect: '/institution',
+    children: [
+      {
+        path: '/institution',
+        component: () => import('@/views/safetyReview/institution/institution.vue'),
+        name: 'Institution',
+        meta: { title: '机构公示', icon: 'form', affix: true }
+      }
+    ]
+  },
+  {
+    path: '/notice',
+    component: Layout,
+    redirect: '/notice',
+    children: [
+      {
+        path: '/notice',
+        component: () => import('@/views/safetyReview/notice/notice.vue'),
+        name: 'Notice',
+        meta: { title: '公告发布',icon: 'form',  affix: true }
+      }
+    ]
+  },
+  {
+    path: '/law',
+    component: Layout,
+    redirect: '/law',
+    children: [
+      {
+        path: '/law',
+        component: () => import('@/views/safetyReview/law/law.vue'),
+        name: 'Law',
+        meta: { title: '法律法规',icon: 'form', affix: true }
+      }
+    ]
+  },
+  {
+    path: '/userManage',
+    component: Layout,
+    redirect: '/userManage/supervise',
+    meta: { title: '用户管理'},
+    children: [
+      {
+        path: 'supervise',
+        component: () => import('@/views/safetyReview/userManage/superviseUsers/index.vue'),
+        name: 'supervise',
+        meta: { title: '监管用户管理',icon: 'form'}
+      },
+      {
+        path: 'institutionUser',
+        component: () => import('@/views/safetyReview/userManage/institutionUsers/index.vue'),
+        name: 'institutionUser',
+        meta: { title: '机构用户管理',icon: 'form'}
+      },
+      {
+        path: 'expertUsers',
+        component: () => import('@/views/safetyReview/userManage/expertUsers/index.vue'),
+        name: 'expertUsers',
+        meta: { title: '专家用户管理',icon: 'form'}
+      },
+    ]
+  },
+  {
+    path: '/expertManage',
+    component: Layout,
+    redirect: '/expertManage/expert',
+    meta: { title: '厅专家库管理'},
+    children: [
+      {
+        path: 'expert',
+        component: () => import('@/views/index'),
+        name: 'expert',
+        meta: { title: '厅专家库',icon: 'form'}
+      },
+      {
+        path: 'record',
+        component: () => import('@/views/index'),
+        name: 'record',
+        meta: { title: '专家申请记录',icon: 'form'}
+      },
+      {
+        path: 'expertUser',
+        component: () => import('@/views/safetyReview/userManage/expertUsers/index.vue'),
+        name: 'expertUser',
+        meta: { title: '专家用户管理',icon: 'form'}
+      },
+    ]
+  },
+  {
+    path: '/baseSet',
+    component: Layout,
+    redirect: '/baseSet/evaluate',
+    meta: { title: '基础设置'},
+    children: [
+      {
+        path: 'evaluate',
+        component: () => import('@/views/safetyReview/baseSet/evaluateType/index.vue'),
+        name: 'evaluate',
+        meta: { title: '评价类型管理',icon: 'form'}
+      },
+      {
+        path: 'business',
+        component: () => import('@/views/safetyReview/baseSet/business/index.vue'),
+        name: 'business',
+        meta: { title: '业务范围',icon: 'form'}
+      },
+      {
+        path: 'area',
+        component: () => import('@/views/safetyReview/baseSet/area/index.vue'),
+        name: 'area',
+        meta: { title: '地区维护',icon: 'form'}
+      },
+    ]
+  },
+
+
+
+  {
     path: '/user',
     component: Layout,
     hidden: true,
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index 733c04a..d1d60e7 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -1,7 +1,7 @@
 import { login, logout, getInfo } from '@/api/login'
 import { getToken, setToken, removeToken } from '@/utils/auth'
 import defAva from '@/assets/images/profile.jpg'
-
+import Cookies from "js-cookie";
 const useUserStore = defineStore(
   'user',
   {
@@ -23,6 +23,7 @@
         return new Promise((resolve, reject) => {
           login(username, password, code, uuid).then(res => {
             setToken(res.data.token)
+            Cookies.set('userInfo',JSON.stringify(res.data))
             this.token = res.data.token
             resolve()
           }).catch(error => {
diff --git a/src/views/components/loginForm.vue b/src/views/components/loginForm.vue
index 08b6651..2f5995e 100644
--- a/src/views/components/loginForm.vue
+++ b/src/views/components/loginForm.vue
@@ -135,7 +135,11 @@
           }
           return acc;
         }, {});
-        router.push({ path: redirect.value || "/", query: otherQueryParams });
+        const routers = JSON.parse(Cookies.get('routers'))
+          router.push({
+              path: routers[0].path
+          })
+        // router.push({ path: redirect.value || "/", query: otherQueryParams });
       }).catch(() => {
         loading.value = false;
         // 重新获取验证码
diff --git a/src/views/safetyReview/baseSet/area/components/areaDialog.vue b/src/views/safetyReview/baseSet/area/components/areaDialog.vue
new file mode 100644
index 0000000..3a5be65
--- /dev/null
+++ b/src/views/safetyReview/baseSet/area/components/areaDialog.vue
@@ -0,0 +1,118 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="500px"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.form" size="default" ref="areaRef" :rules="state.formRules" label-width="110px" >
+                <el-form-item>
+                    <el-radio-group v-model="state.form.area" style="margin-left: -50px" >
+                        <el-radio :label="1">地(市、州)</el-radio>
+                        <el-radio :label="2">区县</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item v-if="state.form.area === 1" style="margin-left: -50px" prop="stateName">
+                    <el-input v-model.trim="state.form.stateName" placeholder="请输入地州名" ></el-input>
+                </el-form-item>
+                <div v-if="state.form.area === 2">
+                    <el-form-item style="margin-left: -50px" prop="stateCode">
+                        <el-select v-model="state.form.stateCode" class="m-2" placeholder="请选择所属地(市、州)" style="width: 100%">
+                            <el-option
+                                v-for="item in state.areaList"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                            />
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item  style="margin-left: -50px" prop="countyName">
+                        <el-input v-model.trim="state.form.countyName" placeholder="请输入区县名"></el-input>
+                    </el-form-item>
+                </div>
+
+            </el-form>
+            <template #footer>
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const areaRef = ref();
+const state = reactive({
+    form: {
+        area: 1,
+        stateCode: '',
+        stateName: '',
+        countyName: ''
+    },
+    formRules:{
+        stateName: [{ required: true, message: '请输入地州名', trigger: 'blur' }],
+        countyName: [{ required: true, message: '请输入区县名', trigger: 'blur' }],
+        stateCode: [{ required: true, message: '请选择所属地(市、州)', trigger: 'blur' }],
+    },
+    areaList: []
+
+})
+
+const openDialog = (type, value) => {
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.form = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await areaRef.value.validate();
+    if(valid){
+        areaRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    areaRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.form = {
+        area: 1,
+        state: '',
+        county: '',
+        stateCode: '',
+    }
+}
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/baseSet/area/index.vue b/src/views/safetyReview/baseSet/area/index.vue
new file mode 100644
index 0000000..309e39b
--- /dev/null
+++ b/src/views/safetyReview/baseSet/area/index.vue
@@ -0,0 +1,92 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true" row-key="name">
+            <el-table-column label="地区"  align="center">
+                <template #default="scope">
+                    <span>{{scope.row.name}}</span>
+
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <area-dialog ref="areaRef" @getList="getList"></area-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
+import {ElMessageBox} from "element-plus";
+import areaDialog from "./components/areaDialog.vue"
+import { getArea } from "@/api/backManage/area";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const areaRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: [
+    ]
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+//页面加载
+onMounted(() => {
+    getList();
+});
+const getList = async () => {
+    loading.value = true;
+    // let res = await getArea();
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    areaRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/baseSet/business/components/businessDialog.vue b/src/views/safetyReview/baseSet/business/components/businessDialog.vue
new file mode 100644
index 0000000..b4e9586
--- /dev/null
+++ b/src/views/safetyReview/baseSet/business/components/businessDialog.vue
@@ -0,0 +1,87 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="500px"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="110px" >
+                <el-form-item label="业务范围:" prop="business">
+                    <el-input v-model.trim="state.form.business"></el-input>
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const busRef = ref();
+const state = reactive({
+    form: {
+        business: ''
+    },
+    formRules:{
+        business: [{ required: true, message: '请输入业务范围', trigger: 'blur' }],
+    },
+
+})
+
+const openDialog = (type, value) => {
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.form = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await busRef.value.validate();
+    if(valid){
+        busRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    busRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.form = {
+        business: ""
+    }
+}
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/baseSet/business/index.vue b/src/views/safetyReview/baseSet/business/index.vue
new file mode 100644
index 0000000..8a8aecb
--- /dev/null
+++ b/src/views/safetyReview/baseSet/business/index.vue
@@ -0,0 +1,82 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="业务范围" prop="business" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <business-dialog ref="busRef" @getList=getList></business-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import businessDialog from "./components/businessDialog.vue"
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const busRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: [
+    ]
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    busRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/baseSet/evaluateType/components/typeDialog.vue b/src/views/safetyReview/baseSet/evaluateType/components/typeDialog.vue
new file mode 100644
index 0000000..287b8ce
--- /dev/null
+++ b/src/views/safetyReview/baseSet/evaluateType/components/typeDialog.vue
@@ -0,0 +1,100 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="500px"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.form" size="default" ref="typeRef" :rules="state.formRules" label-width="110px" >
+                <el-form-item label="评价类型:" prop="type">
+                    <el-input v-model.trim="state.form.type"></el-input>
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const typeRef = ref();
+const isReview = ref(false);
+const state = reactive({
+    form: {
+        type: ''
+    },
+    formRules:{
+        type: [{ required: true, message: '请输入评价类型', trigger: 'blur' }],
+    },
+
+})
+
+const openDialog = (type, value) => {
+    isReview.value = false;
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.form = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await typeRef.value.validate();
+    if(valid){
+        typeRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    typeRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.form = {
+        type: ""
+    }
+}
+const handleRemove = (file, fileList) => {
+    console.log(file, fileList);
+}
+const handlePreview = (uploadFile) => {
+    console.log(uploadFile)
+}
+const beforeRemove = (file, fileList) => {
+    return this.$confirm(`确定移除 ${ file.name }?`);
+}
+
+
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/baseSet/evaluateType/index.vue b/src/views/safetyReview/baseSet/evaluateType/index.vue
new file mode 100644
index 0000000..f9779d1
--- /dev/null
+++ b/src/views/safetyReview/baseSet/evaluateType/index.vue
@@ -0,0 +1,82 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="评价类型" prop="type" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <type-dialog ref="typeRef" @getList=getList></type-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import typeDialog from "./components/typeDialog.vue"
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const typeRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: [
+    ]
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    typeRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/institution/institution.vue b/src/views/safetyReview/institution/institution.vue
new file mode 100644
index 0000000..8c4bd61
--- /dev/null
+++ b/src/views/safetyReview/institution/institution.vue
@@ -0,0 +1,79 @@
+<template>
+    <div class="app-container">
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="序号" type="index" align="center" width="80" />
+            <el-table-column label="机构名称" prop="name" align="center"  />
+            <el-table-column label="社会信用代码" prop="code" align="center"  />
+            <el-table-column label="机构属性" prop="lawSubTitle" align="center" />
+            <el-table-column label="所属区域" prop="area" align="center"  />
+            <el-table-column label="资质证书编号" prop="institution" align="center"  />
+            <el-table-column label="发证日期" prop="date" align="center"  />
+            <el-table-column label="有效期" prop="date" align="center"  />
+            <el-table-column label="公示状态" prop="status" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
+                    <el-button link type="primary"  @click="publicity(scope.row)" >{{publicMsg}}</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const inRef = ref();
+const publicMsg = ref("公示");
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: [
+    ]
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    inRef.value.openDialog(type, value);
+}
+
+const publicity = (val) => {
+
+}
+
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/law/components/lawDialog.vue b/src/views/safetyReview/law/components/lawDialog.vue
new file mode 100644
index 0000000..9033c6c
--- /dev/null
+++ b/src/views/safetyReview/law/components/lawDialog.vue
@@ -0,0 +1,183 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="50%"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.form" size="default" ref="lawRef" :rules="title === '新增' || title === '编辑' ? state.formRules : {}" label-width="110px" >
+                <el-form-item label="标题:" prop="title">
+                    <el-input v-model.trim="state.form.title" v-if="!isReview" ></el-input>
+                    <span v-else>{{state.form.title}}</span>
+                </el-form-item>
+                <el-form-item label="副标题:" prop="subTitle">
+                    <el-input v-model.trim="state.form.subTitle" v-if="!isReview" ></el-input>
+                    <span v-else>{{state.form.title}}</span>
+                </el-form-item>
+                <el-form-item label="类别:" prop="level">
+                    <el-radio-group v-model="state.form.level" v-if="!isReview">
+                        <el-radio :label="1">法律</el-radio>
+                        <el-radio :label="2">法规</el-radio>
+                        <el-radio :label="3">地方性规定</el-radio>
+                        <el-radio :label="4">其他</el-radio>
+                    </el-radio-group>
+                    <span v-else>{{state.form.level === 1 ? '法律' : state.form.level === 2? '法规' :state.form.level === 3?'地方性规定': '其他'}}</span>
+                </el-form-item>
+                <el-form-item label="颁布机构:" prop="institution">
+                    <el-input v-model.trim="state.form.institution" v-if="!isReview" ></el-input>
+                    <span v-else>{{state.form.institution}}</span>
+                </el-form-item>
+                <el-form-item label="颁布日期:" prop="publishTime">
+                    <el-date-picker
+                        v-if="!isReview"
+                        v-model="state.form.publishTime"
+                        type="date"
+                        placeholder="请选择日期"
+                        size="default"
+                    />
+                    <span v-else>{{state.form.publishTime}}</span>
+                </el-form-item>
+                <div style="margin: 0 0 15px 30px" v-if="!isReview">
+                    <el-upload
+                        v-model:file-list="fileList"
+                        class="upload-demo"
+                        action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
+                        multiple
+                        :on-preview="handlePreview"
+                        :on-remove="handleRemove"
+                        :before-remove="beforeRemove"
+                        :limit="3"
+                    >
+                        <el-button type="primary">附件上传</el-button>
+                    </el-upload>
+                </div>
+                <el-form-item v-else label="附件:" >
+                    <div class="file">
+                        <el-link v-for="(item,index) in state.form.fileList"  type="primary" :key="index" :underline="false">
+                            <i class="el-icon-paperclip" style="margin-right: 5px;color: #1e6abc"></i>{{item.fileName}}
+                        </el-link>
+                    </div>
+                </el-form-item>
+                <el-form-item v-if="!isReview" style="margin-left: -80px" prop="content">
+                    <editor  ref="myQuillEditor" v-model="state.form.content" :height="300"></editor>
+                </el-form-item>
+                <el-form-item label="公告内容:" v-else>
+                    <div class="ql-container ql-snow" style="height: 300px;width: 100%;margin-top: 10px;" >
+                        <div class="ql-editor">
+                            <div v-html="state.form.content"></div>
+                        </div>
+                    </div>
+                </el-form-item>
+            </el-form>
+            <template #footer v-if="!isReview">
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认发布</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const lawRef = ref();
+const fileList = ref([]);
+const myQuillEditor = ref();
+const isReview = ref(false);
+const state = reactive({
+    form: {
+        title: '',
+        subTitle: '',
+        content: '',
+        level: 1,
+        fileList: []
+    },
+    formRules:{
+        title: [{ required: true, message: '请填写标题', trigger: 'blur' }],
+        institution: [{ required: true, message: '请填写颁布机构', trigger: 'blur' }],
+        content: [{ required: true, message: '请输入公告内容', trigger: 'change' }],
+    },
+
+})
+
+const openDialog = (type, value) => {
+    isReview.value = false;
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.noticeForm = value;
+    }
+    if(type === 'review') {
+        isReview.value = true;
+        state.noticeForm = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await lawRef.value.validate();
+    if(valid){
+        if(state.noticeForm.content === "<p><br></p>"){
+            ElMessage({
+                type: 'warning',
+                message: '请输入公告内容'
+            });
+            return;
+        }
+        console.log('file, fileList',state.noticeForm.content);
+        lawRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    lawRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.form = {
+        title: '',
+        subTitle: '',
+        content: '',
+        level: 1,
+        fileList: []
+    }
+}
+const handleRemove = (file, fileList) => {
+    console.log(file, fileList);
+}
+const handlePreview = (uploadFile) => {
+    console.log(uploadFile)
+}
+const beforeRemove = (file, fileList) => {
+    return this.$confirm(`确定移除 ${ file.name }?`);
+}
+
+
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/law/law.vue b/src/views/safetyReview/law/law.vue
new file mode 100644
index 0000000..101f29b
--- /dev/null
+++ b/src/views/safetyReview/law/law.vue
@@ -0,0 +1,87 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="颁布时间" prop="publishTime" align="center"  />
+            <el-table-column label="标题" prop="lawTitle" align="center" :show-overflow-tooltip="true" width="400" />
+            <el-table-column label="副标题" prop="lawSubTitle" align="center" :show-overflow-tooltip="true" width="400" />
+            <el-table-column label="类别" prop="level" align="center"  />
+            <el-table-column label="颁布机构" prop="institution" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <law-dialog ref="lawRef" @getList="getList"></law-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import lawDialog from './components/lawDialog.vue'
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const lawRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: []
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    lawRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/notice/components/noticeDialog.vue b/src/views/safetyReview/notice/components/noticeDialog.vue
new file mode 100644
index 0000000..28ca3c6
--- /dev/null
+++ b/src/views/safetyReview/notice/components/noticeDialog.vue
@@ -0,0 +1,150 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="50%"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.noticeForm" size="default" ref="noticeRef" :rules="title === '新增' || title === '编辑' ? state.formRules : {}" label-width="110px" >
+                <el-form-item label="公告标题:" prop="noticeTitle">
+                    <el-input v-model.trim="state.noticeForm.noticeTitle" v-if="!isReview" ></el-input>
+                    <span v-else>{{state.noticeForm.noticeTitle}}</span>
+                </el-form-item>
+                <div style="margin: 0 0 15px 30px" v-if="!isReview">
+                    <el-upload
+                        v-model:file-list="fileList"
+                        class="upload-demo"
+                        action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
+                        multiple
+                        :on-preview="handlePreview"
+                        :on-remove="handleRemove"
+                        :before-remove="beforeRemove"
+                        :limit="3"
+                    >
+                        <el-button type="primary">附件上传</el-button>
+                    </el-upload>
+                </div>
+                <el-form-item v-else label="附件:" >
+                    <div class="file">
+                        <el-link v-for="(item,index) in state.noticeForm.fileList"  type="primary" :key="index" :underline="false">
+                            <i class="el-icon-paperclip" style="margin-right: 5px;color: #1e6abc"></i>{{item.fileName}}
+                        </el-link>
+                    </div>
+                </el-form-item>
+                <el-form-item v-if="!isReview" style="margin-left: -80px" prop="noticeContent">
+                    <editor  ref="myQuillEditor" v-model="state.noticeForm.noticeContent" :height="300"></editor>
+                </el-form-item>
+                <el-form-item label="公告内容:" v-else>
+                    <div class="ql-container ql-snow" style="height: 300px;width: 100%;margin-top: 10px;" >
+                        <div class="ql-editor">
+                            <div v-html="state.noticeForm.noticeContent"></div>
+                        </div>
+                    </div>
+                </el-form-item>
+            </el-form>
+            <template #footer v-if="!isReview">
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认发布</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const noticeRef = ref();
+const fileList = ref([]);
+const myQuillEditor = ref();
+const isReview = ref(false);
+const state = reactive({
+    noticeForm: {
+        noticeTitle: '',
+        noticeContent: '',
+        fileList: []
+    },
+    formRules:{
+        noticeTitle: [{ required: true, message: '请填写公告标题', trigger: 'blur' }],
+        noticeContent: [{ required: true, message: '请输入公告内容', trigger: 'change' }],
+    },
+
+})
+
+const openDialog = (type, value) => {
+    isReview.value = false;
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.noticeForm = value;
+    }
+    if(type === 'review') {
+        isReview.value = true;
+        state.noticeForm = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await noticeRef.value.validate();
+    if(valid){
+        if(state.noticeForm.noticeContent === "<p><br></p>"){
+            ElMessage({
+                type: 'warning',
+                message: '请输入公告内容'
+            });
+            return;
+        }
+        console.log('file, fileList',state.noticeForm.noticeContent);
+        noticeRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    noticeRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.noticeForm = {
+        noticeTitle: '',
+        noticeContent: ''
+    }
+}
+const handleRemove = (file, fileList) => {
+    console.log(file, fileList);
+}
+const handlePreview = (uploadFile) => {
+    console.log(uploadFile)
+}
+const beforeRemove = (file, fileList) => {
+    return this.$confirm(`确定移除 ${ file.name }?`);
+}
+
+
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/notice/notice.vue b/src/views/safetyReview/notice/notice.vue
new file mode 100644
index 0000000..0579b20
--- /dev/null
+++ b/src/views/safetyReview/notice/notice.vue
@@ -0,0 +1,84 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="发布时间" prop="publishTime" align="center"  />
+            <el-table-column label="标题" prop="noticeTitle" align="center" :show-overflow-tooltip="true" width="650" />
+            <el-table-column label="最近修改时间" prop="updateTime" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <notice-dialog ref="noticeRef" @getList = "getList"></notice-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import noticeDialog from "./components/noticeDialog.vue"
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: []
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    noticeRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
diff --git a/src/views/safetyReview/userManage/expertUsers/index.vue b/src/views/safetyReview/userManage/expertUsers/index.vue
new file mode 100644
index 0000000..68dd33b
--- /dev/null
+++ b/src/views/safetyReview/userManage/expertUsers/index.vue
@@ -0,0 +1,169 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <div style="margin-top: 15px;margin-bottom: 15px;">
+            <el-radio-group v-model="queryParams.checkType" @change="changeType">
+                <el-radio-button label="all">全部</el-radio-button>
+                <el-radio-button label="1">安全评价</el-radio-button>
+                <el-radio-button label="2">检验检测</el-radio-button>
+            </el-radio-group>
+        </div>
+
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="用户ID" prop="userID" align="center"  />
+            <el-table-column label="姓名" prop="name" align="center"  />
+            <el-table-column label="手机号" prop="phone" align="center" />
+            <el-table-column label="用户名" prop="username" align="center"  />
+            <el-table-column label="性别" prop="sex" align="center"  />
+            <el-table-column label="所属机构" prop="institution" align="center"  />
+            <el-table-column label="社保" prop="socialSecurity" align="center" width="120">
+                <template #default="scope">
+                    <div class="demo-image__preview" v-if="scope.row.socialList && scope.row.socialList.length>0">
+                          <el-image
+                              style="width: 100px; height: 100px"
+                              :src="scope.row.socialList[0]"
+                              :zoom-rate="1.2"
+                              :max-scale="7"
+                              :min-scale="0.2"
+                              :preview-src-list="scope.row.socialList"
+                              :initial-index="0"
+                              fit="cover"
+                              preview-teleported="true"
+                          />
+                    </div>
+                </template>
+            </el-table-column>
+            <el-table-column label="医保" prop="medicalInsurance" align="center" width="120">
+                <template #default="scope">
+                    <div class="demo-image__preview" v-if="scope.row.medicalList && scope.row.medicalList.length>0">
+                        <el-image
+                            style="width: 100px; height: 100px"
+                            :src="scope.row.medicalList[0]"
+                            :zoom-rate="1.2"
+                            :max-scale="7"
+                            :min-scale="0.2"
+                            :preview-src-list="scope.row.medicalList"
+                            :initial-index="0"
+                            fit="cover"
+                            preview-teleported="true"
+                        />
+                    </div>
+                </template>
+            </el-table-column>
+            <el-table-column label="工资清单" prop="salaryList" align="center" width="120">
+                <template #default="scope">
+                    <div class="demo-image__preview" v-if="scope.row.salaryList && scope.row.salaryList.length>0">
+                        <el-image
+                            style="width: 100px; height: 100px"
+                            :src="scope.row.salaryList[0]"
+                            :zoom-rate="1.2"
+                            :max-scale="7"
+                            :min-scale="0.2"
+                            :preview-src-list="scope.row.salaryList"
+                            :initial-index="0"
+                            fit="cover"
+                            preview-teleported="true"
+                        />
+                    </div>
+                </template>
+            </el-table-column>
+            <el-table-column label="职务" prop="duty" align="center"  />
+            <el-table-column label="职称" prop="lecture" align="center"  />
+            <el-table-column label="专业方向" prop="major" align="center"  />
+            <el-table-column label="业绩汇总" prop="summary" align="center"  />
+            <el-table-column label="最近评价时间" prop="lastTime" align="center" width="120" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const expertRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        checkType: "all"
+
+    },
+    total: 0,
+    dataList: [
+    ]
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    expertRef.value.openDialog(type, value);
+}
+const changeType = (val) => {
+    console.log("val", val)
+    queryParams.checkType = val;
+    queryParams.pageNum = 1;
+    getList();
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>
+<style scoped lang="scss">
+.demo-image__error .image-slot {
+    font-size: 30px;
+}
+.demo-image__error .image-slot .el-icon {
+    font-size: 30px;
+}
+.demo-image__error .el-image {
+    width: 100%;
+    height: 200px;
+}
+</style>
diff --git a/src/views/safetyReview/userManage/institutionUsers/index.vue b/src/views/safetyReview/userManage/institutionUsers/index.vue
new file mode 100644
index 0000000..ca1f829
--- /dev/null
+++ b/src/views/safetyReview/userManage/institutionUsers/index.vue
@@ -0,0 +1,96 @@
+<template>
+    <div class="app-container">
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="用户ID" prop="userID" align="center"  />
+            <el-table-column label="机构名称" prop="name" align="center" />
+            <el-table-column label="信用代码" prop="code" align="center"  />
+            <el-table-column label="用户名" prop="username" align="center"  />
+            <el-table-column label="注册手机号" prop="phone" align="center"  />
+            <el-table-column label="注册审批" prop="examine" align="center" >
+                <template #default="scope">
+                    <span v-if="scope.row.examine === 1">待审批</span>
+                    <span v-if="scope.row.examine === 2">未通过</span>
+                    <span v-if="scope.row.examine === 3">已通过</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="状态" prop="status" align="center" >
+                <template #default="scope">
+                    <span v-if="scope.row.status === 1">可用</span>
+                    <span v-if="scope.row.status === 2">不可用</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width"  width="300px">
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger" v-if="!(scope.row.status === 1 && scope.row.examine === 3)" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                    <el-button link type="primary" v-if="scope.row.examine === 3 && scope.row.status === 1"  @click="stop(scope.row)" >停用</el-button>
+                    <el-button link type="primary" v-if="scope.row.examine !== 3 && scope.row.status === 2"  @click="pass(scope.row)" >审批通过</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import {ElMessageBox} from "element-plus";
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const superRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: []
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    superRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+const stop = (val) => {
+
+}
+const pass= (val) => {
+
+}
+</script>
diff --git a/src/views/safetyReview/userManage/superviseUsers/components/superviseDialog.vue b/src/views/safetyReview/userManage/superviseUsers/components/superviseDialog.vue
new file mode 100644
index 0000000..64e0161
--- /dev/null
+++ b/src/views/safetyReview/userManage/superviseUsers/components/superviseDialog.vue
@@ -0,0 +1,195 @@
+<template>
+    <div class="notice">
+        <el-dialog
+            v-model="dialogVisible"
+            :title="title"
+            width="500px"
+            :before-close="handleClose"
+        >
+            <el-form :model="state.form" size="default" ref="superRef" :rules="title === '新增'  ? state.formRules : {}" label-width="110px" >
+                <el-form-item label="姓名:" prop="name" >
+                    <el-input v-model.trim="state.form.name" ></el-input>
+                </el-form-item>
+                <el-form-item label="用户名:"  prop="username">
+                    <el-input v-model.trim="state.form.username" ></el-input>
+                </el-form-item>
+                <el-form-item label="密码:" prop="password">
+                    <el-input v-model.trim="state.form.password" :type="passwordType" placeholder="请输入密码" autocomplete="new-password">
+                        <template #append>
+                            <el-button :icon="View" @click="showPwd" />
+                        </template>
+                    </el-input>
+                </el-form-item>
+                <el-form-item label="重复密码:" prop="confirmPassword">
+                    <el-input v-model.trim="state.form.confirmPassword" :type="confirmPasswordType" placeholder="请输入确认密码" autocomplete="new-password">
+                        <template #append>
+                            <el-button :icon="View" @click="showConfirmPwd" />
+                        </template>
+                    </el-input>
+                </el-form-item>
+                <el-form-item label="手机号:" prop="phone">
+                    <el-input v-model.trim="state.form.phone" :maxlength="11" ></el-input>
+                </el-form-item>
+                <el-form-item label="账号类型:" >
+                    <el-radio-group v-model="state.form.accountType" >
+                        <el-radio :label="1">工作人员</el-radio>
+                        <el-radio :label="2">领导</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item label="管辖地区:" >
+                    <el-select v-model="state.form.area" class="m-2" placeholder="请选择" style="width:100%">
+                        <el-option
+                            v-for="item in state.areaList"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        />
+                    </el-select>
+                </el-form-item>
+            </el-form>
+            <template #footer >
+                    <span class="dialog-footer">
+                        <el-button @click="handleClose" size="default">取 消</el-button>
+                        <el-button type="primary"  @click="onSubmit" size="default">确认</el-button>
+                    </span>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs} from 'vue'
+import { View } from "@element-plus/icons-vue";
+import {ElMessage} from "element-plus";
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false);
+const title = ref("");
+const superRef = ref();
+const passwordType = ref('password');
+const confirmPasswordType= ref('password');
+const validatePwd = (rule, value, callback)=>{
+    if(title.value === '新增'){
+        if(value === ''){
+            callback(new Error('请再次输入密码'))
+        }else if(value !== state.form.password){
+            callback(new Error('两次输入密码不同'))
+        }else{
+            callback()
+        }
+    }else{
+        if(state.form.password!==''){
+            if(value === ''){
+                callback(new Error('请再次输入密码'))
+            }else if(value !== state.form.password){
+                callback(new Error('两次输入密码不同'))
+            }else{
+                callback()
+            }
+        }else{
+            callback()
+        }
+    }
+}
+const phoneRegex = /^1[3456789]\d{9}$/;
+const validatePhone = (rule, value, callback)=>{
+    if(value === ''){
+        callback(new Error('请输入手机号'))
+    }else{
+        if(!phoneRegex.test(value)){
+            callback(new Error('请按要求格式输入手机号'))
+        }else{
+            callback()
+        }
+    }
+}
+const state = reactive({
+    form: {
+        name: '',
+        phone: '',
+        password: '',
+        confirmPassword: '',
+        username: '',
+        accountType: 1,
+        area: ''
+    },
+    formRules:{
+        name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+        password: [{ required: true, message: '密码不能为空', trigger: 'blur' }],
+        confirmPassword: [{ required: true, validator: validatePwd, trigger: 'blur' }],
+        phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
+    },
+    areaList: []
+
+})
+
+const showPwd = () => {
+    if (passwordType.value === 'password') {
+        passwordType.value = ''
+    } else {
+        passwordType.value = 'password'
+    }
+};
+const showConfirmPwd = () => {
+    if (confirmPasswordType.value === 'password') {
+        confirmPasswordType.value = ''
+    } else {
+        confirmPasswordType.value = 'password'
+    }
+};
+
+
+const openDialog = (type, value) => {
+    title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+    if(type === 'edit') {
+        state.form = value;
+    }
+    dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+    const valid = await superRef.value.validate();
+    if(valid){
+        superRef.value.clearValidate();
+        reset();
+        dialogVisible.value = false;
+
+    }
+}
+
+const handleClose = () => {
+    superRef.value.clearValidate();
+    reset();
+    dialogVisible.value = false;
+
+}
+const reset = () => {
+    state.form = {
+        name: '',
+        phone: '',
+        password: '',
+        confirmPassword: '',
+        username: '',
+        accountType: 1,
+        area: ''
+    }
+}
+
+
+defineExpose({
+    openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+    :deep(.el-form .el-form-item__label) {
+        font-size: 15px;
+    }
+    .file {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+</style>
diff --git a/src/views/safetyReview/userManage/superviseUsers/index.vue b/src/views/safetyReview/userManage/superviseUsers/index.vue
new file mode 100644
index 0000000..86de17d
--- /dev/null
+++ b/src/views/safetyReview/userManage/superviseUsers/index.vue
@@ -0,0 +1,91 @@
+<template>
+    <div class="app-container">
+        <div style="margin-bottom: 10px">
+            <el-button
+                type="primary"
+                plain
+                icon="Plus"
+                @click="openDialog('add',{})"
+            >新增</el-button>
+        </div>
+        <!-- 表格数据 -->
+        <el-table v-loading="loading" :data="dataList" :border="true">
+            <el-table-column label="姓名" prop="name" align="center"  />
+            <el-table-column label="手机号" prop="phone" align="center" />
+            <el-table-column label="用户名" prop="username" align="center"  />
+            <el-table-column label="账号类型" prop="accountType" align="center" >
+                <template #default="scope">
+                    <span v-if="scope.row.accountType === 1">工作人员</span>
+                    <span v-if="scope.row.accountType === 2">领导</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="监管地区" prop="area" align="center"  />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+                <template #default="scope">
+                    <el-button link type="primary"  @click="openDialog('edit',scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
+                    <el-button link type="danger"  @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination
+            v-show="total > 0"
+            :total="total"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+        />
+        <supervise-dialog ref="superRef" @getList=getList></supervise-dialog>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import {ElMessageBox} from "element-plus";
+import superviseDialog from "./components/superviseDialog.vue"
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const superRef = ref();
+const data = reactive({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    },
+    total: 0,
+    dataList: [
+    ]
+
+
+});
+
+const { queryParams, total, dataList } = toRefs(data);
+
+const getList = () => {
+    loading.value = true;
+    console.log("获取数据")
+    loading.value = false;
+}
+
+const openDialog = (type, value) => {
+    superRef.value.openDialog(type, value);
+}
+
+/** 重置新增的表单以及其他数据  */
+function reset() {
+    proxy.resetForm("roleRef");
+}
+const handleDelete = (val) => {
+    ElMessageBox.confirm(
+        '确定删除此条数据?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        })
+        .then( async() => {
+
+        })
+}
+
+</script>

--
Gitblit v1.9.2