Explorar o código

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	src/types/components.d.ts
Hwf hai 10 meses
pai
achega
499d93638e

+ 111 - 0
src/api/globalMap/layerConfig/index.ts

@@ -0,0 +1,111 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from './types';
+
+// 查询菜单列表
+export const listMenu = (query?: MenuQuery): AxiosPromise<MenuVO[]> => {
+  return request({
+    url: '/api/system/menu/list',
+    method: 'get',
+    params: query
+  });
+};
+
+// 查询图层 列表
+export const LayerlistMenu = (query?: MenuQuery): AxiosPromise<MenuVO[]> => {
+  return request({
+    url: '/api/layerConfiguration/layer_list',
+    method: 'get',
+    params: query
+  });
+};
+
+// 查询菜单详细
+export const getMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
+  return request({
+    url: '/api/system/menu/' + menuId,
+    method: 'get'
+  });
+};
+
+// 查询图层详细
+export const getLayerMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
+  return request({
+    url: '/api/layerConfiguration/' + menuId,
+    method: 'get'
+  });
+};
+// 查询菜单下拉树结构
+export const treeselect = (): AxiosPromise<MenuTreeOption[]> => {
+  return request({
+    url: '/api/system/menu/treeselect',
+    method: 'get'
+  });
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const roleMenuTreeselect = (roleId: string | number): AxiosPromise<RoleMenuTree> => {
+  return request({
+    url: '/api/system/menu/roleMenuTreeselect/' + roleId,
+    method: 'get'
+  });
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const tenantPackageMenuTreeselect = (packageId: string | number): AxiosPromise<RoleMenuTree> => {
+  return request({
+    url: '/api/system/menu/tenantPackageMenuTreeselect/' + packageId,
+    method: 'get'
+  });
+};
+
+// 新增菜单
+export const addMenu = (data: MenuForm) => {
+  return request({
+    url: '/api/system/menu/create',
+    method: 'post',
+    data: data
+  });
+};
+
+// 新增图层
+export const addLayerMenu = (data: MenuForm) => {
+  return request({
+    url: '/api/layerConfiguration/create',
+    method: 'post',
+    data: data
+  });
+};
+
+// 修改菜单
+export const updateMenu = (data: MenuForm) => {
+  return request({
+    url: '/api/system/menu',
+    method: 'put',
+    data: data
+  });
+};
+
+// 修改图层
+export const updateLayerMenu = (data: MenuForm) => {
+  return request({
+    url: '/api/layerConfiguration',
+    method: 'put',
+    data: data
+  });
+};
+// 删除菜单
+export const delMenu = (menuId: string | number) => {
+  return request({
+    url: '/api/system/menu/' + menuId,
+    method: 'delete'
+  });
+};
+
+// 删除图层
+export const delLayerMenu = (menuId: string | number) => {
+  return request({
+    url: '/api/layerConfiguration/' + menuId,
+    method: 'delete'
+  });
+};

+ 71 - 0
src/api/globalMap/layerConfig/types.ts

@@ -0,0 +1,71 @@
+import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
+
+/**
+ * 菜单树形结构类型
+ */
+export interface MenuTreeOption {
+  id: string | number;
+  label: string;
+  parentId: string | number;
+  weight: number;
+  children?: MenuTreeOption[];
+}
+
+export interface RoleMenuTree {
+  menus: MenuTreeOption[];
+  checkedKeys: string[];
+}
+
+/**
+ * 菜单查询参数类型
+ */
+export interface MenuQuery {
+  keywords?: string;
+  menuName?: string;
+  status?: string;
+  topicName?: string;
+}
+
+/**
+ * 菜单视图对象类型
+ */
+export interface MenuVO extends BaseEntity {
+  parentName: string;
+  parentId: string | number;
+  children: MenuVO[];
+  menuId: string | number;
+  menuName: string;
+  orderNum: number;
+  path: string;
+  component: string;
+  queryParam: string;
+  isFrame: string;
+  isCache: string;
+  menuType: MenuTypeEnum;
+  visible: string;
+  status: string;
+  icon: string;
+  remark: string;
+}
+
+export interface MenuForm {
+  parentName?: string;
+  parentId?: string | number;
+  children?: MenuForm[];
+  menuId?: string | number;
+  menuName: string;
+  orderNum: number;
+  path: string;
+  component?: string;
+  queryParam?: string;
+  isFrame?: string;
+  isCache?: string;
+  menuType?: MenuTypeEnum;
+  visible?: string;
+  status?: string;
+  icon?: string;
+  remark?: string;
+  query?: string;
+  perms?: string;
+  layer_template?: string;
+}

+ 33 - 1
src/api/inspectionWork/inspector.ts

@@ -31,6 +31,14 @@ export function inspectorDetail(id) {
     params: id
   });
 }
