xiaochan 4 ماه پیش
والد
کامیت
64f54682fb
1فایلهای تغییر یافته به همراه107 افزوده شده و 93 حذف شده
  1. 107 93
      src/components/nursing-dashboard/dashboard-editor/index.vue

+ 107 - 93
src/components/nursing-dashboard/dashboard-editor/index.vue

@@ -1,123 +1,131 @@
 <script setup lang="ts">
-import { uuid } from "@/utils/getUuid";
+import { reactive, onMounted, defineExpose, defineOptions } from "vue";
 
 defineOptions({
   name: "DashboardEditor",
 });
 
+// 内部生成唯一 ID 的方法
+let idCounter = 0;
+
+function generateId() {
+  return `id-${idCounter++}`;
+}
+
 const store = reactive({
   isDragging: false,
   startCell: {
     row: 0,
     col: 0,
+    td: {},
   },
   selectedCells: [],
 });
 
+type TableChildren = {
+  type: "tablerow" | "tablecell";
+  id: string;
+  display: boolean;
+  data: any[];
+  rowspan: number | null;
+  colspan: number | null;
+};
+
+type TableType = {
+  type: "tablerow" | "tablecell";
+  id: string;
+  children: TableChildren[];
+};
+
 const tableConfig = reactive({
-  table: [],
+  table: [] as TableType[],
 });
 
-function startDrag(row: number, col: number, event: MouseEvent) {
-  if (event.buttons == 2) return;
+function startDrag(row: number, col: number, tditem, event: MouseEvent) {
+  if (event.buttons === 2) return;
   store.isDragging = true;
-  store.startCell = { row, col };
+  store.startCell = { row, col, td: tditem };
   store.selectedCells = [{ row, col }];
 }
 
-function onMouseMove(row: number, col: number, tritem, tditem) {
+function getMinCell(endRow: number, endCol: number) {
+  const startRow = store.startCell!.row;
+  const startCol = store.startCell!.col;
+
+  return {
+    startRow: Math.min(startRow, endRow),
+    startCol: Math.min(endCol, startCol),
+    endRow: Math.max(startRow, endRow),
+    endCol: Math.max(endCol, startCol),
+  };
+}
+
+function onMouseMove(row: number, col: number, td) {
   if (!store.isDragging) {
     return;
   }
 
+  console.log("getMinCell", getMinCell(row, col));
   const startRow = store.startCell!.row;
   const startCol = store.startCell!.col;
 
-  const startCell = tableConfig.table[startRow].children[startCol];
-  const endCell = tableConfig.table[row].children[col];
-
-  const startRowSpan = startCell.rowspan || 1;
-  const startColSpan = startCell.colspan || 1;
-  const endRowSpan = endCell.rowspan || 1;
-  const endColSpan = endCell.colspan || 1;
-
   const minRow = Math.min(startRow, row);
-  const maxRow = Math.max(startRow + startRowSpan - 1, row + endRowSpan - 1);
+  const maxRow = Math.max(startRow, row);
   const minCol = Math.min(startCol, col);
-  const maxCol = Math.max(startCol + startColSpan - 1, col + endColSpan - 1);
+  const maxCol = Math.max(startCol, col);
+  console.log("startRow:", startRow, "startCol", startCol);
 
   store.selectedCells = [];
+
+  const tmp = [];
+
   for (let r = minRow; r <= maxRow; r++) {
     for (let c = minCol; c <= maxCol; c++) {
-      store.selectedCells.push({ row: r, col: c });
+      tmp.push({ row: r, col: c });
     }
   }
-  console.log(store.selectedCells);
+
+  // console.log(tmp);
+  tmp.forEach(({ row, col }) => {
+    // console.log(row, col);
+  });
+
+  store.selectedCells = tmp;
 }
 
 function endDrag() {
   store.isDragging = false;
 }
 
+function getData(row: number, col: number) {
+  return tableConfig.table[row].children[col];
+}
+
 function mergeCells() {
   if (store.selectedCells.length < 2) return;
 
   const firstCell = store.selectedCells[0];
   const mergedCells = store.selectedCells.slice(1);
 
-  const targetCell = tableConfig.table[firstCell.row].children[firstCell.col];
-
-  // Calculate the total row and column span
-  let maxRow = firstCell.row;
-  let maxCol = firstCell.col;
-
-  for (const cell of store.selectedCells) {
-    const currentCell = tableConfig.table[cell.row].children[cell.col];
-    maxRow = Math.max(maxRow, cell.row + (currentCell.rowspan || 1) - 1);
-    maxCol = Math.max(maxCol, cell.col + (currentCell.colspan || 1) - 1);
-  }
-
-  const rowSpan = maxRow - firstCell.row + 1;
-  const colSpan = maxCol - firstCell.col + 1;
-
-  // Update the first cell's colspan and rowspan
-  targetCell.colspan = colSpan;
-  targetCell.rowspan = rowSpan;
-
-  // Remove other cells and update table structure. Iterate in reverse to avoid index issues
-  for (let i = mergedCells.length - 1; i >= 0; i--) {
-    const cellToRemove = mergedCells[i];
-    const rowIndex = cellToRemove.row;
-    const colIndex = cellToRemove.col;
-
-    // Remove cell from its row
-    tableConfig.table[rowIndex].children.splice(colIndex, 1);
-
-    //If the row becomes empty, remove it
-    if (tableConfig.table[rowIndex].children.length === 0) {
-      tableConfig.table.splice(rowIndex, 1);
-      // adjust the start cell if needed
-      if (firstCell.row > rowIndex) {
-        firstCell.row--;
-      }
-
-      // adjust selected cells if needed
-      store.selectedCells.forEach(cell => {
-        if (cell.row > rowIndex) {
-          cell.row--;
-        }
-      });
+  const minRow = Math.min(...store.selectedCells.map(cell => cell.row));
+  const maxRow = Math.max(...store.selectedCells.map(cell => cell.row));
+  const minCol = Math.min(...store.selectedCells.map(cell => cell.col));
+  const maxCol = Math.max(...store.selectedCells.map(cell => cell.col));
+
+  // 设置合并单元格的显示范围
+  const firstCellData = getData(firstCell.row, firstCell.col);
+  firstCellData.rowspan = maxRow - minRow + 1;
+  firstCellData.colspan = maxCol - minCol + 1;
+
+  // 隐藏其他合并单元格
+  store.selectedCells.forEach(({ row, col }) => {
+    if (row !== firstCell.row || col !== firstCell.col) {
+      const cell = getData(row, col);
+      cell.display = false;
     }
+  });
 
-    // Adjust the index of selected cells and other cells after removing
-    store.selectedCells.forEach(cell => {
-      if (cell.row === rowIndex && cell.col > colIndex) {
-        cell.col--;
-      }
-    });
-  }
-
-  // Clear selection
+  // 清空选区
   store.selectedCells = [];
   store.isDragging = false;
 }
@@ -130,14 +138,18 @@ function createTable(row: number, column: number) {
     for (let j = 0; j < column; j++) {
       children.push({
         type: "tablecell",
-        id: uuid(),
-      });
+        id: generateId(),
+        display: true,
+        data: [],
+        rowspan: null,
+        colspan: null,
+      } as TableChildren);
     }
 
     tableConfig.table.push({
       type: "tablerow",
       children: children,
-      id: uuid(),
+      id: generateId(),
     });
   }
 }
