Browse Source

填报管理

yangyuxuan 2 months ago
parent
commit
a0ed98d35d
3 changed files with 206 additions and 151 deletions
  1. 0 29
      src/types/components.d.ts
  2. 5 22
      src/views/dataFilling/informantSelect.vue
  3. 201 100
      src/views/dataFilling/tableDetails.vue

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

@@ -24,24 +24,14 @@ declare module 'vue' {
     DistributionMap: typeof import('./../components/Map/YztMap/DistributionMap.vue')['default']
     DrawMap: typeof import('./../components/Map/YztMap/DrawMap.vue')['default']
     Editor: typeof import('./../components/Editor/index.vue')['default']
-    ElAnchor: typeof import('element-plus/es')['ElAnchor']
-    ElAnchorLink: typeof import('element-plus/es')['ElAnchorLink']
     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']
-    ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
-    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']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -51,45 +41,29 @@ 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']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
-    ElTabPane: typeof import('element-plus/es')['ElTabPane']
-    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
-    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']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     ExcelEditor: typeof import('./../components/ExcelEditor/index.vue')['default']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
@@ -101,9 +75,6 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
-    IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
-    IEpCaretTop: typeof import('~icons/ep/caret-top')['default']
-    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']

+ 5 - 22
src/views/dataFilling/informantSelect.vue

@@ -1,21 +1,3 @@
-<!--<template>-->
-<!--  <div class="common-dialog">-->
-<!--    选择填报人-->
-<!--  </div>-->
-
-
-<!--</template>-->
-
-<!--<script setup lang="ts">-->
-
-<!--</script>-->
-
-
-
-<!--<style scoped lang="scss">-->
-
-<!--</style>-->
-
 <template>
   <el-dialog v-model="visible" title="选择消息接收人" width="780px" append-to-body @close="closeDialog">
     <div class="container">
@@ -70,7 +52,6 @@
 import { deepClone } from '@/utils/index';
 import userImg from '@/assets/images/user.png';
 import fileImg from '@/assets/images/file.png';