+// 查询用户详情
+export function inspectorDivision(params) {
+  return request({
+    url: '/api/riskManagement/allAreas',
+    method: 'get',
+    params: params
+  });
+}
 export function inspectorUpload(data) {
   return request({
     url: '/api/riskManagement/inspection/user/update',
@@ -56,7 +64,7 @@ export function inspectorDelete(data) {
 // 获取新建用户列表
 export function userList(params) {
   return request({
-    url: '/api/riskManagement/inspection/user/',
+    url: '/api/riskManagement/system/user/list',
     method: 'get',
     params: params
   });
@@ -85,3 +93,27 @@ export function workDetail(id) {
     params: id
   });
 }
+// 任务更新
+export function updatetask(data) {
+  return request({
+    url: '/api/riskManagement/inspection/task/update',
+    method: 'put',
+    data: data
+  });
+}
+// 新增任务
+export function addtask(data) {
+  return request({
+    url: '/api/riskManagement/inspection/task/create',
+    method: 'post',
+    data: data
+  });
+}
+// 查询用户详情
+export function workSubList(task_id) {
+  return request({
+    url: '/api/riskManagement/inspection/task/children/task/' + task_id + '/list',
+    method: 'get',
+    params: task_id
+  });
+}

+ 7 - 0
src/api/system/menu/index.ts

@@ -27,6 +27,13 @@ export const getMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
   });
 };
 
