Browse Source

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

# Conflicts:
#	src/types/components.d.ts
Hwf 9 months ago
parent
commit
083c3977c4

+ 4 - 0
.env.development

@@ -19,6 +19,10 @@ VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
 # SnailJob 控制台地址
 VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
 
+# 粤政易回调页面
+YZY_REDIRECT_URI = 'http://19.155.220.206:8086/tyrz/login'
+YZY_TYRZ_URL = 'https://xtbg.digitalgd.com.cn/zwrz/rz/sso/oauth/authorize?response_type=code&scope=all&client_id=zwrz_mmzhyj&redirect_uri='
+
 VITE_APP_PORT = 8086
 
 # 接口加密功能开关(如需关闭 后端也必须对应关闭)

+ 14 - 14
package-lock.json

@@ -36,9 +36,9 @@
         "diagram-js": "12.3.0",
         "didi": "9.0.2",
         "echarts": "5.5.0",
-        "element-plus": "2.7.5",
+        "element-plus": "^2.7.5",
         "element-resize-detector": "^1.2.4",
-        "file-saver": "2.0.5",
+        "file-saver": "^2.0.5",
         "fuse.js": "7.0.0",
         "highlight.js": "11.9.0",
         "html2canvas": "^1.4.1",
@@ -57,7 +57,7 @@
         "vue-router": "4.3.2",
         "vue-types": "5.1.1",
         "vue3-print-nb": "^0.1.4",
-        "vxe-table": "4.5.22",
+        "vxe-table": "^4.6.21",
         "xlsx": "^0.18.5"
       },
       "devDependencies": {
@@ -5353,9 +5353,9 @@
       }
     },
     "node_modules/dom-zindex": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmmirror.com/dom-zindex/-/dom-zindex-1.0.4.tgz",
-      "integrity": "sha512-PNk7u71TJ1C9Lwjjp5nNuQcVWuECFMmr9kZAwi2UbgWUM7jXdTCe4O4x5bhLUa07jpcZUVA5Du3ho7/FXzS9Ng=="
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/dom-zindex/-/dom-zindex-1.0.6.tgz",
+      "integrity": "sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA=="
     },
     "node_modules/domelementtype": {
       "version": "1.3.1",
@@ -12595,12 +12595,12 @@
       }
     },
     "node_modules/vxe-table": {
-      "version": "4.5.22",
-      "resolved": "https://registry.npmmirror.com/vxe-table/-/vxe-table-4.5.22.tgz",
-      "integrity": "sha512-bUmn6KSL9FE0Dfrsw7VjJAS8tratL1OBIDVzt1djgijU6WAwyp3697POkMR9TZ4HHvV6uGDSCuGzUUXGFodvVQ==",
+      "version": "4.6.21",
+      "resolved": "https://registry.npmmirror.com/vxe-table/-/vxe-table-4.6.21.tgz",
+      "integrity": "sha512-txrqMbzM9MBWU6g+1B51+wRvPfH2pCA8IGAUlgSF61xoVxAAN/vmgLGoUANd1p7q1osYs8FDV34OZE2KIUibAA==",
       "dependencies": {
-        "dom-zindex": "^1.0.1",
-        "xe-utils": "^3.5.24"
+        "dom-zindex": "^1.0.6",
+        "xe-utils": "^3.5.30"
       },
       "peerDependencies": {
         "vue": "^3.2.28"
@@ -12746,9 +12746,9 @@
       "dev": true
     },
     "node_modules/xe-utils": {
-      "version": "3.5.29",
-      "resolved": "https://registry.npmmirror.com/xe-utils/-/xe-utils-3.5.29.tgz",
-      "integrity": "sha512-9Ty3k/nHUptUzBZ/S+Z6umfpNWKU6ZFdGR2qHeynKRTjI/Tjd5ku/n6O1oKQCwtxQ3QzCl3NnD2LRy9SCTmnNw=="
+      "version": "3.5.31",
+      "resolved": "https://registry.npmmirror.com/xe-utils/-/xe-utils-3.5.31.tgz",
+      "integrity": "sha512-oS4yv8qktvlE0wc9yYkitDidEmThc5qN0UTRvKCvrWnejxbTyIxbwfrdZmPKdKGZtB+/U8cEAMFywLJjHtD11A=="
     },
     "node_modules/xlsx": {
       "version": "0.18.5",

+ 3 - 3
package.json

@@ -45,9 +45,9 @@
     "diagram-js": "12.3.0",
     "didi": "9.0.2",
     "echarts": "5.5.0",
-    "element-plus": "2.7.5",
+    "element-plus": "^2.7.5",
     "element-resize-detector": "^1.2.4",
-    "file-saver": "2.0.5",
+    "file-saver": "^2.0.5",
     "fuse.js": "7.0.0",
     "highlight.js": "11.9.0",
     "html2canvas": "^1.4.1",
@@ -66,7 +66,7 @@
     "vue-router": "4.3.2",
     "vue-types": "5.1.1",
     "vue3-print-nb": "^0.1.4",
-    "vxe-table": "4.5.22",
+    "vxe-table": "^4.6.21",
     "xlsx": "^0.18.5"
   },
   "devDependencies": {

+ 30 - 0
src/api/inspectionWork/inspector.ts

@@ -117,3 +117,33 @@ export function workSubList(task_id) {
     params: task_id
   });
 }
