Browse Source

菜单、巡查人员区域选择器

yangyuxuan 5 months ago
parent
commit
a925168ce4

+ 1 - 2
src/api/riskPrevention/BusinessPortraits.ts

@@ -27,8 +27,7 @@ export function addCompany(data) {
 export function CompanyDetail(id) {
   return request({
     url: '/api/companyManagement/company/' + id,
-    method: 'get',
-    params: id
+    method: 'get'
   });
 }
 

+ 24 - 2
src/layout/components/Sidebar/SidebarItem.vue

@@ -3,7 +3,7 @@
     <template v-if="hasOneShowingChild(item, item.children) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
       <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
         <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
-          <svg-icon :icon-class="getIconClass(onlyOneChild)" />
+          <svg-icon v-if="getIconClass(onlyOneChild)" :icon-class="getIconClass(onlyOneChild)" />
           <template #title>
             <span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
           </template>
@@ -13,7 +13,7 @@
 
     <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
       <template v-if="item.meta" #title>
-        <svg-icon :icon-class="getIconClass(item)" />
+        <svg-icon v-if="getIconClass(item)" :icon-class="getIconClass(item)" />
         <span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span>
       </template>
       <sidebar-item
@@ -134,6 +134,18 @@ const getIconClass = (item) => {
   }
 }
 
+.nest-menu .el-sub-menu__title .menu-title {
+  margin-left: 10px;
+}
+.nest-menu .el-menu-item .menu-title {
+  margin-left: 10px;
+
+}
+.nest-menu .nest-menu .el-menu-item .menu-title {
+  margin-left: 3px;
+}
+
+
 .is-opened {
   :deep(.el-sub-menu__title) {
     color: #fff;
@@ -146,6 +158,16 @@ const getIconClass = (item) => {
       .el-sub-menu__title {
         color: #fff;
       }
+      .nest-menu {
+        .el-sub-menu__title {
+          color: #939faa;
+        }
+        .is-opened {
+          .el-sub-menu__title {
+            color: #fff;
+          }
+        }
+      }
     }
   }
 }

+ 0 - 13
src/types/components.d.ts

