|
@@ -427,7 +427,7 @@ export default {
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
/* 使用html-docx-js方法替换 */
|
|
/* 使用html-docx-js方法替换 */
|
|
- // 预处理内容,处理分页��和表格
|
|
|
|
|
|
+ // 预处理内容,处理分页和表格
|
|
preprocessContent(content) {
|
|
preprocessContent(content) {
|
|
const tempDiv = document.createElement("div");
|
|
const tempDiv = document.createElement("div");
|
|
tempDiv.innerHTML = content;
|
|
tempDiv.innerHTML = content;
|
|
@@ -859,7 +859,7 @@ export default {
|
|
return hasCellBorder && !hasNoBorderMark;
|
|
return hasCellBorder && !hasNoBorderMark;
|
|
},
|
|
},
|
|
|
|
|
|
- // 添加处理分��的辅助方法
|
|
|
|
|
|
+ // 添加处理分的辅助方法
|
|
addPageBreaks(content) {
|
|
addPageBreaks(content) {
|
|
// 查找需要分页的位置(可以根据实际需求调整)
|
|
// 查找需要分页的位置(可以根据实际需求调整)
|
|
const pageBreakMarkers = ["<h1", "<h2", "<!-- pagebreak -->"];
|
|
const pageBreakMarkers = ["<h1", "<h2", "<!-- pagebreak -->"];
|
|
@@ -906,7 +906,7 @@ export default {
|
|
);
|
|
);
|
|
},
|
|
},
|
|
|
|
|
|
- // 添加内容处��方法
|
|
|
|
|
|
+ // 添加内容处方法
|
|
processContentForWord(content) {
|
|
processContentForWord(content) {
|
|
const tempDiv = document.createElement("div");
|
|
const tempDiv = document.createElement("div");
|
|
tempDiv.innerHTML = content;
|
|
tempDiv.innerHTML = content;
|
|
@@ -1116,7 +1116,7 @@ export default {
|
|
if (table.style.border || table.classList.contains("bordered"))
|
|
if (table.style.border || table.classList.contains("bordered"))
|
|
return true;
|
|
return true;
|
|
|
|
|
|
- // 检查第一个单���格是否有边框
|
|
|
|
|
|
+ // 检查第一个单格是否有边框
|
|
const firstCell = table.querySelector("td, th");
|
|
const firstCell = table.querySelector("td, th");
|
|
if (firstCell && firstCell.style.border) return true;
|
|
if (firstCell && firstCell.style.border) return true;
|
|
|
|
|
|
@@ -1888,7 +1888,7 @@ export default {
|
|
const fullMatch = match[0];
|
|
const fullMatch = match[0];
|
|
const segments = [match[1], match[2], match[3], match[4]];
|
|
const segments = [match[1], match[2], match[3], match[4]];
|
|
|
|
|
|
- // 验证��个段落的格式
|
|
|
|
|
|
+ // 验证个段落的格式
|
|
const isValid = segments.every((segment) => segment.length > 0);
|
|
const isValid = segments.every((segment) => segment.length > 0);
|
|
|
|
|
|
if (isValid) {
|
|
if (isValid) {
|
|
@@ -2919,27 +2919,24 @@ export default {
|
|
//搜索
|
|
//搜索
|
|
async search() {
|
|
async search() {
|
|
try {
|
|
try {
|
|
|
|
+ // 1. 先加载并显示项目列表
|
|
const res = await searchProject(this.queryForm);
|
|
const res = await searchProject(this.queryForm);
|
|
if (!res) return;
|
|
if (!res) return;
|
|
-
|
|
|
|
- // 获取所有项目的完成度
|
|
|
|
- const calculatePromises = res.data.dataList.map(async (item) => {
|
|
|
|
- try {
|
|
|
|
- const calcRes = await calculate({ id: item.id });
|
|
|
|
- if (calcRes.status === 200) {
|
|
|
|
- item.calculate = calcRes.data.completionRate;
|
|
|
|
- }
|
|
|
|
- } catch (err) {
|
|
|
|
- console.error(`获取项目${item.id}完成度失败:`, err);
|
|
|
|
- item.calculate = 0;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- await Promise.all(calculatePromises);
|
|
|
|
-
|
|
|
|
- this.dataList = res.data.dataList;
|
|
|
|
|
|
+
|
|
|
|
+ // 2. 先用0初始化完成度,让列表可以立即渲染
|
|
|
|
+ const projectList = res.data.dataList.map(item => ({
|
|
|
|
+ ...item,
|
|
|
|
+ calculate: 0
|
|
|
|
+ }));
|
|
|
|
+
|
|
|
|
+ // 3. 立即更新列表数据
|
|
|
|
+ this.dataList = projectList;
|
|
this.recordCount = res.data.totalRecord;
|
|
this.recordCount = res.data.totalRecord;
|
|
this.pageTotal = res.data.totalPage;
|
|
this.pageTotal = res.data.totalPage;
|
|
|
|
+
|
|
|
|
+ // 4. 异步加载完成度
|
|
|
|
+ this.loadProjectCompletions(projectList);
|
|
|
|
+
|
|
} catch (err) {
|
|
} catch (err) {
|
|
console.error("搜索失败:", err);
|
|
console.error("搜索失败:", err);
|
|
this.$message.error("获取项目列表失败");
|
|
this.$message.error("获取项目列表失败");
|
|
@@ -3298,7 +3295,74 @@ export default {
|
|
this.templateQueryForm.page = 1; // 重置页码
|
|
this.templateQueryForm.page = 1; // 重置页码
|
|
this.loadTemplateList(); // 重新加载列表
|
|
this.loadTemplateList(); // 重新加载列表
|
|
},
|
|
},
|
|
|
|
+
|
|
|
|
+ // 新增方法:异步加载完成度
|
|
|
|
+ async loadProjectCompletions(projects) {
|
|
|
|
+ // 使用 Promise.all 和 chunk 分批处理
|
|
|
|
+ const chunkSize = 5; // 每批处理5个项目
|
|
|
|
+ const chunks = this.chunkArray(projects, chunkSize);
|
|
|
|
+
|
|
|
|
+ for (const chunk of chunks) {
|
|
|
|
+ const promises = chunk.map(async (project) => {
|
|
|
|
+ try {
|
|
|
|
+ const calcRes = await calculate({ id: project.id });
|
|
|
|
+ if (calcRes.status === 200) {
|
|
|
|
+ // 使用 Vue.set 更新单个项目的完成度
|
|
|
|
+ const index = this.dataList.findIndex(item => item.id === project.id);
|
|
|
|
+ if (index !== -1) {
|
|
|
|
+ this.$set(this.dataList[index], 'calculate', calcRes.data.completionRate);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (err) {
|
|
|
|
+ console.error(`获取项目${project.id}完成度失败:`, err);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await Promise.all(promises);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 辅助方法:将数组分成小块
|
|
|
|
+ chunkArray(array, size) {
|
|
|
|
+ const chunks = [];
|
|
|
|
+ for (let i = 0; i < array.length; i += size) {
|
|
|
|
+ chunks.push(array.slice(i, i + size));
|
|
|
|
+ }
|
|
|
|
+ return chunks;
|
|
|
|
+ },
|
|
},
|
|
},
|
|
|
|
+ computed: {
|
|
|
|
+ tableColumns() {
|
|
|
|
+ return [
|
|
|
|
+ // ... 其他列配置 ...
|
|
|
|
+ {
|
|
|
|
+ prop: 'calculate',
|
|
|
|
+ label: '完成度',
|
|
|
|
+ width: '100',
|
|
|
|
+ render: (h, { row }) => {
|
|
|
|
+ // 使用过渡效果显示完成度
|
|
|
|
+ return h('el-tooltip', {
|
|
|
|
+ props: {
|
|
|
|
+ content: '加载中...',
|
|
|
|
+ disabled: row.calculate !== 0
|
|
|
|
+ }
|
|
|
|
+ }, [
|
|
|
|
+ h('span', {
|
|
|
|
+ class: [
|
|
|
|
+ this.getCompletionClass(row.calculate),
|
|
|
|
+ 'completion-text'
|
|
|
|
+ ]
|
|
|
|
+ }, [
|
|
|
|
+ row.calculate === 0
|
|
|
|
+ ? h('i', { class: 'el-icon-loading' })
|
|
|
|
+ : this.formatCompletion(row.calculate)
|
|
|
|
+ ])
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
};
|
|
};
|
|
</script>
|
|
</script>
|
|
|
|
|