+// 删除风险任务
+export const deleteRisk = (id) => {
+  return request({
+    url: '/api/riskManagement/inspection/task/delete/' + id,
+    method: 'delete',
+    params: id
+  });
+};
+// 查询巡查结果列表
+export function resultList(children_task_id, queryParams) {
+  return request({
+    url: '/api/riskManagement/inspection/task/children/task/result/' + children_task_id + '/list',
+    method: 'get',
+    params: {
+      page: queryParams.page,
+      pageSize: queryParams.pageSize,
+      inspection_result: queryParams.inspection_result,
+      area_code: queryParams.area,
+      nick_name: queryParams.nick_name
+    }
+  });
+}
+// 查询用户详情
+export function fileDownload(url) {
+  return request({
+    url: '/api/file/download/' + url,
+    method: 'get',
+    params: url
+  });
+}

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

@@ -26,13 +26,9 @@ declare module 'vue' {
     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']
-    ElCollapse: typeof import('element-plus/es')['ElCollapse']
-    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
-    ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
@@ -45,31 +41,23 @@ declare module 'vue' {
     ElEmpty: typeof import('element-plus/es')['ElEmpty']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElHeader: typeof import('element-plus/es')['ElHeader']
     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']
-    ElMain: typeof import('element-plus/es')['ElMain']
     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']
-    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSegmented: typeof import('element-plus/es')['ElSegmented']
     ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
-    ElSpace: typeof import('element-plus/es')['ElSpace']
-    ElStep: typeof import('element-plus/es')['ElStep']
-    ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
@@ -94,9 +82,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']
-    IEpUploadFilled: typeof import('~icons/ep/upload-filled')['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']

+ 134 - 0
src/views/dataFilling/myFilling.vue

@@ -0,0 +1,134 @@
+<template>
+  <div>
+    <div v-show="!writeFormState.show" class="app-container">
+      <div>
+        <transition name="fade">
+          <div v-show="showSearch">
+            <el-form ref="queryFormRef" :model="queryParams">
+              <el-row :gutter="20">
+                <el-col :span="6">
+                  <el-form-item label="表格名称:" prop="table_name" label-width="auto">
+                    <el-input v-model="queryParams.table_name" placeholder="请输入巡查人"></el-input>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="6">
+                  <el-form-item label="任务状态:" prop="task_status">
+                    <el-radio-group v-model="queryParams.task_status">
+                      <el-radio value="0" size="large">待填报</el-radio>
+                      <el-radio value="1" size="large">已上报</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="6">
+                  <el-button type="primary" @click="handleQuery">查询</el-button>
+                  <el-button @click="resetQuery">重置</el-button>
+                </el-col>
+              </el-row>
+            </el-form>
+          </div>
+        </transition>
+        <!-- 表格组件 -->
+        <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+          <el-table-column label="序号" align="center" prop="table_id" />
+          <el-table-column label="表格名称" align="center" prop="table_name" />
+          <el-table-column label="开始日期" align="center" prop="run_time" />
+          <el-table-column label="截止填报时间" align="center" prop="filling_time" />
+          <el-table-column label="任务状态" align="center" prop="status" />
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <template #default="scope">
+              <el-text v-if="scope.row.status === '待填报'" class="common-btn-text-primary" @click="handleWrite(scope.row)">填表</el-text>
+              <el-text class="common-btn-text-primary" @click="handleView(scope.row)">详情</el-text>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="tableData" />
+      </div>
+    </div>
+  </div>
+  <WriteForm v-if="writeFormState.show" :event-id="writeFormState.eventId" @close="handleCancel" />
+</template>
+<script setup lang="ts">
+import { onMounted, reactive, ref } from 'vue';
+import WriteForm from './writeForm.vue';
+const loading = ref(true);
+const showSearch = ref(true);
+const multiple = ref(true);
+const ids = ref<Array<number | string>>([]);
+const single = ref(true);
+const total = ref(0);
+const tableData = ref([]);
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const initFormData = reactive({
+  table_id: '',
+  table_name: '',
+  filling_time: '',
+  run_time: '',
+  task_status: ''
+});
+const data = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    page: 1,
+    pageSize: 10,
+    table_name: '',
+    task_status: ''
+  }
+});
+
+const { queryParams, form } = toRefs(data);
+// 模拟数据源
+const staticData = [
+  {
+    table_id: 1,
+    table_name: '测试表单',
+    run_time: '2024-10-15',
+    filling_time: '2024-10-15 18:00:00',
+    status: '待填报'
+  },
+  {
+    table_id: 2,
+    table_name: '应急工单数据表',
+    run_time: '2024-06-24',
+    filling_time: '2025-06-24 18:00:00',
+    status: '待填报'
+  },
+  {
+    table_id: 3,
+    table_name: '安全风险通告数据表',
+    run_time: '2024-06-24',
+    filling_time: '2025-06-24 18:00:00',
+    status: '已上报'
+  }
+];
+let writeFormState = reactive({
+  show: false,
+  eventId: ''
+});
+const handleCancel = () => {
+  writeFormState.show = false;
+};
+const handleWrite = (row) => {
+  if (row) {
+    writeFormState.eventId = row.id;
+    writeFormState.show = true;
+  }
+};
+// 初始化数据
+onMounted(() => {
+  tableData.value = staticData;
+  total.value = staticData.length;
+  loading.value = false;
+});
+const handleQuery = () => {
+  queryParams.value.page = 1;
+  fetchWorkrData();
+};
+// 重置查询条件
+const resetQuery = () => {
+  queryParams.value = { page: 1, pageSize: 10, table_name: '', task_status: '' };
+  handleQuery();
+};
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+};
+</script>