@@ -30,14 +30,10 @@ declare module 'vue' {
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
-    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
-    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
-    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -48,17 +44,12 @@ declare module 'vue' {
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
-    ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
-    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
-    ElLink: typeof import('element-plus/es')['ElLink']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
-    ElRadio: typeof import('element-plus/es')['ElRadio']
-    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -70,8 +61,6 @@ declare module 'vue' {
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
-    ElTimeline: typeof import('element-plus/es')['ElTimeline']
-    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
@@ -86,8 +75,6 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
-    IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
-    IEpCaretTop: typeof import('~icons/ep/caret-top')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
     ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
     ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']

+ 25 - 14
src/views/inspectionWork/inspectorAdd.vue

@@ -2,18 +2,21 @@
   <div class="common-dialog">
     <div class="common-dialog-content">
       <div class="common-dialog-title-box">
-        <h3 class="common-dialog-title">新建巡查人员</h3>
+        <i class="common-dialog-title-icon" />
+        <div>新建巡查人员</div>
       </div>
       <div class="common-dialog-box">
         <el-form ref="form" :model="formData" :rules="rules" label-width="120px">
-          <el-form-item label="姓名:" prop="nick_name">
+          <el-form-item label="姓名:" prop="user_id">
             <el-tree-select
-              v-model="formData.uuid"
+              v-model="formData.user_id"
               :data="treeData"
-              :props="{ label: 'label', value: 'id', children: 'children' }"
+              :props="defaultProps"
+              node-key="id"
               :render-after-expand="false"
               style="width: 468px"
               @change="onUserNameChange"
+              filterable
             />
           </el-form-item>
           <el-form-item label="粤政易组织:" prop="ancestors_names">
@@ -22,14 +25,15 @@
           <el-form-item label="联系方式:" prop="phonenumber">
             <el-input v-model="formData.phonenumber" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="责任区划:" prop="area">
+          <el-form-item label="责任区划:" prop="area_code">
             <el-tree-select
-              v-model="divisionSelectedId"
+              v-model="formData.area_code"
               :data="formattedDivisionData"
               :props="{ label: 'label', value: 'code', children: 'children' }"
               :render-after-expand="false"
               style="width: 468px"
               @change="onDivisionChange"
+              check-strictly
             />
           </el-form-item>
         </el-form>
@@ -44,7 +48,7 @@
 
 <script setup lang="ts">
 import { inspectorAdd, phoneList, userList, inspectorDivision } from '@/api/inspectionWork/inspector';
-import { ref, watch } from 'vue';
+import { reactive, ref, watch } from 'vue';
 import { ElMessage } from 'element-plus';
 import { useRouter } from 'vue-router';
 
@@ -57,6 +61,7 @@ const formData = ref({
   user_id: '',
   nick_name: '',
   phonenumber: '',
+  area_code: '',
   uuid: ''
 });
 
@@ -64,14 +69,20 @@ const treeData = ref([]);
 const rawDivisionData = ref([]);
 const formattedDivisionData = ref([]);
 
-const divisionSelectedId = ref(null);
-
 const closeDialog = () => {
   emits('close');
 };
 
 const router = useRouter();
 
+const defaultProps = reactive({
+  children:'children',
+  label:'label',
+  disabled:(node) => {
+    return node.deptType && !node.children;
+  }
+})
+
 // 更新表单数据
 const updateFormData = (userData) => {
   formData.value = {
@@ -87,10 +98,10 @@ const updateFormData = (userData) => {
 };
 // 表单验证规则
 const rules = ref({
-  nick_name: [{ required: true, message: '请选择姓名', trigger: 'change' }],
+  user_id: [{ required: true, message: '请选择姓名', trigger: 'change' }],
   ancestors_names: [{ required: true, message: '请输入粤政易组织', trigger: 'blur' }],
   phonenumber: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
-  area: [{ required: true, message: '请选择责任区划', trigger: 'change' }]
+  area_code: [{ required: true, message: '请选择责任区划', trigger: 'change' }]
 });
 // 监听姓名变化,一旦发生变化就请求用户列表
 const onUserNameChange = async (value) => {
@@ -109,8 +120,8 @@ const submitForm = async () => {
   try {
     let areaCode = '';
     // 确保在提交前有选中的区划
-    if (divisionSelectedId.value) {
-      const selectedDivision = findNode(formattedDivisionData.value, divisionSelectedId.value);
+    if (formData.value.area_code) {
+      const selectedDivision = findNode(formattedDivisionData.value, formData.value.area_code);
       if (selectedDivision) {
         areaCode = selectedDivision.code;
       } else {
@@ -161,7 +172,7 @@ const onDivisionChange = (value) => {
   if (!selectedDivision) {
     ElMessage.warning('未找到匹配的责任区划。');
     // 将选中的值重置为 null 或空字符串,防止后续逻辑错误
-    divisionSelectedId.value = null;
+    formData.value.area_code = null;
   } else {
     console.log('Selected Division:', selectedDivision); // 调试输出
   }

+ 139 - 13
src/views/inspectionWork/inspectorEdit.vue

@@ -2,12 +2,25 @@
   <div class="common-dialog">
     <div class="common-dialog-content">
       <div class="common-dialog-title-box">
-        <h3 class="common-dialog-title">修改巡查人员</h3>
+        <i class="common-dialog-title-icon" />
+        <div>修改巡查人员</div>
       </div>
       <div class="common-dialog-box">
         <el-form ref="form" :model="formData" :rules="rules" label-width="120px">
-          <el-form-item label="姓名:" prop="nick_name">
-            <el-input v-model="formData.nick_name" style="width: 468px !important" />
+<!--          <el-form-item label="姓名:" prop="nick_name">-->
+<!--            <el-input v-model="formData.nick_name" style="width: 468px !important" />-->
+<!--          </el-form-item>-->
+          <el-form-item label="姓名:" prop="user_id">
+            <el-tree-select
+              v-model="formData.user_id"
+              :data="treeData"
+              :props="defaultProps"
+              node-key="id"
+              :render-after-expand="false"
+              style="width: 468px"
+              @change="onUserNameChange"
+              filterable
+            />
           </el-form-item>
           <el-form-item label="粤政易组织:" prop="yzy_account">
             <el-input v-model="formData.yzy_account" style="width: 468px !important" />
@@ -15,8 +28,19 @@
           <el-form-item label="联系方式:" prop="phonenumber">
             <el-input v-model="formData.phonenumber" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="责任区划:" prop="area">
-            <el-input v-model="formData.area" style="width: 468px !important" />
+<!--          <el-form-item label="责任区划:" prop="area_code">-->
+<!--            <el-input v-model="formData.area_code" style="width: 468px !important" />-->
+<!--          </el-form-item>-->
+          <el-form-item label="责任区划:" prop="area_code">
+            <el-tree-select
+              v-model="formData.area_code"
+              :data="formattedDivisionData"
+              :props="{ label: 'label', value: 'code', children: 'children' }"
+              :render-after-expand="false"
+              style="width: 468px"
+              @change="onDivisionChange"
+              check-strictly
+            />
           </el-form-item>
         </el-form>
         <div class="common-dialog-footer">
@@ -28,25 +52,35 @@
   </div>
 </template>
 <script setup lang="ts">
-import { inspectorDetail, inspectorUpload } from '@/api/inspectionWork/inspector';
-import { ref, watch } from 'vue';
+import {
+  inspectorDetail,
+  inspectorDivision,
+  inspectorUpload,
+  phoneList,
+  userList
+} from '@/api/inspectionWork/inspector';
+import { reactive, ref, watch } from 'vue';
 import { ElMessage } from 'element-plus';
 const emits = defineEmits(['close']);
+const treeData = ref([]);
+const formattedDivisionData = ref([]);
+const rawDivisionData = ref([]);
 const props = defineProps<{
   eventId: string | number;
 }>();
 const formData = ref({
+  user_id: '',
   nick_name: '',
   phonenumber: '',
   yzy_account: '',
-  area: ''
+  area_code: ''
 });
 // 表单验证规则
 const rules = ref({
   nick_name: [{ required: true, message: '请选择姓名', trigger: 'change' }],
   yzy_account: [{ required: true, message: '请输入粤政易组织', trigger: 'blur' }],
   phonenumber: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
-  area: [{ required: true, message: '请选择责任区划', trigger: 'change' }]
+  area_code: [{ required: true, message: '请选择责任区划', trigger: 'change' }]
 });
 const fetchDetail = async () => {
   const response = await inspectorDetail(props.eventId);
@@ -68,16 +102,108 @@ watch(
 const closeDialog = () => {
   emits('close');
 };
+const findNode = (nodes, code) => {
+  for (let i = 0; i < nodes.length; i++) {
+    const node = nodes[i];
+    if (node.code === code) {
+      return node;
+    }
+    if (node.children && node.children.length > 0) {
+      const found = findNode(node.children, code);
+      if (found) {
+        return found;
+      }
+    }
+  }
+  return null;
+};
 // 提交表单
 const submitForm = async () => {
-  // 假设表单已经通过验证
-  const response = await inspectorUpload(formData.value);
+  try {
+    let area_codeCode = '';
+    // 确保在提交前有选中的区划
+    if (formData.value.area_code) {
+      const selectedDivision = findNode(formattedDivisionData.value, formData.value.area_code);
+      if (selectedDivision) {
+        area_codeCode = selectedDivision.code;
+      } else {
+        ElMessage.error('请选择责任区划。');
+        return;
+      }
+    }
+    if (!area_codeCode) {
+      ElMessage.error('请选择责任区划。');
+      return;
+    }
+    // 假设表单已经通过验证
+    const response = await inspectorUpload(formData.value);
+    if (response.code === 200) {
+      ElMessage.success('提交成功');
+      closeDialog(); // 关闭对话框
+    } else {
+      ElMessage.error(response.msg);
+    }
+  } catch (error) {
+    ElMessage.error('提交失败,请检查输入信息。');
+  }
+
+};
+const fetchPhoneList = async () => {
+  const response = await phoneList();
+  treeData.value = response.data;
+};
+
+const defaultProps = reactive({
+  children:'children',
+  label:'label',
+  disabled:(node) => {
+    return node.deptType && !node.children;
+  }
+})
+const onUserNameChange = async (value) => {
+  if (value) {
+    const response = await userList({ userId: value });
+    if (response.code === 200 && response.rows.length > 0) {
+      updateFormData(response);
+    } else {
+      ElMessage.error(response.msg);
+    }
+  }
+};
+// 格式化责任区划数据
+const formatDivisionData = (data) => {
+  return data.map((item) => ({
+    id: item.id,
+    label: item.label,
+    code: item.code,
+    children: item.children ? formatDivisionData(item.children) : []
+  }));
+};
+const fetchDivisionData = async () => {
+  const response = await inspectorDivision();
   if (response.code === 200) {
-    ElMessage.success('提交成功');
-    closeDialog(); // 关闭对话框
+    rawDivisionData.value = response.data;
+    formattedDivisionData.value = formatDivisionData(rawDivisionData.value);
+    console.log('Formatted Division Data:', formattedDivisionData.value);
   } else {
     ElMessage.error(response.msg);
   }
 };
+const onDivisionChange = (value) => {
+  // 确认选中的项存在
+  const selectedDivision = findNode(formattedDivisionData.value, value);
+  if (!selectedDivision) {
+    ElMessage.warning('未找到匹配的责任区划。');
+    // 将选中的值重置为 null 或空字符串,防止后续逻辑错误
+    formData.value.area_code = null;
+  } else {
+    console.log('Selected Division:', selectedDivision); // 调试输出
+  }
+};
+
+onMounted(() => {
+  fetchPhoneList();
+  fetchDivisionData();
+});
 </script>
 <style scoped></style>

+ 2 - 1
src/views/riskPrevention/SafetyProductionManagement/BusinessPortraits.vue

@@ -11,11 +11,12 @@
 <!--                  <el-option v-for="item in county" :key="item.value" :label="item.label" :value="item.value"></el-option>-->
 <!--                </el-select>-->
                 <el-tree-select
-                  v-model="region"
+                  v-model="queryParams.area_code"
                   lazy
                   :load="loadNodes"
                   node-key="id"
                   :props="props"
+                  clearable
                   style="width: 240px"
                 />
               </el-form-item>

+ 36 - 14
src/views/riskPrevention/SafetyProductionManagement/BussinessEdit.vue

@@ -12,19 +12,19 @@
             <el-form-item label="企业名称:" prop="company_name">
               <el-input v-model="form.company_name" placeholder="请输入企业名称" style="width: 468px" />
             </el-form-item>
-            <el-form-item label="辖区省:" prop="province">
-              <el-select v-model="form.province" placeholder="请选择辖区省">
-                <el-option v-for="item in provinceList" :label="item.label" :value="item.value" />
+            <el-form-item label="辖区省:" prop="province_code">
+              <el-select v-model="form.province_code" placeholder="请选择辖区省" @click="getDistrict(form.province_code,2)">
+                <el-option v-for="item in provinceList" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
-            <el-form-item label="辖区市:" prop="city">
-              <el-select v-model="form.city" placeholder="请选择辖区市">
-                <el-option v-for="item in cityList" :label="item.label" :value="item.value" />
+            <el-form-item label="辖区市:" prop="city_code">
+              <el-select v-model="form.city_code" placeholder="请选择辖区市" @click="getDistrict(form.city_code,3)">
+                <el-option v-for="item in cityList" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
-            <el-form-item label="辖区县:" prop="district">
-              <el-select v-model="form.district" placeholder="请选择辖区县">
-                <el-option v-for="item in district_type" :label="item.label" :value="item.value" />
+            <el-form-item label="辖区县:" prop="district_code">
+              <el-select v-model="form.district_code" placeholder="请选择辖区县">
+                <el-option v-for="item in districtList" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="企业地址:" prop="company_address">
@@ -53,9 +53,9 @@
 </template>
 <script setup lang="ts">
 import { workDetail, updatetask } from '@/api/inspectionWork/inspector';
-import { ref, toRefs, watch } from 'vue';
+import { onMounted, ref, toRefs, watch } from 'vue';
 import { ElMessage } from 'element-plus';
-import {CompanyDetail, updateCompany} from "@/api/riskPrevention/BusinessPortraits";
+import { CompanyDetail, getZoning, updateCompany } from '@/api/riskPrevention/BusinessPortraits';
 import { validatePhone } from '@/utils/validate';
 const demoFormRef = ref(null);
 const buttonLoading = ref(false);
@@ -63,6 +63,9 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { enterprise_type, district_type } = toRefs<any>(proxy?.useDict('enterprise_type','district_type'));
 const emit = defineEmits(['close']);
 const props = defineProps<{ eventId: string }>();
+const districtList = ref();
+const provinceList = ref();
+const cityList = ref();
 let form = ref({
   company_name: '',
   province: '',
@@ -87,7 +90,12 @@ const businessOptions = [
 const fetchDetail = async () => {
   const response = await CompanyDetail(props.eventId);
   if (response.code === 200) {
+    response.data.province_code = Number(response.data.province_code);
+    response.data.city_code = Number(response.data.city_code);
+    response.data.district_code = Number(response.data.district_code);
     form.value = response.data;
+    getDistrict(response.data.province_code,2);
+    getDistrict(response.data.city_code,3);
   } else {
     ElMessage.error(response.msg);
   }
@@ -96,9 +104,9 @@ const fetchDetail = async () => {
 const rules = ref({
   // id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
   company_name: [{ required: true, message: '请选择企业名称', trigger: 'blur' }],
-  province: [{ required: true, message: '请选择辖区省', trigger: 'change' }],
-  city: [{ required: true, message: '请选择辖区市', trigger: 'change' }],
-  district: [{ required: true, message: '请选择辖区县', trigger: 'change' }],
+  province_code: [{ required: true, message: '请选择辖区省', trigger: 'change' }],
+  city_code: [{ required: true, message: '请选择辖区市', trigger: 'change' }],
+  district_code: [{ required: true, message: '请选择辖区县', trigger: 'change' }],
   company_address: [{ required: true, message: '请选择企业地址', trigger: 'change' }],
   responsible_person: [{ required: true, message: '请选择企业负责人', trigger: 'change' }],
   phone: [
@@ -133,5 +141,19 @@ const cancel = () => {
   emit('close');
 };
 
+const getDistrict = (id,level) => {
+  getZoning(id,level).then((res) => {
+    if (level === 1) {
+      provinceList.value = res.data;
+    } else if (level === 2) {
+      cityList.value = res.data;
+    } else if (level === 3) {
+      districtList.value = res.data;
+    }
+  })
+}
 
+onMounted(() => {
+  getDistrict(100000,1);
+});
 </script>