feat: 重构勘察业务为明细模式并新增定时任务人性化配置
- 重构勘察业务:移除SOP相关表,新增勘察明细表支持建筑/楼层/房间/照片管理 - 新增定时任务人性化频率配置,支持分钟/小时/天/周/月/自定义六种模式 - 新增频率预览接口,支持配置转换为cron表达式与执行时间预览 - 更新系统品牌名称为鑫潼智电,修改全局标题与登录页文案
This commit is contained in:
1 parent
f72644c24f
commit
22d27a940d
29 files changed
+1908
-576
No files matched your search
@@ -514,29 +514,31 @@
|
||||
<div v-else class="detail-text">—</div>
|
||||
</div>
|
||||
|
||||
<div v-if="detailRecord.sopResults?.length" class="detail-block">
|
||||
<div class="detail-label">
|
||||
勘察回执({{ detailSopDone }} / {{ detailRecord.sopResults.length }} 项已完成)
|
||||
</div>
|
||||
<div v-for="row in detailRecord.sopResults" :key="row.id" class="sop-item">
|
||||
<div class="sop-item-head">
|
||||
<span class="sop-item-name">{{ row.itemName || row.sopItem?.itemName || '检查项' }}</span>
|
||||
<span class="chip" :style="sopChipStyle(row.checked)">{{ row.checked ? '已回执' : '未回执' }}</span>
|
||||
<div v-if="detailRecord.details?.length" class="detail-block">
|
||||
<div class="detail-label">勘察明细({{ detailRecord.details.length }} 条)</div>
|
||||
<div class="detail-list">
|
||||
<div v-for="(row, idx) in detailRecord.details" :key="row.id ?? idx" class="detail-row">
|
||||
<div class="detail-row-head">
|
||||
<span class="detail-row-idx">明细 {{ idx + 1 }}</span>
|
||||
<span class="detail-row-scope">
|
||||
{{ row.buildingName || '—' }} · {{ floorLabel(row.floorNo) }}
|
||||
<template v-if="row.roomName"> · {{ row.roomName }}</template>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="row.photoUrls?.length" class="photo-list">
|
||||
<a-image-preview-group>
|
||||
<a-image
|
||||
v-for="(url, pi) in row.photoUrls"
|
||||
:key="pi"
|
||||
:src="url"
|
||||
:width="110"
|
||||
:height="80"
|
||||
style="object-fit: cover; border-radius: 8px"
|
||||
/>
|
||||
</a-image-preview-group>
|
||||
</div>
|
||||
<div v-if="row.remark" class="detail-row-remark">备注:{{ row.remark }}</div>
|
||||
</div>
|
||||
<div v-if="row.receiptUrls?.length" class="photo-list">
|
||||
<a-image
|
||||
v-for="(url, idx) in row.receiptUrls"
|
||||
:key="idx"
|
||||
:src="url"
|
||||
:width="110"
|
||||
:height="80"
|
||||
style="object-fit: cover; border-radius: 8px"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="row.receiptValue?.length" class="detail-text">
|
||||
{{ row.receiptValue.join('、') }}
|
||||
</div>
|
||||
<div v-if="row.remark" class="sop-item-remark">备注:{{ row.remark }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1120,9 +1122,6 @@ async function handleCancelSubmit() {
|
||||
// ==================== 详情 / 编辑 ====================
|
||||
const detailVisible = ref(false);
|
||||
const detailRecord = ref<SurveyOrderInfo | null>(null);
|
||||
const detailSopDone = computed(
|
||||
() => (detailRecord.value?.sopResults || []).filter((row) => row.checked).length
|
||||
);
|
||||
|
||||
async function openDetail(record: SurveyOrderInfo) {
|
||||
detailRecord.value = record;
|
||||
@@ -1152,12 +1151,13 @@ function formatRange(start?: string, end?: string) {
|
||||
return `${s} ~ ${e}`;
|
||||
}
|
||||
|
||||
const sopChipStyle = (checked?: boolean) =>
|
||||
chipStyle(
|
||||
checked
|
||||
? { color: '#059669', bg: '#d1fae5', border: '#a7f3d0' }
|
||||
: { color: '#94a3b8', bg: '#f8fafc', border: '#e2e8f0' }
|
||||
);
|
||||
// 楼层:正数为地上、负数为地下(value 为字符串,如 '1' / '-1')
|
||||
function floorLabel(floorNo?: string | null) {
|
||||
if (floorNo === undefined || floorNo === null || floorNo === '') return '未标注楼层';
|
||||
const n = Number(floorNo);
|
||||
if (Number.isNaN(n)) return String(floorNo);
|
||||
return n < 0 ? `负${Math.abs(n)}层` : `${n}层`;
|
||||
}
|
||||
|
||||
function money(value?: number | string) {
|
||||
if (value == null || value === '') return '—';
|
||||
@@ -1926,33 +1926,46 @@ function maskPhone(phone?: string) {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sop-item {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px dashed #eef1f6;
|
||||
.detail-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sop-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
.detail-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #eef1f6;
|
||||
border-radius: 8px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.sop-item-head {
|
||||
.detail-row-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.sop-item-name {
|
||||
.detail-row-idx {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #0054cd;
|
||||
}
|
||||
|
||||
.detail-row-scope {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #0d1c2c;
|
||||
}
|
||||
|
||||
.sop-item-remark {
|
||||
margin-top: 6px;
|
||||
.detail-row-remark {
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
color: #8a97a8;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* AntD 覆盖 */
|
||||
|
||||
Reference in new issue
Block a user