@@ -163,27 +175,27 @@ defineExpose({
     <table :class="{ isDragging: store.isDragging }">
       <tbody>
         <tr v-for="(tritem, rowIndex) in tableConfig.table" :key="tritem.id">
-          <td
-            :id="tditem.id"
-            v-for="(tditem, colIndex) in tritem.children"
-            :key="tditem.id"
-            :colspan="handleSpan(tditem?.colspan)"
-            :rowspan="handleSpan(tditem?.rowspan)"
-            :class="{
-              selected: store.selectedCells.some(
-                cell => cell.row === rowIndex && cell.col === colIndex
-              ),
-            }"
-            @mousedown="startDrag(rowIndex, colIndex, $event)"
-            @mouseenter.prevent="
-              onMouseMove(rowIndex, colIndex, tritem, tditem)
-            "
-            @contextmenu.stop.prevent="mergeCells"
-          >
-            <div class="edl-cell-renderer">
-              {{ `(${rowIndex} , ${colIndex})` }}
-            </div>
-          </td>
+          <template v-for="(tditem, colIndex) in tritem.children">
+            <td
+              v-if="tditem.display"
+              :id="tditem.id"
+              :key="tditem.id"
+              :colspan="handleSpan(tditem?.colspan)"
+              :rowspan="handleSpan(tditem?.rowspan)"
+              :class="{
+                selected: store.selectedCells.some(
+                  cell => cell.row === rowIndex && cell.col === colIndex
+                ),
+              }"
+              @mousedown="startDrag(rowIndex, colIndex, tditem, $event)"
+              @mouseenter.prevent="onMouseMove(rowIndex, colIndex, tditem)"
+              @contextmenu.stop.prevent="mergeCells"
+            >
+              <div class="edl-cell-renderer">
+                {{ `(${rowIndex} , ${colIndex})` }}
+              </div>
+            </td>
+          </template>
         </tr>
       </tbody>
     </table>
@@ -211,6 +223,8 @@ table.isDragging {
 td {
   border: 1px solid white;
   text-align: center;
+  color: white;
+  background-color: black;
 }
 
 td.selected {