-import { getPhoneList} from '@/api/informationissue/informationissue';
 const props = defineProps({
   modelValue: Boolean,
   treeData: Array,
@@ -99,10 +80,12 @@ const initData = () => {
 watch(
   () => props.modelValue,
   () => {
-    if (!!props.modelValue) {
-      initData();
-    }
     visible.value = props.modelValue;
+    nextTick(() => {
+      if (!!props.modelValue) {
+        initData();
+      }
+    })
   },
   {
     immediate: true

+ 201 - 100
src/views/dataFilling/tableDetails.vue

@@ -1,76 +1,91 @@
 <template>
   <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>
+        <el-col :span="1.5">
+          <el-button v-if="is_filling_ended === 0" 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>
+<!--        <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()">暂存</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button v-if="is_filling_ended === 0" 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()">发布</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button type="danger" @click="handleReturn()">返回</el-button>
+        </el-col>
+      </el-row>
       <el-col :lg="30" :xs="24" style="">
         <el-row :span="24" :gutter="10">
-          <el-col :span="6">
+          <el-col :span="8">
             <el-form-item label="联系人姓名:" prop="creator_name" label-width="auto">
               <div>{{ reportInfo.creator_name }}</div>
             </el-form-item>
           </el-col>
-          <el-col :span="6">
+          <el-col :span="8">
             <el-form-item label="联系电话:" prop="creator_phone" label-width="auto">
               <div>{{ reportInfo.creator_phone }}</div>
             </el-form-item>
           </el-col>
-          <el-col :span="6">
-            <el-form-item label="选择填报人:" prop="people_name" label-width="auto">
-              <el-select v-model="selectedReporter" placeholder="请选择填报人">
-                <el-option v-for="reporter in reporters" :key="reporter.id" :label="reporter.name" :value="reporter.id" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
+          <el-col :span="8">
             <el-form-item label="截止时间:" prop="release_time">
               <div>{{ reportInfo.end_time }}</div>
               <span class="label">前报送该表</span>
             </el-form-item>
           </el-col>
-          <el-col :span="6">
+          <el-col :span="8">
             <el-form-item label="表名:" prop="table_name" label-width="auto">
               <div>{{ reportInfo.table_name }}</div>
             </el-form-item>
           </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="isBeforeDeadline" type="primary" @click="handleReport()">智能识别</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="isBeforeDeadline" type="primary" @click="handleSaveTemporarily()">暂存</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="!isBeforeDeadline" type="primary" @click="handleData()">数据</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="isBeforeDeadline" type="primary" @click="handleSave()">发布</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" @click="handleReturn()">返回</el-button>
+          <el-col :span="8">
+            <el-form-item label="" prop="people_name" label-width="auto">
+<!--              <el-select v-model="selectedReporter" placeholder="请选择填报人">-->
+<!--                <el-option v-for="reporter in reporters" :key="reporter.id" :label="reporter.name" :value="reporter.id" />-->
+<!--              </el-select>-->
+              <el-form-item label="选择填报人:" prop="user_ids" label-width="auto" style="font-weight: bold;">
+                <div>
+                  <el-tag
+                    v-for="tag in selectedReporter"
+                    :key="tag"
+                    closable
+                    :disable-transitions="false"
+                    @close="handleClose(tag)"
+                    style="margin-right: 10px"
+                  >
+                    {{ tag.label }}
+                  </el-tag>
+                </div>
+                <el-button @click="showSelect">点击选择</el-button>
+              </el-form-item>
+            </el-form-item>
           </el-col>
+
         </el-row>
       </el-col>
-      <el-row :gutter="20" class="mb8">
-        <el-col :span="1.5">
-          <el-button v-if="isBeforeDeadline" type="primary" @click="handleImportExcel">导入Excel文件</el-button>
-        </el-col>
-        <el-col :span="1.5">
-          <el-button v-if="isBeforeDeadline" type="primary" @click="handleNewTemplate">空白模板</el-button>
-        </el-col>
-        <el-col :span="1.5">
-          <el-button v-if="isBeforeDeadline" type="primary" @click="handleReload">重新加载</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 #default="{ row, $index }">
-              <el-input v-model="row[header]" @blur="saveEdit($index, header, row[header])" />
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-col>
     </el-row>
   </div>
+  <div style="height: 350px">
+    <hot-table v-if="tableData && tableData.length > 0" ref="wrapper" :data="tableData" :settings="hotSettings" />
+    <hot-table v-if="isShowTable" ref="wrapper" :data="hotData" :settings="hotSettings" />
+  </div>
+  <informantSelect
+    v-model="isShowSelect"
+    :tree-data="treeData"
+    :default-check-data="reportInfo.user_ids"
+    @confirm="handleContactSelectData"  />
 </template>
 
 <script setup lang="ts">
@@ -79,7 +94,12 @@ import { ElButton, ElCol, ElFormItem, ElInput, ElOption, ElRow, ElSelect, ElTabl
 import * as XLSX from 'xlsx';
 import { fillingList } from '@/api/dataFilling/fillingManage';
 import { useRoute, useRouter } from 'vue-router';
+import { HotTable } from '@handsontable/vue3';
+import { getPhoneList } from '@/api/informationissue/informationissue';
+import informantSelect from './informantSelect.vue'
 
+const isShowSelect = ref(false);
+let treeData = ref([]);
 const emits = defineEmits(['close']);
 const reportInfo = ref({
   id: 0,
@@ -98,13 +118,12 @@ const reportInfo = ref({
   created_at: '',
   updated_at: '',
   num_reported: 0,
-  num_unreported: 0
+  num_unreported: 0,
+  user_ids:[]
 });
-const tableStructure = ref([]);
-const editableHeaders = ref([]);
+const is_filling_ended = ref(0);
 const tableData = ref([]);
 const selectedReporter = ref(null);
-const reporters = ref([]);
 const route = useRoute();
 const router = useRouter();
 
@@ -113,12 +132,6 @@ const props = defineProps({
 });
 const reportId = ref(props.eventId);
 
-// 计算属性来判断是否在截止时间之前
-const isBeforeDeadline = computed(() => {
-  const deadline = new Date(reportInfo.value.end_time);
-  return new Date() < deadline;
-});
-
 watch(reportId, async (newVal) => {
   if (newVal) {
     await fetchReportDetails(newVal);
@@ -127,54 +140,149 @@ watch(reportId, async (newVal) => {
 
 // 初始化表格数据
 onMounted(async () => {
+  fetchTreeData();
+  created();
   if (reportId.value) {
     await fetchReportDetails(reportId.value);
   }
 });
 
-const fetchReportDetails = async (reportId) => {
-  try {
-    const response = await fillingList(reportId);
-    console.log('接口返回的数据:', response);
-    if (response.code === 200) {
-      reportInfo.value = {
-        ...response.report_info
-      };
-      tableStructure.value = response.table_structure;
-      editableHeaders.value = ['序号', ...response.table_structure.map((item) => item.comment)];
-      tableData.value = Array.from({ length: 10 }, (v, k) => ({
-        序号: k + 1,
-        ...response.table_structure.reduce((acc, item) => {
-          acc[item.comment] = '';
-          return acc;
-        }, {})
-      }));
-    } else {
-      throw new Error(`接口返回错误,状态码:${response.code},数据:${JSON.stringify(response)}`);
-    }
-  } catch (error) {
-    console.error('获取报告信息失败:', error);
-    alert(error.message);
-    throw error;
+const fetchReportDetails = (reportId) => {
+  fillingList(reportId).then(res => {
+    res.report_info.user_ids = [7, 8,11,4,1,12];
+    let user1 = [];
+    res.report_info.user_ids.forEach((user) => {
+      user1.push({uuid: user});
+    })
+    reportInfo.value = res.report_info;
+    reportInfo.value.user_ids = user1;
+    tableData.value = res.table_data
+    debugger
+  })
+}
+
+const handleClose = (tag: string) => {
+  selectedReporter.value.splice(selectedReporter.value.indexOf(tag), 1)
+}
+const showSelect = () => {
+  isShowSelect.value = true;
+}
+const fetchTreeData = async () => {
+  const response = await getPhoneList({});
+  if (response && response.data) {
+    treeData.value = response.data;
   }
 };
+const selectContactSelectData = ref([]);
+const handleContactSelectData = (data) => {
+  console.log('handleContactSelectData:', data);
+  selectContactSelectData.value = data;
+  // data.user_ids = data;
+  selectedReporter.value = data;
+  const data1 = [];
+  selectContactSelectData.value.forEach((item) => {
+    data1.push(item.id);
+  })
+  reportInfo.value.user_ids = data1;
+};
 
 function saveEdit(rowIndex, header, value) {
   tableData.value[rowIndex][header] = value;
 }
 
+const hotData = ref([]);
+const showTable = ref(false);
+const isShowTable = ref(false);
 const handleNewTemplate = () => {
-  const newHeaders = Array.from({ length: 10 }, (_, index) => `列${String.fromCharCode(65 + index)}`);
-  field_names.value = Array.from({ length: 10 }, (v, k) => ({
-    序号: k + 1,
-    ...newHeaders.reduce((acc, header) => {
-      acc[header] = '';
-      return acc;
-    }, {})
-  }));
-  editableHeaders.value = ['序号', ...newHeaders];
-  alert('空白模板已创建');
+  tableData.value = [];
+  isShowTable.value = true;
+  created();
+};
+
+const created = () => {
+  let data = [];
+  for (let i = 0; i < 10; i++) {
+    let arr = [];
+    for (let x = 0; x < 10; x++) {
+      arr.push('');
+    }
+    data.push(arr);
+  }
+  showTable.value = false;
+  nextTick(() => {
+    hotData.value = data;
+    showTable.value = true;
+  });
 };
+const hotSettings = reactive({
+  language: 'zh-CN',
+  colHeaders: true,
+  rowHeaders: true,
+  autoColumnSize: true,
+  width: '100%', // auto  or  100%
+  height: '100%', // auto  or  100%
+  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: '取消固定列'
+      }
+    }
+  }
+});
 
 const handleImportExcel = () => {
   const input = document.createElement('input');
@@ -222,16 +330,9 @@ const handleSave = async () => {
     field_names: tableData.value,
     user_ids: []
   };
-  try {
-    const response = await fillingList(data); // 确保 fillingAdd 函数被定义
-    if (response && response.success) {
-      alert('数据已成功保存');
-    } else {
-      alert('数据保存失败');
-    }
-  } catch (error) {
-    console.error('保存数据失败:', error);
-    alert('数据保存失败');
+  const response = await fillingList(data); // 确保 fillingAdd 函数被定义
+  if (response && response.success) {
+    alert('数据已成功保存');
   }
 };