+// 查询菜单详细
+export const getLayerMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
+  return request({
+    url: '/api/system/layer_menu/' + menuId,
+    method: 'get'
+  });
+};
 // 查询菜单下拉树结构
 export const treeselect = (): AxiosPromise<MenuTreeOption[]> => {
   return request({

+ 0 - 4
src/types/auto-imports.d.ts

@@ -312,10 +312,6 @@ declare module 'vue' {
   interface GlobalComponents {}
   interface ComponentCustomProperties {
     readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
-    readonly ElLoading: UnwrapRef<typeof import('element-plus/es')['ElLoading']>
-    readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
-    readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
-    readonly ElNotification: UnwrapRef<typeof import('element-plus/es')['ElNotification']>
     readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
     readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
     readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>

+ 10 - 8
src/types/components.d.ts

@@ -22,10 +22,10 @@ declare module 'vue' {
     ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     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']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -36,26 +36,26 @@ 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']
-    ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     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']
-    ElUpload: typeof import('element-plus/es')['ElUpload']
+    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ExcelEditor: typeof import('./../components/ExcelEditor/index.vue')['default']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FooterSection: typeof import('./../components/FooterSection/index.vue')['default']
@@ -66,6 +66,8 @@ 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']

+ 448 - 0
src/views/globalMap/layerConfiguration.vue

@@ -0,0 +1,448 @@
+<template>
+  <div class="app-container">
+    <div v-show="!dialog.visible">
+      <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+        <div v-show="showSearch">
+          <el-form ref="queryFormRef" :model="queryParams">
+            <el-row :gutter="20">
+              <!-- 第一行 -->
+              <el-col :span="6">
+                <el-form-item label="图层名称:" prop="menuName">
+                  <el-input v-model="queryParams.menuName" placeholder="请输入图层名称" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="专题:" prop="status">
+                  <el-select v-model="queryParams.topicName" placeholder="请选择" clearable>
+                    <el-option v-for="dict in topic_name" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="状态:" prop="status">
+                  <el-select v-model="queryParams.status" placeholder="状态" clearable>
+                    <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item>
+                  <el-button type="primary" @click="handleQuery">搜索</el-button>
+                  <el-button @click="resetQuery">重置</el-button>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </div>
+      </transition>
+
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button v-hasPermi="['system:menu:add']" icon="Plus" type="primary" @click="handleAdd()">新增 </el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button type="danger" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
+        </el-col>
+        <!--      <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar>-->
+      </el-row>
+
+      <el-table
+        ref="menuTableRef"
+        v-loading="loading"
+        :data="menuList"
+        row-key="menuId"
+        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+        :default-expand-all="isExpandAll"
+      >
+        <!--        <el-table-column type="selection" width="55"> </el-table-column>-->
+        <el-table-column prop="menuName" align="center" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
+        <!--        <el-table-column prop="menuType" align="center" label="菜单类型" :show-overflow-tooltip="true" width="160"></el-table-column>-->
+        <el-table-column prop="menuType" label="菜单类型" align="center" width="100">
+          <template #default="scope">
+            <dict-tag :options="menu_type" :value="scope.row.menuType" />
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
+        <el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="status" label="状态" width="80">
+          <template #default="scope">
+            <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
+          </template>
+        </el-table-column>
+        <el-table-column label="创建时间" align="center" prop="createTime">
+          <template #default="scope">
+            <span>{{ scope.row.createTime }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-text v-hasPermi="['system:menu:edit']" class="common-btn-text-primary" @click="handleUpdate(scope.row)">修改</el-text>
+            <el-text v-hasPermi="['system:menu:add']" class="common-btn-text-primary" @click="handleAdd(scope.row)">新增</el-text>
+            <el-text v-hasPermi="['system:menu:remove']" class="common-btn-text-danger" @click="handleDelete(scope.row)">删除</el-text>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div v-show="dialog.visible" class="common-dialog">
+      <div class="common-dialog-content">
+        <div class="common-dialog-title-box">
+          <i class="common-dialog-title-icon" />
+          <div>{{ dialog.title }}</div>
+        </div>
+        <div class="common-dialog-box">
+          <el-form ref="menuFormRef" :model="form" :rules="rules" label-width="100px">
+            <el-col :span="24">
+              <el-form-item style="width: 500px" label="上级菜单:">
+                <el-tree-select
+                  v-model="form.parentId"
+                  :data="menuOptions"
+                  :props="{ value: 'menuId', label: 'menuName', children: 'children' }"
+                  value-key="menuId"
+                  placeholder="选择上级菜单"
+                  check-strictly
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="菜单类型:" prop="menuType">
+                <el-radio-group v-model="form.menuType">
+                  <el-radio value="M">目录</el-radio>
+                  <el-radio value="C">菜单</el-radio>
+                  <el-radio value="F">按钮</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'F'" :span="24">
+              <el-form-item label="菜单图标:" prop="icon">
+                <!-- 图标选择器 -->
+                <icon-select v-model="form.icon" />
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'F'" :span="24">
+              <el-form-item label="菜单模板:" prop="template">
+                <!-- 模板选择器 -->
+                <el-select v-model="form.template" placeholder="请选择模板">
+                  <el-option v-for="item in templateOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="显示排序:" prop="orderNum">
+                <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'F'" :span="12">
+              <el-form-item>
+                <template #label>
+                  <span>
+                    <el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon> </el-tooltip
+                    >是否外链:
+                  </span>
+                </template>
+                <el-radio-group v-model="form.isFrame">
+                  <el-radio label="0">是</el-radio>
+                  <el-radio label="1">否</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'F'" :span="12">
+              <el-form-item prop="path" style="width: 500px">
+                <template #label>
+                  <span>
+                    <el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    路由地址:
+                  </span>
+                </template>
+                <el-input v-model="form.path" placeholder="请输入路由地址" />
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType === 'C'" :span="12">
+              <el-form-item prop="component">
+                <template #label>
+                  <span>
+                    <el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    组件路径:
+                  </span>
+                </template>
+                <el-input v-model="form.component" placeholder="请输入组件路径" />
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'M'" :span="12">
+              <el-form-item>
+                <el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
+                <template #label>
+                  <span>
+                    <el-tooltip content="控制器中定义的权限字符,如:@SaCheckPermission('system:user:list')" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    权限字符:
+                  </span>
+                </template>
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType === 'C'" :span="12">
+              <el-form-item>
+                <el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
+                <template #label>
+                  <span>
+                    <el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    路由参数:
+                  </span>
+                </template>
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType === 'C'" :span="12">
+              <el-form-item>
+                <template #label>
+                  <span>
+                    <el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    是否缓存:
+                  </span>
+                </template>
+                <el-radio-group v-model="form.isCache">
+                  <el-radio label="0">缓存</el-radio>
+                  <el-radio label="1">不缓存</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col v-if="form.menuType !== 'F'" :span="12">
+              <el-form-item>
+                <template #label>
+                  <span>
+                    <el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    显示状态:
+                  </span>
+                </template>
+                <el-radio-group v-model="form.visible">
+                  <el-radio v-for="dict in sys_show_hide" :key="dict.value" :label="dict.value">{{ dict.label }} </el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item>
+                <template #label>
+                  <span>
+                    <el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
+                      <el-icon>
+                        <question-filled />
+                      </el-icon>
+                    </el-tooltip>
+                    菜单状态:
+                  </span>
+                </template>
+                <el-radio-group v-model="form.status">
+                  <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">
+                    {{ dict.label }}
+                  </el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-form>
+        </div>
+        <div class="common-dialog-footer" style="display: flex; justify-content: center">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup name="Menu" lang="ts">
+import {
+  addMenu,
+  addLayerMenu,
+  delMenu,
+  delLayerMenu,
+  getMenu,
+  getLayerMenu,
+  listMenu,
+  LayerlistMenu,
+  updateMenu,
+  updateLayerMenu
+} from '@/api/globalMap/layerConfig';
+import { MenuForm, MenuQuery, MenuVO } from '@/api/globalMap/layerConfig/types';
+import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
+
+interface MenuOptionsType {
+  menuId: number;
+  menuName: string;
+  children: MenuOptionsType[] | undefined;
+}
+
+import { ref, onMounted } from 'vue';
+import { ElMessage } from 'element-plus';
+import { addInformation, getTemplateList } from '@/api/informationissue/informationissue';
+
+const templateOptions = ref([
+  { value: 'template1', label: '图层分析一' },
+  { value: 'template2', label: '图层分析二' },
+  { value: 'template3', label: '图层分析三' }
+  // 更多模板选项...
+]);
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_show_hide, sys_normal_disable, topic_name, menu_type } = toRefs<any>(
+  proxy?.useDict('sys_show_hide', 'sys_normal_disable', 'topic_name', 'menu_type')
+);
+const menuList = ref<MenuVO[]>([]);
+const loading = ref(true);
+const showSearch = ref(true);
+const menuOptions = ref<MenuOptionsType[]>([]);
+const isExpandAll = ref(false);
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const queryFormRef = ref<ElFormInstance>();
+const menuFormRef = ref<ElFormInstance>();
+const initFormData = {
+  path: '',
+  menuId: undefined,
+  parentId: 0,
+  menuName: '',
+  icon: '',
+  menuType: MenuTypeEnum.M,
+  orderNum: 1,
+  isFrame: '1',
+  isCache: '0',
+  visible: '0',
+  status: '0'
+};
+const data = reactive<PageData<MenuForm, MenuQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    menuName: undefined,
+    status: undefined
+  },
+  rules: {
+    menuName: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
+    orderNum: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }],
+    path: [{ required: true, message: '路由地址不能为空', trigger: 'blur' }]
+  }
+});
+
+const menuTableRef = ref<ElTableInstance>();
+
+const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data);
+/** 查询菜单列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await LayerlistMenu(queryParams.value);
+  const data = proxy?.handleTree<MenuVO>(res.data, 'menuId');
+  if (data) {
+    menuList.value = data;
+  }
+  loading.value = false;
+};
+/** 查询菜单下拉树结构 */
+const getTreeselect = async () => {
+  menuOptions.value = [];
+  const response = await LayerlistMenu();
+  const menu: MenuOptionsType = { menuId: 0, menuName: '主类目', children: [] };
+  menu.children = proxy?.handleTree<MenuOptionsType>(response.data, 'menuId');
+  menuOptions.value.push(menu);
+};
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  menuFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  getList();
+};
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+/** 新增按钮操作 */
+const handleAdd = (row?: MenuVO) => {
+  reset();
+  getTreeselect();
+  row && row.menuId ? (form.value.parentId = row.menuId) : (form.value.parentId = 0);
+  dialog.visible = true;
+  dialog.title = '添加菜单';
+  // fullscreen: false;
+};
+/** 展开/折叠操作 */
+const handleToggleExpandAll = () => {
+  isExpandAll.value = !isExpandAll.value;
+  toggleExpandAll(menuList.value, isExpandAll.value);
+};
+/** 展开/折叠所有 */
+const toggleExpandAll = (data: MenuVO[], status: boolean) => {
+  data.forEach((item: MenuVO) => {
+    menuTableRef.value?.toggleRowExpansion(item, status);
+    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
+  });
+};
+/** 修改按钮操作 */
+const handleUpdate = async (row: MenuVO) => {
+  reset();
+  await getTreeselect();
+  if (row.menuId) {
+    const { data } = await getLayerMenu(row.menuId);
+    form.value = data;
+  }
+  dialog.visible = true;
+  dialog.title = '修改菜单';
+};
+/** 提交按钮 */
+const submitForm = () => {
+  menuFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      form.value.menuId ? await updateLayerMenu(form.value) : await addLayerMenu(form.value);
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+/** 删除按钮操作 */
+const handleDelete = async (row: MenuVO) => {
+  await proxy?.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?');
+  await delLayerMenu(row.menuId);
+  await getList();
+  proxy?.$modal.msgSuccess('删除成功');
+};
+
+onMounted(() => {
+  getList();
+});
+</script>

+ 2 - 2
src/views/inspectionWork/inspector.vue

@@ -62,7 +62,7 @@
     </el-row>
   </div>
   <InspectorEdit v-if="inspectorEditState.show" :event-id="inspectorEditState.eventId" @close="handleCancel" />
-  <InspectorAdd v-if="inspectorAddState.show" @close="handleCancel" />
+  <InspectorAdd v-if="inspectorAddState.show" @close="handleCancel" @refresh="fetchUserData" />
 </template>
 
 <script setup lang="ts">
@@ -127,7 +127,7 @@ const fetchUserData = async () => {
     id: item.id,
     nickName: item.nick_name,
     phone: item.phonenumber,
-    yzy_organization: item.yzy_account || '', // 如果 yzy_account 为空,则显示空字符串
+    yzy_organization: item.ancestors_names || '', // 如果 yzy_account 为空,则显示空字符串
     division_responsibility: item.area // 显示责任区划
   }));
   total.value = res.total;