+ 180 - 0
src/views/dataFilling/writeForm.vue

@@ -0,0 +1,180 @@
+<template>
+  <div class="app-container p-2">
+    <el-row :gutter="20">
+      <el-col :lg="30" :xs="24" style="">
+        <el-row :span="24" :gutter="10">
+          <el-col :span="18" label="任务名称">
+            <h2 v-if="detailData.title" key="business" style="font-weight: bolder">{{ detailData.title }}</h2>
+            <p class="report-period">【填报周期】:{{ detailData.start }} 至 {{ detailData.end }}</p>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" @click="handleReport()"> 上报 </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" @click="exportToExcel()"> 导出表格 </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" @click="handleSave()"> 保存 </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" @click="handleReturn()"> 返回 </el-button>
+          </el-col>
+        </el-row>
+      </el-col>
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button type="primary" @click="handleAdd">批量导入</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button type="primary" @click="handleDownloadEmptyTable"> 下载空表格 </el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button type="primary" @click="handleAddRow"> 新增一行 </el-button>
+        </el-col>
+      </el-row>
+      <el-col :lg="30" :xs="24">
+        <el-table :data="tableData" border>
+          <el-table-column v-for="header in editableHeaders" :key="header" :label="header" :prop="header">
+            <template #header="{ column }">
+              <span
+                class="editable-header"
+                contenteditable="true"
+                @blur="saveHeader(column.label, $event.target.innerText)"
+                v-text="column.label"
+              ></span>
+            </template>
+            <template #default="{ row, $index }">
+              <span
+                class="editable-span"
+                contenteditable="true"
+                @blur="saveEdit($index, header, $event.target.innerText)"
+                v-text="row[header]"
+              ></span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue';
+import { ElTable, ElButton, ElCol, ElRow, ElTableColumn } from 'element-plus';
+import * as XLSX from 'xlsx';
+
+const detailData = ref({
+  title: '测试表单',
+  start: '2024-10-15 17:02:22',
+  end: '2024-10-15 18:00:00'
+});
+
+const editableHeaders = ref(['时间', '地点', '损坏程度', '救援人员', '物资']);
+const tableData = ref([
+  {
+    时间: '2024-01-01',
+    地点: '某地',
+    损坏程度: '轻度',
+    救援人员: '张三, 李四',
+    物资: '食品, 水'
+  },
+  {
+    时间: '2024-01-02',
+    地点: '某地',
+    损坏程度: '中度',
+    救援人员: '王五, 赵六',
+    物资: '帐篷, 医疗用品'
+  }
+]);
+
+function saveEdit(rowIndex, header, value) {
+  tableData.value[rowIndex][header] = value;
+}
+
+function saveHeader(header, newValue) {
+  const index = editableHeaders.value.indexOf(header);
+  if (index !== -1) {
+    editableHeaders.value.splice(index, 1, newValue);
+  }
+}
+
+function addDefaultRow() {
+  tableData.value.push({
+    时间: '',
+    地点: '',
+    损坏程度: '',
+    救援人员: '',
+    物资: ''
+  });
+}
+
+onMounted(() => {
+  addDefaultRow();
+});
+
+const exportToExcel = () => {
+  const worksheet = XLSX.utils.json_to_sheet(tableData.value);
+  const workbook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
+  const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
+
+  const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+  const link = document.createElement('a');
+  const url = window.URL.createObjectURL(blob);
+  link.href = url;
+  link.download = 'SheetJS.xlsx';
+  link.click();
+  window.URL.revokeObjectURL(url); // 清理
+};
+
+const handleAdd = () => console.log('批量导入');
+const handleDownloadEmptyTable = () => console.log('下载空表格');
+const handleAddRow = () => addDefaultRow();
+const handleReport = () => console.log('上报');
+const handleSave = () => console.log('保存');
+const handleReturn = () => console.log('返回');
+</script>
+
+<style scoped>
+.app-container {
+  font-family: Avenir, Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-align: center;
+  color: #2c3e50;
+}
+.report-period {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #606266;
+}
+.editable-span {
+  cursor: pointer;
+  display: inline-block;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.editable-span[contenteditable='true'] {
+  white-space: normal;
+  outline: none; /* 移除编辑时的焦点边框 */
+}
+.editable-span[contenteditable='true']:empty::before {
+  content: attr(data-placeholder); /* 可选:为空时显示占位符 */
+  color: #999;
+}
+.editable-header {
+  cursor: pointer;
+  display: inline-block;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.editable-header[contenteditable='true'] {
+  white-space: normal;
+  outline: none; /* 移除编辑时的焦点边框 */
+}
+.editable-header[contenteditable='true']:empty::before {
+  content: attr(data-placeholder); /* 可选:为空时显示占位符 */
+  color: #999;
+}
+</style>

+ 13 - 7
src/views/informationissue/informationApplication.vue

@@ -99,13 +99,13 @@
         </div>
       </div>
     </div>
+    <ContactSelect
+      v-model="contactSelectState.show"
+      :tree-data="treeData"
+      :default-check-data="selectContactSelectData"
+      @confirm="handleContactSelectData"
+    />
   </div>
-  <ContactSelect
-    v-model="contactSelectState.show"
-    :tree-data="treeData"
-    :default-check-data="selectContactSelectData"
-    @confirm="handleContactSelectData"
-  />
 </template>
 
 <script setup lang="ts">
@@ -266,6 +266,11 @@ const fetchTreeData = async () => {
     console.error('Failed to fetch information:', error);
   }
 };
+
+const openUserSelect = async() => {
+
+};
+
 onMounted(() => {
   fetchTreeData();
   formData.value.publish_time = formattedCurrentTime.value;
@@ -274,7 +279,8 @@ onMounted(() => {
       presetTemplates.value.push({ value: item.name, label: item.name, content: item.content });
     });
     getUser({}).then((res) => {
-      users.value = res.data.map((user) => ({ value: user.username, username: user.username }));
+      // console.log('res:', res);
+      users.value = res.rows.map((user) => ({ value: user.username, username: user.username }));
     });
   });
 });

