lizhouming před 6 měsíci
rodič
revize
9d4d415445
4 změnil soubory, kde provedl 245 přidání a 131 odebrání
  1. 25 0
      package-lock.json
  2. 1 0
      package.json
  3. 2 0
      src/types/components.d.ts
  4. 217 131
      src/views/dataFilling/fillingAdd.vue

+ 25 - 0
package-lock.json

@@ -53,6 +53,7 @@
         "uuid": "^10.0.0",
         "vue": "3.4.25",
         "vue-cropper": "1.1.1",
+        "vue-good-table": "^2.21.11",
         "vue-i18n": "9.10.2",
         "vue-router": "4.3.2",
         "vue-types": "5.1.1",
@@ -5099,6 +5100,21 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/date-fns": {
+      "version": "2.30.0",
+      "resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-2.30.0.tgz",
+      "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+      "dependencies": {
+        "@babel/runtime": "^7.21.0"
+      },
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
     "node_modules/dayjs": {
       "version": "1.11.13",
       "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
@@ -12418,6 +12434,15 @@
         "eslint": ">=6.0.0"
       }
     },
+    "node_modules/vue-good-table": {
+      "version": "2.21.11",
+      "resolved": "https://registry.npmmirror.com/vue-good-table/-/vue-good-table-2.21.11.tgz",
+      "integrity": "sha512-OpVPdxbBTahtfq1aXxEa5P1CMy1wiLcBg4mo7k6Qs537l9v8KVrvF+fXqbnxqNrAfmd1Mw9LidcjgTErjmVU8g==",
+      "dependencies": {
+        "date-fns": "^2.17.0",
+        "lodash.isequal": "^4.5.0"
+      }
+    },
     "node_modules/vue-i18n": {
       "version": "9.10.2",
       "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.10.2.tgz",

+ 1 - 0
package.json

@@ -62,6 +62,7 @@
     "uuid": "^10.0.0",
     "vue": "3.4.25",
     "vue-cropper": "1.1.1",
+    "vue-good-table": "^2.21.11",
     "vue-i18n": "9.10.2",
     "vue-router": "4.3.2",
     "vue-types": "5.1.1",

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

@@ -40,12 +40,14 @@ declare module 'vue' {
     ElInput: typeof import('element-plus/es')['ElInput']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
+    ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']

+ 217 - 131
src/views/dataFilling/fillingAdd.vue

@@ -1,153 +1,239 @@
 <template>
-  <div>
-    <div v-show="!fillingAddState.show && !tableDetailsState.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="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="table_name" label-width="auto"> </el-form-item>
-                </el-col>
-                <el-col :span="6">
-                  <el-form-item label="截止时间:" prop="release_time">
-                    <el-date-picker
-                      v-model="selectedTime"
-                      type="daterange"
-                      range-separator="至"
-                      start-placeholder="开始日期"
-                      end-placeholder="结束日期"
-                      @change="handleTimeChange"
-                    />
-                  </el-form-item>
-                </el-col>
-                <el-col :span="6">
-                  <el-button type="primary" @click="handleQuery">查询</el-button>
-                  <el-button type="primary" @click="resetQuery">重置</el-button>
-                  <el-button type="primary" @click="exportTableData()">导出</el-button>
-                  <el-button type="primary" @click="handleAdd()">新增</el-button>
-                </el-col>
-              </el-row>
-            </el-form>
-          </div>
-        </transition>
-        <!-- 表格组件 -->
-        <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange"> </el-table>
-        <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="tableData" />
-      </div>
-    </div>
+  <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="6">
+            <el-form-item label="联系人姓名:" prop="table_name" label-width="auto">
+              <el-input v-model="table_name" placeholder="请输入联系人姓名"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="联系电话:" prop="table_name" label-width="auto">
+              <el-input v-model="table_phone" placeholder="请输入联系电话"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="选择填报人:" prop="table_name" label-width="auto">
+              <el-select v-model="selectedReporter" placeholder="请选择填报人">
+                <el-option v-for="reporter in reporters" :key="reporter.id" :label="reporter.name" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="截止时间:" prop="release_time">
+              <el-date-picker v-model="selectedTime" type="date" placeholder="选择截止时间" @change="handleTimeChange" />
+              <span class="label">前报送该表</span>
+            </el-form-item>
+          </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="handleSaveTemporarily">暂存</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="20" class="mb8">
+        <el-col :span="1.5">
+          <el-button type="primary" @click="handleImportExcel">导入Excel文件</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button type="primary" @click="handleNewTemplate">空白模板</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button 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 #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>
-  <FillingAdd v-if="fillingAddState.show" :event-id="fillingAddState.eventId" @close="handleCancel" />
-  <TableDetails v-if="tableDetailsState.show" :event-id="tableDetailsState.eventId" @close="handleCancel" />
 </template>
+
 <script setup lang="ts">
-import { onMounted, reactive, ref } from 'vue';
-import FillingAdd from './fillingAdd.vue';
-import TableDetails from './tableDetails.vue';
-import { ElButton, ElCol } from 'element-plus';
+import { ref, onMounted } from 'vue';
+import { ElTable, ElButton, ElCol, ElRow, ElTableColumn } from 'element-plus';
+import * as XLSX from 'xlsx';
 
-const loading = ref(true);
-const showSearch = ref(true);
-const selectedTime = ref([]);
-const ids = ref<Array<number | string>>([]);
-const total = ref(0);
-const tableData = ref([]);
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const initFormData = reactive({
-  table_id: '',
-  table_name: '',
-  filling_time: '',
-  release_time: '',
-  release_status: '',
-  task_status: ''
-});
-const data = reactive({
-  form: { ...initFormData },
-  queryParams: {
-    page: 1,
-    pageSize: 10,
-    table_name: '',
-    release_status: '',
-    task_status: ''
-  }
+const emits = defineEmits(['close']);
+const detailData = ref({
+  title: '测试表单',
+  start: '2024-10-15 17:02:22',
+  end: '2024-10-15 18:00:00'
 });
 
-const { queryParams, form } = toRefs(data);
+const editableHeaders = ref(['时间', '地点', '损坏程度', '救援人员', '物资']);
+const tableData = ref([]);
 
-let fillingAddState = reactive({
-  show: false,
-  eventId: ''
+// 初始化表格数据
+onMounted(() => {
+  loadFromLocalStorage();
 });
 
-let tableDetailsState = reactive({
-  show: false,
-  eventId: ''
-});
+// 加载数据
+function loadFromLocalStorage() {
+  const storedData = localStorage.getItem('tableData');
+  if (storedData) {
+    tableData.value = JSON.parse(storedData);
+  } else {
+    tableData.value = [
+      {
+        时间: '2024-01-01',
+        地点: '某地',
+        损坏程度: '轻度',
+        救援人员: '张三, 李四',
+        物资: '食品, 水'
+      },
+      {
+        时间: '2024-01-02',
+        地点: '某地',
+        损坏程度: '中度',
+        救援人员: '王五, 赵六',
+        物资: '帐篷, 医疗用品'
+      }
+    ];
+  }
+}
 
-const handleCancel = () => {
-  fillingAddmState.show = false;
-  tableDetailsState.show = false;
-};
-const handleAdd = () => {
-  fillingAddState.eventId = null; // 表示新增记录
-  fillingAddState.show = true;
-};
-const handleView = (row) => {
-  if (row) {
-    tableDetailsState.eventId = row.id;
-    tableDetailsState.show = true;
+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);
   }
-};
+}
 
-// 初始化数据
-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: '', release_status: '', task_status: '' };
-  selectedTime.value = [];
-  handleQuery();
+const handleNewTemplate = () => {
+  tableData.value = [];
+  for (let i = 0; i < 10; i++) {
+    tableData.value.push({
+      时间: '',
+      地点: '',
+      损坏程度: '',
+      救援人员: '',
+      物资: ''
+    });
+  }
+  alert('空白模板已创建');
 };
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.id);
+
+const handleImportExcel = () => {
+  const input = document.createElement('input');
+  input.type = 'file';
+  input.accept = '.xlsx';
+  input.onchange = async (e) => {
+    const file = e.target.files[0];
+    const reader = new FileReader();
+    reader.onload = async () => {
+      const data = await new Promise((resolve, reject) => {
+        const result = XLSX.read(reader.result);
+        resolve(result);
+      });
+      reader.readAsArrayBuffer(file);
+    };
+    const workbook = XLSX.utils.read(data);
+    const firstSheetName = workbook.SheetNames[0];
+    const worksheet = workbook.Sheets[firstSheetName];
+    const data = XLSX.utils.sheet_to_json(worksheet);
+    tableData.value = data;
+    alert('Excel文件已导入');
+  };
+  input.click();
 };
 
-const handleTimeChange = (value) => {
-  selectedTimeLabel.value = value ? `${value[0]} 至 ${value[1]}` : '请选择时间';
+const handleReload = () => {
+  tableData.value = [];
+  alert('表格已清空');
 };
 
-const exportTableData = () => {
-  const dataForExport = tableData.value.map((item) => ({
-    table_id: item.table_id,
-    table_name: item.table_name,
-    release_time: item.release_time,
-    release_status: item.release_status,
-    filling_time: item.filling_time,
-    status: item.status
-  }));
+const handleSaveTemporarily = () => {
+  localStorage.setItem('tableData', JSON.stringify(tableData.value));
+  alert('数据已暂存');
+};
 
-  // 使用 xlsx库创建一个工作簿和工作表,然后填入数据
-  const workbook = XLSXLSX.utils.book_new();
-  XLSX.utils.sheet_add_aoa(workbook, dataForExport, { name: 'sheet1' });
+const handleReport = () => console.log('上报');
 
-  // 生成Excel文件并下载
-  XLSX.utils.save_a(workbook, 'tableData.xlsx');
+const handleSave = () => {
+  // 保存本地状态
+  localStorage.setItem('tableData', JSON.stringify(tableData.value));
+  alert('数据已保存');
+};
+const handleReturn = () => {
+  emits('close');
 };
 </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>