From fbb61549bf96e9e0910b676a5524b0760d29c4be Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期二, 07 四月 2026 15:16:54 +0800
Subject: [PATCH] 测试完成

---
 src/views/sfstatistics/ProblemStatistics/index.vue |  536 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 536 insertions(+), 0 deletions(-)

diff --git a/src/views/sfstatistics/ProblemStatistics/index.vue b/src/views/sfstatistics/ProblemStatistics/index.vue
new file mode 100644
index 0000000..0a4f091
--- /dev/null
+++ b/src/views/sfstatistics/ProblemStatistics/index.vue
@@ -0,0 +1,536 @@
+<template>
+  <div class="indexanalysis">
+    <div class="analysis-top">
+      <div class="title-top">鏌ヨ鏉′欢</div>
+      <div class="value">
+        <el-form ref="form" :model="queryParams" label-width="120px">
+          <el-form-item label="閫夋嫨闂鍚嶇О">
+            <el-select
+              ref="questionSelect"
+              remote
+              :remote-method="remoteMethod"
+              default-first-option
+              v-model="selectedTargets"
+              @change="handleTargetChange"
+              @keyup.enter.native="handleEnterSearch"
+              filterable
+              multiple
+              collapse-tags
+              reserve-keyword
+              :loading="searchLoading"
+              placeholder="璇疯緭鍏ラ棶棰樺悕绉版悳绱紝鎸夊洖杞︾‘璁�"
+            >
+              <el-option
+                v-for="item in targetList"
+                :key="item.id"
+                :label="item.scriptContent || item.targetname"
+                :value="item.id"
+              >
+                <span>{{ item.scriptContent || item.targetname }}</span>
+                <span style="float: right; color: #8492a6; font-size: 13px">
+                  ID: {{ item.id }}
+                </span>
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="宸查�夐鐩�">
+            <div class="selected-ids">
+              {{ selectedContentsText }}
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+
+    <div class="formindex">
+      <el-table
+        v-loading="loading"
+        :data="processedTableData"
+        :span-method="objectSpanMethod"
+        border
+        :summary-method="getSummaries"
+        show-summary
+        style="width: 100%"
+        empty-text="璇烽�夋嫨瑕佺粺璁$殑棰樼洰"
+      >
+        <el-table-column prop="targetname" label="闂鍚嶇О" width="200">
+          <template slot-scope="scope">
+            <div class="target-name-cell">
+              {{ scope.row.targetname }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="targetShowCount" label="闂鍑虹幇娆℃暟" width="120">
+          <template slot-scope="scope">
+            {{ scope.row.targetShowCount }}娆�
+          </template>
+        </el-table-column>
+        <el-table-column prop="completedPercentage" label="棰樼洰瀹屾垚搴�" width="120">
+          <template slot-scope="scope">
+            {{ formatPercentage(scope.row.completedPercentage) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="matchedtext" label="閫夐」鍐呭" width="150">
+          <template slot-scope="scope">
+            {{ scope.row.matchedtext || '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="count" label="閫変腑娆℃暟" width="100">
+          <template slot-scope="scope">
+            {{ scope.row.count }}娆�
+          </template>
+        </el-table-column>
+        <el-table-column prop="percentage" label="鍗犳瘮" width="100">
+          <template slot-scope="scope">
+            <span>{{ formatPercentage(scope.row.percentage) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="杩涘害鏉�" min-width="200">
+          <template slot-scope="scope">
+            <el-progress
+              :percentage="Number(scope.row.percentage) * 100"
+              :show-text="false"
+              :color="customColors"
+            />
+            <span class="progress-text">{{ formatPercentage(scope.row.percentage) }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getissuelist, compileissuestatistics } from "@/api/AiCentre/index";
+
+export default {
+  name: "indexanalysis",
+  data() {
+    return {
+      targetList: [],
+      selectedTargets: [], // 瀛樺偍閫変腑鐨勯鐩甀D
+      tableData: [],
+      processedTableData: [],
+      loading: false,
+      searchLoading: false,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 66,
+        scriptContent: '',
+      },
+      customColors: [
+        { color: '#f56c6c', percentage: 20 },
+        { color: '#e6a23c', percentage: 40 },
+        { color: '#5cb87a', percentage: 60 },
+        { color: '#1989fa', percentage: 80 },
+        { color: '#6f7ad3', percentage: 100 }
+      ],
+      spanArr: [],
+      searchTimer: null,
+      currentSearchQuery: '', // 褰撳墠鎼滅储鍏抽敭璇�
+    };
+  },
+
+  computed: {
+    // 璁$畻閫変腑鐨勯棶棰樺唴瀹规枃鏈�
+    selectedContentsText() {
+      if (this.selectedTargets.length === 0) {
+        return '鏈�夋嫨浠讳綍棰樼洰';
+      }
+
+      // 鏍规嵁閫変腑鐨処D鑾峰彇瀵瑰簲鐨剆criptContent
+      const selectedContents = this.selectedTargets.map(id => {
+        const target = this.targetList.find(item => item.id === id);
+        return target ? (target.scriptContent || target.targetname || `棰樼洰${id}`) : `棰樼洰${id}`;
+      });
+
+      return selectedContents.join('; ');
+    },
+
+    // 鑾峰彇閫変腑椤圭殑鍐呭鏁扮粍锛堢敤浜庢樉绀猴級
+    selectedContents() {
+      return this.selectedTargets.map(id => {
+        const target = this.targetList.find(item => item.id === id);
+        return target ? (target.scriptContent || target.targetname) : `棰樼洰${id}`;
+      });
+    }
+  },
+
+  watch: {
+    processedTableData: {
+      handler(newVal) {
+        if (newVal && newVal.length > 0) {
+          this.getSpanArr(newVal);
+        } else {
+          this.spanArr = [];
+        }
+      },
+      immediate: true,
+      deep: true
+    }
+  },
+
+  created() {
+    this.getList();
+  },
+
+  methods: {
+    // 鏌ヨ闂嵎鍒楄〃
+    async getList() {
+      this.loading = true;
+      try {
+        const response = await getissuelist(this.queryParams);
+        this.targetList = response.rows || [];
+      } catch (error) {
+        console.error('鑾峰彇棰樼洰鍒楄〃澶辫触:', error);
+        this.$message.error('鑾峰彇棰樼洰鍒楄〃澶辫触');
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    // 鍥炶溅閿悳绱㈠鐞哰6,8](@ref)
+    handleEnterSearch(event) {
+      const inputElement = event.target;
+      const searchQuery = inputElement.value.trim();
+
+
+        this.currentSearchQuery = searchQuery;
+        this.executeSearch(searchQuery);
+
+        // 闃叉榛樿琛屼负
+        event.preventDefault();
+        event.stopPropagation();
+
+    },
+
+    // 杩滅▼鎼滅储鏂规硶锛堝甫闃叉姈锛�
+    remoteMethod(query) {
+      if (this.searchTimer) {
+        clearTimeout(this.searchTimer);
+      }
+
+      this.searchTimer = setTimeout(() => {
+        this.currentSearchQuery = query;
+        this.executeSearch(query);
+      }, 300);
+    },
+
+    // 鎵ц鎼滅储
+    async executeSearch(query) {
+      if (query === '') {
+        this.queryParams.scriptContent = '';
+        await this.getList();
+        return;
+      }
+
+      this.searchLoading = true;
+
+      try {
+        const searchParams = {
+          pageNum: 1,
+          pageSize: 50,
+          scriptType: "1",
+          scriptContent: query
+        };
+
+        const response = await getissuelist(searchParams);
+        this.targetList = response.rows || [];
+
+        if (this.targetList.length === 0) {
+          this.$message.info(`鏈壘鍒板寘鍚�"${query}"鐨勯棶棰榒);
+        }
+      } catch (error) {
+        console.error('鎼滅储棰樼洰澶辫触:', error);
+        this.$message.error('鎼滅储鏈嶅姟寮傚父锛岃绋嶅悗閲嶈瘯');
+        this.targetList = [];
+      } finally {
+        this.searchLoading = false;
+      }
+    },
+
+    // 澶氶�夐鐩敼鍙樺鐞�
+    handleTargetChange(selectedIds) {
+      if (selectedIds && selectedIds.length > 0) {
+        this.Labelstatistics(selectedIds.join(','));
+      } else {
+        this.processedTableData = [];
+        this.spanArr = [];
+      }
+    },
+
+    // 鑾峰彇缁熻淇℃伅
+    async Labelstatistics(scriptIds) {
+      if (!scriptIds) {
+        this.processedTableData = [];
+        this.spanArr = [];
+        return;
+      }
+
+      this.loading = true;
+      try {
+        const response = await compileissuestatistics({ scriptids: scriptIds });
+        this.tableData = response.data || [];
+        this.processTableData();
+      } catch (error) {
+        console.error('鑾峰彇缁熻淇℃伅澶辫触:', error);
+        this.$message.error('鑾峰彇缁熻淇℃伅澶辫触');
+        this.processedTableData = [];
+        this.spanArr = [];
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    // 澶勭悊琛ㄦ牸鏁版嵁
+    processTableData() {
+      if (!this.tableData || Object.keys(this.tableData).length === 0) {
+        this.processedTableData = [];
+        return;
+      }
+
+      const processedData = [];
+
+      Object.keys(this.tableData).forEach(scriptId => {
+        const questionData = this.tableData[scriptId];
+
+        if (questionData && questionData.details) {
+          const targetName = questionData.scriptContent || `棰樼洰${scriptId}`;
+          const targetShowCount = questionData.allQuantity || 0;
+          const completedPercentage = questionData.completedPercentage || "0";
+
+          questionData.details.forEach(detail => {
+            if (detail.optionText) {
+              processedData.push({
+                scriptid: scriptId,
+                targetname: targetName,
+                targetShowCount: targetShowCount,
+                matchedtext: detail.optionText,
+                count: detail.chosenQuantity || 0,
+                percentage: detail.chosenPercentage || "0",
+                completedPercentage: completedPercentage,
+                allQuantity: questionData.allQuantity || 0,
+                completedQuantity: questionData.completedQuantity || 0
+              });
+            }
+          });
+
+          if (questionData.details.length === 0) {
+            processedData.push({
+              scriptid: scriptId,
+              targetname: targetName,
+              targetShowCount: targetShowCount,
+              matchedtext: '-',
+              count: 0,
+              percentage: "0",
+              completedPercentage: completedPercentage,
+              allQuantity: questionData.allQuantity || 0,
+              completedQuantity: questionData.completedQuantity || 0
+            });
+          }
+        }
+      });
+
+      this.processedTableData = processedData;
+    },
+
+    // 鐢熸垚鍚堝苟淇℃伅鏁扮粍
+    getSpanArr(data) {
+      this.spanArr = [];
+
+      if (!data || data.length === 0) return;
+
+      for (let i = 0; i < data.length; i++) {
+        if (i === 0) {
+          this.spanArr.push(1);
+          this.pos = 0;
+        } else {
+          if (data[i].scriptid === data[i - 1].scriptid) {
+            this.spanArr[this.pos] += 1;
+            this.spanArr.push(0);
+          } else {
+            this.spanArr.push(1);
+            this.pos = i;
+          }
+        }
+      }
+    },
+
+    // 鍗曞厓鏍煎悎骞舵柟娉�
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2) {
+        if (this.spanArr.length > rowIndex) {
+          const rowspan = this.spanArr[rowIndex];
+          const colspan = rowspan > 0 ? 1 : 0;
+
+          return {
+            rowspan: rowspan,
+            colspan: colspan
+          };
+        }
+      }
+    },
+
+    // 鏍煎紡鍖栫櫨鍒嗘瘮鏄剧ず
+    formatPercentage(value) {
+      const numValue = Number(value);
+      return isNaN(numValue) ? '0%' : `${(numValue * 100).toFixed(2)}%`;
+    },
+
+    // 琛ㄦ牸鍚堣琛岃绠�
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = '鍚堣';
+          return;
+        }
+
+        if (data.length === 0) {
+          sums[index] = '-';
+          return;
+        }
+
+        switch (column.property) {
+          case 'targetShowCount':
+            const totalQuestions = new Set(data.map(item => item.scriptid)).size;
+            sums[index] = `${totalQuestions}涓鐩甡;
+            break;
+
+          case 'count':
+            const values = data.map(item => Number(item.count));
+            const totalCount = values.reduce((prev, curr) => prev + curr, 0);
+            sums[index] = `${totalCount}娆;
+            break;
+
+          case 'percentage':
+            const percentages = data.map(item => Number(item.percentage));
+            const validPercentages = percentages.filter(p => !isNaN(p));
+            if (validPercentages.length > 0) {
+              const avgPercentage = validPercentages.reduce((a, b) => a + b, 0) / validPercentages.length;
+              sums[index] = `${(avgPercentage * 100).toFixed(2)}%`;
+            } else {
+              sums[index] = '0%';
+            }
+            break;
+
+          case 'completedPercentage':
+            const completedPercentages = data.map(item => Number(item.completedPercentage));
+            const validCompleted = completedPercentages.filter(p => !isNaN(p));
+            if (validCompleted.length > 0) {
+              const avgCompleted = validCompleted.reduce((a, b) => a + b, 0) / validCompleted.length;
+              sums[index] = `${(avgCompleted * 100).toFixed(2)}%`;
+            } else {
+              sums[index] = '0%';
+            }
+            break;
+
+          default:
+            sums[index] = '-';
+            break;
+        }
+      });
+
+      return sums;
+    }
+  },
+
+  beforeDestroy() {
+    if (this.searchTimer) {
+      clearTimeout(this.searchTimer);
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.analysis-top {
+  border: 1px solid #dcdfe6;
+  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
+  margin: 15px;
+
+  .title-top {
+    background-color: #6784f2;
+    color: #fff;
+    padding: 10px 20px;
+    font-size: 20px;
+    font-weight: 500;
+    margin-bottom: 20px;
+  }
+
+  .value {
+    padding: 0 20px 20px;
+  }
+}
+
+.formindex {
+  margin: 0 15px;
+  border: 1px solid #dcdfe6;
+  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
+  padding: 20px;
+}
+
+.selected-ids {
+  padding: 8px 12px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  border: 1px solid #e4e7ed;
+  min-height: 36px;
+  word-break: break-all;
+  line-height: 1.5;
+}
+
+.target-name-cell {
+  font-weight: 600;
+  color: #409eff;
+}
+
+.progress-text {
+  margin-left: 10px;
+  font-size: 12px;
+  color: #909399;
+}
+
+::v-deep .el-progress-bar {
+  padding-right: 0;
+  margin-right: 0;
+}
+
+::v-deep .el-select {
+  width: 100%;
+}
+
+::v-deep .el-table {
+  .cell {
+    word-break: break-word;
+  }
+
+  .el-table__body tr:hover > td.el-table__cell {
+    background-color: #f5f7fa;
+  }
+
+  .el-table__body .el-table__cell {
+    vertical-align: top;
+  }
+}
+
+.merged-cell {
+  background-color: #f0f9ff;
+  font-weight: 600;
+}
+
+::v-deep .el-select__tags {
+  .el-tag {
+    max-width: 200px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+
+    .el-tag__close {
+      margin-left: 4px;
+    }
+  }
+}
+</style>

--
Gitblit v1.9.3