+ 5 - 1
src/views/informationissue/informationApproval.vue

@@ -62,7 +62,7 @@
                     <el-row :gutter="18">
                       <el-col :span="6">
                         <el-form-item label="发布时间:" prop="releaseTime">
-                          <el-button type="text" @click="publishNow">立即发布</el-button>
+                          <el-button @click="publishNow">立即发布</el-button>
                         </el-form-item>
                       </el-col>
                       <el-col :span="12">
@@ -231,6 +231,10 @@ const fetchInformation = async () => {
   }
 };
 
+const publishNow = ()=> {
+
+};
+
 // 审批form
 const form2Ref = ref(null);
 const buttonLoading = ref(false);

+ 2 - 2
src/views/informationissue/informationList.vue

@@ -220,7 +220,7 @@ let informationApprovalState = reactive({
 
 const handleView = (row) => {
   if (row) {
-    informationViewState.eventId = row.id; // 假设eventId是id字段
+    informationViewState.eventId = row.id+""; // 假设eventId是id字段
     informationViewState.show = true;
   }
 };
@@ -233,7 +233,7 @@ const handleUpdate = (row) => {
 
 const handleApproval = (row) => {
   if (row) {
-    informationApprovalState.eventId = row.id; // 假设eventId是id字段
+    informationApprovalState.eventId = row.id+""; // 假设eventId是id字段
     informationApprovalState.show = true;
   }
 };

+ 5 - 2
src/views/informationissue/informationView.vue

@@ -94,7 +94,7 @@
                     <el-row :gutter="18">
                       <el-col :span="6">
                         <el-form-item label="发布时间:" prop="publish_time">
-                          <el-button type="text" disabled @click="publishNow">立即发布</el-button>
+                          <el-button disabled @click="publishNow">立即发布</el-button>
                         </el-form-item>
                       </el-col>
                       <el-col :span="12">
@@ -164,8 +164,8 @@
         </div>
       </div>
     </div>
+    <SendDetail v-if="sendDetailState.show" :info_id="sendDetailState.info_id" @close="handleCancel" />
   </div>
-  <SendDetail v-if="sendDetailState.show" :info_id="sendDetailState.info_id" @close="handleCancel" />
 </template>
 
 <script setup lang="ts">
@@ -234,6 +234,9 @@ const showSendDetails = () => {
   sendDetailState.info_id = props.eventId; // 假设eventId是id字段
   sendDetailState.show = true;
 };
+const publishNow = () => {
+
+};
 
 const showTemplateExample = () => {
   ElMessage.info('点击了查看模板样例');

+ 236 - 0
src/views/inspectionWork/patrolSubResult.vue

@@ -0,0 +1,236 @@
+<template>
+  <div>
+    <el-dialog v-model="showSearch" title="巡查结果" width="80%" @close="$emit('close')">
+      <div class="app-container">
+        <transition name="fade">
+          <div v-show="showSearch">
+            <el-form ref="queryFormRef" :model="queryParams">
+              <el-row :gutter="20">
+                <el-col :span="6">
+                  <el-form-item label="所属区划:" prop="area" label-width="auto">
+                    <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-col>
+                <el-col :span="6">
+                  <el-form-item label="巡查结果:" prop="inspection_result" label-width="auto">
+                    <el-select v-model="queryParams.inspection_result" placeholder="全部" clearable>
+                      <el-option v-for="item in cycleOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="6">
+                  <el-form-item prop="nick_name" label-width="auto">
+                    <el-input v-model="queryParams.nick_name" placeholder="请输入巡查人"></el-input>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="6">
+                  <el-button type="primary" @click="handleQuery">搜索</el-button>
+                  <el-button @click="resetQuery">重置</el-button>
+                </el-col>
+              </el-row>
+            </el-form>
+          </div>
+        </transition>
+
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="Plus" @click="handleExport">导出</el-button>
+          </el-col>
+        </el-row>
+        <!-- 表格组件 -->
+        <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+          <el-table-column label="巡查点" align="center" prop="inspection_point_name" />
+          <el-table-column label="所属区划" align="center" prop="area" />
+          <el-table-column label="执行日期" align="center" prop="create_time" />
+          <el-table-column label="巡查人" align="center" prop="nick_name" />
+          <el-table-column label="巡查结果" align="center">
+            <template #default="{ row }">
+              {{ getInspectionResultText(row.inspection_result) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="现场照片" align="center" prop="fileList">
+            <template #default="{ row }">
+              <div v-if="row.fileList && row.fileList.length > 0">
+                <img v-for="file in row.fileList" :key="file.uid" :src="file.previewUrl" alt="" style="max-width: 100px" />
+              </div>
+              <div v-else>无图片</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="备注" align="center" prop="remark" />
+        </el-table>
+        <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="tableData" />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script setup lang="ts">
+import { onMounted, reactive, ref } from 'vue';
+import { inspectorDivision, resultList, fileDownload } from '@/api/inspectionWork/inspector';
+import { ElMessage } from 'element-plus';
+const loading = ref(true);
+const showSearch = ref(true);
+const multiple = ref(true);
+const ids = ref<Array<number | string>>([]);
+const single = ref(true);
+const total = ref(0);
+const tableData = ref([]);
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const divisionSelectedId = ref(null);
+const formattedDivisionData = ref([]);
+const rawDivisionData = ref([]);
+const props = defineProps<{
+  eventId: string | number;
+}>();
+const initFormData = reactive({
+  id: '',
+  children_task_id: '',
+  inspection_point_name: '',
+  area: '',
+  create_time: '',
+  nick_name: '',
+  inspection_result: '',
+  remark: '',
+  fileList: []
+});
+const data = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    page: '',
+    pageSize: '',
+    inspection_result: '',
+    area_code: '',
+    nick_name: ''
+  }
+});
+const { queryParams, form } = toRefs(data);
+const cycleOptions = ref([
+  { label: '全部', value: '' }, // 通常“全部”对应空值或者特定的标识符,表示不按此条件过滤
+  { label: '正常', value: '1' },
+  { label: '异常', value: '2' }
+]);
+const getInspectionResultText = (resultCode) => {
+  switch (resultCode) {
+    case '1':
+      return '正常';
+    case '2':
+      return '异常';
+    default:
+      return '全部';
+  }
+};
+
+const fetchResulData = () => {
+  loading.value = true; // 开始加载
+  return resultList(props.eventId, queryParams.value)
+    .then((res) => {
+      if (res.code === 200) {
+        tableData.value = res.data || []; // 确保tableData是一个数组
+        total.value = res.total || 0; // 确保total是一个数字
+        console.log('Fetched subtasks data:', tableData.value);
+      } else {
+        console.error(res.msg);
+      }
+      loading.value = false; // 结束加载
+    })
+    .catch((error) => {
+      console.error('Error fetching sub tasks:', error);
+      loading.value = false; // 结束加载
+    });
+};
+const loadFilePreviews = (rowData) => {
+  if (rowData.fileList && rowData.fileList.length > 0) {
+    for (const file of rowData.fileList) {
+      try {
+        fileDownload(file.url)
+          .then((response) => {
+            if (response && response.data) {
+              file.previewUrl = URL.createObjectURL(new Blob([response.data]));
+            }
+          })
+          .catch((error) => {
+            console.error(`Failed to load image at ${file.url}:`, error);
+          });
+      } catch (error) {
+        console.error(`Failed to start download for ${file.url}:`, error);
+      }
+    }
+  }
+};
+const fetchAndLoadPreviews = () => {
+  fetchResulData().then(() => {
+    tableData.value.forEach(loadFilePreviews);
+  });
+};
+const handleQuery = () => {
+  queryParams.value.page = 1;
+  fetchResulData();
+};
+// 重置查询条件
+const resetQuery = () => {
+  queryParams.value = { page: 1, pageSize: 10, nick_name: '', area_code: '', inspection_result: '' };
+  handleQuery();
+};
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+  selectedRow.value = selection.length === 1 ? selection[0] : null;
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+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(() => {
+  fetchResulData();
+  fetchDivisionData();
+});
+</script>

+ 44 - 3
src/views/inspectionWork/patrolSubTasks.vue

@@ -20,7 +20,7 @@
             <el-button type="primary" @click="handlefinal()"> 完成任务 </el-button>
           </el-col>
           <el-col :span="1.5">
-            <el-button type="danger" @click="handleDelete"> 删除预案 </el-button>
+            <el-button type="danger" @click="handleDelete()"> 删除 </el-button>
           </el-col>
         </el-row>
         <div class="line" style="background: #e7e7e7; width: auto; height: 0.6px; position: relative"></div>
@@ -51,7 +51,7 @@
             <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>
+                <el-text class="common-btn-text-primary" @click="handleResult(scope.row)">巡查结果</el-text>
               </template>
             </el-table-column>
           </el-table>
@@ -66,12 +66,18 @@
       </el-col>
     </el-row>
   </div>
+  <PatrolSubResult v-if="patrolSubResultState.show" :event-id="patrolSubResultState.eventId" @close="handleCancel" />
+  <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh-parent="refreshBoth" />
 </template>
 <script setup lang="ts">
-import { workDetail, workSubList, updatetask } from '@/api/inspectionWork/inspector';
+import { workDetail, workSubList, updatetask, deleteRisk } from '@/api/inspectionWork/inspector';
 import { reactive, ref } from 'vue';
 import { ElMessageBox } from 'element-plus';
+import PatrolSubResult from './patrolSubResult.vue';
+import PatrolTaskEdit from './patrolTaskEdit.vue';
+import { to } from 'await-to-js';
 const props = defineProps<{ eventId: string }>();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const total = ref(0);
 const tableData = ref([]);
 const multiple = ref(true);
@@ -136,6 +142,28 @@ const taskStatusMap = {
   2: '未完成',
   3: '已完结'
 };
+let patrolTaskEditState = reactive({
+  show: false,
+  eventId: ''
+});
+let patrolSubResultState = reactive({
+  show: false,
+  eventId: ''
+});
+const handleCancel = () => {
+  patrolTaskEditState.show = false;
+  patrolSubResultState.show = false;
+};
+const handleUpdate = () => {
+  patrolTaskEditState.eventId = props.eventId; // 假设eventId是id字段
+  patrolTaskEditState.show = true;
+};
+const handleResult = (row) => {
+  if (row) {
+    patrolSubResultState.eventId = row.id; // 假设eventId是id字段
+    patrolSubResultState.show = true;
+  }
+};
 const loading = ref(false);
 const fetchWorkDetail = () => {
   loading.value = true;
@@ -176,6 +204,15 @@ const fetchSubTasks = () => {
       console.error('Error fetching sub tasks:', error);
     });
 };
+const handleDelete = async () => {
+  const [err] = await to(proxy?.$modal.confirm('是否确认删除?') as any);
+  if (!err) {
+    await deleteRisk([props.eventId]);
+    proxy?.$modal.msgSuccess('删除成功');
+    emits('close');
+    emits('refreshsub');
+  }
+};
 const handleSelectionChange = (selection) => {
   ids.value = selection.map((item) => item.id);
   single.value = selection.length != 1;
@@ -206,6 +243,10 @@ const handlefinal = async () => {
 const goBack = () => {
   emits('close');
 };
+const refreshBoth = () => {
+  fetchWorkDetail();
+  fetchSubTasks();
+};
 onMounted(() => {
   fetchWorkDetail(); // 在组件挂载后调用此函数以获取数据
   fetchSubTasks();

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

@@ -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" v-if="scope.row.task_status !== '3'" @click="handleWork(scope.row)">完成任务</el-text>
+              <el-text v-if="scope.row.task_status !== '3'" class="common-btn-text-danger" @click="handleWork(scope.row)">完成任务</el-text>
               <el-text class="common-btn-text-danger" @click="handleDelete(scope.row)">删除</el-text>
             </template>
           </el-table-column>
@@ -76,7 +76,7 @@
       </div>
     </div>
   </div>
-  <PatrolSubTasks v-if="patrolSubTasksState.show" :event-id="patrolSubTasksState.eventId" @close="handleCancel" />
+  <PatrolSubTasks v-if="patrolSubTasksState.show" :event-id="patrolSubTasksState.eventId" @close="handleCancel" @refreshsub="fetchWorkrData" />
   <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh="fetchWorkrData" />
   <PatrolTaskAdd v-if="patrolTaskAddState.show" @close="handleCancel" @refresh="fetchWorkrData" />
 </template>

+ 5 - 4
src/views/inspectionWork/patrolTaskEdit.vue

@@ -71,7 +71,7 @@ import { ElMessage } from 'element-plus';
 const demoFormRef = ref(null);
 const buttonLoading = ref(false);
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const emits = defineEmits(['close']);
+const emit = defineEmits(['close']);
 const props = defineProps<{ eventId: string }>();
 let form = ref({
   id: '',
@@ -111,14 +111,15 @@ const submitForm = async () => {
   const response = await updatetask(form.value);
   if (response.code === 200) {
     ElMessage.success('提交成功');
-    emits('refresh'); // 提交成功后通知父组件刷新
-    emits('close'); // 关闭弹窗
+    emit('refresh'); // 提交成功后通知父组件刷新
+    emit('refreshParent'); // 提交成功后通知子任务组件刷新
+    cancel(); // 关闭弹窗
   } else {
     ElMessage.error(response.msg);
   }
 };
 
 const cancel = () => {
-  emits('close');
+  emit('close');
 };
 </script>

+ 13 - 2
src/views/login.vue

@@ -5,7 +5,7 @@
       <div class="title2">智慧应急工作台</div>
       <div class="login-box">
         <div class="login-tabs">
-          <div v-for="(item, index) in tabs" :key="index" :class="tabActive === index ? 'login-tab tab-active' : 'login-tab'">{{ item }}</div>
+          <div v-for="(item, index) in tabs" :key="index" :class="tabActive === index ? 'login-tab tab-active' : 'login-tab'" @click="handleTab(index)">{{ item }}</div>
         </div>
         <el-form-item prop="username">
           <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
@@ -75,7 +75,7 @@ const userStore = useUserStore();
 const router = useRouter();
 const tabActive = ref(0);
 // '粤政易扫码登录',
-const tabs = reactive(['账号密码登录']);
+const tabs = reactive(['账号密码登录', '粤政易登录']);
 const loginForm = ref<LoginData>({
   tenantId: '000000',
   username: 'admin',
@@ -205,6 +205,16 @@ const doSocialLogin = (type: string) => {
   });
 };
 
+const handleTab = (tab) => {
+  if(tab == 1) {
+    // const redirect_uri = encodeURIComponent(import.meta.env.YZY_REDIRECT_URI);
+    // const tyrz_url = import.meta.env.YZY_TYRZ_URL + redirect_uri;
+    const redirect_uri = encodeURIComponent("http://19.155.220.206:8086/tyrz/login");
+    const tyrz_url = "https://xtbg.digitalgd.com.cn/zwrz/rz/sso/oauth/authorize?response_type=code&scope=all&client_id=zwrz_mmzhyj&redirect_uri="+redirect_uri;
+    window.location.href = tyrz_url;
+  }
+}
+
 onMounted(() => {
   getCode();
   initTenantList();
@@ -303,6 +313,7 @@ onMounted(() => {
   border-bottom: 1px solid #eeeeee;
   margin-bottom: 15px;
   .login-tab {
+    padding: 0 10px;
   }
   .tab-active {
     color: #5695eb;

+ 41 - 40
src/views/setting/riskPrevention/userManage.vue

@@ -58,50 +58,51 @@
       </el-table>
     </div>
     <pagination v-show="total > 0" v-model:page="queryForm.page" v-model:limit="queryForm.pageSize" :total="total" @pagination="getList" />
-  </div>
-  <!-- 新增/修改弹窗 -->
-  <div v-show="addDialog.visible" class="common-dialog">
-    <div class="common-dialog-content">
-      <div class="common-dialog-title-box">
-        <i class="common-dialog-title-icon" />
-        <div>{{ addDialog.title }}</div>
+
+    <!-- 新增/修改弹窗 -->
+    <div v-show="addDialog.visible" class="common-dialog">
+      <div class="common-dialog-content">
+        <div class="common-dialog-title-box">
+          <i class="common-dialog-title-icon" />
+          <div>{{ addDialog.title }}</div>
+        </div>
+        <div class="common-dialog-box">
+          <el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="120px">
+            <el-form-item label="单位名称:" prop="unitId">
+              <el-select v-model="addForm.unitId" placeholder="请选择单位" clearable style="width: 468px !important">
+                <el-option v-for="item in unitList" :key="item.deptId" :label="item.deptName" :value="item.deptId"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="联系人:" prop="contactName">
+              <el-input v-model="addForm.contactName" placeholder="请输入联系人" style="width: 468px !important" />
+            </el-form-item>
+            <el-form-item label="职务:" prop="position">
+              <el-input v-model="addForm.position" placeholder="请输入职务" style="width: 468px !important" />
+            </el-form-item>
+            <el-form-item label="粤政易手机号码:" prop="phone">
+              <el-input v-model="addForm.phone" placeholder="请输入粤政易手机号码" style="width: 468px !important" />
+            </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 class="common-dialog-box">
-        <el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="120px">
-          <el-form-item label="单位名称:" prop="unitId">
-            <el-select v-model="addForm.unitId" placeholder="请选择单位" clearable style="width: 468px !important">
-              <el-option v-for="item in unitList" :key="item.deptId" :label="item.deptName" :value="item.deptId"></el-option>
-            </el-select>
-          </el-form-item>
-          <el-form-item label="联系人:" prop="contactName">
-            <el-input v-model="addForm.contactName" placeholder="请输入联系人" style="width: 468px !important" />
-          </el-form-item>
-          <el-form-item label="职务:" prop="position">
-            <el-input v-model="addForm.position" placeholder="请输入职务" style="width: 468px !important" />
-          </el-form-item>
-          <el-form-item label="粤政易手机号码:" prop="phone">
-            <el-input v-model="addForm.phone" placeholder="请输入粤政易手机号码" style="width: 468px !important" />
-          </el-form-item>
+
+      <el-dialog v-model="showImportDlg" title="导入人员" width="500px" append-to-body>
+        <el-form ref="importFormRef" :model="importForm" :rules="importRules">
+          <FileUpload v-model="importForm.filename" :file-type="['xls', 'xlsx']" :limit="1" />
         </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>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button type="primary" @click="submitImportForm">确 定</el-button>
+            <el-button @click="cancelImport">取 消</el-button>
+          </div>
+        </template>
+      </el-dialog>
     </div>
   </div>
-
-  <el-dialog v-model="showImportDlg" title="导入人员" width="500px" append-to-body>
-    <el-form ref="importFormRef" :model="importForm" :rules="importRules">
-      <FileUpload v-model="importForm.filename" :file-type="['xls', 'xlsx']" :limit="1" />
-    </el-form>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitImportForm">确 定</el-button>
-        <el-button @click="cancelImport">取 消</el-button>
-      </div>
-    </template>
-  </el-dialog>
 </template>
 
 <script setup lang="ts">