From 71a0235a576f96adc37d62c1056fd74a593dc4fa Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期一, 24 八月 2026 14:12:27 +0800
Subject: [PATCH] feat: adapt fuel stores and medical product audit details
---
talent-card-admin/src/views/ProductAuditDetailView.vue | 64 ++++++++++++++++++++++++++++++--
1 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/talent-card-admin/src/views/ProductAuditDetailView.vue b/talent-card-admin/src/views/ProductAuditDetailView.vue
index 33c2b00..2439cfc 100644
--- a/talent-card-admin/src/views/ProductAuditDetailView.vue
+++ b/talent-card-admin/src/views/ProductAuditDetailView.vue
@@ -20,6 +20,12 @@
subsidy: boolean
}
+interface HealthCheckItem {
+ name: string
+ meaning: string
+ gender: string[]
+}
+
type LegacyBenefitConfig =
| { rows?: Array<Partial<BenefitRow> & { levelName?: string; governmentSubsidy?: boolean }> }
| Array<Partial<BenefitRow>>
@@ -39,6 +45,7 @@
availableTime: '',
otherRules: '',
})
+const healthCheckItems = ref<HealthCheckItem[]>([])
const benefitRows = reactive<BenefitRow[]>([
{ level: '卓越人才卡', enabled: true, free: true, limitCount: '', discount: '', exceedDiscount: '', resetCycle: '每天', subsidy: true },
@@ -52,6 +59,20 @@
const isHotelProduct = computed(() => {
const merchantType = product.value?.merchantType || ''
return merchantType === '酒店服务' || merchantType === '酒店'
+})
+const isHealthCheckProduct = computed(() => {
+ const productData = product.value as (Product & Record<string, unknown>) | undefined
+ const values = [
+ productData?.merchantType,
+ productData?.merchantTypeCode,
+ productData?.merchant_type,
+ productData?.merchant_type_code,
+ productData?.productType,
+ ].map(value => String(value || '').trim().toLowerCase().replace(/[\s_-]+/g, '')).filter(Boolean)
+ return values.some(value => [
+ '医院服务', '医院', '医疗服务', '医疗', '免费体检', '体检服务', '医疗体检',
+ 'hospital', 'medical', 'healthcheck', 'medicalservice',
+ ].includes(value))
})
const hideTalentBenefitPanel = computed(() => {
const productData = product.value as (Product & Record<string, unknown>) | undefined
@@ -72,12 +93,19 @@
return merchantTypes.some(type => hiddenTypes.includes(type)) || ['hotel', 'hospital', 'medical', 'healthcheck'].includes(productType)
})
const productAmountText = computed(() => {
+ if (isHealthCheckProduct.value) return ''
const salePrice = product.value?.salePrice
const originalPrice = product.value?.originalPrice
if (isHotelProduct.value && salePrice !== undefined && originalPrice !== undefined) {
return `${amountText(salePrice)} - ${amountText(originalPrice)}`
}
return amountText(salePrice ?? originalPrice) || '158'
+})
+const healthCheckPeriodText = computed(() => {
+ const directValue = [product.value?.validStartTime, product.value?.validEndTime].filter(Boolean).join(' 至 ')
+ if (directValue) return directValue
+ const savedNotice = parseJsonValue<Record<string, unknown>>(product.value?.purchaseNotice, {})
+ return String(savedNotice.validPeriod || savedNotice.valid_period || savedNotice.validity || '')
})
const formatDateTime = (value?: string) => value ? value.replace('T', ' ') : ''
const createdAtText = computed(() => formatDateTime(product.value?.createdAt) || '2026-06-18 11:34:25')
@@ -139,6 +167,17 @@
return coverUrl ? [coverUrl] : [fallbackImage]
}
+function parseHealthCheckItems(value?: Product['detailText']) {
+ healthCheckItems.value = []
+ const parsed = parseJsonValue<unknown>(value, [])
+ if (!Array.isArray(parsed)) return
+ healthCheckItems.value = parsed.map((item: any) => ({
+ name: String(item?.name || ''),
+ meaning: String(item?.meaning || ''),
+ gender: Array.isArray(item?.gender) ? item.gender.map((entry: unknown) => String(entry)) : [],
+ }))
+}
+
function parseBenefits(value?: Product['rightsConfig'], legacyValue?: string) {
benefitRows.forEach((row) => {
row.enabled = true
@@ -182,6 +221,7 @@
return
} finally {
galleryImages.value = parseProductImages(product.value?.productImages, product.value?.coverUrl)
+ parseHealthCheckItems(product.value?.detailText)
parseNotice(product.value?.purchaseNotice, product.value)
parseBenefits(product.value?.rightsConfig, product.value?.benefitDesc)
loading.value = false
@@ -238,10 +278,14 @@
<label>商品名称</label>
<el-input :model-value="productNameText" readonly />
</div>
- <div class="detail-field detail-money-field">
+ <div v-if="!isHealthCheckProduct" class="detail-field detail-money-field">
<label>商品金额</label>
<el-input :model-value="productAmountText" readonly />
<span>元</span>
+ </div>
+ <div v-else class="detail-field detail-period-field">
+ <label>可预约时间</label>
+ <el-input :model-value="healthCheckPeriodText" placeholder="未配置" readonly />
</div>
<div class="detail-time-pair">
<label>创建时间</label>
@@ -258,7 +302,7 @@
</div>
</div>
- <div class="audit-gallery-row">
+ <div v-if="!isHealthCheckProduct" class="audit-gallery-row">
<label>商品图片</label>
<div class="audit-thumb-list">
<div v-for="image in imageList" :key="image" class="audit-thumb-box">
@@ -270,12 +314,24 @@
</div>
</div>
- <div class="audit-textarea-row">
+ <div v-if="!isHealthCheckProduct" class="audit-textarea-row">
<label>商品详情</label>
<div class="audit-rich-text-preview" v-html="product?.detailText || ''"></div>
</div>
- <div class="purchase-notice-block">
+ <div v-else class="audit-textarea-row health-check-audit-row">
+ <label>商品详情</label>
+ <el-table :data="healthCheckItems" border class="health-check-audit-table">
+ <el-table-column prop="name" label="检查项目" min-width="220" />
+ <el-table-column prop="meaning" label="项目意义" min-width="320" />
+ <el-table-column label="男/女" width="180">
+ <template #default="{ row }">{{ row.gender.join('、') }}</template>
+ </el-table-column>
+ <template #empty>暂无体检项目</template>
+ </el-table>
+ </div>
+
+ <div v-if="!isHealthCheckProduct" class="purchase-notice-block">
<p>购买须知设置(非必填)</p>
<div class="purchase-notice-grid">
<div>
--
Gitblit v1.7.1