|
|
@@ -75,17 +75,51 @@
|
|
|
</view>
|
|
|
|
|
|
<scroll-view class="content" scroll-y>
|
|
|
- <!-- 溯源结论卡:先给结论,再给证据 -->
|
|
|
+ <!-- 溯源信息卡:融合溯源结论 + 批次核心信息 -->
|
|
|
<view v-if="traceDetail.batch?.exists && traceDetail.traceConclusionCard" class="card cardLevel1 cardConclusion">
|
|
|
<view class="sectionHeader">
|
|
|
<view class="sectionHeaderLeft">
|
|
|
<text class="sectionEn">Conclusion</text>
|
|
|
- <text class="sectionTitle">溯源结论</text>
|
|
|
+ <text class="sectionTitle">溯源信息</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="conclusionBody">
|
|
|
- <text class="conclusionLead">{{ traceDetail.traceConclusionCard.conclusion }}</text>
|
|
|
- <text class="conclusionDesc">{{ traceDetail.traceConclusionCard.desc }}</text>
|
|
|
+
|
|
|
+ <!-- 溯源信息卡片主体:三层竖向结构 -->
|
|
|
+ <view class="conclusionIdentity">
|
|
|
+ <!-- 第一层:批次号主信息区 -->
|
|
|
+ <view class="conclusionBatchWrap">
|
|
|
+ <text class="conclusionBatchLabel">批次编号</text>
|
|
|
+ <text class="conclusionBatchNo">{{ traceDetail.batch.no }}</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 第二层:时间摘要区 -->
|
|
|
+ <view v-if="traceDetail.batch?.harvestTime || traceDetail.batch?.packTime" class="conclusionSummary">
|
|
|
+ <template v-if="traceDetail.batch?.harvestTime && traceDetail.batch?.packTime">
|
|
|
+ <text class="summaryLabel">生产/采收日期:</text>
|
|
|
+ <text class="summaryText">{{ traceDetail.batch.harvestTime }}</text>
|
|
|
+ <text class="summaryDivider">|</text>
|
|
|
+ <text class="summaryLabel">包装日期:</text>
|
|
|
+ <text class="summaryText">{{ traceDetail.batch.packTime }}</text>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="traceDetail.batch?.harvestTime">
|
|
|
+ <text class="summaryLabel">生产/采收日期:</text>
|
|
|
+ <text class="summaryText">{{ traceDetail.batch.harvestTime }}</text>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="traceDetail.batch?.packTime">
|
|
|
+ <text class="summaryLabel">包装日期:</text>
|
|
|
+ <text class="summaryText">{{ traceDetail.batch.packTime }}</text>
|
|
|
+ </template>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 第三层:结论标签区 -->
|
|
|
+ <view class="conclusionTags">
|
|
|
+ <view class="conclusionTag">
|
|
|
+ <text>全程可追溯</text>
|
|
|
+ </view>
|
|
|
+ <view class="conclusionTag">
|
|
|
+ <text>已通过安全检测</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -424,31 +458,6 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 批次信息(可选:batch 可能不存在) -->
|
|
|
- <view v-if="traceDetail.batch?.exists" class="card cardLevel1 cardBatch">
|
|
|
- <view class="sectionHeader">
|
|
|
- <view class="sectionHeaderLeft">
|
|
|
- <text class="sectionEn">Batch</text>
|
|
|
- <text class="sectionTitle">批次信息</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 批次信息主体:左右两列布局,左列标签固定宽度,右列内容左对齐 -->
|
|
|
- <view class="batchBody">
|
|
|
- <view v-if="traceDetail.batch?.no" class="batchRow">
|
|
|
- <text class="batchRowLabel">批次号</text>
|
|
|
- <text class="batchRowValue">{{ traceDetail.batch.no }}</text>
|
|
|
- </view>
|
|
|
- <view v-if="traceDetail.batch?.harvestTime" class="batchRow">
|
|
|
- <text class="batchRowLabel">生产/采收时间</text>
|
|
|
- <text class="batchRowValue">{{ traceDetail.batch.harvestTime }}</text>
|
|
|
- </view>
|
|
|
- <view v-if="traceDetail.batch?.packTime" class="batchRow">
|
|
|
- <text class="batchRowLabel">包装时间</text>
|
|
|
- <text class="batchRowValue">{{ traceDetail.batch.packTime }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
|
|
|
<!-- 批次不存在/已下线的说明 -->
|
|
|
<view v-else-if="traceDetail.batch?.statusBadge" class="card soft cardLevel1 cardBatchState">
|
|
|
@@ -705,6 +714,7 @@ const MOCK_TRACE_DETAILS = {
|
|
|
exists: false,
|
|
|
statusBadge: { text: '', type: '' },
|
|
|
no: '',
|
|
|
+ plantStartTime: '2026-03-01',
|
|
|
harvestTime: '',
|
|
|
packTime: ''
|
|
|
},
|
|
|
@@ -761,7 +771,7 @@ const MOCK_TRACE_DETAILS = {
|
|
|
time: '2026-03-20',
|
|
|
stage: 'inspection',
|
|
|
title: '田间巡检',
|
|
|
- desc: '种植期间已开展长势检查与环境巡检'
|
|
|
+ desc: '种植期间已持续开展长势检查与环境巡检'
|
|
|
},
|
|
|
{
|
|
|
time: '2026-03-30',
|
|
|
@@ -778,8 +788,8 @@ const MOCK_TRACE_DETAILS = {
|
|
|
{
|
|
|
time: '2026-04-01',
|
|
|
stage: 'pack',
|
|
|
- title: '包装出库',
|
|
|
- desc: '已完成包装整理,进入销售流通环节'
|
|
|
+ title: '包装日期:出库',
|
|
|
+ desc: '已完成包装日期:整理,进入销售流通环节'
|
|
|
}
|
|
|
],
|
|
|
camera: {
|
|
|
@@ -828,6 +838,7 @@ reportPending: {
|
|
|
exists: false,
|
|
|
statusBadge: { text: '', type: '' },
|
|
|
no: '',
|
|
|
+ plantStartTime: '',
|
|
|
harvestTime: '',
|
|
|
packTime: ''
|
|
|
},
|
|
|
@@ -870,6 +881,7 @@ reportPending: {
|
|
|
exists: false,
|
|
|
statusBadge: { text: '', type: '' },
|
|
|
no: '',
|
|
|
+ plantStartTime: '',
|
|
|
harvestTime: '',
|
|
|
packTime: ''
|
|
|
},
|
|
|
@@ -913,6 +925,7 @@ reportPending: {
|
|
|
batch: {
|
|
|
exists: false,
|
|
|
statusBadge: { text: '', type: '' },
|
|
|
+ plantStartTime: '',
|
|
|
emptyMessage: ''
|
|
|
},
|
|
|
report: null,
|
|
|
@@ -941,6 +954,7 @@ reportPending: {
|
|
|
batch: {
|
|
|
exists: false,
|
|
|
statusBadge: { text: '', type: '' },
|
|
|
+ plantStartTime: '',
|
|
|
emptyMessage: ''
|
|
|
},
|
|
|
report: null,
|
|
|
@@ -1670,6 +1684,11 @@ const traceDetail = computed(() => {
|
|
|
let certFiles = []
|
|
|
let reportFiles = []
|
|
|
|
|
|
+ // 查找 farmTimeline 中 stage === 'planting' 的节点,用于兜底种植时间
|
|
|
+ const plantingNode = Array.isArray(data.farmTimeline)
|
|
|
+ ? data.farmTimeline.find(item => item.stage === 'planting')
|
|
|
+ : null
|
|
|
+
|
|
|
try {
|
|
|
if (data.certificate?.certFiles) {
|
|
|
certFiles = JSON.parse(data.certificate.certFiles)
|
|
|
@@ -1698,6 +1717,8 @@ const traceDetail = computed(() => {
|
|
|
? { text: '检验合格', type: 'ok' }
|
|
|
: { text: '批次不存在', type: 'muted' },
|
|
|
no: data.batchNo || '',
|
|
|
+ // 临时前端演示:始终显示固定种植时间
|
|
|
+ plantStartTime: '2026-03-01',
|
|
|
harvestTime: data.produceDate || '',
|
|
|
packTime: data.packageDate || '',
|
|
|
emptyMessage: data.status !== '2' ? '未找到对应溯源批次信息。请确认二维码是否为佳友厚苑正品批次。' : ''
|
|
|
@@ -1780,7 +1801,7 @@ const traceDetail = computed(() => {
|
|
|
{ time: '2026-03-20', stage: 'inspection', title: '田间巡检', desc: '种植期间已持续开展长势检查与环境巡检' },
|
|
|
{ time: data.produceDate || '', stage: 'harvest', title: '成熟采收', desc: '本批次产品进入成熟采收阶段' },
|
|
|
{ time: (data.reports?.[0]?.reportDate) || '', stage: 'test', title: '安全检测', desc: '已完成安全检测,相关结果可查' },
|
|
|
- { time: data.packageDate || '', stage: 'pack', title: '包装出库', desc: '已完成包装整理,进入销售流通环节' }
|
|
|
+ { time: data.packageDate || '', stage: 'pack', title: '包装日期:出库', desc: '已完成包装日期:整理,进入销售流通环节' }
|
|
|
]
|
|
|
} else {
|
|
|
// 真实态:使用真实数据 + 补充系统节点
|
|
|
@@ -1813,13 +1834,13 @@ const traceDetail = computed(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 包装出库
|
|
|
+ // 包装日期:出库
|
|
|
if (data.packageDate && !stageSet.has('pack')) {
|
|
|
timeline.push({
|
|
|
time: data.packageDate,
|
|
|
stage: 'pack',
|
|
|
- title: '包装出库',
|
|
|
- desc: '已完成包装整理,进入销售流通环节'
|
|
|
+ title: '包装日期:出库',
|
|
|
+ desc: '已完成包装日期:整理,进入销售流通环节'
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
@@ -2568,10 +2589,6 @@ function previewDoc(kind, index) {
|
|
|
background: rgba(250, 248, 242, 0.82);
|
|
|
}
|
|
|
|
|
|
-.cardBatch {
|
|
|
- background: rgba(251, 248, 242, 0.8);
|
|
|
-}
|
|
|
-
|
|
|
.cardCredential {
|
|
|
background: rgba(252, 248, 240, 0.84);
|
|
|
}
|
|
|
@@ -2580,31 +2597,94 @@ function previewDoc(kind, index) {
|
|
|
background: rgba(252, 248, 244, 0.74);
|
|
|
}
|
|
|
|
|
|
-/* 检测结论卡:结论型卡片,比普通资料卡更有结论感 */
|
|
|
+/* 检测结论卡:融合溯源信息,与农场卡视觉统一 */
|
|
|
.cardConclusion {
|
|
|
- background: rgba(252, 250, 244, 0.82);
|
|
|
+ background: rgba(250, 248, 242, 0.82);
|
|
|
+ padding-top: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+/* 溯源信息卡主体:三层竖向结构 */
|
|
|
+.conclusionIdentity {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 16rpx;
|
|
|
}
|
|
|
|
|
|
-.conclusionBody {
|
|
|
- padding-top: 6rpx;
|
|
|
+/* 第一层:批次号主信息区 */
|
|
|
+.conclusionBatchWrap {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4rpx;
|
|
|
}
|
|
|
|
|
|
-.conclusionLead {
|
|
|
+.conclusionBatchLabel {
|
|
|
display: block;
|
|
|
- font-size: 30rpx;
|
|
|
- font-weight: 600;
|
|
|
- line-height: 1.5;
|
|
|
- letter-spacing: 0.01em;
|
|
|
- color: rgba(24, 38, 30, 0.96);
|
|
|
- margin-bottom: 14rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ line-height: 1.4;
|
|
|
+ color: rgba(84, 106, 93, 0.6);
|
|
|
+ letter-spacing: 0.02em;
|
|
|
}
|
|
|
|
|
|
-.conclusionDesc {
|
|
|
+.conclusionBatchNo {
|
|
|
display: block;
|
|
|
+ font-size: 26rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ line-height: 1.4;
|
|
|
+ color: rgba(27, 41, 33, 0.78);
|
|
|
+ letter-spacing: 0.02em;
|
|
|
+}
|
|
|
+
|
|
|
+/* 第二层:时间摘要区,一行式表达 */
|
|
|
+.conclusionSummary {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 6rpx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.summaryLabel {
|
|
|
+ font-size: 20rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: rgba(84, 106, 93, 0.6);
|
|
|
+ letter-spacing: 0.01em;
|
|
|
+ margin-right: 6rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.summaryText {
|
|
|
+ font-size: 21rpx;
|
|
|
+ font-weight: 400;
|
|
|
+ color: rgba(27, 41, 33, 0.78);
|
|
|
+ letter-spacing: 0.01em;
|
|
|
+}
|
|
|
+
|
|
|
+.summaryDivider {
|
|
|
font-size: 20rpx;
|
|
|
font-weight: 400;
|
|
|
- line-height: 1.9;
|
|
|
- color: rgba(84, 106, 93, 0.5);
|
|
|
+ color: rgba(84, 106, 93, 0.4);
|
|
|
+ margin: 0 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+/* 第三层:结论标签区,独立横向排列 */
|
|
|
+.conclusionTags {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ gap: 12rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.conclusionTag {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 6rpx 16rpx;
|
|
|
+ border-radius: 999rpx;
|
|
|
+ background: rgba(39, 113, 76, 0.08);
|
|
|
+}
|
|
|
+
|
|
|
+.conclusionTag text {
|
|
|
+ font-size: 19rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ letter-spacing: 0.02em;
|
|
|
+ color: rgba(39, 113, 76, 0.8);
|
|
|
}
|
|
|
|
|
|
/* 农事时间轴:关键种植过程 */
|
|
|
@@ -2689,7 +2769,7 @@ function previewDoc(kind, index) {
|
|
|
color: rgba(27, 41, 33, 0.9);
|
|
|
}
|
|
|
|
|
|
-/* 当前节点(包装出库):主高亮 */
|
|
|
+/* 当前节点(包装日期:出库):主高亮 */
|
|
|
.timelineItem.is-current .timelineDot {
|
|
|
background: #2f7d55;
|
|
|
box-shadow: 0 0 0 6rpx rgba(47, 125, 85, 0.12);
|
|
|
@@ -3107,9 +3187,9 @@ function previewDoc(kind, index) {
|
|
|
animation: cardEnter 0.5s cubic-bezier(0.22, 0.78, 0.35, 1) 0.25s both;
|
|
|
}
|
|
|
|
|
|
-/* 批次卡 */
|
|
|
-.cardBatch {
|
|
|
- animation: cardEnter 0.5s cubic-bezier(0.22, 0.78, 0.35, 1) 0.35s both;
|
|
|
+/* 批次状态卡(不存在/已下线) */
|
|
|
+.cardBatchState {
|
|
|
+ animation: cardEnter 0.5s cubic-bezier(0.22, 0.78, 0.35, 1) 0.2s both;
|
|
|
}
|
|
|
|
|
|
/* 凭证卡 */
|
|
|
@@ -3243,11 +3323,6 @@ function previewDoc(kind, index) {
|
|
|
margin-top: auto;
|
|
|
}
|
|
|
|
|
|
-/* 底部辅助卡 */
|
|
|
-.cardBatchState {
|
|
|
- animation: cardEnter 0.5s cubic-bezier(0.22, 0.78, 0.35, 1) 0.55s both;
|
|
|
-}
|
|
|
-
|
|
|
/* 卡片触摸反馈:阴影增强(模拟按压感) */
|
|
|
.card:active {
|
|
|
transition: box-shadow 0.15s ease, transform 0.15s ease;
|
|
|
@@ -3667,48 +3742,6 @@ function previewDoc(kind, index) {
|
|
|
color: rgba(64, 75, 67, 0.8);
|
|
|
}
|
|
|
|
|
|
-/* 批次信息主体:连续信息排版,标签-值对应,与商品信息卡风格统一 */
|
|
|
-.batchBody {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-
|
|
|
-/* 批次信息主体:左右两列布局,左列固定,右列自适应,内容左对齐 */
|
|
|
-.batchBody {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-
|
|
|
-.batchRow {
|
|
|
- display: flex;
|
|
|
- align-items: baseline;
|
|
|
- padding: 16rpx 0;
|
|
|
-}
|
|
|
-
|
|
|
-.batchRow + .batchRow {
|
|
|
- border-top: 1rpx solid rgba(39, 75, 57, 0.05);
|
|
|
-}
|
|
|
-
|
|
|
-.batchRowLabel {
|
|
|
- flex-shrink: 0;
|
|
|
- width: 162rpx;
|
|
|
- font-size: 21rpx;
|
|
|
- font-weight: 460;
|
|
|
- color: rgba(84, 106, 93, 0.68);
|
|
|
- letter-spacing: 0.02em;
|
|
|
- line-height: 1.5;
|
|
|
-}
|
|
|
-
|
|
|
-.batchRowValue {
|
|
|
- flex: 1;
|
|
|
- min-width: 0;
|
|
|
- font-size: 23rpx;
|
|
|
- font-weight: 400;
|
|
|
- line-height: 1.4;
|
|
|
- letter-spacing: 0.01em;
|
|
|
- color: rgba(0, 0, 0, 0.85);
|
|
|
-}
|
|
|
-
|
|
|
.cardCredential .certSummary {
|
|
|
margin-top: 4rpx;
|
|
|
}
|