代码提交-3-13
This commit is contained in:
@@ -7,24 +7,84 @@
|
||||
</template>
|
||||
</uni-section>
|
||||
|
||||
<!-- 汇总图表 -->
|
||||
<qiun-data-charts type="ring" :opts="opts" :chartData="chartData" :errorShow="false" :tapLegend="false" />
|
||||
|
||||
<!-- 统计数据卡片 -->
|
||||
<uni-row :width="730" class="stats">
|
||||
<uni-col :span="6"><view class="stat"><text class="stat-label">总打卡</text><text class="stat-value">{{ stats.total }}</text></view></uni-col>
|
||||
<uni-col :span="6"><view class="stat"><text class="stat-label">活跃天</text><text class="stat-value">{{ stats.activeDays }}</text></view></uni-col>
|
||||
<uni-col :span="6"><view class="stat"><text class="stat-label">平均/天</text><text class="stat-value">{{ stats.avgPerDay }}</text></view></uni-col>
|
||||
<uni-col :span="6"><view class="stat"><text class="stat-label">最长连打</text><text class="stat-value">{{ stats.maxStreak }}</text></view></uni-col>
|
||||
</uni-row>
|
||||
|
||||
<!-- 统计概览 -->
|
||||
<uni-section class="mb-10" title="统计概览" type="line" />
|
||||
<view class="charts">
|
||||
<view class="chart-box">
|
||||
<qiun-data-charts type="column" :opts="optsBar" :chartData="chartWeek" :errorShow="false" />
|
||||
</view>
|
||||
<view class="chart-box">
|
||||
<qiun-data-charts type="column" :opts="optsBar" :chartData="chartHour" :errorShow="false" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 打卡数据卡片(样式与异常巡检一致) -->
|
||||
<uni-card v-if="summary.clockIn > 0 || latestRecord" :title="'本月总打卡:' + (summary.clockIn || 0)" :thumbnail="avatar" @click="onSummaryClick">
|
||||
<uni-row class="demo-uni-row" :width="nvueWidth">
|
||||
<!-- 左侧信息 -->
|
||||
<uni-col :span="16">
|
||||
<view>
|
||||
<text class="uni-body">打卡状态:{{ summary.clockState || '-' }}</text>
|
||||
</view>
|
||||
<view v-if="latestRecord">
|
||||
<text class="uni-body">最近时间:{{ formatDate(latestRecord.inspectionTime) }}</text>
|
||||
</view>
|
||||
<view v-if="latestRecord">
|
||||
<text class="uni-body">巡检点:{{ latestRecord.inspectionPoint || '-' }}</text>
|
||||
</view>
|
||||
<view v-if="latestRecord">
|
||||
<text class="uni-body">巡检人:{{ latestRecord.inspectorUser || '-' }}</text>
|
||||
</view>
|
||||
</uni-col>
|
||||
<!-- 右侧缩略图 -->
|
||||
<uni-col :span="8" v-if="latestRecord">
|
||||
<view class="thumbs" v-if="firstThreeImages(latestImages).length">
|
||||
<image v-for="(img,i) in firstThreeImages(latestImages)" :key="i" :src="imageUrl(img)" mode="aspectFill" class="thumb" @click.stop="previewImages(latestImages, i)" />
|
||||
</view>
|
||||
<view class="tag-view">
|
||||
<uni-tag :inverted="true" :circle="true" text="已打卡" size="small" />
|
||||
</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
</uni-card>
|
||||
|
||||
<uni-section class="mb-10" title="打卡列表" List="info">
|
||||
<template v-slot:right>
|
||||
<uni-data-select style="width:70px;" :clear=false v-model="queryform.weekType" :localdata="weekList"
|
||||
@change="weekTypeSelectChange"></uni-data-select>
|
||||
</template>
|
||||
</uni-section>
|
||||
<uni-card v-for="item of cardList" :title="item.inspectionPoint" :thumbnail="avatar">
|
||||
<!-- 列表卡片,点击可查看详情 -->
|
||||
<uni-card v-for="item of cardList" :key="item.id || item.recordId" :title="item.inspectionPoint" :thumbnail="avatar" @click="onCardClick($event, item)">
|
||||
<uni-row class="demo-uni-row" :width="nvueWidth">
|
||||
<uni-col :span="20">
|
||||
<!-- 左侧信息 -->
|
||||
<uni-col :span="16">
|
||||
<view>
|
||||
<text class="uni-body">
|
||||
打卡时间:{{item.inspectionTime}}
|
||||
</text>
|
||||
<text class="uni-body">打卡时间:{{ formatDate(item.inspectionTime) }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="uni-body">巡检人:{{ item.inspectorUser || '-' }}</text>
|
||||
</view>
|
||||
<view v-if="item.remark">
|
||||
<text class="uni-body">备注:{{ item.remark }}</text>
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<!-- 右侧缩略图 -->
|
||||
<uni-col :span="8">
|
||||
<view class="thumbs" v-if="firstThreeImages(item.inspectionImg || item.clockInImg || item.signImg).length">
|
||||
<image v-for="(img,i) in firstThreeImages(item.inspectionImg || item.clockInImg || item.signImg)" :key="i" :src="imageUrl(img)" mode="aspectFill" class="thumb" @click.stop="previewImages(item.inspectionImg || item.clockInImg || item.signImg, i)" />
|
||||
</view>
|
||||
<view class="tag-view">
|
||||
<uni-tag :inverted="true" :circle="true" text="已打卡" size="small" />
|
||||
</view>
|
||||
@@ -38,9 +98,8 @@
|
||||
|
||||
|
||||
<script>
|
||||
import {
|
||||
listRecordView
|
||||
} from '@/api/inspection/record.js'
|
||||
import { listRecordView, getRecord } from '@/api/inspection/record.js'
|
||||
import config from '@/config'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -50,6 +109,10 @@
|
||||
// 数据可视化
|
||||
inspectionRecordViewTable: [],
|
||||
cardList: [],
|
||||
// 汇总卡片数据
|
||||
summary: { clockIn: 0, clockState: '' },
|
||||
latestRecord: null,
|
||||
latestImages: [],
|
||||
weekList: [{
|
||||
text: "全部",
|
||||
value: 0
|
||||
@@ -128,92 +191,97 @@
|
||||
chartData: {},
|
||||
//这里的 opts 是图表类型 type="ring" 的全部配置参数,您可以将此配置复制到 config-ucharts.js 文件中下标为 ['ring'] 的节点中来覆盖全局默认参数。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
|
||||
opts: {
|
||||
timing: "easeOut",
|
||||
duration: 1000,
|
||||
rotate: false,
|
||||
rotateLock: false,
|
||||
color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
|
||||
padding: [5, 5, 5, 5],
|
||||
fontSize: 13,
|
||||
fontColor: "#666666",
|
||||
dataLabel: false,
|
||||
dataPointShape: false,
|
||||
dataPointShapeType: "hollow",
|
||||
touchMoveLimit: 60,
|
||||
enableScroll: false,
|
||||
enableMarkLine: false,
|
||||
legend: {
|
||||
show: true,
|
||||
position: "bottom",
|
||||
lineHeight: 25,
|
||||
float: "center",
|
||||
padding: 5,
|
||||
margin: 5,
|
||||
backgroundColor: "rgba(0,0,0,0)",
|
||||
borderColor: "rgba(0,0,0,0)",
|
||||
borderWidth: 0,
|
||||
fontSize: 13,
|
||||
fontColor: "#666666",
|
||||
hiddenColor: "#CECECE",
|
||||
itemGap: 10
|
||||
},
|
||||
title: {
|
||||
name: "已打卡",
|
||||
fontSize: 15,
|
||||
color: "#666666",
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
subtitle: {
|
||||
name: "30",
|
||||
fontSize: 25,
|
||||
color: "#fbbd08",
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
extra: {
|
||||
ring: {
|
||||
ringWidth: 30,
|
||||
activeOpacity: 0.5,
|
||||
activeRadius: 10,
|
||||
offsetAngle: 0,
|
||||
labelWidth: 15,
|
||||
border: false,
|
||||
borderWidth: 3,
|
||||
borderColor: "#FFFFFF",
|
||||
centerColor: "#FFFFFF",
|
||||
customRadius: 0,
|
||||
linearType: "none"
|
||||
},
|
||||
tooltip: {
|
||||
showBox: true,
|
||||
showArrow: true,
|
||||
showCategory: false,
|
||||
borderWidth: 0,
|
||||
borderRadius: 0,
|
||||
borderColor: "#000000",
|
||||
borderOpacity: 0.7,
|
||||
bgColor: "#000000",
|
||||
bgOpacity: 0.7,
|
||||
gridType: "solid",
|
||||
dashLength: 4,
|
||||
gridColor: "#CCCCCC",
|
||||
boxPadding: 3,
|
||||
fontSize: 13,
|
||||
lineHeight: 20,
|
||||
fontColor: "#FFFFFF",
|
||||
legendShow: true,
|
||||
legendShape: "auto",
|
||||
splitLine: true,
|
||||
horizentalLine: false,
|
||||
xAxisLabel: false,
|
||||
yAxisLabel: false,
|
||||
labelBgColor: "#FFFFFF",
|
||||
labelBgOpacity: 0.7,
|
||||
labelFontColor: "#666666"
|
||||
}
|
||||
}
|
||||
}
|
||||
timing: "easeOut",
|
||||
duration: 1000,
|
||||
rotate: false,
|
||||
rotateLock: false,
|
||||
color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
|
||||
padding: [5, 5, 5, 5],
|
||||
fontSize: 13,
|
||||
fontColor: "#666666",
|
||||
dataLabel: false,
|
||||
dataPointShape: false,
|
||||
dataPointShapeType: "hollow",
|
||||
touchMoveLimit: 60,
|
||||
enableScroll: false,
|
||||
enableMarkLine: false,
|
||||
legend: {
|
||||
show: true,
|
||||
position: "bottom",
|
||||
lineHeight: 25,
|
||||
float: "center",
|
||||
padding: 5,
|
||||
margin: 5,
|
||||
backgroundColor: "rgba(0,0,0,0)",
|
||||
borderColor: "rgba(0,0,0,0)",
|
||||
borderWidth: 0,
|
||||
fontSize: 13,
|
||||
fontColor: "#666666",
|
||||
hiddenColor: "#CECECE",
|
||||
itemGap: 10
|
||||
},
|
||||
title: {
|
||||
name: "已打卡",
|
||||
fontSize: 15,
|
||||
color: "#666666",
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
subtitle: {
|
||||
name: "30",
|
||||
fontSize: 25,
|
||||
color: "#fbbd08",
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
extra: {
|
||||
ring: {
|
||||
ringWidth: 30,
|
||||
activeOpacity: 0.5,
|
||||
activeRadius: 10,
|
||||
offsetAngle: 0,
|
||||
labelWidth: 15,
|
||||
border: false,
|
||||
borderWidth: 3,
|
||||
borderColor: "#FFFFFF",
|
||||
centerColor: "#FFFFFF",
|
||||
customRadius: 0,
|
||||
linearType: "none"
|
||||
},
|
||||
tooltip: {
|
||||
showBox: true,
|
||||
showArrow: true,
|
||||
showCategory: false,
|
||||
borderWidth: 0,
|
||||
borderRadius: 0,
|
||||
borderColor: "#000000",
|
||||
borderOpacity: 0.7,
|
||||
bgColor: "#000000",
|
||||
bgOpacity: 0.7,
|
||||
gridType: "solid",
|
||||
dashLength: 4,
|
||||
gridColor: "#CCCCCC",
|
||||
boxPadding: 3,
|
||||
fontSize: 13,
|
||||
lineHeight: 20,
|
||||
fontColor: "#FFFFFF",
|
||||
legendShow: true,
|
||||
legendShape: "auto",
|
||||
splitLine: true,
|
||||
horizentalLine: false,
|
||||
xAxisLabel: false,
|
||||
yAxisLabel: false,
|
||||
labelBgColor: "#FFFFFF",
|
||||
labelBgOpacity: 0.7,
|
||||
labelFontColor: "#666666"
|
||||
}
|
||||
}
|
||||
},
|
||||
// 新增:统计与柱状图数据
|
||||
stats: { total: 0, activeDays: 0, avgPerDay: 0, maxStreak: 0 },
|
||||
optsBar: { legend: { show: false }, xAxis: { disableGrid: true }, yAxis: { disableGrid: false } },
|
||||
chartWeek: { categories: [], series: [{ name: '按周几', data: [] }] },
|
||||
chartHour: { categories: [], series: [{ name: '按时段', data: [] }] },
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -223,6 +291,12 @@
|
||||
this.queryform.month = currentMonth;
|
||||
listRecordView(this.queryform).then(res => {
|
||||
let data = res.data
|
||||
// 汇总卡片数据
|
||||
this.summary.clockIn = data.clockIn || 0
|
||||
this.summary.clockState = data.clockState || ''
|
||||
this.latestRecord = (data.inspectionRecordTables && data.inspectionRecordTables.length) ? data.inspectionRecordTables[0] : null
|
||||
this.latestImages = this.latestRecord ? (this.latestRecord.inspectionImg || this.latestRecord.clockInImg || this.latestRecord.signImg || []) : []
|
||||
// 图表数据
|
||||
if (data.clockIn != 0) {
|
||||
let obj = [{
|
||||
"name": data.clockState,
|
||||
@@ -232,7 +306,11 @@
|
||||
} else {
|
||||
this.inspectionRecordViewTable = []
|
||||
}
|
||||
this.cardList = data.inspectionRecordTables
|
||||
this.cardList = data.inspectionRecordTables || []
|
||||
// 新增:构建统计与柱状图
|
||||
this.buildWeekChart(this.cardList)
|
||||
this.buildHourChart(this.cardList)
|
||||
this.buildStats(this.cardList)
|
||||
})
|
||||
this.getServerData()
|
||||
},
|
||||
@@ -278,9 +356,83 @@
|
||||
this.chartData = JSON.parse(JSON.stringify(res));
|
||||
}, 1000);
|
||||
},
|
||||
// 统一图片数组处理(支持字符串或数组)
|
||||
firstThreeImages(imgs) {
|
||||
if (!imgs) return []
|
||||
if (Array.isArray(imgs)) return imgs.slice(0,3)
|
||||
if (typeof imgs === 'string') return imgs.split(',').filter(Boolean).slice(0,3)
|
||||
return []
|
||||
},
|
||||
imageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^https?:\/\//.test(path)) return path
|
||||
return `${config.baseUrl}${path.startsWith('/') ? path : '/' + path}`
|
||||
},
|
||||
previewImages(imgs, index=0) {
|
||||
const list = Array.isArray(imgs) ? imgs : (typeof imgs === 'string' ? imgs.split(',').filter(Boolean) : [])
|
||||
if (!list.length) return
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: list.map(this.imageUrl)
|
||||
})
|
||||
},
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
const d = new Date(dateStr)
|
||||
if (isNaN(d.getTime())) return dateStr
|
||||
const pad = n => (n<10?('0'+n):n)
|
||||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
|
||||
},
|
||||
onCardClick(e, item) {
|
||||
this.goDetail(item)
|
||||
},
|
||||
onSummaryClick() {
|
||||
// 若有最近一条记录,点击汇总卡片也进入其详情
|
||||
if (this.latestRecord) {
|
||||
this.goDetail(this.latestRecord)
|
||||
}
|
||||
},
|
||||
goDetail(item) {
|
||||
const id = item.id || item.recordId
|
||||
if (!id) {
|
||||
uni.showToast({ title: '记录ID缺失', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.navigateTo({ url: `/pages/work/inspection/checkInDetail/index?id=${id}` })
|
||||
},
|
||||
// 新增:统计构建方法
|
||||
buildWeekChart(rows) {
|
||||
const names = ['周一','周二','周三','周四','周五','周六','周日']
|
||||
const counts = Array(7).fill(0)
|
||||
(rows || []).forEach(r => { const d = new Date(r.inspectionTime); if (!isNaN(d)) { const idx = (d.getDay()+6)%7; counts[idx]++ } })
|
||||
this.chartWeek = { categories: names, series: [{ name: '按周几', data: counts }] }
|
||||
},
|
||||
buildHourChart(rows) {
|
||||
const buckets = Array(24).fill(0)
|
||||
(rows || []).forEach(r => { const d = new Date(r.inspectionTime); if (!isNaN(d)) { buckets[d.getHours()]++ } })
|
||||
const labels = buckets.map((_,h)=> (h<10?('0'+h):h)+':00')
|
||||
this.chartHour = { categories: labels, series: [{ name: '按时段', data: buckets }] }
|
||||
},
|
||||
buildStats(rows) {
|
||||
const list = rows || []
|
||||
const total = list.length
|
||||
const daySet = new Set(list.map(r => this.formatDate(r.inspectionTime).slice(0,10)))
|
||||
const activeDays = daySet.size
|
||||
const avgPerDay = activeDays ? (total/activeDays).toFixed(2) : 0
|
||||
// 计算最长连续天数
|
||||
const days = Array.from(daySet).sort()
|
||||
let maxStreak = 0, cur = 0, prev = null
|
||||
const toDate = s => new Date(s+'T00:00:00')
|
||||
days.forEach(s => { if (!prev) { cur=1; } else { const diff=(toDate(s)-toDate(prev))/(24*3600*1000); cur = diff===1 ? cur+1 : 1 } maxStreak = Math.max(maxStreak, cur); prev = s })
|
||||
this.stats = { total, activeDays, avgPerDay, maxStreak }
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
onShow() {
|
||||
// 返回页面时自动刷新列表,保持数据最新
|
||||
this.getList()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -304,6 +456,19 @@
|
||||
/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
|
||||
.charts-box {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.thumbs { display:flex; gap:6px; justify-content:flex-end; }
|
||||
.thumb { width: 60px; height: 60px; border-radius: 4px; background:#f5f5f5; }
|
||||
.tag-view { margin-top: 8px; display:flex; justify-content:flex-end; }
|
||||
|
||||
/* 新增:统计与图表布局样式 */
|
||||
.stats { margin: 10px 0; }
|
||||
.stat { background:#fff; border-radius:8px; padding:10px; display:flex; flex-direction:column; align-items:center }
|
||||
.stat-label { color:#666; font-size:12px }
|
||||
.stat-value { color:#1677ff; font-weight:bold; font-size:18px }
|
||||
.charts { display: grid; grid-template-columns: 1fr; gap: 12px; }
|
||||
@media (min-width: 380px) { .charts { grid-template-columns: 1fr 1fr; } }
|
||||
.chart-box { background: #fff; border-radius: 8px; padding: 6px; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user