|
@@ -1,118 +1,140 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <el-dialog title="巡检报告" :visible.sync="dialogVisible" width="920px" @open="load">
|
|
|
|
|
- <div class="report-wrap" v-loading="loading">
|
|
|
|
|
- <!-- 报告头 -->
|
|
|
|
|
- <div class="report-head" v-if="task">
|
|
|
|
|
- <div class="rh-left">
|
|
|
|
|
- <div class="rh-title">{{ task.storeName }}</div>
|
|
|
|
|
- <div class="rh-meta">巡检日期:{{ fmt(task.taskDate) }} | 巡检员:{{ task.inspectorName || '-' }} | 计划:{{ task.planName }}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="rh-score">
|
|
|
|
|
- <span class="rh-num" :class="{ fail: task.passFlag !== 1 }">{{ fmtNum(task.totalScore) }}</span>
|
|
|
|
|
- <span class="rh-unit">加权总分 / {{ fmtNum(task.maxScore) }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-tag size="small" :type="task.passFlag === 1 ? 'success' : 'danger'" class="rh-tag">{{ task.passFlag === 1 ? '✓ 及格' : '✗ 不及格' }}</el-tag>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="report-grid">
|
|
|
|
|
- <!-- 雷达图 -->
|
|
|
|
|
- <div class="chart-card">
|
|
|
|
|
- <h4>指标得分雷达图</h4>
|
|
|
|
|
- <canvas ref="radar" width="360" height="300" class="radar-canvas"></canvas>
|
|
|
|
|
- <div class="legend-line">
|
|
|
|
|
- <span class="legend-dot ok"></span>及格项
|
|
|
|
|
- <span class="legend-dot fail"></span>不及格项
|
|
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <el-dialog title="巡检报告" :visible.sync="dialogVisible" width="920px" @open="load">
|
|
|
|
|
+ <div class="report-wrap" v-loading="loading">
|
|
|
|
|
+ <div class="report-head" v-if="task">
|
|
|
|
|
+ <div class="rh-left">
|
|
|
|
|
+ <div class="rh-title">{{ task.storeName }}</div>
|
|
|
|
|
+ <div class="rh-meta">巡检日期:{{ fmt(task.taskDate) }} | 巡检员:{{ task.inspectorName || '-' }} | 计划:{{ task.planName }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="rh-score">
|
|
|
|
|
+ <span class="rh-num" :class="{ fail: task.passFlag !== 1 }">{{ fmtNum(task.totalScore) }}</span>
|
|
|
|
|
+ <span class="rh-unit">加权总分 / {{ fmtNum(task.maxScore) }}</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <el-tag size="small" :type="task.passFlag === 1 ? 'success' : 'danger'" class="rh-tag">{{ task.passFlag === 1 ? '✓ 及格' : '✗ 不及格' }}</el-tag>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 各指标得分明细 -->
|
|
|
|
|
- <div class="chart-card">
|
|
|
|
|
- <h4>各指标得分明细</h4>
|
|
|
|
|
- <div v-for="item in items" :key="item.taskItemId" class="ind-card" :class="{ 'ind-fail': item.passFlag !== 1 }">
|
|
|
|
|
- <div class="ind-head">
|
|
|
|
|
- <span class="ind-name">{{ item.indicatorName }}</span>
|
|
|
|
|
- <el-tag size="mini" :type="item.indicatorType === 1 ? 'primary' : 'warning'">{{ item.indicatorType === 1 ? '自动' : '人工' }}</el-tag>
|
|
|
|
|
- <span class="ind-raw" v-if="item.rawValueText">原始值:{{ item.rawValueText }}</span>
|
|
|
|
|
|
|
+ <div class="report-grid">
|
|
|
|
|
+ <div class="chart-card">
|
|
|
|
|
+ <h4>指标得分雷达图</h4>
|
|
|
|
|
+ <canvas ref="radar" width="360" height="300" class="radar-canvas"></canvas>
|
|
|
|
|
+ <div class="legend-line">
|
|
|
|
|
+ <span class="legend-dot ok"></span>及格项
|
|
|
|
|
+ <span class="legend-dot fail"></span>不及格项
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="ind-body">
|
|
|
|
|
- <div class="score-bar">
|
|
|
|
|
- <div class="score-track">
|
|
|
|
|
- <div class="score-fill" :class="item.passFlag === 1 ? 'fill-ok' : 'fill-fail'" :style="{ width: barWidth(item) + '%' }"></div>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="chart-card">
|
|
|
|
|
+ <h4>各指标得分明细</h4>
|
|
|
|
|
+ <div v-for="item in items" :key="item.taskItemId" class="ind-card" :class="{ 'ind-fail': item.passFlag !== 1 }">
|
|
|
|
|
+ <div class="ind-head">
|
|
|
|
|
+ <span class="ind-name">{{ item.indicatorName }}</span>
|
|
|
|
|
+ <el-tag size="mini" :type="item.indicatorType === 1 ? 'primary' : 'warning'">{{ item.indicatorType === 1 ? '自动' : '人工' }}</el-tag>
|
|
|
|
|
+ <span class="ind-raw" v-if="item.rawValueText">原始值:{{ item.rawValueText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="ind-body">
|
|
|
|
|
+ <div class="score-bar">
|
|
|
|
|
+ <div class="score-track">
|
|
|
|
|
+ <div class="score-fill" :class="item.passFlag === 1 ? 'fill-ok' : 'fill-fail'" :style="{ width: barWidth(item) + '%' }"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <span class="score-val">{{ fmtNum(item.score) }}/{{ fmtNum(item.maxScore) }}</span>
|
|
|
</div>
|
|
</div>
|
|
|
- <span class="score-val">{{ fmtNum(item.score) }}/{{ fmtNum(item.maxScore) }}</span>
|
|
|
|
|
|
|
+ <el-tag size="mini" :type="item.passFlag === 1 ? 'success' : 'danger'">{{ item.passFlag === 1 ? '及格' : '不及格' }}</el-tag>
|
|
|
|
|
+ <span class="ind-photo" v-if="pictures(item).length">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-for="(p, i) in pictures(item)"
|
|
|
|
|
+ :key="i"
|
|
|
|
|
+ :src="p"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ :preview-src-list="pictures(item)"
|
|
|
|
|
+ class="thumb-sm" />
|
|
|
|
|
+ </span>
|
|
|
</div>
|
|
</div>
|
|
|
- <el-tag size="mini" :type="item.passFlag === 1 ? 'success' : 'danger'">{{ item.passFlag === 1 ? '及格' : '不及格' }}</el-tag>
|
|
|
|
|
- <span class="ind-photo" v-if="pictures(item).length">
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="detail-block">
|
|
|
|
|
+ <h4>逐项明细</h4>
|
|
|
|
|
+ <el-table :data="items" border size="mini">
|
|
|
|
|
+ <el-table-column prop="indicatorName" label="指标" min-width="110">
|
|
|
|
|
+ <template slot-scope="s"><span :class="{ 'row-fail': s.row.passFlag !== 1 }">{{ s.row.indicatorName }}</span></template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="类型" width="75">
|
|
|
|
|
+ <template slot-scope="s"><el-tag size="mini" :type="s.row.indicatorType === 1 ? 'primary' : 'warning'">{{ s.row.indicatorType === 1 ? '自动' : '人工' }}</el-tag></template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="weight" label="权重" width="65" align="center">
|
|
|
|
|
+ <template slot-scope="s">{{ fmtNum(s.row.weight) }}%</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="原始值" width="90">
|
|
|
|
|
+ <template slot-scope="s">{{ s.row.rawValueText || '-' }}</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="得分" width="90" align="center">
|
|
|
|
|
+ <template slot-scope="s">{{ fmtNum(s.row.score) }}/{{ fmtNum(s.row.maxScore) }}</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="加权分" width="70" align="center">
|
|
|
|
|
+ <template slot-scope="s">{{ fmtNum(s.row.weightedScore) }}</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="结果" width="75">
|
|
|
|
|
+ <template slot-scope="s"><el-tag size="mini" :type="s.row.passFlag === 1 ? 'success' : 'danger'">{{ s.row.passFlag === 1 ? '及格' : '不及格' }}</el-tag></template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="照片" width="150">
|
|
|
|
|
+ <template slot-scope="s">
|
|
|
<el-image
|
|
<el-image
|
|
|
- v-for="(p, i) in pictures(item)"
|
|
|
|
|
|
|
+ v-for="(p, i) in pictures(s.row)"
|
|
|
:key="i"
|
|
:key="i"
|
|
|
:src="p"
|
|
:src="p"
|
|
|
fit="cover"
|
|
fit="cover"
|
|
|
- :preview-src-list="pictures(item)"
|
|
|
|
|
- class="thumb-sm" />
|
|
|
|
|
- </span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ :preview-src-list="pictures(s.row)"
|
|
|
|
|
+ class="thumb" />
|
|
|
|
|
+ <span v-if="!pictures(s.row).length" class="muted">-</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="rmk" label="备注" min-width="120">
|
|
|
|
|
+ <template slot-scope="s">{{ s.row.rmk || '-' }}</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
|
|
|
|
- <!-- 逐项明细表 -->
|
|
|
|
|
- <div class="detail-block">
|
|
|
|
|
- <h4>逐项明细</h4>
|
|
|
|
|
- <el-table :data="items" border size="mini">
|
|
|
|
|
- <el-table-column prop="indicatorName" label="指标" min-width="110">
|
|
|
|
|
- <template slot-scope="s"><span :class="{ 'row-fail': s.row.passFlag !== 1 }">{{ s.row.indicatorName }}</span></template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="类型" width="75">
|
|
|
|
|
- <template slot-scope="s"><el-tag size="mini" :type="s.row.indicatorType === 1 ? 'primary' : 'warning'">{{ s.row.indicatorType === 1 ? '自动' : '人工' }}</el-tag></template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column prop="weight" label="权重" width="65" align="center">
|
|
|
|
|
- <template slot-scope="s">{{ fmtNum(s.row.weight) }}%</template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="原始值" width="90">
|
|
|
|
|
- <template slot-scope="s">{{ s.row.rawValueText || '-' }}</template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="得分" width="90" align="center">
|
|
|
|
|
- <template slot-scope="s">{{ fmtNum(s.row.score) }}/{{ fmtNum(s.row.maxScore) }}</template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="加权分" width="70" align="center">
|
|
|
|
|
- <template slot-scope="s">{{ fmtNum(s.row.weightedScore) }}</template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="结果" width="75">
|
|
|
|
|
- <template slot-scope="s"><el-tag size="mini" :type="s.row.passFlag === 1 ? 'success' : 'danger'">{{ s.row.passFlag === 1 ? '及格' : '不及格' }}</el-tag></template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="照片" width="150">
|
|
|
|
|
- <template slot-scope="s">
|
|
|
|
|
- <el-image
|
|
|
|
|
- v-for="(p, i) in pictures(s.row)"
|
|
|
|
|
- :key="i"
|
|
|
|
|
- :src="p"
|
|
|
|
|
- fit="cover"
|
|
|
|
|
- :preview-src-list="pictures(s.row)"
|
|
|
|
|
- class="thumb" />
|
|
|
|
|
- <span v-if="!pictures(s.row).length" class="muted">-</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column prop="rmk" label="备注" min-width="120">
|
|
|
|
|
- <template slot-scope="s">{{ s.row.rmk || '-' }}</template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table>
|
|
|
|
|
|
|
+ <div class="rect-block" v-if="task && task.passFlag !== 1">
|
|
|
|
|
+ <h4>整改记录</h4>
|
|
|
|
|
+ <el-table :data="rects" border size="mini" v-if="rects.length">
|
|
|
|
|
+ <el-table-column prop="indicatorName" label="指标" min-width="100" />
|
|
|
|
|
+ <el-table-column label="状态" width="110">
|
|
|
|
|
+ <template slot-scope="s">
|
|
|
|
|
+ <el-tag size="mini" :style="rectTagStyle(s.row.status)">{{ rectText(s.row.status) }}</el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="轮次" width="60" align="center">
|
|
|
|
|
+ <template slot-scope="s">第 {{ s.row.rectRound || 1 }} 轮</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="截止日期" width="120">
|
|
|
|
|
+ <template slot-scope="s">{{ fmt(s.row.deadlineDate) }}</template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="操作" width="80">
|
|
|
|
|
+ <template slot-scope="s">
|
|
|
|
|
+ <el-button type="text" size="mini" @click="showRectDetail(s.row)">查看</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <div v-else class="muted" style="padding:12px 0">加载中...</div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
- <el-alert v-if="task && task.passFlag !== 1" type="warning" :closable="false" class="rect-tip"
|
|
|
|
|
- title="该任务存在不及格项,提交时已自动生成整改记录,请到「整改流程管理」中跟进。" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <span slot="footer">
|
|
|
|
|
- <el-button @click="dialogVisible = false">关闭</el-button>
|
|
|
|
|
- </span>
|
|
|
|
|
- </el-dialog>
|
|
|
|
|
|
|
+ <span slot="footer">
|
|
|
|
|
+ <el-button @click="dialogVisible = false">关闭</el-button>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ <rect-detail :visible.sync="rectDetailVisible" :row="rectDetailRow" />
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { post, fmt, fmtNum, splitPictures } from '../common'
|
|
|
|
|
|
|
+import { post, fmt, fmtNum, splitPictures, RECT_STATUS } from '../common'
|
|
|
|
|
+import RectDetail from '../rectification/Detail.vue'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
name: 'InspectTaskReport',
|
|
name: 'InspectTaskReport',
|
|
|
|
|
+ components: { RectDetail },
|
|
|
props: {
|
|
props: {
|
|
|
visible: Boolean,
|
|
visible: Boolean,
|
|
|
taskId: [Number, String]
|
|
taskId: [Number, String]
|
|
@@ -124,7 +146,7 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
data() {
|
|
data() {
|
|
|
- return { loading: false, task: null, items: [] }
|
|
|
|
|
|
|
+ return { loading: false, task: null, items: [], rects: [], rectDetailVisible: false, rectDetailRow: null }
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
load() {
|
|
load() {
|
|
@@ -132,10 +154,12 @@ export default {
|
|
|
this.loading = true
|
|
this.loading = true
|
|
|
Promise.all([
|
|
Promise.all([
|
|
|
post(this.$axios, '/inspectTaskManage/getTaskDetail', { id: this.taskId }),
|
|
post(this.$axios, '/inspectTaskManage/getTaskDetail', { id: this.taskId }),
|
|
|
- post(this.$axios, '/inspectTaskManage/getTaskItems', { taskId: this.taskId })
|
|
|
|
|
- ]).then(([r1, r2]) => {
|
|
|
|
|
|
|
+ post(this.$axios, '/inspectTaskManage/getTaskItems', { taskId: this.taskId }),
|
|
|
|
|
+ post(this.$axios, '/rectificationManage/getRectPage', { taskId: this.taskId, pageSize: 50, currentPage: 1 })
|
|
|
|
|
+ ]).then(([r1, r2, r3]) => {
|
|
|
this.task = (r1 && r1.obj) || null
|
|
this.task = (r1 && r1.obj) || null
|
|
|
this.items = (r2 && r2.list) || []
|
|
this.items = (r2 && r2.list) || []
|
|
|
|
|
+ this.rects = (r3 && r3.list) || []
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
setTimeout(() => this.drawRadar(), 60)
|
|
setTimeout(() => this.drawRadar(), 60)
|
|
|
})
|
|
})
|
|
@@ -147,6 +171,15 @@ export default {
|
|
|
return Math.max(0, Math.min(100, Math.round(Number(item.score || 0) / max * 100)))
|
|
return Math.max(0, Math.min(100, Math.round(Number(item.score || 0) / max * 100)))
|
|
|
},
|
|
},
|
|
|
pictures(row) { return splitPictures(row.pictureUrls) },
|
|
pictures(row) { return splitPictures(row.pictureUrls) },
|
|
|
|
|
+ rectText(v) { return (RECT_STATUS[v] || {}).text || '-' },
|
|
|
|
|
+ rectTagStyle(v) {
|
|
|
|
|
+ const st = RECT_STATUS[v] || {}
|
|
|
|
|
+ return { background: st.color, borderColor: st.color, color: '#fff' }
|
|
|
|
|
+ },
|
|
|
|
|
+ showRectDetail(row) {
|
|
|
|
|
+ this.rectDetailRow = row
|
|
|
|
|
+ this.rectDetailVisible = true
|
|
|
|
|
+ },
|
|
|
drawRadar() {
|
|
drawRadar() {
|
|
|
const canvas = this.$refs.radar
|
|
const canvas = this.$refs.radar
|
|
|
if (!canvas) return
|
|
if (!canvas) return
|
|
@@ -165,7 +198,6 @@ export default {
|
|
|
x: cx + R * ratio * Math.cos(angle(i)),
|
|
x: cx + R * ratio * Math.cos(angle(i)),
|
|
|
y: cy + R * ratio * Math.sin(angle(i))
|
|
y: cy + R * ratio * Math.sin(angle(i))
|
|
|
})
|
|
})
|
|
|
- // 网格环
|
|
|
|
|
ctx.lineWidth = 1
|
|
ctx.lineWidth = 1
|
|
|
for (let g = 1; g <= 4; g++) {
|
|
for (let g = 1; g <= 4; g++) {
|
|
|
ctx.beginPath()
|
|
ctx.beginPath()
|
|
@@ -177,7 +209,6 @@ export default {
|
|
|
ctx.strokeStyle = 'rgba(0,0,0,0.08)'
|
|
ctx.strokeStyle = 'rgba(0,0,0,0.08)'
|
|
|
ctx.stroke()
|
|
ctx.stroke()
|
|
|
}
|
|
}
|
|
|
- // 轴线 + 标签
|
|
|
|
|
ctx.font = '12px Microsoft YaHei, sans-serif'
|
|
ctx.font = '12px Microsoft YaHei, sans-serif'
|
|
|
ctx.fillStyle = '#606266'
|
|
ctx.fillStyle = '#606266'
|
|
|
ctx.textAlign = 'center'
|
|
ctx.textAlign = 'center'
|
|
@@ -192,7 +223,6 @@ export default {
|
|
|
const lp = point(i, 1.18)
|
|
const lp = point(i, 1.18)
|
|
|
ctx.fillText(items[i].indicatorName, lp.x, lp.y)
|
|
ctx.fillText(items[i].indicatorName, lp.x, lp.y)
|
|
|
}
|
|
}
|
|
|
- // 数据多边形
|
|
|
|
|
ctx.beginPath()
|
|
ctx.beginPath()
|
|
|
items.forEach((item, i) => {
|
|
items.forEach((item, i) => {
|
|
|
const max = Number(item.maxScore) || 1
|
|
const max = Number(item.maxScore) || 1
|
|
@@ -207,7 +237,6 @@ export default {
|
|
|
ctx.strokeStyle = '#1890ff'
|
|
ctx.strokeStyle = '#1890ff'
|
|
|
ctx.lineWidth = 2
|
|
ctx.lineWidth = 2
|
|
|
ctx.stroke()
|
|
ctx.stroke()
|
|
|
- // 得分点
|
|
|
|
|
items.forEach((item, i) => {
|
|
items.forEach((item, i) => {
|
|
|
const max = Number(item.maxScore) || 1
|
|
const max = Number(item.maxScore) || 1
|
|
|
const ratio = Math.max(0, Math.min(1, (Number(item.score) || 0) / max))
|
|
const ratio = Math.max(0, Math.min(1, (Number(item.score) || 0) / max))
|
|
@@ -262,5 +291,6 @@ export default {
|
|
|
.row-fail { color: #f56c6c; }
|
|
.row-fail { color: #f56c6c; }
|
|
|
.thumb { width: 40px; height: 40px; margin-right: 6px; border-radius: 4px; }
|
|
.thumb { width: 40px; height: 40px; margin-right: 6px; border-radius: 4px; }
|
|
|
.muted { color: #909399; }
|
|
.muted { color: #909399; }
|
|
|
-.rect-tip { margin-top: 10px; }
|
|
|
|
|
-</style>
|
|
|
|
|
|
|
+.rect-block { margin-top: 16px; }
|
|
|
|
|
+.rect-block h4 { margin: 0 0 10px; font-size: 13px; color: #606266; }
|
|
|
|
|
+</style>
|