+ 139 - 16
src/views/inspectionWork/inspectorAdd.vue

@@ -10,19 +10,27 @@
             <el-tree-select
               v-model="formData.uuid"
               :data="treeData"
-              :props="{ label: 'label', value: 'uuid', children: 'children' }"
+              :props="{ label: 'label', value: 'id', children: 'children' }"
               :render-after-expand="false"
               style="width: 468px"
+              @change="onUserNameChange"
             />
           </el-form-item>
-          <el-form-item label="粤政易组织:" prop="yzy_account">
-            <el-input v-model="formData.yzy_account" style="width: 468px !important" />
+          <el-form-item label="粤政易组织:" prop="ancestors_names">
+            <el-input v-model="formData.ancestors_names" style="width: 468px !important" />
           </el-form-item>
           <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-tree-select
+              v-model="divisionSelectedId"
+              :data="formattedDivisionData"
+              :props="{ label: 'label', value: 'code', children: 'children' }"
+              :render-after-expand="false"
+              style="width: 468px"
+              @change="onDivisionChange"
+            />
           </el-form-item>
         </el-form>
         <div class="common-dialog-footer">
@@ -33,42 +41,157 @@
     </div>
   </div>
 </template>
+
 <script setup lang="ts">
-import { inspectorAdd, phoneList } from '@/api/inspectionWork/inspector';
-import { ref } from 'vue';
-import { ElMessage, ElTreeSelect } from 'element-plus';
+import { inspectorAdd, phoneList, userList, inspectorDivision } from '@/api/inspectionWork/inspector';
+import { ref, watch } from 'vue';
+import { ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+
 const emits = defineEmits(['close']);
 const props = defineProps<{
   eventId: string | number;
 }>();
+
 const formData = ref({
+  user_id: '',
   nick_name: '',
   phonenumber: '',
-  yzy_account: '',
-  area: '',
   uuid: ''
 });
+
 const treeData = ref([]);
+const rawDivisionData = ref([]);
+const formattedDivisionData = ref([]);
+
+const divisionSelectedId = ref(null);
+
 const closeDialog = () => {
   emits('close');
 };
+
+const router = useRouter();
+
+// 更新表单数据
+const updateFormData = (userData) => {
+  formData.value = {
+    ...formData.value,
+    user_id: userData.rows[0].user_id,
+    dept_id: userData.rows[0].dept_id,
+    dept_name: userData.rows[0].dept_name,
+    ancestors_names: userData.rows[0].ancestors_names,
+    user_name: userData.rows[0].user_name,
+    nick_name: userData.rows[0].nick_name,
+    phonenumber: userData.rows[0].phonenumber || ''
+  };
+};
+
+// 监听姓名变化,一旦发生变化就请求用户列表
+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 submitForm = async () => {
-  // 假设表单已经通过验证
-  const response = await inspectorAdd(formData.value);
-  if (response.code === 200) {
-    ElMessage.success('提交成功');
-    closeDialog(); // 关闭对话框
-  } else {
-    ElMessage.error(response.msg);
+  try {
+    let areaCode = '';
+    // 确保在提交前有选中的区划
+    if (divisionSelectedId.value) {
+      const selectedDivision = findNode(formattedDivisionData.value, divisionSelectedId.value);
+      if (selectedDivision) {
+        areaCode = selectedDivision.code;
+      } else {
+        ElMessage.error('请选择责任区划。');
+        return;
+      }
+    }
+    if (!areaCode) {
+      ElMessage.error('请选择责任区划。');
+      return;
+    }
+
+    const response = await inspectorAdd({
+      user_id: formData.value.user_id,
+      area_code: areaCode
+    });
+    if (response.code === 200) {
+      ElMessage.success('提交成功');
+      closeDialog(); // 关闭对话框
+      emits('refresh');
+    } else {
+      ElMessage.error(response.msg);
+    }
+  } catch (error) {
+    ElMessage.error('提交失败,请检查输入信息。');
   }
 };
+
 const fetchPhoneList = async () => {
   const response = await phoneList();
   treeData.value = response.data;
 };
+
+const fetchDivisionData = async () => {
+  const response = await inspectorDivision();
+  if (response.code === 200) {
+    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 或空字符串,防止后续逻辑错误
+    divisionSelectedId.value = null;
+  } else {
+    console.log('Selected Division:', selectedDivision); // 调试输出
+  }
+};
+
+// 递归查找节点
+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 formatDivisionData = (data) => {
+  return data.map((item) => ({
+    id: item.id,
+    label: item.label,
+    code: item.code,
+    children: item.children ? formatDivisionData(item.children) : []
+  }));
+};
+
 onMounted(() => {
   fetchPhoneList();
+  fetchDivisionData();
 });
 </script>
+
 <style scoped></style>

+ 56 - 9
src/views/inspectionWork/patrolSubTasks.vue

@@ -17,7 +17,7 @@
             <el-button type="primary" @click="handleUpdate()"> 编辑 </el-button>
           </el-col>
           <el-col :span="1.5">
-            <el-button type="primary" @click="handleWork()"> 完成任务 </el-button>
+            <el-button type="primary" @click="handlefinal()"> 完成任务 </el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button type="danger" @click="handleDelete"> 删除预案 </el-button>
@@ -42,13 +42,13 @@
         <h3>子任务记录</h3>
         <el-card style="margin-top: 10px" shadow="hover">
           <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
-            <el-table-column label="巡查业务" align="center" prop="business" />
+            <el-table-column label="巡查业务" align="center" :formatter="(row) => businessMap[row.business]" />
             <el-table-column label="要求巡查时间" align="center" prop="task_time" />
-            <el-table-column label="巡查周期" align="center" prop="cycle" />
-            <el-table-column label="巡查范围" walign="center" prop="inspection_range" />
-            <el-table-column label="执行日期" align="center" prop="run_time" />
-            <el-table-column label="已完成" align="center" prop="finished" />
-            <el-table-column label="未完成" align="center" prop="unfinished" />
+            <el-table-column label="巡查周期" align="center" :formatter="(row) => cycleMap[row.cycle]" />
+            <el-table-column label="巡查范围" align="center" :formatter="(row) => inspectionRangeMap[row.inspection_range]" />
+            <el-table-column label="执行日期" align="center" prop="create_time" />
+            <el-table-column label="已完成" align="center" prop="completed_num" />
+            <el-table-column label="未完成" align="center" prop="incomplete_num" />
             <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
               <template #default="scope">
                 <el-text class="common-btn-text-primary" @click="handleView(scope.row)">巡查结果</el-text>
@@ -60,7 +60,7 @@
             v-model:page="queryParams.page"
             v-model:limit="queryParams.pageSize"
             :total="total"
-            @pagination="tableData"
+            @pagination="fetchSubTasks"
           />
         </el-card>
       </el-col>
@@ -68,11 +68,15 @@
   </div>
 </template>
 <script setup lang="ts">
-import { workDetail } from '@/api/inspectionWork/inspector';
+import { workDetail, workSubList, updatetask } from '@/api/inspectionWork/inspector';
 import { reactive, ref } from 'vue';
+import { ElMessageBox } from 'element-plus';
 const props = defineProps<{ eventId: string }>();
 const total = ref(0);
 const tableData = ref([]);
+const multiple = ref(true);
+const ids = ref<Array<number | string>>([]);
+const single = ref(true);
 const emits = defineEmits(['close']);
 const detailData = ref({
   task_number: '',
@@ -157,10 +161,53 @@ const fetchWorkDetail = () => {
       loading.value = false;
     });
 };
+const fetchSubTasks = () => {
+  return workSubList(props.eventId, queryParams.value)
+    .then((res) => {
+      if (res.code === 200) {
+        tableData.value = res.data;
+        total.value = res.total;
+        console.log('Fetched subtasks data:', tableData.value);
+      } else {
+        console.error(res.msg);
+      }
+    })
+    .catch((error) => {
+      console.error('Error fetching sub tasks:', error);
+    });
+};
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+const handlefinal = async () => {
+  try {
+    const confirmed = await ElMessageBox.confirm('确定要完结任务吗?', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning'
+    });
+    if (confirmed) {
+      try {
+        await updatetask({ id: props.eventId, task_status: '3' });
+        console.log(`任务 ${props.eventId} 已完结`);
+        fetchWorkDetail();
+      } catch (error) {
+        console.error(`任务 ${props.eventId} 完结失败:`, error);
+      }
+    } else {
+      console.log(`任务 ${props.eventId} 未完结`);
+    }
+  } catch (error) {
+    console.error('确认对话框处理失败:', error);
+  }
+};
 const goBack = () => {
   emits('close');
 };
 onMounted(() => {
   fetchWorkDetail(); // 在组件挂载后调用此函数以获取数据
+  fetchSubTasks();
 });
 </script>

+ 48 - 3
src/views/inspectionWork/patrolTask.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div v-show="!patrolSubTasksState.show" class="app-container">
+    <div v-show="!patrolSubTasksState.show && !patrolTaskAddState.show" class="app-container">
       <div>
         <transition name="fade">
           <div v-show="showSearch">
@@ -67,7 +67,7 @@
           <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
             <template #default="scope">
               <el-text class="common-btn-text-primary" @click="handleUpdate(scope.row)">编辑</el-text>
-              <el-text class="common-btn-text-danger" @click="handleWork(scope.row)">完成任务</el-text>
+              <el-text class="common-btn-text-danger" v-if="scope.row.task_status !== '3'" @click="handleWork(scope.row)">完成任务</el-text>
               <el-text class="common-btn-text-danger" @click="handleDelete(scope.row)">删除</el-text>
             </template>
           </el-table-column>
@@ -77,12 +77,17 @@
     </div>
   </div>
   <PatrolSubTasks v-if="patrolSubTasksState.show" :event-id="patrolSubTasksState.eventId" @close="handleCancel" />
+  <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh="fetchWorkrData" />
+  <PatrolTaskAdd v-if="patrolTaskAddState.show" @close="handleCancel" @refresh="fetchWorkrData" />
 </template>
 <script setup lang="ts">
 import { onMounted, reactive, ref } from 'vue';
 import PatrolSubTasks from './patrolSubTasks.vue';
-import { workList, workDelete } from '@/api/inspectionWork/inspector';
+import PatrolTaskAdd from './patrolTaskAdd.vue';
+import PatrolTaskEdit from './patrolTaskEdit.vue';
+import { workList, workDelete, updatetask } from '@/api/inspectionWork/inspector';
 import { to } from 'await-to-js';
+import { ElMessageBox } from 'element-plus';
 const loading = ref(true);
 const showSearch = ref(true);
 const multiple = ref(true);
@@ -178,8 +183,17 @@ let patrolSubTasksState = reactive({
   show: false,
   eventId: ''
 });
+let patrolTaskAddState = reactive({
+  show: false
+});
+let patrolTaskEditState = reactive({
+  show: false,
+  eventId: ''
+});
 const handleCancel = () => {
   patrolSubTasksState.show = false;
+  patrolTaskAddState.show = false;
+  patrolTaskEditState.show = false;
 };
 const openPatrolSubTasks = (row) => {
   if (row) {
@@ -187,6 +201,15 @@ const openPatrolSubTasks = (row) => {
     patrolSubTasksState.show = true;
   }
 };
+const handleAdd = () => {
+  patrolTaskAddState.show = true;
+};
+const handleUpdate = (row) => {
+  if (row) {
+    patrolTaskEditState.eventId = row.id; // 假设eventId是id字段
+    patrolTaskEditState.show = true;
+  }
+};
 const handleDelete = async (row) => {
   let id = [];
   if (row) {
@@ -228,6 +251,28 @@ const handleSelectionChange = (selection) => {
   single.value = selection.length != 1;
   multiple.value = !selection.length;
 };
+const handleWork = async (row) => {
+  try {
+    const confirmed = await ElMessageBox.confirm('确定要完结任务吗?', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning'
+    });
+    if (confirmed) {
+      try {
+        await updatetask({ id: row.id, task_status: '3' });
+        console.log(`任务 ${row.id} 已完结`);
+        fetchWorkrData();
+      } catch (error) {
+        console.error(`任务 ${row.id} 完结失败:`, error);
+      }
+    } else {
+      console.log(`任务 ${row.id} 未完结`);
+    }
+  } catch (error) {
+    console.error('确认对话框处理失败:', error);
+  }
+};
 onMounted(() => {
   fetchWorkrData();
 });

+ 135 - 0
src/views/inspectionWork/patrolTaskAdd.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="app-container p-2">
+    <!-- 新增/修改弹窗 -->
+    <div class="common-dialog">
+      <div class="common-dialog-content">
+        <div class="common-dialog-title-box">
+          <i class="common-dialog-title-icon" />
+          <div>新建巡查任务</div>
+        </div>
+        <div class="common-dialog-box">
+          <el-form ref="demoFormRef" :model="form" label-width="100px" :rules="rules">
+            <el-form-item label="巡查业务:" prop="business">
+              <el-select v-model="form.business" placeholder="请选择巡查业务">
+                <el-option v-for="item in businessOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="排查时间范围:" prop="publish">
+              <el-date-picker v-model="form.start_time" type="date" placeholder="选择开始日期" value-format="YYYY-MM-DD"></el-date-picker>
+              <el-date-picker v-model="form.end_time" type="date" placeholder="选择结束日期" value-format="YYYY-MM-DD"></el-date-picker>
+            </el-form-item>
+            <el-form-item label="巡查周期:" prop="cycle">
+              <el-radio-group v-model="form.cycle">
+                <el-radio value="0" size="large">每年</el-radio>
+                <el-radio value="1" size="large">每月</el-radio>
+                <el-radio value="2" size="large">每周</el-radio>
+                <el-radio value="3" size="large">每天</el-radio>
+                <el-radio value="4" size="large">一次</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '0'" label="选择时间:" prop="corn_query">
+              <el-date-picker v-model="form.corn_query" type="date" placeholder="选择日期时间" value-format="YYYY-MM-DD"> </el-date-picker>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '1'" label="选择时间:" prop="corn_query">
+              <el-date-picker v-model="form.corn_query" type="date" placeholder="选择日期时间" value-format="YYYY-MM-DD"> </el-date-picker>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '2'" label="选择时间:" prop="corn_query">
+              <div class="weekday-selector">
+                <el-radio-group v-model="form.corn_query">
+                  <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 label="5">周五</el-radio>
+                  <el-radio label="6">周六</el-radio>
+                  <el-radio label="7">周日</el-radio>
+                </el-radio-group>
+              </div>
+            </el-form-item>
+            <el-form-item label="巡查范围:" prop="inspection_range">
+              <el-radio-group v-model="form.inspection_range">
+                <el-radio value="0" size="large">市级</el-radio>
+                <el-radio value="1" size="large">区县级</el-radio>
+                <el-radio value="2" size="large">镇街级</el-radio>
+                <el-radio value="3" size="large">村居级</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-form>
+        </div>
+        <div class="common-dialog-footer" style="display: flex; justify-content: center">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { updatetask, addtask } from '@/api/inspectionWork/inspector';
+import { ref } from 'vue';
+const demoFormRef = ref(null);
+const buttonLoading = ref(false);
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const emits = defineEmits(['close']);
+let form = ref({
+  id: '',
+  business: '',
+  start_time: '',
+  end_time: '',
+  cycle: '',
+  corn_query: '',
+  inspection_range: ''
+});
+// 巡查业务选项
+const businessOptions = [
+  { value: '0', label: '城市隐患巡查' },
+  { value: '1', label: '森林防火巡查' },
+  { value: '2', label: '重点危化企业巡查' },
+  { value: '3', label: '重点水库水位巡查' }
+];
+// 表单验证规则
+const rules = ref({
+  business: [{ required: true, message: '请选择巡查业务', trigger: 'blur' }],
+  start_time: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
+  end_time: [{ required: true, message: '请选择结束日期', trigger: 'change' }],
+  cycle: [{ required: true, message: '请选择巡查周期', trigger: 'change' }],
+  inspection_range: [{ required: true, message: '请选择巡查范围', trigger: 'change' }],
+  corn_query: [],
+  corn_query_month: [],
+  corn_query_day: [],
+  corn_query_weekday: [] // 添加用于每周的选择的验证
+});
+// 提交表单
+const submitForm = () => {
+  demoFormRef.value?.validate(async (valid) => {
+    if (valid) {
+      try {
+        buttonLoading.value = true;
+        form.value.task_number ? await updatetask(form.value) : await addtask(form.value); //根据 form.value.planId 是否存在,调用 updateReport 或 addReport 方法
+        proxy?.$modal.msgSuccess(form.value.task_number ? '修改成功' : '新增成功');
+        emits('refresh'); // 提交成功后通知父组件刷新
+        emits('close'); // 关闭弹窗
+      } finally {
+        buttonLoading.value = false;
+      }
+    }
+  });
+};
+// 重置表单数据和表单验证状态
+const resetForm = () => {
+  form.value = {
+    business: '',
+    start_time: '',
+    end_time: '',
+    cycle: '',
+    corn_query: '',
+    inspection_range: ''
+  };
+  demoFormRef.value?.resetFields(); // 重置表单的验证状态
+};
+
+const cancel = () => {
+  resetForm();
+  emits('close');
+};
+</script>

+ 124 - 0
src/views/inspectionWork/patrolTaskEdit.vue

@@ -0,0 +1,124 @@
+<template>
+  <div class="app-container p-2">
+    <!-- 新增/修改弹窗 -->
+    <div class="common-dialog">
+      <div class="common-dialog-content">
+        <div class="common-dialog-title-box">
+          <i class="common-dialog-title-icon" />
+          <div>新建巡查任务</div>
+        </div>
+        <div class="common-dialog-box">
+          <el-form ref="demoFormRef" :model="form" label-width="100px" :rules="rules">
+            <el-form-item label="巡查业务:" prop="business">
+              <el-select v-model="form.business" placeholder="请选择巡查业务">
+                <el-option v-for="item in businessOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="排查时间范围:" prop="publish">
+              <el-date-picker v-model="form.start_time" type="date" placeholder="选择开始日期" value-format="YYYY-MM-DD"></el-date-picker>
+              <el-date-picker v-model="form.end_time" type="date" placeholder="选择结束日期" value-format="YYYY-MM-DD"></el-date-picker>
+            </el-form-item>
+            <el-form-item label="巡查周期:" prop="cycle">
+              <el-radio-group v-model="form.cycle">
+                <el-radio value="0" size="large">每年</el-radio>
+                <el-radio value="1" size="large">每月</el-radio>
+                <el-radio value="2" size="large">每周</el-radio>
+                <el-radio value="3" size="large">每天</el-radio>
+                <el-radio value="4" size="large">一次</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '0'" label="选择时间:" prop="corn_query">
+              <el-date-picker v-model="form.corn_query" type="date" placeholder="选择日期时间" value-format="YYYY-MM-DD"> </el-date-picker>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '1'" label="选择时间:" prop="corn_query">
+              <el-date-picker v-model="form.corn_query" type="date" placeholder="选择日期时间" value-format="YYYY-MM-DD"> </el-date-picker>
+            </el-form-item>
+            <el-form-item v-if="form.cycle === '2'" label="选择时间:" prop="corn_query">
+              <div class="weekday-selector">
+                <el-radio-group v-model="form.corn_query">
+                  <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 label="5">周五</el-radio>
+                  <el-radio label="6">周六</el-radio>
+                  <el-radio label="7">周日</el-radio>
+                </el-radio-group>
+              </div>
+            </el-form-item>
+            <el-form-item label="巡查范围:" prop="inspection_range">
+              <el-radio-group v-model="form.inspection_range">
+                <el-radio value="0" size="large">市级</el-radio>
+                <el-radio value="1" size="large">区县级</el-radio>
+                <el-radio value="2" size="large">镇街级</el-radio>
+                <el-radio value="3" size="large">村居级</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-form>
+        </div>
+        <div class="common-dialog-footer" style="display: flex; justify-content: center">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { workDetail, updatetask } from '@/api/inspectionWork/inspector';
+import { ref, watch } from 'vue';
+import { ElMessage } from 'element-plus';
+const demoFormRef = ref(null);
+const buttonLoading = ref(false);
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const emits = defineEmits(['close']);
+const props = defineProps<{ eventId: string }>();
+let form = ref({
+  id: '',
+  business: '',
+  start_time: '',
+  end_time: '',
+  cycle: '',
+  corn_query: '',
+  inspection_range: ''
+});
+// 巡查业务选项
+const businessOptions = [
+  { value: '0', label: '城市隐患巡查' },
+  { value: '1', label: '森林防火巡查' },
+  { value: '2', label: '重点危化企业巡查' },
+  { value: '3', label: '重点水库水位巡查' }
+];
+const fetchDetail = async () => {
+  const response = await workDetail(props.eventId);
+  if (response.code === 200) {
+    form.value = response.data;
+  } else {
+    ElMessage.error(response.msg);
+  }
+};
+watch(
+  () => props.eventId,
+  (newVal) => {
+    if (newVal) {
+      fetchDetail();
+    }
+  },
+  { immediate: true }
+);
+const submitForm = async () => {
+  // 假设表单已经通过验证
+  const response = await updatetask(form.value);
+  if (response.code === 200) {
+    ElMessage.success('提交成功');
+    emits('refresh'); // 提交成功后通知父组件刷新
+    emits('close'); // 关闭弹窗
+  } else {
+    ElMessage.error(response.msg);
+  }
+};
+
+const cancel = () => {
+  emits('close');
+};
+</script>