2026-06-02 08:20:44 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<clinic-page-layout title="订单追溯" :show-back="true">
|
|
|
|
|
|
<view class="trace-container">
|
|
|
|
|
|
<view v-if="loading" class="loading-tip">加载中...</view>
|
|
|
|
|
|
|
|
|
|
|
|
<template v-else-if="traceData">
|
|
|
|
|
|
<!-- 摘要 -->
|
|
|
|
|
|
<view class="summary-card">
|
|
|
|
|
|
<view class="row"><text class="label">商品订单</text><text class="value">{{ summary.product_order_no || '—' }}</text></view>
|
|
|
|
|
|
<view class="row" v-if="summary.register_order_no"><text class="label">挂号订单</text><text class="value">{{ summary.register_order_no }}</text></view>
|
|
|
|
|
|
<view class="row" v-if="summary.prescription_no"><text class="label">处方号</text><text class="value">{{ summary.prescription_no }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">结算状态</text><text class="value">{{ summary.is_settled === 1 ? '已结算' : '未结算' }}</text></view>
|
2026-06-18 10:20:24 +08:00
|
|
|
|
<view class="row" v-if="prescriptionStatusLabel"><text class="label">审方状态</text><text class="value status-audit">{{ prescriptionStatusLabel }}</text></view>
|
2026-06-02 08:20:44 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 主 Tab -->
|
|
|
|
|
|
<view class="main-tabs">
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="tab in mainTabs"
|
|
|
|
|
|
:key="tab.key"
|
|
|
|
|
|
class="main-tab"
|
|
|
|
|
|
:class="{ active: activeTab === tab.key }"
|
|
|
|
|
|
@click="switchMainTab(tab.key)"
|
|
|
|
|
|
>{{ tab.label }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 时间线 -->
|
|
|
|
|
|
<view v-show="activeTab === 'timeline'" class="tab-panel">
|
|
|
|
|
|
<view v-if="!timeline.length" class="empty">暂无时间线数据</view>
|
2026-06-18 10:20:24 +08:00
|
|
|
|
<view v-for="node in timeline" :key="node._wxKey" class="timeline-item">
|
2026-06-02 08:20:44 +08:00
|
|
|
|
<view class="tl-dot" />
|
|
|
|
|
|
<view class="tl-body">
|
|
|
|
|
|
<view class="tl-title">{{ node.title }}</view>
|
|
|
|
|
|
<view class="tl-meta">
|
|
|
|
|
|
<text v-if="node.time">{{ node.time }}</text>
|
|
|
|
|
|
<text v-if="node.status" class="tl-status">{{ node.status }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-if="node.extra" class="tl-extra">{{ node.extra }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分账明细 -->
|
|
|
|
|
|
<view v-show="activeTab === 'ledger'" class="tab-panel">
|
|
|
|
|
|
<view v-if="ledgerLoading" class="loading-tip">加载分账...</view>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<view v-if="hasRegisterLedger" class="sub-tabs">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="sub-tab"
|
|
|
|
|
|
:class="{ active: ledgerSubTab === 'product' }"
|
|
|
|
|
|
@click="switchLedgerSub('product')"
|
|
|
|
|
|
>商品订单</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="sub-tab"
|
|
|
|
|
|
:class="{ active: ledgerSubTab === 'register' }"
|
|
|
|
|
|
@click="switchLedgerSub('register')"
|
|
|
|
|
|
>挂号订单</view>
|
|
|
|
|
|
</view>
|
2026-06-18 10:20:24 +08:00
|
|
|
|
<view v-if="currentLedgerSumMoney != null" class="ledger-sum">
|
|
|
|
|
|
合计分账:{{ formatMoney(currentLedgerSumMoney) }}
|
|
|
|
|
|
</view>
|
2026-06-02 08:20:44 +08:00
|
|
|
|
<view v-if="currentLedgerItems.length">
|
|
|
|
|
|
<view v-for="row in currentLedgerItems" :key="row._wxKey" class="detail-card">
|
|
|
|
|
|
<view class="row"><text class="label">费用类型</text><text class="value">{{ row.fee_type_txt || '-' }}</text></view>
|
|
|
|
|
|
<view class="row" v-if="row.drug_name"><text class="label">药品</text><text class="value">{{ row.drug_name }}</text></view>
|
|
|
|
|
|
<view class="row" v-if="row.specification"><text class="label">规格</text><text class="value">{{ row.specification }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">分账金额</text><text class="value amount">{{ formatMoney(row.money) }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">结算状态</text><text class="value">{{ row.status_txt || '-' }}</text></view>
|
|
|
|
|
|
<view class="row" v-if="row.created_at"><text class="label">时间</text><text class="value">{{ row.created_at }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else class="empty">暂无分账明细</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 对账明细 -->
|
|
|
|
|
|
<view v-show="activeTab === 'reconciliation'" class="tab-panel">
|
|
|
|
|
|
<view v-if="reconciliationLoading" class="loading-tip">加载对账...</view>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<view v-if="reconciliationHint" class="hint-box">{{ reconciliationHint }}</view>
|
|
|
|
|
|
<template v-if="reconciliationSummary">
|
|
|
|
|
|
<view class="recon-summary-card">
|
|
|
|
|
|
<view class="recon-head">
|
|
|
|
|
|
<text class="recon-title">对账汇总</text>
|
|
|
|
|
|
<text v-if="reconciliationSummary.registrationPrice !== '¥0.00'" class="mini-tag">
|
|
|
|
|
|
挂号费 {{ reconciliationSummary.registrationPrice }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-if="reconciliationSummary.registerOrderNo" class="recon-sub">
|
|
|
|
|
|
挂号单号 {{ reconciliationSummary.registerOrderNo }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="hero-data">
|
|
|
|
|
|
<view class="data-box">
|
|
|
|
|
|
<text class="data-label">总销售额</text>
|
|
|
|
|
|
<text class="data-val text-primary">{{ reconciliationSummary.totalSales }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="data-divider" />
|
|
|
|
|
|
<view class="data-box">
|
|
|
|
|
|
<text class="data-label">总供货额</text>
|
|
|
|
|
|
<text class="data-val">{{ reconciliationSummary.totalSupply }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="dashboard-grid">
|
|
|
|
|
|
<view class="dashboard-island">
|
|
|
|
|
|
<view class="island-head">
|
|
|
|
|
|
<text class="island-title">草药</text>
|
|
|
|
|
|
<text class="island-sales">销量 {{ reconciliationSummary.herbal.sales }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="island-line"><text>销售</text><text>{{ reconciliationSummary.herbal.salesPrice }}</text></view>
|
|
|
|
|
|
<view class="island-line"><text>供货</text><text>{{ reconciliationSummary.herbal.supplyPrice }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="dashboard-island">
|
|
|
|
|
|
<view class="island-head">
|
|
|
|
|
|
<text class="island-title">西药</text>
|
|
|
|
|
|
<text class="island-sales">销量 {{ reconciliationSummary.medicine.sales }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="island-line"><text>销售</text><text>{{ reconciliationSummary.medicine.salesPrice }}</text></view>
|
|
|
|
|
|
<view class="island-line"><text>供货</text><text>{{ reconciliationSummary.medicine.supplyPrice }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="dashboard-island">
|
|
|
|
|
|
<view class="island-head">
|
|
|
|
|
|
<text class="island-title">服务包</text>
|
|
|
|
|
|
<text class="island-sales">销量 {{ reconciliationSummary.servicePackage.sales }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="island-line"><text>销售</text><text>{{ reconciliationSummary.servicePackage.salesPrice }}</text></view>
|
|
|
|
|
|
<view class="island-line"><text>供货</text><text>{{ reconciliationSummary.servicePackage.supplyPrice }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="dashboard-island">
|
|
|
|
|
|
<view class="island-head">
|
|
|
|
|
|
<text class="island-title">其他费用</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="island-line"><text>诊疗费</text><text>{{ reconciliationSummary.otherFees.treatment }}</text></view>
|
|
|
|
|
|
<view class="island-line"><text>加工费</text><text>{{ reconciliationSummary.otherFees.process }}</text></view>
|
|
|
|
|
|
<view class="island-line"><text>快递费</text><text>{{ reconciliationSummary.otherFees.express }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<view v-if="reconciliationItems.length" class="recon-drug-section">
|
|
|
|
|
|
<view class="section-title">药品明细</view>
|
|
|
|
|
|
<view v-for="row in reconciliationItems" :key="row._wxKey" class="detail-card">
|
|
|
|
|
|
<view class="row"><text class="label">药品</text><text class="value">{{ row.drug_name || row.drug_id || '-' }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">数量</text><text class="value">{{ row.number }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">销售价</text><text class="value">{{ formatMoney(row.total_price) }}</text></view>
|
|
|
|
|
|
<view class="row"><text class="label">供货价</text><text class="value">{{ formatMoney(row.total_buy_price) }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else-if="!reconciliationHint && !reconciliationSummary" class="empty">暂无对账明细</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-else-if="!loading" class="empty">加载失败,请返回重试</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</clinic-page-layout>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2026-06-05 12:28:36 +08:00
|
|
|
|
import ClinicPageLayout from '@/subPackages/sub_clinic_admin/components/clinic-page-layout.vue'
|
|
|
|
|
|
import { formatMoney } from '@/subPackages/sub_clinic_admin/common/format.js'
|
|
|
|
|
|
import { mapReconciliationOrderSummary } from '@/subPackages/sub_clinic_admin/common/display.js'
|
2026-06-02 08:20:44 +08:00
|
|
|
|
import {
|
|
|
|
|
|
getOrderTrace,
|
|
|
|
|
|
getOrderLedgerDetail,
|
|
|
|
|
|
getOrderReconciliationDetail,
|
|
|
|
|
|
} from '@/api/clinicAdmin.js'
|
|
|
|
|
|
import { withWxKey } from '@/utils/wxListKey.js'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
components: { ClinicPageLayout },
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
orderId: 0,
|
|
|
|
|
|
scene: 'product',
|
|
|
|
|
|
loading: true,
|
|
|
|
|
|
traceData: null,
|
|
|
|
|
|
activeTab: 'timeline',
|
|
|
|
|
|
ledgerSubTab: 'product',
|
|
|
|
|
|
ledgerProduct: null,
|
|
|
|
|
|
ledgerRegister: null,
|
|
|
|
|
|
ledgerLoading: false,
|
|
|
|
|
|
reconciliationData: null,
|
|
|
|
|
|
reconciliationLoading: false,
|
|
|
|
|
|
loadedTabs: {},
|
|
|
|
|
|
mainTabs: [
|
|
|
|
|
|
{ key: 'timeline', label: '时间线' },
|
|
|
|
|
|
{ key: 'ledger', label: '分账' },
|
|
|
|
|
|
{ key: 'reconciliation', label: '对账' },
|
|
|
|
|
|
],
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
summary() {
|
|
|
|
|
|
return this.traceData?.summary || {}
|
|
|
|
|
|
},
|
|
|
|
|
|
timeline() {
|
2026-06-18 10:20:24 +08:00
|
|
|
|
const items = this.traceData?.timeline || []
|
|
|
|
|
|
return withWxKey(items, 'key', 'tl')
|
2026-06-02 08:20:44 +08:00
|
|
|
|
},
|
|
|
|
|
|
links() {
|
|
|
|
|
|
return this.traceData?.links || {}
|
|
|
|
|
|
},
|
|
|
|
|
|
hasRegisterLedger() {
|
|
|
|
|
|
return !!(this.links.register_id && this.ledgerRegister !== null)
|
|
|
|
|
|
},
|
2026-06-18 10:20:24 +08:00
|
|
|
|
currentLedgerData() {
|
|
|
|
|
|
return this.ledgerSubTab === 'register' ? this.ledgerRegister : this.ledgerProduct
|
|
|
|
|
|
},
|
|
|
|
|
|
currentLedgerSumMoney() {
|
|
|
|
|
|
const data = this.currentLedgerData
|
|
|
|
|
|
if (!data || data.sum_money == null || data.sum_money === '') return null
|
|
|
|
|
|
return data.sum_money
|
|
|
|
|
|
},
|
2026-06-02 08:20:44 +08:00
|
|
|
|
currentLedgerItems() {
|
2026-06-18 10:20:24 +08:00
|
|
|
|
const items = this.currentLedgerData?.items || []
|
2026-06-02 08:20:44 +08:00
|
|
|
|
return withWxKey(items, 'id', 'traceLed')
|
|
|
|
|
|
},
|
2026-06-18 10:20:24 +08:00
|
|
|
|
prescriptionStatusLabel() {
|
|
|
|
|
|
if (!this.summary.prescription_id) return ''
|
|
|
|
|
|
const auditNode = (this.timeline || []).find(
|
|
|
|
|
|
n => n.key === 'prescription_audited' || n.key === 'prescription_rejected'
|
|
|
|
|
|
)
|
|
|
|
|
|
if (auditNode && auditNode.status) return auditNode.status
|
|
|
|
|
|
return '待审核'
|
|
|
|
|
|
},
|
2026-06-02 08:20:44 +08:00
|
|
|
|
reconciliationItems() {
|
|
|
|
|
|
const items = this.reconciliationData?.items || []
|
|
|
|
|
|
return withWxKey(items, 'id', 'traceRec')
|
|
|
|
|
|
},
|
|
|
|
|
|
reconciliationSummary() {
|
|
|
|
|
|
return mapReconciliationOrderSummary(this.reconciliationData?.summary)
|
|
|
|
|
|
},
|
|
|
|
|
|
reconciliationHint() {
|
|
|
|
|
|
return this.reconciliationData?.reconciliation_hint || this.summary.reconciliation_hint || ''
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
onLoad(q) {
|
|
|
|
|
|
this.orderId = Number(q.order_id || 0)
|
|
|
|
|
|
this.scene = q.scene || 'product'
|
|
|
|
|
|
this.loadTrace()
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
formatMoney,
|
|
|
|
|
|
loadTrace() {
|
|
|
|
|
|
if (this.orderId <= 0) {
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.loading = true
|
|
|
|
|
|
getOrderTrace({ scene: this.scene, order_id: this.orderId }).then(w => {
|
|
|
|
|
|
if (w.ok) {
|
|
|
|
|
|
this.traceData = w.data
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: (w.res && w.res.message) || '加载失败', icon: 'none' })
|
|
|
|
|
|
}
|
|
|
|
|
|
}).finally(() => { this.loading = false })
|
|
|
|
|
|
},
|
|
|
|
|
|
switchMainTab(key) {
|
|
|
|
|
|
this.activeTab = key
|
|
|
|
|
|
if (key === 'ledger' && !this.loadedTabs.ledger) {
|
|
|
|
|
|
this.loadLedger()
|
|
|
|
|
|
} else if (key === 'reconciliation' && !this.loadedTabs.reconciliation) {
|
|
|
|
|
|
this.loadReconciliation()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
switchLedgerSub(key) {
|
|
|
|
|
|
this.ledgerSubTab = key
|
|
|
|
|
|
},
|
|
|
|
|
|
loadLedger() {
|
|
|
|
|
|
const productId = this.links.product_order_id
|
|
|
|
|
|
const registerId = this.links.register_id
|
|
|
|
|
|
if (!productId && !registerId) {
|
|
|
|
|
|
this.loadedTabs.ledger = true
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.ledgerLoading = true
|
|
|
|
|
|
const reqs = []
|
|
|
|
|
|
if (productId) {
|
|
|
|
|
|
reqs.push(
|
|
|
|
|
|
getOrderLedgerDetail({ order_id: productId, order_type: 1, scope: 'store' }).then(w => {
|
|
|
|
|
|
this.ledgerProduct = w.ok ? w.data : null
|
|
|
|
|
|
})
|
|
|
|
|
|
)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.ledgerProduct = null
|
|
|
|
|
|
}
|
|
|
|
|
|
if (registerId) {
|
|
|
|
|
|
reqs.push(
|
|
|
|
|
|
getOrderLedgerDetail({ order_id: registerId, order_type: 2, scope: 'store' }).then(w => {
|
|
|
|
|
|
this.ledgerRegister = w.ok ? w.data : null
|
|
|
|
|
|
})
|
|
|
|
|
|
)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.ledgerRegister = null
|
|
|
|
|
|
}
|
|
|
|
|
|
Promise.all(reqs).finally(() => {
|
|
|
|
|
|
this.ledgerLoading = false
|
|
|
|
|
|
this.loadedTabs.ledger = true
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
loadReconciliation() {
|
|
|
|
|
|
const productId = this.links.product_order_id || (this.scene === 'product' ? this.orderId : 0)
|
|
|
|
|
|
if (!productId) {
|
|
|
|
|
|
this.reconciliationData = { items: [], reconciliation_hint: '暂无关联商品订单' }
|
|
|
|
|
|
this.loadedTabs.reconciliation = true
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.reconciliationLoading = true
|
|
|
|
|
|
getOrderReconciliationDetail({ product_order_id: productId }).then(w => {
|
|
|
|
|
|
if (w.ok) {
|
|
|
|
|
|
this.reconciliationData = w.data
|
|
|
|
|
|
}
|
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
|
this.reconciliationLoading = false
|
|
|
|
|
|
this.loadedTabs.reconciliation = true
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.trace-container {
|
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
|
padding-bottom: 48rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.loading-tip, .empty {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
padding: 48rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.summary-card, .detail-card {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.summary-card .row, .detail-card .row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
padding: 8rpx 0;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
.label { color: #888; flex-shrink: 0; margin-right: 16rpx; }
|
|
|
|
|
|
.value { text-align: right; word-break: break-all; }
|
|
|
|
|
|
.amount { color: #1677ff; font-weight: 600; }
|
|
|
|
|
|
.main-tabs, .sub-tabs {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.main-tab, .sub-tab {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 20rpx 0;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
.main-tab.active, .sub-tab.active {
|
|
|
|
|
|
color: #1677ff;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
background: #e6f4ff;
|
|
|
|
|
|
}
|
2026-06-18 10:20:24 +08:00
|
|
|
|
.ledger-sum {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
padding: 8rpx 8rpx 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.status-audit { color: #6acdbb; }
|
2026-06-02 08:20:44 +08:00
|
|
|
|
.tab-panel { min-height: 200rpx; }
|
|
|
|
|
|
.timeline-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
padding-left: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tl-dot {
|
|
|
|
|
|
width: 16rpx;
|
|
|
|
|
|
height: 16rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: #1677ff;
|
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tl-body { flex: 1; background: #fff; border-radius: 12rpx; padding: 20rpx; }
|
|
|
|
|
|
.tl-title { font-size: 28rpx; font-weight: 600; color: #333; }
|
|
|
|
|
|
.tl-meta { font-size: 24rpx; color: #999; margin-top: 8rpx; }
|
|
|
|
|
|
.tl-status { margin-left: 12rpx; color: #1677ff; }
|
|
|
|
|
|
.tl-extra { font-size: 24rpx; color: #666; margin-top: 8rpx; }
|
|
|
|
|
|
.hint-box {
|
|
|
|
|
|
background: #fff7e6;
|
|
|
|
|
|
color: #d48806;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
padding: 20rpx 24rpx;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sum-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
padding: 0 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.recon-summary-card {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.recon-head {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.recon-title {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
.recon-sub {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #888;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mini-tag {
|
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
|
padding: 4rpx 12rpx;
|
|
|
|
|
|
background: rgba(106, 205, 187, 0.1);
|
|
|
|
|
|
color: #6ACDBB;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-data {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
background: #F8FBFB;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
padding: 24rpx 0;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.data-box {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.data-label {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #888;
|
|
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.data-val {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
.text-primary { color: #1677ff; }
|
|
|
|
|
|
.data-divider {
|
|
|
|
|
|
width: 1rpx;
|
|
|
|
|
|
height: 60rpx;
|
|
|
|
|
|
background: #eee;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dashboard-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dashboard-island {
|
|
|
|
|
|
background: #F8FBFB;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
padding: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.island-head {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.island-title {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
.island-sales {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #888;
|
|
|
|
|
|
}
|
|
|
|
|
|
.island-line {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
padding: 4rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.recon-drug-section { margin-top: 8rpx; }
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
padding: 0 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|