yangg 3 тижнів тому
батько
коміт
e8a325666d
2 змінених файлів з 224 додано та 12 видалено
  1. 15 8
      src/components/CanvasEditor/index.vue
  2. 209 4
      src/views/project/ProjectInput.vue

+ 15 - 8
src/components/CanvasEditor/index.vue

@@ -768,31 +768,38 @@ export default {
         console.error('Apply bold failed:', error);
       }
     },
-    // 添加自定义粘贴处理方法
-    handlePaste(e) {
+   // 修改为异步的粘贴处理方法
+    async handlePaste(e) {
       try {
         if (!this.editorRef) return;
         
         // 阻止默认粘贴行为
         e.preventDefault();
         
-        // 尝试从剪贴板获取文本
         let text = '';
         
-        // 使用 clipboardData 获取粘贴内容
-        if (e.clipboardData && e.clipboardData.getData) {
+        // 优先尝试使用现代的 Async Clipboard API
+        if (navigator.clipboard && navigator.clipboard.readText) {
+          text = await navigator.clipboard.readText();
+        } 
+        // 作为备选,尝试从粘贴事件对象中获取
+        else if (e.clipboardData && e.clipboardData.getData) {
           text = e.clipboardData.getData('text/plain');
-        } else if (window.clipboardData && window.clipboardData.getData) {
-          // IE 兼容
+        }
+        // 最后降级到已不推荐的 window.clipboardData (主要针对旧版IE)
+        else if (window.clipboardData && window.clipboardData.getData) {
           text = window.clipboardData.getData('Text');
         }
         
-        // 如果获取到文本,则执行粘贴
+        // 如果成功获取到文本,则执行插入操作
         if (text) {
           this.editorRef.command.executeInsertText(text);
+        } else {
+          console.warn('Failed to retrieve text from clipboard.');
         }
       } catch (error) {
         console.error('Custom paste handler failed:', error);
+        // 错误处理见下一步
       }
     }
   },

+ 209 - 4
src/views/project/ProjectInput.vue

@@ -101,6 +101,7 @@
         style="width: 100%"
         :default-sort="{ prop: sort_field, order: sort_order }"
         @sort-change="handleSortChange"
+        :row-class-name="getRowClassName"
       >
         <el-table-column prop="sequence" label="排序" sortable width="80">
           <template slot-scope="scope">
@@ -114,7 +115,12 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column prop="name" label="项目名称" sortable />
+        <el-table-column prop="name" label="项目名称" sortable>
+          <template slot-scope="scope">
+            <span v-if="currentModifiedItem === scope.row.id" class="modified-indicator"></span>
+            {{ scope.row.name }}
+          </template>
+        </el-table-column>
         <el-table-column prop="tech_report_location" label="技术报告位置" />
         <el-table-column prop="department" label="部门" sortable />
         <el-table-column prop="content" label="内容" width="450">
@@ -188,7 +194,7 @@
       </el-table>
       <div class="pagination-container">
         <el-pagination
-          :current-page="currentPage"
+          :current-page.sync="currentPage"
           :page-sizes="[30, 50]"
           :page-size="pageSize"
           layout="total, sizes, prev, pager, next, jumper"
@@ -603,6 +609,10 @@ export default {
       previewContent: "",
       currentPage: 1,
       pageSize: 30,
+      // 修改状态跟踪
+      currentModifiedItem: null, // 当前高亮的项ID(只保持一个)
+      originalData: new Map(), // 存储原始数据用于对比
+      clearTimer: null, // 自动清理定时器
     };
   },
   mounted() {
@@ -697,6 +707,9 @@ export default {
         (p) => p.id === this.selectedProjectId
       );
 
+      // 保存原始数据用于对比
+      this.saveOriginalData(row);
+
       // 处理 content 内容,将文本格式转换为 HTML 并清理空样式
       const processedContent = this.cleanEmptyStyles(
         this.convertTextToHtml(row.content)
@@ -796,6 +809,13 @@ export default {
         await projectUpdate(submitData);
         this.$message.success("内容更新成功");
         this.contentDialogVisible = false;
+        
+        // 检查数据是否有变化,如果有则标记为已修改
+        const originalData = this.originalData.get(this.contentForm.id);
+        if (this.checkDataChanged(submitData, originalData)) {
+          this.markAsModified(this.contentForm.id);
+        }
+        
         this.fetchGsprData();
       } catch (error) {
         this.$message.error("内容更新失败");
@@ -804,6 +824,9 @@ export default {
 
     // 修改现有的 handleEditRemark 方法
     handleEditRemark(row) {
+      // 保存原始数据用于对比
+      this.saveOriginalData(row);
+      
       // 只复制需要的字段
       this.remarkForm = {
         id: row.id,
@@ -831,6 +854,13 @@ export default {
         await projectUpdate(updateData);
         this.$message.success("备注更新成功");
         this.remarkDialogVisible = false;
+        
+        // 检查数据是否有变化,如果有则标记为已修改
+        const originalData = this.originalData.get(this.remarkForm.id);
+        if (this.checkDataChanged(updateData, originalData)) {
+          this.markAsModified(this.remarkForm.id);
+        }
+        
         this.fetchGsprData();
       } catch (error) {
         this.$message.error("备注更新失败");
@@ -839,6 +869,11 @@ export default {
     /* 修改评分 */
     async rateScope(value, row) {
       try {
+        // 保存原始数据用于对比
+        if (!this.originalData.has(row.id)) {
+          this.saveOriginalData(row);
+        }
+        
         const response = await rateScope({
           id: row.id,
           score: value,
@@ -853,6 +888,12 @@ export default {
           if (index !== -1) {
             this.gsprTableData[index].score = value;
           }
+          
+          // 检查数据是否有变化,如果有则标记为已修改
+          const originalData = this.originalData.get(row.id);
+          if (originalData && originalData.score !== value) {
+            this.markAsModified(row.id);
+          }
         } else {
           throw new Error(response.message || "评分更新失败");
         }
@@ -864,6 +905,9 @@ export default {
     },
     /* 修改序号 */
     handleEditSequence(row) {
+      // 保存原始数据用于对比
+      this.saveOriginalData(row);
+      
       this.sequenceForm.sequence = row.sequence;
       this.sequenceForm.id = row.id;
       this.dialogVisible = true;
@@ -877,6 +921,13 @@ export default {
         });
         this.$message.success("修改序号成功");
         this.dialogVisible = false;
+        
+        // 检查数据是否有变化,如果有则标记为已修改
+        const originalData = this.originalData.get(this.sequenceForm.id);
+        if (originalData && originalData.sequence !== this.sequenceForm.sequence) {
+          this.markAsModified(this.sequenceForm.id);
+        }
+        
         // 重新加载数据
         this.fetchGsprData();
       } catch (error) {
@@ -1294,6 +1345,24 @@ export default {
         })
       );
 
+      // 恢复该项目上次的分页设置
+      try {
+        const savedPage = Number(
+          localStorage.getItem(`gspr_page_${this.selectedProjectId}`)
+        );
+        const savedPageSize = Number(
+          localStorage.getItem(`gspr_page_size_${this.selectedProjectId}`)
+        );
+        if (!Number.isNaN(savedPage) && savedPage > 0) {
+          this.currentPage = savedPage;
+        }
+        if (!Number.isNaN(savedPageSize) && savedPageSize > 0) {
+          this.pageSize = savedPageSize;
+        }
+      } catch (e) {
+        // 忽略本地存储异常
+      }
+
       this.gsprSearchForm.project_id = this.selectedProjectId;
       this.fetchGsprData();
     },
@@ -1510,6 +1579,13 @@ export default {
         this.gsprTableData = responseData.list; //filteredItems
         this.gsprTotal = responseData.total; // 使用API返回的总数
         this.hasExistingData = this.gsprTableData.length > 0;
+        
+        // 保存原始数据用于后续对比
+        this.gsprTableData.forEach(item => {
+          if (!this.originalData.has(item.id)) {
+            this.saveOriginalData(item);
+          }
+        });
       } catch (error) {
         console.error("数据加载失败:", error);
         this.$message.error(error.message || "获取数据失败");
@@ -1529,8 +1605,12 @@ export default {
     },
 
     handleGsprSearch() {
-      this.currentPage = 1; // 搜索时重置到第一页
+      this.currentPage = Number(
+          localStorage.getItem(`gspr_page_${this.selectedProjectId}`)
+        ) ; // 搜索时重置到第一页
+        console.log(this.currentPage);
       this.searchList();
+      /* this.fetchGsprData(); */
     },
     /* 搜索 */
     async searchList() {
@@ -1561,7 +1641,16 @@ export default {
         });
         this.gsprTableData = response.data.list; //filteredItems
         this.gsprTotal = response.data.total; // 使用API返回的总数
+        /* this.currentPage = response.data.current_page; */
         this.hasExistingData = this.gsprTableData.length > 0;
+        
+        // 保存原始数据用于后续对比
+        this.gsprTableData.forEach(item => {
+          if (!this.originalData.has(item.id)) {
+            this.saveOriginalData(item);
+          }
+        });
+        
         console.log(response);
       } finally {
         loading.close();
@@ -1602,14 +1691,90 @@ export default {
 
     handleGsprSizeChange(val) {
       this.pageSize = val;
-      this.currentPage = 1; // 切换每页显示数量时重置到第一页
+     // this.currentPage = 1; // 切换每页显示数量时重置到第一页
+      try {
+        localStorage.setItem(
+          `gspr_page_size_${this.selectedProjectId}`,
+          String(this.pageSize)
+        );
+        localStorage.setItem(
+          `gspr_page_${this.selectedProjectId}`,
+          String(this.currentPage)
+        );
+      } catch (e) {
+        // 忽略本地存储异常
+      }
       this.fetchGsprData();
     },
 
     handleGsprCurrentChange(val) {
       this.currentPage = val;
+      try {
+        localStorage.setItem(
+          `gspr_page_${this.selectedProjectId}`,
+          String(this.currentPage)
+        );
+      } catch (e) {
+        // 忽略本地存储异常
+      }
       this.fetchGsprData();
     },
+
+    // 获取行样式类名
+    getRowClassName({ row }) {
+      if (this.currentModifiedItem === row.id) {
+        return 'modified-row';
+      }
+      return '';
+    },
+
+    // 标记项为已修改(只保持一个高亮)
+    markAsModified(itemId) {
+      // 清除之前的定时器
+      if (this.clearTimer) {
+        clearTimeout(this.clearTimer);
+        this.clearTimer = null;
+      }
+      
+      // 设置新的高亮项
+      this.currentModifiedItem = itemId;
+      
+      // 设置10秒后自动清除
+      this.clearTimer = setTimeout(() => {
+        this.currentModifiedItem = null;
+        this.clearTimer = null;
+      }, 10000); // 10秒
+    },
+
+    // 清除修改标记
+    clearModifiedMark() {
+      if (this.clearTimer) {
+        clearTimeout(this.clearTimer);
+        this.clearTimer = null;
+      }
+      this.currentModifiedItem = null;
+    },
+
+    // 检查数据是否有变化
+    checkDataChanged(newData, originalData) {
+      if (!originalData) return true;
+      
+      const fieldsToCheck = ['name', 'tech_report_location', 'department', 'content', 'remarks', 'score'];
+      return fieldsToCheck.some(field => newData[field] !== originalData[field]);
+    },
+
+    // 保存原始数据
+    saveOriginalData(item) {
+      this.originalData.set(item.id, { ...item });
+    },
+  },
+  
+  // 组件销毁时清理定时器
+  beforeDestroy() {
+    if (this.clearTimer) {
+      clearTimeout(this.clearTimer);
+      this.clearTimer = null;
+    }
   },
 };
 </script>
@@ -1689,4 +1854,44 @@ export default {
 ::v-deep .el-dialog {
   margin-top: 0 !important;
 }
+
+/* 修改项高亮样式 */
+.modified-row {
+  background-color: #e6f7ff !important; /* 浅蓝色背景 */
+  border-left: 4px solid #1890ff !important; /* 左侧蓝色边框 */
+  transition: all 0.3s ease; /* 添加过渡效果 */
+}
+
+.modified-row:hover {
+  background-color: #bae7ff !important; /* 悬停时更深的蓝色 */
+}
+
+
+
+@keyframes pulse {
+  0% {
+    opacity: 1;
+    transform: scale(1);
+  }
+  50% {
+    opacity: 0.7;
+    transform: scale(1.1);
+  }
+  100% {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
+@keyframes fadeOut {
+  0% {
+    opacity: 1;
+  }
+  90% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
 </style>