| | |
| | | <el-option v-for="rn in ruleOptions" :key="rn" :label="rn" :value="rn"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="问题类型"> |
| | | <el-radio-group v-model="issueScope" size="small" @change="updateBatchSelection"> |
| | | <el-radio-button label="verify">核实型</el-radio-button> |
| | | <el-radio-button label="all">全部</el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="状态"> |
| | | <el-select v-model="statusScope" style="width:110px" @change="updateBatchSelection"> |
| | | <el-option label="全部" value="all"></el-option> |
| | | <el-option label="待处理" value="pending"></el-option> |
| | | <el-option label="已处理" value="handled"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="视图"> |
| | | <el-radio-group v-model="viewMode"> |
| | | <el-radio label="detail">按条明细</el-radio> |
| | |
| | | 共 {{ results.length }} 条问题,{{ mergedResults.length }} 家企业 |
| | | </div> |
| | | <div class="table-area" style="flex:1;min-height:0"> |
| | | <!-- 明细视图:一条问题一张卡片 --> |
| | | <!-- 明细视图:一条问题一行(与导出模板 Sheet“审核结果”同款) --> |
| | | <div v-if="viewMode === 'detail'" class="detail-cards-wrap" v-loading="loading"> |
| | | <div class="detail-toolbar"> |
| | | <el-checkbox :value="allSelected" :indeterminate="someSelected" @change="toggleSelectAll">全选当前 {{ filteredResults.length }} 条</el-checkbox> |
| | | <span class="toolbar-tip">勾选后可批量确认 / 忽略</span> |
| | | </div> |
| | | <div v-for="row in filteredResults" :key="row.id" class="detail-card" |
| | | :class="{ 'card-red': row.alertLevel === 'RED', 'card-yellow': row.alertLevel === 'YELLOW', 'card-done': row.status !== 'PENDING' }"> |
| | | <div class="card-head"> |
| | | <el-checkbox v-model="row._selected" @change="updateBatchSelection"></el-checkbox> |
| | | <div class="card-ent"> |
| | | <div class="ent-name">{{ row.enterpriseName || row.city || '未知企业' }}</div> |
| | | <div class="ent-sub">{{ row.reportPeriod }}</div> |
| | | </div> |
| | | <el-tag :type="row.alertLevel === 'RED' ? 'danger' : 'warning'" size="small" effect="dark">{{ row.alertLevel }}</el-tag> |
| | | <el-tag :type="statusType(row.status)" size="small" effect="plain" class="status-tag"> |
| | | <i :class="statusIcon(row.status)"></i> {{ statusText(row.status) }} |
| | | </el-tag> |
| | | <span class="spacer"></span> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(row)">数据</el-link> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="success" icon="el-icon-check" round @click="review(row, 'CONFIRMED')">确认</el-button> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="info" icon="el-icon-close" round plain @click="review(row, 'IGNORED')">忽略</el-button> |
| | | <span v-else class="done-text">已处理</span> |
| | | <el-table :data="filteredResults" border stripe height="100%" |
| | | :header-cell-style="{ background: '#F5F7FA', color: '#303133', fontWeight: 600 }"> |
| | | <el-table-column width="40"> |
| | | <template slot-scope="{ row }"> |
| | | <el-checkbox v-model="row._selected" @change="updateBatchSelection"></el-checkbox> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="reportPeriod" label="报表期" width="90"></el-table-column> |
| | | <el-table-column label="企业/市州" min-width="200" show-overflow-tooltip> |
| | | <template slot-scope="{ row }">{{ row.enterpriseName || row.city || '未知企业' }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="ruleCode" label="规则编码" width="100"></el-table-column> |
| | | <el-table-column prop="ruleName" label="审核规则" min-width="150" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="等级" width="76"> |
| | | <template slot-scope="{ row }"> |
| | | <el-tag :type="row.alertLevel === 'RED' ? 'danger' : 'warning'" size="mini">{{ row.alertLevel }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="actualValue" label="实际值" min-width="230" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="thresholdValue" label="阈值/基准" min-width="140" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="deviation" label="偏差说明" min-width="170" show-overflow-tooltip></el-table-column> |
| | | <el-table-column label="状态" width="92"> |
| | | <template slot-scope="{ row }"> |
| | | <el-tag :type="statusType(row.status)" size="mini"> |
| | | <i :class="statusIcon(row.status)"></i> {{ statusText(row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="185" align="right"> |
| | | <template slot-scope="{ row }"> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(row)">数据</el-link> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="success" icon="el-icon-check" round @click="review(row, 'CONFIRMED')">确认</el-button> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="info" icon="el-icon-close" round plain @click="review(row, 'IGNORED')">忽略</el-button> |
| | | <span v-else class="done-text">已处理</span> |
| | | </template> |
| | | </el-table-column> |
| | | <div slot="empty"> |
| | | <el-empty description="当前筛选条件下没有问题数据"></el-empty> |
| | | </div> |
| | | <div class="card-body"> |
| | | <div class="rule-title"> |
| | | <b>{{ row.ruleName }}</b> |
| | | <span class="rule-code">{{ row.ruleCode }}</span> |
| | | </div> |
| | | <div class="card-details"> |
| | | <div class="detail-line"><span class="dt-label">实际</span><span class="dt-val">{{ row.actualValue }}</span></div> |
| | | <div class="detail-line"><span class="dt-label">基准</span><span class="dt-val">{{ row.thresholdValue }}</span></div> |
| | | <div class="detail-line"><span class="dt-label">差异</span><span class="dt-val dt-warn">{{ row.deviation }}</span></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-if="!filteredResults.length" class="empty-tip"> |
| | | <el-empty description="当前筛选条件下没有问题数据"></el-empty> |
| | | </div> |
| | | </el-table> |
| | | </div> |
| | | <!-- 合并视图 --> |
| | | <el-table v-else :data="mergedResults" border stripe v-loading="loading" height="100%" |
| | |
| | | data() { |
| | | return { |
| | | period: '', reportType: 'H2032', loading: false, marking: false, results: [], ruleStats: [], statsCollapsed: false, |
| | | enterpriseFilter: '', ruleFilter: '', viewMode: 'merged', batchSelection: [], focusMode: false, |
| | | enterpriseFilter: '', ruleFilter: '', viewMode: 'detail', issueScope: 'verify', statusScope: 'all', batchSelection: [], focusMode: false, |
| | | explainDrafts: {}, savingExplainId: null, expandedExplain: null, |
| | | monthVisible: false, monthLoading: false, monthType: '', monthPeriod: '', monthKeyword: '', monthRecords: [], monthColumns: [] |
| | | } |
| | |
| | | const list = this.filteredResults |
| | | return list.some(r => r._selected) && !this.allSelected |
| | | }, |
| | | isReminderRow(r) { |
| | | return !!(r && r.ruleCode === 'RULE_004') |
| | | }, |
| | | filteredResults() { |
| | | const kw = (this.enterpriseFilter || '').trim() |
| | | const rule = this.ruleFilter |
| | | if (!kw && !rule) return this.results |
| | | const scope = this.issueScope || 'verify' |
| | | const st = this.statusScope || 'all' |
| | | return this.results.filter(r => { |
| | | if (kw && !(r.enterpriseName || '').includes(kw)) return false |
| | | if (rule && r.ruleName !== rule) return false |
| | | if (scope === 'verify' && this.isReminderRow(r)) return false |
| | | if (st === 'pending' && r.status !== 'PENDING') return false |
| | | if (st === 'handled' && (!r.status || r.status === 'PENDING')) return false |
| | | return true |
| | | }) |
| | | }, |
| | |
| | | }, |
| | | exportExcel() { |
| | | if (!this.period) { this.$message.warning('请选择报表期'); return } |
| | | window.open('/api/audit/export?period=' + this.period + '&reportType=' + this.reportType) |
| | | const q = 'period=' + this.period + '&reportType=' + this.reportType + '&onlyVerify=' + (this.issueScope !== 'all') + '&status=' + (this.statusScope || 'all') |
| | | window.open('/api/audit/export?' + q) |
| | | }, |
| | | review(row, status) { |
| | | if (status === 'IGNORED') { |