2026-09-10 10:57:40 +08:00
|
|
|
|
<template>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<view class="page" :style="pageStyle()">
|
2026-10-12 09:28:09 +08:00
|
|
|
|
<AppHeader title="AI匹配结果" :customBack="true" @back="back" />
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<scroll-view scroll-y :style="contentStyle(96, false)">
|
|
|
|
|
|
<view v-if="pageActive" class="content">
|
2026-10-12 09:28:09 +08:00
|
|
|
|
<view class="summary-card"><text class="summary-title">{{ summaryTitle }}</text><text class="summary-note">依据本次资料筛选 · 查看产品了解具体条件</text></view>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<view v-if="assessmentId.length == 0 && error.length == 0" class="state-panel"><text class="state-title">先选择一份评估</text><text class="muted">从融资档案查看已完成的评估,再获取对应匹配结果。</text><button class="primary" @click="history">选择历史评估</button><button class="secondary" @click="start">开始新评估</button></view>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<view class="tabs">
|
|
|
|
|
|
<view v-for="item in groups" :key="item.id" :class="group == item.id ? 'tab chosen' : 'tab'" @click="selectGroup(item.id)"><text :class="group == item.id ? 'tab-label selected' : 'tab-label'">{{ item.label }}</text><text class="count">{{ count(item.id) }}</text></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text v-if="loading && matches.length == 0" class="state-copy">正在读取本次匹配结果…</text>
|
|
|
|
|
|
<view v-if="error.length > 0" class="state-panel"><text class="state-title">暂时无法读取</text><text class="muted">{{ error }}</text><button class="secondary" @click="retry">重新加载</button><text class="link" @click="history">返回融资档案</text></view>
|
2026-10-07 10:01:05 +08:00
|
|
|
|
<view v-if="pageError.length > 0" class="state-panel"><text class="muted">{{ pageError }}</text><button class="secondary" :disabled="loading" @click="loadMore">重试加载更多</button></view>
|
2026-10-14 14:53:13 +08:00
|
|
|
|
<view v-if="!loading && error.length == 0 && matches.length == 0" class="state-panel"><text class="state-title">{{ status == 'unavailable' ? '本次未执行匹配' : (group == 'eligible' ? '暂无符合已知条件的产品' : (group == 'ineligible' ? '暂无条件不符的产品' : '暂无资料不足或待确认的产品')) }}</text><text class="muted">{{ status == 'unavailable' ? '历史结果不会自动补算。可从融资档案发起新的评估。' : '可切换分组查看其他结果,或返回报告了解资料准备情况。' }}</text><text class="link" @click="report">查看本次报告</text></view>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<view v-for="item in matches" :key="item.id" class="card" @click="openProduct(item.id)">
|
2026-10-14 14:53:13 +08:00
|
|
|
|
<view class="card-head"><view :class="bankMarkClass(item.product.bank)"><image v-if="item.product.logo.length > 0" class="mark-logo" :src="item.product.logo" mode="aspectFit" @error="item.product.logo = ''" /><text v-else class="mark-text">{{ item.product.bank.length > 0 ? item.product.bank.slice(0, 1) : item.product.name.slice(0, 1) }}</text></view><view class="identity"><text v-if="item.product.bank.length > 0" class="bank-name">{{ item.product.bank }}</text><text class="product-name">{{ item.product.name }}</text></view><view class="card-status"><text :class="item.state == 'eligible' ? 'match-state good' : (item.state == 'ineligible' ? 'match-state blocked' : 'match-state pending')">{{ item.stateLabel }}</text><text v-if="matchPercentage(item.state, item.score).length > 0" class="match-score">匹配度 {{ matchPercentage(item.state, item.score) }}</text></view><text class="card-arrow">›</text></view>
|
|
|
|
|
|
<view class="tags"><text v-if="hasProductValue(item.product.rate)" class="tag">年化 {{ item.product.rate }}</text><text v-if="hasProductValue(item.product.term)" class="tag">{{ item.product.term }}</text><text class="tag">{{ item.product.objects }}</text></view>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<text v-if="item.availability != 'available'" class="availability">{{ item.availabilityLabel }};历史结果仍可查看。</text>
|
2026-10-12 09:28:09 +08:00
|
|
|
|
<view class="card-foot"><text class="detail-link">查看匹配依据</text><view class="choose-control" @click.stop="toggleCompare(item.id)"><text :class="selectedIds.includes(item.id) ? 'selection-box selected-box' : 'selection-box'">{{ selectedIds.includes(item.id) ? '✓' : '+' }}</text><text class="choose-label">{{ selectedIds.includes(item.id) ? '已选对比' : '加入对比' }}</text></view></view>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
</view>
|
2026-10-12 09:28:09 +08:00
|
|
|
|
<button v-if="hasMore && pageError.length == 0" class="more-button" :disabled="loading" @click="loadMore">{{ loading ? '正在加载…' : '查看更多产品(共' + count(group) + '项)' }}</button>
|
|
|
|
|
|
<view v-if="error.length == 0 && matches.length > 0" class="compare-bar"><text class="compare-caption">已选 {{ selectedIds.length }} / 3 项</text><button class="compare-button" :disabled="selectedIds.length < 2" @click="openCompare">对比所选产品</button></view>
|
2026-10-14 14:53:13 +08:00
|
|
|
|
<text v-if="matches.length > 0 && !hasMore" class="end-note">已显示本组全部结果</text>
|
2026-10-12 09:28:09 +08:00
|
|
|
|
<text v-if="message.length > 0" class="muted notice">{{ message }}</text>
|
2026-09-28 14:56:46 +08:00
|
|
|
|
<text class="link" @click="report">返回本次报告</text>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
</view>
|
2026-09-10 10:57:40 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="uts">
|
2026-09-28 14:56:46 +08:00
|
|
|
|
import AppHeader from '@/components/AppHeader.uvue'
|
|
|
|
|
|
import { usePageLayout } from '@/services/layout.uts'
|
|
|
|
|
|
import { getSession } from '@/services/api.uts'
|
2026-10-14 14:53:13 +08:00
|
|
|
|
import { MatchView, MatchPage, fetchMatchPage, validRecordId, hasProductValue, matchPercentage } from '@/packages/finance/services/matches.uts'
|
2026-10-07 10:01:05 +08:00
|
|
|
|
import { parseCompareIds, compareSelection, saveCompareSelection, compareQuery, matchReturnPath } from '@/packages/finance/services/compare.uts'
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const { pageStyle, contentStyle } = usePageLayout()
|
|
|
|
|
|
type MatchGroup = { id: string, label: string }
|
2026-10-14 14:53:13 +08:00
|
|
|
|
const groups: MatchGroup[] = [{ id: 'eligible', label: '符合条件' }, { id: 'ineligible', label: '条件不符' }, { id: 'unknown', label: '待确认' }]
|
2026-09-30 19:11:44 +08:00
|
|
|
|
const revisionId = ref(''); const assessmentId = ref(''); const group = ref('eligible'); const matches = ref<MatchView[]>([])
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const selectedIds = ref<string[]>([])
|
|
|
|
|
|
const pageActive = ref(false)
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const loading = ref(false); const error = ref(''); const pageError = ref(''); const message = ref(''); const status = ref('')
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const eligible = ref('—'); const ineligible = ref('—'); const unknown = ref('—'); const hasMore = ref(false)
|
|
|
|
|
|
let cursor = ''; let generation = 0; let visible = false; let routeError = ''; let owner = ''
|
2026-10-07 10:01:05 +08:00
|
|
|
|
let firstPage: MatchPage | null = null; let accountTimer = 0
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const count = (id: string): string => id == 'eligible' ? eligible.value : (id == 'ineligible' ? ineligible.value : unknown.value)
|
2026-10-12 09:28:09 +08:00
|
|
|
|
const summaryTitle = computed((): string => {
|
|
|
|
|
|
if (assessmentId.value.length == 0) return '选择评估,查看融资匹配'
|
|
|
|
|
|
if (error.value.length > 0) return '匹配结果暂不可读取'
|
|
|
|
|
|
if (status.value == 'unavailable') return '这份报告尚未执行产品匹配'
|
|
|
|
|
|
if (eligible.value == '—') return '正在为你读取匹配结果'
|
|
|
|
|
|
return eligible.value == '0' ? '暂未筛选出符合已知条件的产品' : '为你筛选出' + eligible.value + '项符合已知条件的产品'
|
|
|
|
|
|
})
|
|
|
|
|
|
const bankMarkClass = (bank: string): string => bank.includes('工商') || bank.includes('招商') || bank.includes('中国银行') ? 'mark mark-red' : (bank.includes('农业') || bank.includes('邮储') ? 'mark mark-green' : 'mark mark-blue')
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const clear = () => { matches.value = []; message.value = ''; status.value = ''; pageError.value = ''; hasMore.value = false; cursor = ''; firstPage = null; eligible.value = '—'; ineligible.value = '—'; unknown.value = '—' }
|
|
|
|
|
|
const stopAccountTimer = () => { if (accountTimer != 0) clearInterval(accountTimer); accountTimer = 0 }
|
|
|
|
|
|
const login = () => { uni.redirectTo({ url: '/packages/account/login/login?resumeMatch=1&matchPage=matches' + compareQuery(assessmentId.value, selectedIds.value, revisionId.value).replace('?', '&') + '&group=' + group.value }) }
|
|
|
|
|
|
const current = (request: number, token: string): boolean => {
|
|
|
|
|
|
if (!visible || request != generation) return false
|
|
|
|
|
|
if (getSession()?.getString('token') == token) return true
|
|
|
|
|
|
generation++; clear(); loading.value = false; stopAccountTimer()
|
|
|
|
|
|
if (getSession() == null) login(); else error.value = '账户已切换,请重新加载本人匹配。'
|
|
|
|
|
|
selectedIds.value = []
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
const updateUrl = () => {
|
|
|
|
|
|
// #ifdef WEB
|
|
|
|
|
|
window.history.replaceState(window.history.state, '', location.pathname + location.search + '#' + matchReturnPath('matches', assessmentId.value, selectedIds.value.join(','), revisionId.value, '', group.value))
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
}
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const load = async (append: boolean) => {
|
|
|
|
|
|
const request = ++generation
|
2026-10-07 10:01:05 +08:00
|
|
|
|
if (!append) { stopAccountTimer(); clear() }
|
|
|
|
|
|
error.value = ''; pageError.value = ''
|
2026-09-28 14:56:46 +08:00
|
|
|
|
if (routeError.length > 0) { error.value = routeError; loading.value = false; return }
|
|
|
|
|
|
if (assessmentId.value.length == 0) { loading.value = false; return }
|
|
|
|
|
|
const session = getSession()
|
2026-10-07 10:01:05 +08:00
|
|
|
|
if (session == null) { loading.value = false; login(); return }
|
|
|
|
|
|
const token = session.getString('token') ?? ''; if (owner.length > 0 && owner != token) selectedIds.value = []; owner = token; loading.value = true
|
|
|
|
|
|
if (accountTimer == 0) accountTimer = setInterval(() => { current(generation, owner) }, 1000)
|
2026-09-28 14:56:46 +08:00
|
|
|
|
try {
|
2026-09-30 19:11:44 +08:00
|
|
|
|
const result = await fetchMatchPage(assessmentId.value, group.value, append ? cursor : '', revisionId.value)
|
2026-10-07 10:01:05 +08:00
|
|
|
|
if (!current(request, token)) return
|
|
|
|
|
|
// 分页只追加同一冻结结果,失败时保留已读行与原游标供局部重试。
|
|
|
|
|
|
if (append && (firstPage == null || firstPage!.assessmentId != result.assessmentId || firstPage!.revisionId != result.revisionId || firstPage!.resultVersion != result.resultVersion || firstPage!.snapshotId != result.snapshotId || firstPage!.ruleVersion != result.ruleVersion || firstPage!.orderingVersion != result.orderingVersion || firstPage!.status != result.status || firstPage!.eligible != result.eligible || firstPage!.ineligible != result.ineligible || firstPage!.unknown != result.unknown || result.items.some((item: MatchView): boolean => matches.value.some((old: MatchView): boolean => old.id == item.id)) || (result.hasMore && result.cursor == cursor))) throw new Error('分页与已读取的冻结结果不一致,请重试或重新加载。')
|
2026-09-30 19:11:44 +08:00
|
|
|
|
revisionId.value = result.revisionId
|
2026-10-07 10:01:05 +08:00
|
|
|
|
if (!append) firstPage = result
|
|
|
|
|
|
saveCompareSelection(assessmentId.value, selectedIds.value, revisionId.value); updateUrl()
|
2026-09-28 14:56:46 +08:00
|
|
|
|
matches.value = append ? matches.value.concat(result.items) : result.items
|
|
|
|
|
|
message.value = result.message; status.value = result.status; eligible.value = result.eligible; ineligible.value = result.ineligible; unknown.value = result.unknown
|
|
|
|
|
|
cursor = result.cursor; hasMore.value = result.hasMore
|
2026-10-07 10:01:05 +08:00
|
|
|
|
} catch (err) { if (current(request, token)) { const message = err instanceof Error ? err.message : '匹配结果读取失败'; if (append) pageError.value = message; else error.value = message } }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
finally { if (request == generation) loading.value = false }
|
|
|
|
|
|
}
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const selectGroup = (id: string) => { if (!current(generation, owner) || id == group.value) return; group.value = id; load(false) }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const retry = () => { load(false) }
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const loadMore = () => { if (current(generation, owner) && !loading.value && hasMore.value) load(true) }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const history = () => { uni.navigateTo({ url: '/packages/finance/archive/archive' }) }
|
|
|
|
|
|
const start = () => { uni.navigateTo({ url: '/packages/finance/entry/entry' }) }
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const report = () => { if (owner.length > 0 && !current(generation, owner)) return; if (validRecordId(assessmentId.value)) uni.redirectTo({ url: '/packages/finance/report/report?assessmentId=' + assessmentId.value + (revisionId.value.length > 0 ? '&revisionId=' + revisionId.value : '') }); else history() }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
const back = () => { if (getCurrentPages().length > 1) uni.navigateBack(); else if (assessmentId.value.length > 0) report(); else history() }
|
|
|
|
|
|
const toggleCompare = (id: string) => {
|
2026-10-07 10:01:05 +08:00
|
|
|
|
if (!current(generation, owner) || !matches.value.some((item: MatchView): boolean => item.id == id)) return
|
2026-09-28 14:56:46 +08:00
|
|
|
|
if (selectedIds.value.includes(id)) selectedIds.value = selectedIds.value.filter((value: string): boolean => value != id)
|
|
|
|
|
|
else {
|
|
|
|
|
|
if (selectedIds.value.length >= 3) { uni.showToast({ title: '最多选择3个产品,请先移除一项', icon: 'none' }); return }
|
|
|
|
|
|
selectedIds.value.push(id)
|
|
|
|
|
|
}
|
2026-10-07 10:01:05 +08:00
|
|
|
|
saveCompareSelection(assessmentId.value, selectedIds.value, revisionId.value); updateUrl()
|
2026-09-28 14:56:46 +08:00
|
|
|
|
}
|
2026-10-07 10:01:05 +08:00
|
|
|
|
const openCompare = () => { if (current(generation, owner) && selectedIds.value.length >= 2) uni.navigateTo({ url: '/packages/finance/compare/compare' + compareQuery(assessmentId.value, selectedIds.value, revisionId.value) }) }
|
|
|
|
|
|
const openProduct = (id: string) => { if (current(generation, owner) && matches.value.some((item: MatchView): boolean => item.id == id)) uni.navigateTo({ url: '/packages/finance/product/product' + compareQuery(assessmentId.value, selectedIds.value, revisionId.value) + '&productId=' + id + '&tab=explanation&from=matches' }) }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
onLoad((options) => {
|
2026-09-30 19:11:44 +08:00
|
|
|
|
revisionId.value = options?.['revisionId'] ?? '';
|
|
|
|
|
|
if (revisionId.value.length > 0 && !validRecordId(revisionId.value)) routeError = '版本编号无效,请返回重新选择。'
|
2026-09-28 14:56:46 +08:00
|
|
|
|
assessmentId.value = options?.['assessmentId'] ?? ''
|
|
|
|
|
|
const selected = options?.['group'] ?? 'eligible'
|
|
|
|
|
|
if (['eligible','ineligible','unknown'].includes(selected)) group.value = selected
|
|
|
|
|
|
else routeError = '匹配分组参数无效,请从报告重新进入。'
|
|
|
|
|
|
if (assessmentId.value.length > 0 && !validRecordId(assessmentId.value)) routeError = '评估编号无效,请从融资档案重新选择。'
|
|
|
|
|
|
if (options?.['productIds'] != null) {
|
2026-09-30 19:11:44 +08:00
|
|
|
|
try { saveCompareSelection(assessmentId.value, parseCompareIds(options!['productIds']!), revisionId.value) }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
catch (err) { routeError = err instanceof Error ? err.message : '对比参数无效' }
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2026-09-30 19:11:44 +08:00
|
|
|
|
onShow(() => { visible = true; pageActive.value = true; selectedIds.value = compareSelection(assessmentId.value, revisionId.value); if (getSession()?.getString('token') != owner) clear(); load(false) })
|
2026-09-28 14:56:46 +08:00
|
|
|
|
// 先关闭内容渲染再清空资料,避免卸载途中因空数组重新挂载状态节点。
|
2026-10-07 10:01:05 +08:00
|
|
|
|
onHide(() => { visible = false; pageActive.value = false; stopAccountTimer(); generation++; clear(); loading.value = false; error.value = '' })
|
|
|
|
|
|
onUnload(() => { visible = false; pageActive.value = false; stopAccountTimer(); generation++; clear() })
|
2026-09-10 10:57:40 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
<style>
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.page { background-color: #fff; }
|
|
|
|
|
|
.summary-card { background-color: #edf5ff; padding: 28rpx 26rpx; border-radius: 10rpx; }
|
|
|
|
|
|
.summary-title { color: #1a5aa8; font-size: 31rpx; line-height: 47rpx; font-weight: 600; }
|
|
|
|
|
|
.summary-note { color: #7188a4; font-size: 22rpx; line-height: 35rpx; margin-top: 9rpx; }
|
|
|
|
|
|
.compare-bar { flex-direction: row; align-items: center; justify-content: space-between; border-top: 1rpx solid #edf1f6; padding: 20rpx 0; margin-top: 20rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.compare-caption { color: #506c8b; font-size: 24rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.compare-button { background-color: #0868f7; color: #fff; font-size: 24rpx; border-radius: 10rpx; margin: 0; padding: 0 22rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.content { padding: 30rpx 28rpx 60rpx; }
|
|
|
|
|
|
.eyebrow { font-size: 22rpx; color: #61758f; }
|
|
|
|
|
|
.headline { font-size: 37rpx; font-weight: 700; color: #142d4e; margin-top: 14rpx; }
|
|
|
|
|
|
.intro { font-size: 24rpx; line-height: 38rpx; color: #718198; margin-top: 14rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.tabs { flex-direction: row; background-color: #f7f9fc; border-radius: 10rpx; padding: 6rpx; margin-top: 24rpx; margin-bottom: 24rpx; }
|
|
|
|
|
|
.tab { flex: 1; flex-direction: row; align-items: center; justify-content: center; padding: 15rpx 2rpx; border-radius: 8rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.chosen { background-color: #eaf3ff; }
|
|
|
|
|
|
.tab-label { font-size: 24rpx; color: #6e7e93; }
|
|
|
|
|
|
.selected { color: #0868f7; font-weight: 700; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.count { font-size: 24rpx; color: #61768e; margin-left: 8rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.muted { font-size: 24rpx; line-height: 39rpx; color: #758399; }
|
|
|
|
|
|
.notice { margin: 20rpx 4rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.card { padding: 24rpx 22rpx 18rpx; background-color: #fff; border: 1rpx solid #e2e8ef; border-radius: 10rpx; margin-bottom: 20rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.card-head { flex-direction: row; align-items: center; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.mark { width: 66rpx; height: 66rpx; border-radius: 33rpx; align-items: center; justify-content: center; margin-right: 16rpx; flex-shrink: 0; }
|
2026-10-14 14:53:13 +08:00
|
|
|
|
.mark-logo { width: 52rpx; height: 52rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.mark-blue { background-color: #edf4fd; }
|
|
|
|
|
|
.mark-red { background-color: #fcedef; }
|
|
|
|
|
|
.mark-green { background-color: #eaf6f1; }
|
|
|
|
|
|
.mark-text { font-size: 30rpx; color: #2765ad; font-weight: 700; }
|
|
|
|
|
|
.mark-red .mark-text { color: #b84554; }
|
|
|
|
|
|
.mark-green .mark-text { color: #28856b; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.identity { flex: 1; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.bank-name { font-size: 28rpx; line-height: 40rpx; color: #24354b; font-weight: 600; }
|
|
|
|
|
|
.product-name { font-size: 22rpx; color: #7a899d; line-height: 34rpx; margin-top: 3rpx; }
|
|
|
|
|
|
.match-state { font-size: 20rpx; line-height: 30rpx; max-width: 140rpx; flex-shrink: 0; text-align: right; margin-left: 10rpx; }
|
2026-10-14 14:53:13 +08:00
|
|
|
|
.card-status { align-items: flex-end; margin-left: 8rpx; }
|
|
|
|
|
|
.match-score { font-size: 21rpx; line-height: 32rpx; color: #0868f7; margin-top: 4rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.card-arrow { font-size: 38rpx; color: #a3aebe; margin-left: 12rpx; }
|
|
|
|
|
|
.tags { flex-direction: row; flex-wrap: wrap; margin-top: 18rpx; }
|
|
|
|
|
|
.tag { background-color: #f2f5f9; color: #718197; font-size: 20rpx; line-height: 30rpx; padding: 4rpx 10rpx; border-radius: 4rpx; margin-right: 8rpx; margin-bottom: 6rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.badge-row { flex-direction: row; align-items: center; margin-top: 20rpx; }
|
|
|
|
|
|
.badge { padding: 8rpx 16rpx; border-radius: 8rpx; font-size: 22rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.good { color: #187857; }
|
|
|
|
|
|
.blocked { color: #ae593d; }
|
|
|
|
|
|
.pending { color: #9a7320; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.demo { font-size: 21rpx; margin-left: 14rpx; color: #78879b; }
|
|
|
|
|
|
.amount-row { margin-top: 26rpx; }
|
|
|
|
|
|
.amount { font-size: 38rpx; font-weight: 700; color: #123a6c; line-height: 54rpx; }
|
|
|
|
|
|
.caption { font-size: 22rpx; color: #8390a2; margin-top: 6rpx; }
|
|
|
|
|
|
.metrics { flex-direction: row; margin-top: 20rpx; }
|
|
|
|
|
|
.metric { flex: 1; }
|
|
|
|
|
|
.value { font-size: 25rpx; color: #344c6a; line-height: 38rpx; }
|
|
|
|
|
|
.reasons { margin-top: 22rpx; border-top: 1rpx solid #edf2f8; padding-top: 12rpx; }
|
|
|
|
|
|
.reason { font-size: 23rpx; line-height: 37rpx; color: #60758e; margin-top: 8rpx; }
|
|
|
|
|
|
.availability { font-size: 23rpx; line-height: 37rpx; color: #a87534; margin-top: 12rpx; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.card-foot { flex-direction: row; align-items: center; justify-content: space-between; margin-top: 10rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.version { font-size: 21rpx; color: #98a3b2; }
|
2026-10-12 09:28:09 +08:00
|
|
|
|
.detail-link { font-size: 20rpx; color: #8c99aa; }
|
|
|
|
|
|
.choose-control { flex-direction: row; align-items: center; padding: 5rpx 0 5rpx 12rpx; }
|
|
|
|
|
|
.selection-box { width: 28rpx; height: 28rpx; text-align: center; line-height: 26rpx; border: 1rpx solid #c3d4e9; border-radius: 6rpx; color: #527ba9; font-size: 22rpx; }
|
|
|
|
|
|
.selected-box { background-color: #0868f7; color: #fff; border-color: #0868f7; }
|
|
|
|
|
|
.choose-label { font-size: 21rpx; color: #527ba9; margin-left: 8rpx; }
|
|
|
|
|
|
.more-button { background-color: #0868f7; color: #fff; font-size: 24rpx; border-radius: 10rpx; margin-top: 6rpx; }
|
2026-09-28 14:56:46 +08:00
|
|
|
|
.state-panel { padding: 42rpx 28rpx; background-color: #fff; border-radius: 18rpx; margin-top: 24rpx; }
|
|
|
|
|
|
.state-title { font-size: 30rpx; font-weight: 700; color: #273f5f; margin-bottom: 16rpx; }
|
|
|
|
|
|
.state-copy { padding: 40rpx 12rpx; font-size: 26rpx; color: #73839a; }
|
|
|
|
|
|
.primary { background-color: #0868f7; color: #fff; font-size: 26rpx; margin-top: 28rpx; border-radius: 12rpx; }
|
|
|
|
|
|
.secondary { background-color: #eaf3ff; color: #0868f7; font-size: 26rpx; margin-top: 22rpx; border-radius: 12rpx; }
|
|
|
|
|
|
.link { color: #0868f7; font-size: 25rpx; padding: 24rpx 0; }
|
|
|
|
|
|
.end-note { text-align: center; font-size: 22rpx; color: #8795a9; padding: 18rpx 0; }
|
2026-09-10 10:57:40 +08:00
|
|
|
|
</style>
|