瀏覽代碼

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

yangyuxuan 2 月之前
父節點
當前提交
23b9993d8a

+ 9 - 0
src/api/dataFilling/datafilling.ts

@@ -32,3 +32,12 @@ export function submitFill(data) {
     data: data
   });
 }
+
+// 我的填报-保存
+export function dataFillingSaveData(data) {
+  return request({
+    url: '/api/dataFilling/save_data',
+    method: 'post',
+    data: data
+  });
+}

+ 35 - 0
src/api/expert/index.ts

@@ -0,0 +1,35 @@
+import request from '@/utils/request';
+
+// 获取专家列表
+export function getExpertList(params) {
+  return request({
+    url: '/api/expert/list',
+    method: 'get',
+    params: params
+  });
+}
+
+// 获取专家详情
+export function getExpertInfo(id) {
+  return request({
+    url: '/api/expert/info/' + id,
+    method: 'get'
+  });
+}
+
+// 更新专家详情
+export function updateExpertInfo(id, data) {
+  return request({
+    url: '/api/expert/update/' + id,
+    method: 'put',
+    data: data
+  });
+}
+
+// 获取专家分组统计
+export function getExpertProfessionalGroupCount() {
+  return request({
+    url: '/api/gateway/v1/get_emergency_expert_professional_group_count',
+    method: 'get'
+  });
+}

+ 6 - 1
src/types/components.d.ts

@@ -27,12 +27,14 @@ declare module 'vue' {
     ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -56,6 +58,8 @@ declare module 'vue' {
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    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']
@@ -64,6 +68,7 @@ declare module 'vue' {
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
+    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']

+ 76 - 36
src/views/comprehensiveGuarantee/emergencySpecialistManagement/edit.vue

@@ -5,42 +5,63 @@
         <h3 class="common-dialog-title">查看详情</h3>
       </div>
       <div class="common-dialog-box">
-        <el-form ref="form" :model="formData" :rules="rules" label-width="120px">
+        <el-form ref="form" :model="formData" label-width="120px">
           <el-form-item label="姓名:" prop="name">
             <el-input v-model="formData.name" style="width: 468px !important" />
           </el-form-item>
           <el-form-item label="所属区县:" prop="county">
             <el-input v-model="formData.county" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="专家类型:" prop="expert_type">
-            <el-input v-model="formData.expert_type" style="width: 468px !important" />
+<!--          <el-form-item label="专家类型:" prop="expert_type">-->
+<!--            <el-input v-model="formData.expert_type" style="width: 468px !important" />-->
+<!--          </el-form-item>-->
+          <el-form-item label="经度:" prop="longitude">
+            <el-input v-model="formData.longitude" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="职位:" prop="position">
-            <el-input v-model="formData.position" style="width: 468px !important" />
+          <el-form-item label="纬度:" prop="latitude">
+            <el-input v-model="formData.latitude" style="width: 468px !important" />
+          </el-form-item>
+          <el-form-item label="荣誉称号:" prop="honorary_title">
+            <el-input v-model="formData.honorary_title" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="单位:" prop="unit">
+          <el-form-item label="工作单位:" prop="unit">
             <el-input v-model="formData.unit" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="联系电话:" prop="phone">
-            <el-input v-model="formData.phone" style="width: 468px !important" />
+          <el-form-item label="职务:" prop="position">
+            <el-input v-model="formData.position" style="width: 468px !important" />
+          </el-form-item>
+          <el-form-item label="职称:" prop="professional_title">
+            <el-input v-model="formData.professional_title" class="custom-disabled" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="现在地址:" prop="address">
-            <el-input v-model="formData.address" style="width: 468px !important" />
+          <el-form-item label="发证日期:" prop="certificate_issue_date">
+            <el-input v-model="formData.certificate_issue_date" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="状态:" prop="status">
-            <el-input v-model="formData.status" style="width: 468px !important" />
+          <el-form-item label="专业分组:" prop="professional_group">
+            <el-input v-model="formData.professional_group" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="擅长事故类型:" prop="accident_type">
-            <el-input v-model="formData.accident_type" style="width: 468px !important" />
+          <el-form-item label="专业领域:" prop="professional_field">
+            <el-input v-model="formData.professional_field" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="救援经历:" prop="rescue_experience">
-            <el-input v-model="formData.rescue_experience" style="width: 468px !important" />
+<!--          <el-form-item label="擅长事故类型:" prop="specialty">-->
+<!--            <el-input v-model="formData.specialty" style="width: 468px !important" />-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="救援经历:" prop="rescue_experience">-->
+<!--            <el-input v-model="formData.rescue_experience" style="width: 468px !important" />-->
+<!--          </el-form-item>-->
+          <el-form-item label="工作电话:" prop="work_phone">
+            <el-input v-model="formData.work_phone" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="出生日期:" prop="birthdate">
-            <el-input v-model="formData.birthdate" style="width: 468px !important" />
+          <el-form-item label="住宅电话:" prop="home_phone">
+            <el-input v-model="formData.home_phone" style="width: 468px !important" />
           </el-form-item>
-          <el-form-item label="工作日期:" prop="work_date">
-            <el-input v-model="formData.work_date" style="width: 468px !important" />
+          <el-form-item label="移动电话:" prop="mobile_phone">
+            <el-input v-model="formData.mobile_phone" style="width: 468px !important" />
+          </el-form-item>
+          <el-form-item label="电子邮箱:" prop="email">
+            <el-input v-model="formData.email" style="width: 468px !important" />
+          </el-form-item>
+          <el-form-item label="联系地址:" prop="contact_address">
+            <el-input v-model="formData.contact_address" style="width: 468px !important" />
           </el-form-item>
         </el-form>
         <div class="common-dialog-footer">
@@ -52,27 +73,46 @@
   </div>
 </template>
 <script setup lang="ts">
-import { ref, watch } from 'vue';
-const emits = defineEmits(['close']);
+import { getExpertInfo, updateExpertInfo } from '@/api/expert';
+
+const emits = defineEmits(['close', 'refresh']);
 const props = defineProps<{
-  eventId: string | number;
+  id: string | number;
 }>();
+const proxy = getCurrentInstance()?.proxy;
 const formData = ref({
-  name: '张xx',
-  county: '茂南',
-  expert_type: '安全工程',
-  position: '高级工程师',
-  unit: '茂名市应急管理局',
-  phone: '13800138000',
-  address: '茂名市茂南XX路XX号',
-  status: '在职',
-  accident_type: '火灾、爆炸',
-  rescue_experience: '参与过多次重大事故救援,经验丰富。',
-  birthdate: '1975-05-20',
-  work_date: '2000-01-01'
+  name: '',
+  county: '',
+  longitude: '',
+  latitude: '',
+  honorary_title: '',
+  professional_title: '',
+  unit: '',
+  expert_type: '',
+  rescue_experience: '',
+  position: '',
+  certificate_issue_date: '',
+  professional_group: '',
+  professional_field: '',
+  work_phone: '',
+  home_phone: '',
+  mobile_phone: '',
+  email: '',
+  contact_address: '',
+  specialty: ''
 });
 const closeDialog = () => {
   emits('close');
 };
+const submitForm = () => {
+  updateExpertInfo(props.id, formData.value).then(() => {
+    proxy?.$modal.msgSuccess('修改成功');
+    emits('refresh');
+  });
+};
+onMounted(() => {
+  getExpertInfo(props.id).then((res) => {
+    formData.value = res.data;
+  });
+});
 </script>
-<style scoped></style>

+ 59 - 121
src/views/comprehensiveGuarantee/emergencySpecialistManagement/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div v-show="!viewState.show" class="app-container">
+    <div v-show="!viewState.show && !editState.show" class="app-container">
       <div>
         <transition name="fade">
           <div v-show="showSearch">
@@ -8,52 +8,39 @@
               <el-row :gutter="20">
                 <el-col :span="6">
                   <el-form-item label="关键字搜索:" prop="center">
-                    <el-input v-model="queryParams.center" placeholder="请输入内容" clearable />
+                    <el-input v-model="queryParams.keyword" placeholder="请输入内容" clearable />
                   </el-form-item>
                 </el-col>
                 <el-col :span="6">
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                   <el-button icon="Refresh" @click="resetQuery">重置</el-button>
                 </el-col>
-                <el-col :span="12" style="text-align: right;">
+                <el-col :span="12" style="text-align: right">
                   <el-button type="primary" @click="exportExcel">导出excel</el-button>
                 </el-col>
               </el-row>
             </el-form>
-
           </div>
         </transition>
         <!-- 表格组件 -->
         <el-table ref="multipleTable" v-loading="loading" :data="tableData" style="width: 100%" :max-height="400">
-          <el-table-column label="序号" align="center" width="55" fixed="left">
-            <template #default="scope">
-              {{ (queryParams.page - 1) * queryParams.pageSize + scope.$index + 1 }}
-            </template>
-          </el-table-column>
           <el-table-column label="姓名" align="center" prop="name" width="100" fixed="left" />
-          <el-table-column label="荣誉称号" align="center" prop="" />
-          <el-table-column label="单位" align="center" prop="unit" />
-          <el-table-column label="职位" align="center" prop="position" />
-          <el-table-column label="职称" align="center" prop="" />
-          <el-table-column label="发证日期" align="center" prop="" />
-          <el-table-column label="专业分组" align="center" prop="" />
-          <el-table-column label="专业领域" align="center" prop="" />
-          <el-table-column label="工作电话" align="center" prop="phone" />
-          <el-table-column label="住宅电话" align="center" prop="phone" />
-          <el-table-column label="移动电话" align="center" prop="phone" />
-          <el-table-column label="电子邮箱" align="center" prop="" />
-          <el-table-column label="联系地址" align="center" prop="address" />
-          <el-table-column label="增量标识" align="center" prop="" />
-          <el-table-column label="增量时间" align="center" prop="" />
-          <el-table-column label="批次号" align="center" prop="" />
-          <el-table-column label="新增时间" align="center" prop="" />
-<!--          <el-table-column label="所属区县" align="center" prop="county" />-->
+          <el-table-column label="所属区县" align="center" prop="county" />
 <!--          <el-table-column label="专家类型" align="center" prop="expert_type" />-->
-<!--          <el-table-column label="状态" align="center" prop="status" />-->
-<!--          <el-table-column label="擅长事故类型" align="center" prop="accident_type" />-->
-<!--          <el-table-column label="救援经历" align="center" prop="rescue_experience" />-->
-<!--          <el-table-column label="出生日期" align="center" prop="birthdate" />-->
-<!--          <el-table-column label="工作日期" align="center" prop="work_date" />-->
+          <el-table-column label="荣誉称号" align="center" prop="honorary_title" />
+          <el-table-column label="工作单位" align="center" prop="unit" />
+          <el-table-column label="职务" align="center" prop="position" />
+          <el-table-column label="职称" align="center" prop="professional_title" />
+          <el-table-column label="发证日期" align="center" prop="certificate_issue_date" />
+          <el-table-column label="专业分组" align="center" prop="professional_group" />
+          <el-table-column label="专业领域" align="center" prop="professional_field" />
+<!--          <el-table-column label="擅长事故类型" align="center" prop="specialty" />-->
+          <el-table-column label="工作电话" align="center" prop="work_phone" />
+          <el-table-column label="住宅电话" align="center" prop="home_phone" />
+          <el-table-column label="移动电话" align="center" prop="mobile_phone" />
+          <el-table-column label="电子邮箱" align="center" prop="email" />
+          <el-table-column label="联系地址" align="center" prop="contact_address" />
+
           <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
             <template #default="scope">
               <el-text class="common-btn-text-primary" @click="handleView(scope.row)">查看</el-text>
@@ -109,14 +96,11 @@
         <Map :active-map="activeMap" :point-type="pointType" style="height: 600px" />
       </el-card>
     </div>
-    <View v-if="viewState.show" :event-id="viewState.eventId" @close="handleCancel" />
-    <Edit v-if="editState.show" :event-id="editState.eventId" @close="handleCancel" />
+    <View v-if="viewState.show" :id="viewState.eventId" @close="handleCancel" />
+    <Edit v-if="editState.show" :id="editState.eventId" @close="handleCancel" @refresh="handleRefresh" />
   </div>
 </template>
 <script setup lang="ts">
-import { onMounted, reactive, ref, toRefs } from 'vue';
-import { ElTable, ElTableColumn, ElForm, ElFormItem, ElInput, ElButton, ElText } from 'element-plus';
-import { ComponentInternalInstance, getCurrentInstance } from 'vue';
 import View from './view.vue';
 import Edit from './edit.vue';
 import { PatrolVO } from '@/views/inspectionWork/patrolTask.vue';
@@ -125,94 +109,43 @@ import Map from './Map.vue';
 import { PointType } from '@/api/globalMap/type';
 import { fillingTable } from '@/api/dataFilling/fillingManage';
 import { download2 } from '@/utils/request';
+import { getExpertList, getExpertProfessionalGroupCount } from '@/api/expert';
 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<PatrolVO[]>([]);
 const baseUrl = import.meta.env.VITE_APP_BASE_API;
-const filename = '专家信息表';
-const selectedRow = ref<PatrolVO | null>(null);
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const initFormData = reactive({
-  name: '',
-  county: '',
-  expert_type: '',
-  position: '',
-  unit: '',
-  phone: '',
-  address: '',
-  status: '',
-  accident_type: '',
-  rescue_experience: '',
-  birthdate: '',
-  work_date: ''
-});
 
 let activeMap = ref('satellite');
 let pointType = ref<PointType[]>([]);
-const data = reactive({
-  form: { ...initFormData },
-  queryParams: {
-    page: 1,
-    pageSize: 10
-  }
-});
 
-const { queryParams, form } = toRefs(data);
+const queryParams = reactive({
+  page: 1,
+  pageSize: 10,
+  keyword: ''
+});
 
-const fetchWorkrData = () => {
+const fetchData = () => {
   loading.value = true;
-  const mockData = [
-    {
-      id: 1,
-      name: '张三',
-      county: '茂南',
-      expert_type: '技术专家',
-      position: '工程师',
-      unit: '某科技公司',
-      phone: '13800000000',
-      address: '茂名市茂南XX路XX号',
-      status: '在线',
-      accident_type: '网络故障',
-      rescue_experience: '5年以上',
-      birthdate: '1990-01-01',
-      work_date: '2015-01-01'
-    },
-    {
-      id: 2,
-      name: '李四',
-      county: '高州',
-      expert_type: '安全专家',
-      position: '高级安全顾问',
-      unit: '某安全咨询公司',
-      phone: '13800000001',
-      address: '茂名市高州XX路XX号',
-      status: '离线',
-      accident_type: '安全事故',
-      rescue_experience: '10年以上',
-      birthdate: '1985-01-01',
-      work_date: '2010-01-01'
-    }
-  ];
-
-  tableData.value = mockData;
-  total.value = mockData.length;
-
-  loading.value = false;
+  getExpertList(queryParams)
+    .then((res) => {
+      tableData.value = res.data;
+      total.value = res.total;
+    })
+    .finally(() => {
+      loading.value = false;
+    });
 };
 
 const handleQuery = () => {
-  queryParams.value.page = 1;
-  fetchWorkrData();
+  queryParams.page = 1;
+  fetchData();
 };
 
 const resetQuery = () => {
-  queryParams.value = { page: 1, pageSize: 10 };
+  queryParams.page = 1;
+  queryParams.keyword = '';
   handleQuery();
 };
 let viewState = reactive({
@@ -223,21 +156,25 @@ let editState = reactive({
   show: false,
   eventId: ''
 });
-const handleView = () => {
-  // viewState.eventId = row.id;
+const handleView = (row) => {
+  viewState.eventId = row.id;
   viewState.show = true;
 };
-const handleUpdate = () => {
-  // editState.eventId = row.id;
+const handleUpdate = (row) => {
+  editState.eventId = row.id;
   editState.show = true;
 };
 const handleCancel = () => {
   viewState.show = false;
   editState.show = false;
 };
+const handleRefresh = () => {
+  editState.show = false;
+  fetchData();
+  initData();
+};
 const exportExcel = () => {
-  fillingTable(ids.value[0]);
-  download2(baseUrl + '/api/dataFilling/export_to_excel?report_id='+ids.value[0], filename + '.xlsx');
+  download2(baseUrl + '/api/expert/export', '应急专家信息表.xlsx');
 };
 let option1 = ref({
   grid: {
@@ -570,14 +507,9 @@ const initData = () => {
   option1.value.xAxis.data = ['茂南区', '电白区', '高州市', '化州市', '信宜市', '高新区', '滨海新区'];
   option1.value.series[0].data = [569, 251, 264, 187, 663, 649, 247];
   // 类型统计
-  // option2.value.legend.data = ['洪水灾害', '城市内涝', '地质灾害', '气象灾害', '生物灾害', '森林火灾'];
-  option2.value.series[0].data = [
-    { name: '自然灾害类', value: 50 },
-    { name: '事故灾害类', value: 69 },
-    { name: '公共卫生类', value: 9 },
-    { name: '社会安全类', value: 9 },
-    { name: '综合管理类', value: 5 }
-  ];
+  getExpertProfessionalGroupCount().then((res) => {
+    option2.value.series[0].data = res.data.list;
+  });
   // 年龄统计
   const data1 = [6, 6, 14, 23, 32];
   let max = 0;
@@ -612,7 +544,7 @@ const initData = () => {
   option4.value.series[1].data = maxData2;
 };
 onMounted(() => {
-  fetchWorkrData();
+  fetchData();
   initData();
 });
 </script>
@@ -629,4 +561,10 @@ onMounted(() => {
     width: calc(50% - 10px);
   }
 }
+:deep(.amap-info-content) {
+  padding: 0 !important;
+}
+:deep(.amap-info-close) {
+  display: none;
+}
 </style>

+ 129 - 38
src/views/comprehensiveGuarantee/emergencySpecialistManagement/view.vue

@@ -5,42 +5,105 @@
         <h3 class="common-dialog-title">查看详情</h3>
       </div>
       <div class="common-dialog-box">
-        <el-form ref="form" :model="formData" :rules="rules" label-width="120px">
+        <el-form ref="form" :model="formData" label-width="120px">
           <el-form-item label="姓名:" prop="name">
-            <el-input v-model="formData.name" style="width: 468px !important" disabled />
+            <el-input v-model="formData.name" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
           <el-form-item label="所属区县:" prop="county">
-            <el-input v-model="formData.county" style="width: 468px !important" disabled />
+            <el-input v-model="formData.county" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+          <el-form-item label="经度:" prop="longitude">
+            <el-input v-model="formData.longitude" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+          <el-form-item label="纬度:" prop="latitude">
+            <el-input v-model="formData.latitude" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
           <el-form-item label="专家类型:" prop="expert_type">
-            <el-input v-model="formData.expert_type" style="width: 468px !important" disabled />
+            <el-input v-model="formData.expert_type" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+<!--          <el-form-item label="救援经历:" prop="rescue_experience">-->
+<!--            <el-input-->
+<!--              v-model="formData.rescue_experience"-->
+<!--              type="textarea"-->
+<!--              autosize-->
+<!--              class="custom-disabled"-->
+<!--              style="width: 468px !important"-->
+<!--              disabled-->
+<!--            />-->
+<!--          </el-form-item>-->
+          <el-form-item label="荣誉称号:" prop="honorary_title">
+            <el-input v-model="formData.honorary_title" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+          <el-form-item label="工作单位:" prop="unit">
+            <el-input v-model="formData.unit" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
-          <el-form-item label="职位:" prop="position">
-            <el-input v-model="formData.position" style="width: 468px !important" disabled />
+          <el-form-item label="职:" prop="position">
+            <el-input v-model="formData.position" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
-          <el-form-item label="单位:" prop="unit">
-            <el-input v-model="formData.unit" style="width: 468px !important" disabled />
+          <el-form-item label="职称:" prop="professional_title">
+            <el-input
+              v-model="formData.professional_title"
+              type="textarea"
+              autosize
+              class="custom-disabled"
+              style="width: 468px !important"
+              disabled
+            />
           </el-form-item>
-          <el-form-item label="联系电话:" prop="phone">
-            <el-input v-model="formData.phone" style="width: 468px !important" disabled />
+          <el-form-item label="发证日期:" prop="certificate_issue_date">
+            <el-input
+              v-model="formData.certificate_issue_date"
+              type="textarea"
+              autosize
+              class="custom-disabled"
+              style="width: 468px !important"
+              disabled
+            />
           </el-form-item>
-          <el-form-item label="现在地址:" prop="address">
-            <el-input v-model="formData.address" style="width: 468px !important" disabled />
+          <el-form-item label="专业分组:" prop="professional_group">
+            <el-input
+              v-model="formData.professional_group"
+              type="textarea"
+              autosize
+              class="custom-disabled"
+              style="width: 468px !important"
+              disabled
+            />
           </el-form-item>
-          <el-form-item label="状态:" prop="status">
-            <el-input v-model="formData.status" style="width: 468px !important" disabled />
+          <el-form-item label="专业领域:" prop="professional_field">
+            <el-input
+              v-model="formData.professional_field"
+              type="textarea"
+              autosize
+              class="custom-disabled"
+              style="width: 468px !important"
+              disabled
+            />
           </el-form-item>
-          <el-form-item label="擅长事故类型:" prop="accident_type">
-            <el-input v-model="formData.accident_type" style="width: 468px !important" disabled />
+          <el-form-item label="擅长事故类型:" prop="specialty">
+            <el-input
+              v-model="formData.specialty"
+              type="textarea"
+              autosize
+              class="custom-disabled"
+              style="width: 468px !important"
+              disabled
+            />
           </el-form-item>
-          <el-form-item label="救援经历:" prop="rescue_experience">
-            <el-input v-model="formData.rescue_experience" style="width: 468px !important" disabled />
+          <el-form-item label="工作电话:" prop="work_phone">
+            <el-input v-model="formData.work_phone" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
-          <el-form-item label="出生日期:" prop="birthdate">
-            <el-input v-model="formData.birthdate" style="width: 468px !important" disabled />
+          <el-form-item label="住宅电话:" prop="home_phone">
+            <el-input v-model="formData.home_phone" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
-          <el-form-item label="工作日期:" prop="work_date">
-            <el-input v-model="formData.work_date" style="width: 468px !important" disabled />
+          <el-form-item label="移动电话:" prop="mobile_phone">
+            <el-input v-model="formData.mobile_phone" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+          <el-form-item label="电子邮箱:" prop="email">
+            <el-input v-model="formData.email" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
+          </el-form-item>
+          <el-form-item label="联系地址:" prop="contact_address">
+            <el-input v-model="formData.contact_address" type="textarea" autosize class="custom-disabled" style="width: 468px !important" disabled />
           </el-form-item>
         </el-form>
         <div class="common-dialog-footer">
@@ -52,32 +115,60 @@
 </template>
 
 <script setup lang="ts">
-import { ref, watch } from 'vue';
+import { getExpertInfo } from '@/api/expert';
 
 const emits = defineEmits(['close']);
 const props = defineProps<{
-  eventId: string | number;
+  id: string | number;
 }>();
 
-// 模拟的数据
 const formData = ref({
-  name: '张xx',
-  county: '茂南',
-  expert_type: '安全工程',
-  position: '高级工程师',
-  unit: '茂名市应急管理局',
-  phone: '13800138000',
-  address: '茂名市茂南XX路XX号',
-  status: '在职',
-  accident_type: '火灾、爆炸',
-  rescue_experience: '参与过多次重大事故救援,经验丰富。',
-  birthdate: '1975-05-20',
-  work_date: '2000-01-01'
+  name: '',
+  county: '',
+  longitude: '',
+  latitude: '',
+  honorary_title: '',
+  professional_title: '',
+  unit: '',
+  expert_type: '',
+  rescue_experience: '',
+  position: '',
+  certificate_issue_date: '',
+  professional_group: '',
+  professional_field: '',
+  work_phone: '',
+  home_phone: '',
+  mobile_phone: '',
+  email: '',
+  contact_address: '',
+  specialty: ''
 });
 
 const closeDialog = () => {
   emits('close');
 };
+onMounted(() => {
+  getExpertInfo(props.id).then((res) => {
+    formData.value = res.data;
+  });
+});
 </script>
 
-<style scoped></style>
+<style lang="scss" scoped>
+.custom-disabled {
+  :deep(.el-select__wrapper.is-disabled),
+  :deep(.el-input__wrapper),
+  :deep(.el-textarea__inner) {
+    background-color: #ffffff !important;
+  }
+  :deep(.el-select__wrapper.is-disabled .el-select__selected-item),
+  :deep(.el-input__inner),
+  :deep(.el-textarea__inner) {
+    color: rgba(0, 0, 0, 0.85) !important;
+    -webkit-text-fill-color: rgba(0, 0, 0, 0.85) !important;
+  }
+  :deep(.el-textarea__inner) {
+    resize: none !important;
+  }
+}
+</style>

+ 2 - 9
src/views/dataFilling/fillingAdd.vue

@@ -2,9 +2,9 @@
   <div class="app-container p-2">
     <el-row :gutter="20" class="mb8" style="margin-top: 5px">
       <el-col :span="1.5">
-        <el-upload class="upload-demo" :http-request="handleFileUpload" :before-upload="beforeUpload" :file-list="fileList" accept=".xlsx, .xls">
+        <el-upload class="upload-demo" :http-request="handleFileUpload" :file-list="fileList" accept=".xlsx, .xls">
           <template #trigger>
-            <el-button size="big" type="primary">选择Excel文件</el-button>
+            <el-button type="primary">选择Excel文件</el-button>
           </template>
         </el-upload>
       </el-col>
@@ -333,13 +333,6 @@ const hotSettings = reactive({
     }
   }
 });
-const beforeUpload = (file) => {
-  const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel';
-  if (!isExcel) {
-    proxy.$modal.msgError('只能上传xlsx/xls文件!');
-  }
-  return isExcel;
-};
 const handleFileUpload = ({ file }) => {
   const reader = new FileReader();
   reader.onload = (event) => {

+ 2 - 9
src/views/dataFilling/fillingIssued.vue

@@ -2,9 +2,9 @@
   <div class="app-container p-2">
     <el-row :gutter="20" class="mb8" style="margin-top: 5px">
       <el-col :span="1.5">
-        <el-upload class="upload-demo" :http-request="handleFileUpload" :before-upload="beforeUpload" :file-list="fileList" accept=".xlsx, .xls">
+        <el-upload class="upload-demo" :http-request="handleFileUpload" :file-list="fileList" accept=".xlsx, .xls">
           <template #trigger>
-            <el-button size="big" type="primary">选择Excel文件</el-button>
+            <el-button type="primary">选择Excel文件</el-button>
           </template>
         </el-upload>
       </el-col>
@@ -301,13 +301,6 @@ const hotSettings = reactive({
     }
   }
 });
-const beforeUpload = (file) => {
-  const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel';
-  if (!isExcel) {
-    proxy.$modal.msgError('只能上传xlsx/xls文件!');
-  }
-  return isExcel;
-};
 const handleFileUpload = ({ file }) => {
   const reader = new FileReader();
   reader.onload = (event) => {

+ 32 - 74
src/views/dataFilling/formDetail.vue

@@ -30,6 +30,7 @@ import { HotTable } from '@handsontable/vue3';
 import 'handsontable/languages';
 import 'handsontable/dist/handsontable.full.css';
 import { registerAllModules } from 'handsontable/registry';
+import { deepClone } from '@/utils';
 registerAllModules();
 
 const emits = defineEmits(['close']);
@@ -38,7 +39,7 @@ const props = defineProps<{
 }>();
 
 // 更新表头以匹配新的数据结构
-const editableHeaders = ref(['员工姓名', '员工性别', '加班小时', '新的备注', '新的地址']);
+const editableHeaders = ref([]);
 const tableData = ref([]);
 const hotData = ref([]);
 const detailData = ref({
@@ -46,28 +47,42 @@ const detailData = ref({
   start: '',
   end: ''
 });
-let tableHeight = window.innerHeight - 230
+let tableHeight = window.innerHeight - 230;
 
 const exportToExcel = () => {
-  const worksheet = XLSX.utils.json_to_sheet(tableData.value);
+  const data = deepClone(tableData.value);
+  data.unshift(editableHeaders.value);
+  const worksheet = XLSX.utils.aoa_to_sheet(data, {});
   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); // 清理
+  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+  XLSX.writeFile(workbook, '导出数据.xlsx');
 };
 
 const fetchFillDetail = async () => {
-  fillDetail({ report_id: props.eventId }).then((res) => {
+  fillDetail({ report_id: props.eventId }).then((res: any) => {
     detailData.value.start = res.start_time;
     detailData.value.end = res.end_time;
-    tableData.value = res.data;
-  })
+    const headers = [];
+    const data = [];
+    res.data.forEach((item, index) => {
+      let arr = [];
+      for (let key in item) {
+        if (item.hasOwnProperty(key)) {
+          const value = item[key];
+          if (index === 0) {
+            headers.push(value);
+          } else {
+            arr.push(value);
+          }
+        }
+      }
+      if (arr.length > 0) {
+        data.push(arr);
+      }
+    });
+    editableHeaders.value = headers;
+    tableData.value = data;
+  });
 };
 
 const handleReturn = () => {
@@ -76,8 +91,8 @@ const handleReturn = () => {
 
 const hotSettings = reactive({
   language: 'zh-CN',
+  colHeaders: editableHeaders,
   readOnly: true,
-  colHeaders: true,
   rowHeaders: true,
   autoColumnSize: true,
   width: '100%', // auto  or  100%
@@ -85,64 +100,7 @@ const hotSettings = reactive({
   licenseKey: 'non-commercial-and-evaluation', // 隐藏版权文字
   colWidths: 129, // 默认单元格宽度
   rowHeights: 28, // 默认单元格高度
-  wordWrap: true, // 单元格文字是否换行展示
-  contextMenu: {
-    // 自定义右键菜单
-    items: {
-      'row_above': {
-        name: '向上插一行'
-      },
-      'row_below': {
-        name: '向下插一行'
-      },
-      'col_left': {
-        name: '向左插一列'
-      },
-      'col_right': {
-        name: '向右插一列'
-      },
-      'hsep1': '---------', // 分隔线
-      'remove_row': {
-        name: '删除当前行'
-      },
-      'remove_col': {
-        name: '删除当前列'
-      },
-      'clear_column': {
-        name: '清空当前列'
-      },
-      'hsep2': '---------', // 必须和上次的变量名不一样
-      'undo': {
-        name: '撤销'
-      },
-      'cut': {
-        name: '剪切'
-      },
-      'copy': {
-        name: '复制'
-      },
-      // 'alignment': {
-      //   name: '对齐'
-      // },
-      // 'hsep3': '---------',
-      // 'commentsAddEdit': {
-      //   // 必须开启 comments: true
-      //   name: '添加备注'
-      // },
-      // 'commentsRemove': {
-      //   // 必须开启 comments: true
-      //   name: '删除备注'
-      // },
-      // 'freeze_column': {
-      //   // 必须开启 manualColumnFreeze: true
-      //   name: '固定列'
-      // },
-      // 'unfreeze_column': {
-      //   // 必须开启 manualColumnFreeze: true
-      //   name: '取消固定列'
-      // }
-    }
-  }
+  wordWrap: true // 单元格文字是否换行展示
 });
 onMounted(() => {
   fetchFillDetail();

+ 7 - 1
src/views/dataFilling/myFilling.vue

@@ -72,7 +72,13 @@
             </template>
           </el-table-column>
         </el-table>
-        <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="fetchFillList" />
+        <pagination
+          v-show="total > 0"
+          v-model:page="queryParams.page"
+          v-model:limit="queryParams.pageSize"
+          :total="total"
+          @pagination="fetchFillList"
+        />
       </div>
     </div>
     <WriteForm v-if="writeFormState.show" :event-id="writeFormState.eventId" @refresh="fetchFillList" @close="handleCancel" />

+ 93 - 73
src/views/dataFilling/tableDetails.vue

@@ -2,58 +2,85 @@
   <div class="app-container p-2">
     <el-row :gutter="20">
       <el-row :gutter="20" class="mb8">
-        <el-col :span="1.5">
-          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleImportExcel">导入Excel文件</el-button>
+        <el-col v-if="reportInfo.issued_status === 1" :span="1.5">
+          <el-button type="primary" @click="handleImportExcel">导入Excel文件</el-button>
         </el-col>
-        <el-col :span="1.5">
-          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleNewTemplate">空白模板</el-button>
+        <el-col v-if="reportInfo.issued_status === 1" :span="1.5">
+          <el-button type="primary" @click="handleNewTemplate">空白模板</el-button>
         </el-col>
-        <el-col :span="1.5">
-          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleReload">重新加载</el-button>
+        <el-col v-if="reportInfo.issued_status === 1" :span="1.5">
+          <el-button type="primary" @click="handleReload">重新加载</el-button>
         </el-col>
-<!--        <el-col :span="1.5">-->
-<!--          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleReport()">智能识别</el-button>-->
-<!--        </el-col>-->
-        <el-col :span="1.5">
-          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleSaveTemporarily(1)">暂存</el-button>
+        <!--        <el-col :span="1.5">-->
+        <!--          <el-button v-if="reportInfo.issued_status === 0" type="primary" @click="handleReport()">智能识别</el-button>-->
+        <!--        </el-col>-->
+        <el-col v-if="reportInfo.issued_status === 1" :span="1.5">
+          <el-button type="primary" @click="handleSaveTemporarily(1)">暂存</el-button>
         </el-col>
-<!--        <el-col :span="1.5">-->
-<!--          <el-button v-if="reportInfo.issued_status === 2" type="primary" @click="handleData()">数据</el-button>-->
-<!--        </el-col>-->
-        <el-col :span="1.5">
-          <el-button v-if="is_filling_ended === 0" type="primary" @click="handleSave(formRef, 2)">发布</el-button>
+        <!--        <el-col :span="1.5">-->
+        <!--          <el-button v-if="reportInfo.issued_status === 2" type="primary" @click="handleData()">数据</el-button>-->
+        <!--        </el-col>-->
+        <el-col v-if="reportInfo.issued_status === 1" :span="1.5">
+          <el-button type="primary" @click="handleSave(formRef, 2)">发布</el-button>
         </el-col>
         <el-col :span="1.5">
           <el-button type="danger" @click="handleReturn()">返回</el-button>
         </el-col>
       </el-row>
     </el-row>
-    <el-form :model="reportInfo" :rules="rules" ref="formRef" style="margin-top: 20px">
+    <el-form ref="formRef" :model="reportInfo" :rules="rules" style="margin-top: 20px">
       <el-row :gutter="20">
         <el-col :lg="30" :xs="24" style="margin-top: -10px">
           <el-row :span="24" :gutter="10">
             <!-- 联系人姓名 -->
             <el-col :span="8">
               <el-form-item label="联系人姓名:" prop="creator_name" label-width="auto">
-                <el-input v-model="reportInfo.creator_name" placeholder="请输入联系人姓名" style="width: 300px"></el-input>
+                <el-input
+                  v-model="reportInfo.creator_name"
+                  placeholder="请输入联系人姓名"
+                  :disabled="reportInfo.issued_status === 2"
+                  :class="{ 'custom-disabled': reportInfo.issued_status === 2 }"
+                  style="width: 300px"
+                />
               </el-form-item>
             </el-col>
             <!-- 联系电话 -->
             <el-col :span="8">
               <el-form-item label="联&nbsp系&nbsp电&nbsp话:" prop="creator_phone" label-width="auto">
-                <el-input v-model="reportInfo.creator_phone" placeholder="请输入联系电话" style="width: 300px"></el-input>
+                <el-input
+                  v-model="reportInfo.creator_phone"
+                  placeholder="请输入联系电话"
+                  :disabled="reportInfo.issued_status === 2"
+                  :class="{ 'custom-disabled': reportInfo.issued_status === 2 }"
+                  style="width: 300px"
+                />
               </el-form-item>
             </el-col>
             <!-- 截止时间 -->
             <el-col :span="8">
               <el-form-item label="截&nbsp止&nbsp时&nbsp间&nbsp:" prop="end_time">
-                <el-date-picker v-model="reportInfo.end_time" value-format="YYYY-MM-DD HH:mm:ss" time-format="HH:mm" type="datetime" placeholder="选择截止时间" style="width: 300px" @change="handleTimeChange" />
+                <el-date-picker
+                  v-model="reportInfo.end_time"
+                  value-format="YYYY-MM-DD HH:mm:ss"
+                  time-format="HH:mm"
+                  type="datetime"
+                  placeholder="选择截止时间"
+                  :disabled="reportInfo.issued_status === 2"
+                  :class="{ 'custom-disabled': reportInfo.issued_status === 2 }"
+                  style="width: 300px"
+                />
               </el-form-item>
             </el-col>
             <!-- 操作按钮 -->
             <el-col :span="8">
               <el-form-item label="表&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp名:" prop="table_name" label-width="auto">
-                <el-input v-model="reportInfo.table_name" placeholder="请输入表名" style="width: 300px"></el-input>
+                <el-input
+                  v-model="reportInfo.table_name"
+                  placeholder="请输入表名"
+                  :disabled="reportInfo.issued_status === 2"
+                  :class="{ 'custom-disabled': reportInfo.issued_status === 2 }"
+                  style="width: 300px"
+                />
               </el-form-item>
             </el-col>
             <!-- 选择填报人 -->
@@ -64,21 +91,21 @@
                     <el-tag
                       v-for="tag in selectedReporter"
                       :key="tag"
-                      closable
+                      :closable="reportInfo.issued_status !== 2"
                       :disable-transitions="false"
-                      @close="handleClose(tag)"
                       style="margin-right: 10px"
+                      @close="handleClose(tag)"
                     >
                       {{ tag.label }}
                     </el-tag>
                   </div>
-                  <el-button @click="showSelect">点击选择</el-button>
+                  <el-button v-if="reportInfo.issued_status !== 2" @click="showSelect">点击选择</el-button>
                 </el-form-item>
               </el-form-item>
             </el-col>
-            <el-col :span="8" v-if="reportInfo.issued_status === 2">
+            <el-col v-if="reportInfo.issued_status === 2" :span="8">
               <el-form-item>
-                应填报{{reportInfo.num_reporters}}人,已填报{{reportInfo.num_reported}}人,未填报{{reportInfo.num_unreported}}人
+                应填报{{ reportInfo.num_reporters }}人,已填报{{ reportInfo.num_reported }}人,未填报{{ reportInfo.num_unreported }}人
                 <el-text class="common-btn-text-primary" @click="viewSituation">完成情况</el-text>
               </el-form-item>
             </el-col>
@@ -114,9 +141,7 @@ import { HotTable } from '@handsontable/vue3';
 import { getPhoneList } from '@/api/informationissue/informationissue';
 import informantSelect from './informantSelect.vue';
 import { deepClone } from '@/utils';
-import { ElButton, ElCol, ElDatePicker, ElFormItem, ElInput, ElRow } from 'element-plus';
 import { validatePhone } from '@/utils/validate';
-import { ref } from 'vue';
 
 const { proxy } = getCurrentInstance();
 const isShowSelect = ref(false);
@@ -153,11 +178,9 @@ const rules = {
     { required: true, message: '联系电话不能为空', trigger: 'blur' },
     { validator: validatePhone, message: '请输入正确格式的联系电话', trigger: 'blur' }
   ],
-  user_ids: [{ required: true, message: '请选择填报人', trigger: 'blur' }],
-}
-const is_filling_ended = ref(0);
+  user_ids: [{ required: true, message: '请选择填报人', trigger: 'blur' }]
+};
 const selectedReporter = ref(null);
-const router = useRouter();
 const personNum = ref();
 
 const props = defineProps({
@@ -182,21 +205,23 @@ onMounted(async () => {
 const fetchReportDetails = (reportId) => {
   return fillingList(reportId).then((res: any) => {
     reportInfo.value = res.report_info;
+    hotSettings.readOnly = reportInfo.value.issued_status === 2;
     reportInfo.value.user_filling_status = res.report_info.user_filling_status;
-    personNum.value = reportInfo.value.user_ids.length;  //统计需要填报的总人数
+    personNum.value = reportInfo.value.user_ids.length; //统计需要填报的总人数
     let headers = [];
-    if (!res.table_data["0"]) {
+    if (!res.table_data[0]) {
       return;
     } else {
-      headers = Object.keys(res.table_data["0"]);
+      headers = Object.keys(res.table_data[0]);
     }
-    const result = [
-      headers.map(header => res.table_data["0"][header])
-    ];
+    const result = res.table_data.map(row =>
+      headers.map(header => row[header])
+    );
+    debugger
     hotData.value = result;
     nextTick(() => {
       showTable.value = true;
-    })
+    });
   });
 };
 
@@ -231,10 +256,6 @@ const handleContactSelectData = (data) => {
   reportInfo.value.user_ids = data1;
 };
 
-function saveEdit(rowIndex, header, value) {
-  hotData.value[rowIndex][header] = value;
-}
-
 const hotData = ref([]);
 const showTable = ref(false);
 const handleNewTemplate = () => {
@@ -260,6 +281,7 @@ const created = () => {
 };
 const hotSettings = reactive({
   language: 'zh-CN',
+  readOnly: false,
   colHeaders: true,
   rowHeaders: true,
   autoColumnSize: true,
@@ -303,7 +325,7 @@ const hotSettings = reactive({
       },
       'copy': {
         name: '复制'
-      },
+      }
       // 'alignment': {
       //   name: '对齐'
       // },
@@ -345,7 +367,7 @@ const handleImportExcel = () => {
       hotData.value = jsonData.splice(0, 1); // 只要第一行
       nextTick(() => {
         showTable.value = true;
-      })
+      });
       // reportInfo.value.field_names = XLSX.utils.sheet_to_json(worksheet);
       // alert('Excel文件已导入');
     };
@@ -366,19 +388,11 @@ const handleSaveTemporarily = async (statuCode) => {
       if (!!item) {
         data2.push(item);
       }
-    })
+    });
     reportInfo.value.field_names = hotData.value;
   }
 
   reportInfo.value.issued_status = statuCode;
-  let tempHead = [];
-  if (!reportInfo.value.field_names) {
-    tempHead = [];
-  } else {
-    tempHead = reportInfo.value.field_names.flatMap(obj =>
-      Object.values(obj).filter(value => typeof value === "string")
-    );
-  }
 
   let data = {
     creator_name: reportInfo.value.creator_name,
@@ -387,18 +401,15 @@ const handleSaveTemporarily = async (statuCode) => {
     status: reportInfo.value.issued_status,
     period_type: reportInfo.value.period_type,
     end_time: reportInfo.value.end_time,
-    new_fields: tempHead,
+    new_fields: reportInfo.value.field_names[0],
     user_ids: reportInfo.value.user_ids
-  }
+  };
   fillingChange(reportId.value, data).then(() => {
     proxy.$modal.msgSuccess('暂存成功');
     emits('close');
   });
 };
 
-const handleReport = () => console.log('上报');
-
-
 const handleSave = async (formEl, statuCode) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
@@ -413,13 +424,11 @@ const handleSave = async (formEl, statuCode) => {
           if (!!item) {
             data2.push(item);
           }
-        })
-      };
+        });
+      }
       reportInfo.value.field_names = data2;
       // reportInfo.value.field_names = hotData.value;
-      const tempHead = reportInfo.value.field_names.flatMap(obj =>
-        Object.values(obj).filter(value => typeof value === "string")
-      );
+      const tempHead = reportInfo.value.field_names.flatMap((obj) => Object.values(obj).filter((value) => typeof value === 'string'));
       let data = {
         table_name: reportInfo.value.table_name,
         issued_status: reportInfo.value.issued_status,
@@ -430,7 +439,7 @@ const handleSave = async (formEl, statuCode) => {
         creator_phone: reportInfo.value.creator_phone,
         status: reportInfo.value.status,
         user_ids: reportInfo.value.user_ids
-      }
+      };
       fillingChange(reportId.value, data).then(() => {
         proxy.$modal.msgSuccess('发布成功');
         emits('close');
@@ -456,11 +465,6 @@ const handleReturn = () => {
   emits('close');
 };
 
-const handleData = () => {
-  // 跳转到数据档案管理-详情页
-  router.push({ name: 'DataArchiveDetail', params: { reportId: reportInfo.value.report_id } });
-};
-
 function findNodeById(data, targetId) {
   for (const node of data) {
     if ((node.id === targetId || node.id.toString() === targetId) && !node.deptType) {
@@ -476,7 +480,7 @@ function findNodeById(data, targetId) {
 const popUp = ref(false);
 const viewSituation = () => {
   popUp.value = true;
-}
+};
 const handleDialogClose = () => {
   popUp.value = false;
 };
@@ -484,12 +488,28 @@ const handleDialogClose = () => {
 
 <style lang="scss" scoped>
 .unreported {
-  color: #F56C6C;
+  color: #f56c6c;
   font-weight: bold;
 }
 
 .reported {
-  color: #67C23A;
+  color: #67c23a;
   font-weight: bold;
 }
+.custom-disabled {
+  :deep(.el-input.is-disabled) {
+    .el-input__wrapper {
+      background-color: #ffffff !important;
+    }
+  }
+  :deep(.el-select__wrapper.is-disabled),
+  :deep(.el-input__wrapper) {
+    background-color: #ffffff !important;
+  }
+  :deep(.el-select__wrapper.is-disabled .el-select__selected-item),
+  :deep(.el-input__inner) {
+    color: rgba(0, 0, 0, 0.85) !important;
+    -webkit-text-fill-color: rgba(0, 0, 0, 0.85) !important;
+  }
+}
 </style>

+ 61 - 105
src/views/dataFilling/writeForm.vue

@@ -23,10 +23,10 @@
       </el-col>
       <el-row :gutter="10" class="mb8">
         <el-col :span="1.5">
-<!--          <el-button type="primary" @click="handleAdd">导入</el-button>-->
-          <el-upload class="upload-demo" :http-request="handleAdd" :before-upload="beforeUpload" accept=".xlsx, .xls">
+          <!--          <el-button type="primary" @click="handleAdd">导入</el-button>-->
+          <el-upload class="upload-demo" :http-request="handleAdd" accept=".xlsx, .xls">
             <template #trigger>
-              <el-button size="big" type="primary">导入</el-button>
+              <el-button type="primary">导入</el-button>
             </template>
           </el-upload>
         </el-col>
@@ -41,12 +41,6 @@
         <div :style="{ height: tableHeight + 'px' }">
           <hot-table ref="wrapper" :data="tableData" :settings="hotSettings" />
         </div>
-<!--        <div  :style="{ height: tableHeight + 'px' }" style="height: 400px">-->
-<!--          <hot-table :settings="hotSettings">-->
-<!--            <hot-column v-for="item in editableHeaders" :title="item.field_comment">-->
-<!--            </hot-column>-->
-<!--          </hot-table>-->
-<!--        </div>-->
       </el-col>
     </el-row>
   </div>
@@ -54,14 +48,11 @@
 
 <script setup lang="ts">
 import * as XLSX from 'xlsx';
-import { writeView, submitFill } from '@/api/dataFilling/datafilling';
-import { HotTable, HotColumn } from '@handsontable/vue3';
+import { writeView, submitFill, dataFillingSaveData } from '@/api/dataFilling/datafilling';
+import { HotTable } from '@handsontable/vue3';
 import 'handsontable/languages';
 import 'handsontable/dist/handsontable.full.css';
 import { registerAllModules } from 'handsontable/registry';
-import { ElButton } from 'element-plus';
-import { ref } from 'vue';
-import { fillingReport } from '@/api/dataFilling/fillingManage';
 registerAllModules();
 
 const props = defineProps({
@@ -70,11 +61,11 @@ const props = defineProps({
 
 const emits = defineEmits(['close', 'refresh']);
 let wrapper = ref();
-let tableHeight = window.innerHeight - 230
+let tableHeight = window.innerHeight - 230;
 const detailData = ref({
-  title: '表单数据',
-  start: '2024-10-15 17:02:22',
-  end: '2024-10-15 18:00:00'
+  title: '',
+  start: '',
+  end: ''
 });
 
 const fileList = ref([]);
@@ -84,7 +75,7 @@ const tableData = ref<any[]>([]);
 const headerMapping = ref<{ [key: string]: string }>({});
 const fields = ref([]);
 // 获取表头数据
-const fetchHeaders = async () => {
+const fetchDetails = async () => {
   const response = await writeView({ report_id: props.eventId });
   fields.value = response.fields;
   const headers = response.fields.map((field) => field.field_comment);
@@ -95,24 +86,23 @@ const fetchHeaders = async () => {
 
   // tableData.value = response.tableData;
   //如果tableData是空就用下满这段,tableData有数据就用tableData的内容
-  if (!response.tableData || response.tableData.length === 0) {
+  if (!response.data || response.data.length === 0) {
     headers.forEach((item) => {
       arr1.push('');
       arr2.push('');
       arr3.push('');
-    })
-    tableData.value = [arr1, arr2 ,arr3];
-    wrapper.value.hotInstance.loadData([arr1, arr2 ,arr3]);
+    });
+    tableData.value = [arr1, arr2, arr3];
+    wrapper.value.hotInstance.loadData([arr1, arr2, arr3]);
   } else {
-    tableData.value = response.tableData
-    wrapper.value.hotInstance.loadData(response.tableData);
+    tableData.value = response.data;
+    wrapper.value.hotInstance.loadData(response.data);
   }
 
-      // 填充映射
-      // response.fields.forEach(field => {
-      //   headerMapping.value[field.field_comment] = field.field_name;
-      // });
-
+  // 填充映射
+  // response.fields.forEach(field => {
+  //   headerMapping.value[field.field_comment] = field.field_name;
+  // });
 };
 
 const addDefaultRow = () => {
@@ -123,17 +113,6 @@ const addDefaultRow = () => {
   tableData.value.push(newRow);
 };
 
-const saveEdit = (rowIndex, header, value) => {
-  tableData.value[rowIndex][header] = value;
-};
-
-const saveHeader = (header, newValue) => {
-  const index = editableHeaders.value.indexOf(header);
-  if (index !== -1) {
-    editableHeaders.value.splice(index, 1, newValue);
-  }
-};
-
 const exportToExcel = () => {
   let resultList = [];
   resultList.push(editableHeaders.value);
@@ -142,23 +121,15 @@ const exportToExcel = () => {
   // })
   tableData.value.forEach((item) => {
     resultList.push(item);
-  })
+  });
 
   const worksheet = XLSX.utils.aoa_to_sheet(resultList);
   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); // 清理
+  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+  XLSX.writeFile(workbook, '导出数据.xlsx');
 };
 
-const handleAdd = ({file}) => {
-
+const handleAdd = ({ file }) => {
   const reader = new FileReader();
   reader.onload = (event) => {
     nextTick(() => {
@@ -167,7 +138,16 @@ const handleAdd = ({file}) => {
       const firstSheetName = workbook.SheetNames[0];
       const worksheet = workbook.Sheets[firstSheetName];
       const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
-      tableData.value = jsonData.slice(1); // 假设第一行是标题行,我们跳过它
+      const newData = jsonData.slice(1); // 假设第一行是标题行,我们跳过它
+      newData.forEach((item: any) => {
+        if (item.length < editableHeaders.value.length) {
+          const len = editableHeaders.value.length - item.length;
+          for (let i = 0; i < len; i++) {
+            item.push('');
+          }
+        }
+      });
+      tableData.value = jsonData.slice(1);
       wrapper.value.hotInstance.loadData(tableData.value);
     });
   };
@@ -175,37 +155,44 @@ const handleAdd = ({file}) => {
   fileList.value = [];
   return { success: true, file };
 };
-const beforeUpload = (file) => {
-  const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel';
-  if (!isExcel) {
-    proxy.$modal.msgError('只能上传xlsx/xls文件!');
-  }
-  return isExcel;
-};
 
-const handleDownloadEmptyTable = () => console.log('下载空表格');
+const handleDownloadEmptyTable = () => {
+  const worksheet = XLSX.utils.aoa_to_sheet([editableHeaders.value], {});
+  const workbook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
+  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+  XLSX.writeFile(workbook, '空表格.xlsx');
+};
 const handleAddRow = () => {
   wrapper.value.hotInstance.alter('insert_row_below', wrapper.value.hotInstance.countRows()); // 在末尾插入空行
-}
+};
 const handleSave = () => {
-
-
-
-  // localStorage.setItem('tableData', JSON.stringify(tableData.value));
-  // alert('数据已保存');
+  const data = [];
+  tableData.value.forEach((arr) => {
+    let obj = {};
+    arr.forEach((item, index) => {
+      if (fields.value[index] && fields.value[index].field_name) {
+        obj[fields.value[index].field_name] = item;
+      }
+    });
+    data.push(obj);
+  });
+  dataFillingSaveData({ report_id: props.eventId, data: data }).then(() => {
+    proxy.$modal.msgSuccess('保存成功');
+    emits('refresh');
+    emits('close');
+  });
 };
 const handleReturn = () => {
   emits('close');
 };
 
-
 const handleReport = async () => {
-  const keyArr = []
+  const keyArr = [];
   for (let obj of fields.value) {
-   keyArr.push(obj.field_name)
+    keyArr.push(obj.field_name);
   }
   const dataTemp = [];
-  for (let i =0; i< tableData.value.length; i++) {
+  for (let i = 0; i < tableData.value.length; i++) {
     let objectTemp = {};
     for (let j = 0; j < tableData.value[i].length; j++) {
       let temp = keyArr[j];
@@ -218,16 +205,14 @@ const handleReport = async () => {
     emits('close');
     emits('refresh');
   });
-
 };
 // 组件挂载时调用
 onMounted(() => {
-  fetchHeaders();
+  fetchDetails();
   addDefaultRow();
 });
 
 const hotSettings = reactive({
-  data: [['1','2']],
   language: 'zh-CN',
   colHeaders: editableHeaders,
   rowHeaders: true,
@@ -247,19 +232,10 @@ const hotSettings = reactive({
       'row_below': {
         name: '向下插一行'
       },
-      'col_left': {
-        name: '向左插一列'
-      },
-      'col_right': {
-        name: '向右插一列'
-      },
       'hsep1': '---------', // 分隔线
       'remove_row': {
         name: '删除当前行'
       },
-      'remove_col': {
-        name: '删除当前列'
-      },
       'clear_column': {
         name: '清空当前列'
       },
@@ -272,27 +248,7 @@ const hotSettings = reactive({
       },
       'copy': {
         name: '复制'
-      },
-      // 'alignment': {
-      //   name: '对齐'
-      // },
-      // 'hsep3': '---------',
-      // 'commentsAddEdit': {
-      //   // 必须开启 comments: true
-      //   name: '添加备注'
-      // },
-      // 'commentsRemove': {
-      //   // 必须开启 comments: true
-      //   name: '删除备注'
-      // },
-      // 'freeze_column': {
-      //   // 必须开启 manualColumnFreeze: true
-      //   name: '固定列'
-      // },
-      // 'unfreeze_column': {
-      //   // 必须开启 manualColumnFreeze: true
-      //   name: '取消固定列'
-      // }
+      }
     }
   }
 });