import { formatMoney } from './format.js' /** 展示用:优先顶层合并医嘱(含系统规则文案),fallback content 纯医嘱 */ export function formatDoctorOrder(item) { const pres = item && item.prescription ? item.prescription : item if (!pres) return '-' const raw = pres.doctor_order != null && pres.doctor_order !== '' ? pres.doctor_order : (pres.content && pres.content.doctor_order) || '' if (Array.isArray(raw)) { const list = raw.map(s => String(s).trim()).filter(Boolean) return list.length ? list.join(';') : '-' } const parts = String(raw).split('|').map(s => s.trim()).filter(Boolean) return parts.length ? parts.join(';') : (raw ? String(raw) : '-') } const DEFAULT_DRUG_IMAGE = 'https://xkyp-web2.obs.cn-south-1.myhuaweicloud.com/buy/public/drug_no_mage.png' /** 兼容 int 时间戳 / datetime 字符串 */ export function formatDateTime(v) { if (v === null || v === undefined || v === '') return '-' if (typeof v === 'number') { const ms = v < 1e12 ? v * 1000 : v const d = new Date(ms) if (Number.isNaN(d.getTime())) return '-' return d.toLocaleString() } const s = String(v) if (s === '2021-01-01 00:00:00') return '-' return s } export function withdrawalCheckStatusText(s) { const m = { 1: '待审核', 2: '审核成功', 3: '拒绝', 4: '提现失败' } return m[s] || '-' } export function dakuanStatusText(s) { if (s === -1) return '打款失败' if (s === 0) return '处理中' if (s === 1) return '打款成功' return '-' } export function isWithdrawalRejected(item) { return item && Number(item.check_status) === 3 } /** 提现列表行展示(yii_cash_apply) */ export function mapWithdrawalRow(item) { if (!item) return {} const checkStatus = item.check_status return { id: item.id, orderNo: item.order_no || '-', applyCash: formatMoney(item.apply_cash), trueCash: formatMoney(item.true_cash), chargeCash: formatMoney(item.charge_cash), applyTime: formatDateTime(item.apply_time), checkStatusText: item.check_status_txt || withdrawalCheckStatusText(checkStatus), checkResult: item.check_result || '', isRejected: isWithdrawalRejected(item), dakuanStatusText: item.dakuan_status_txt || dakuanStatusText(item.dakuan_status), dakuanTime: formatDateTime(item.dakuan_time), _raw: item, } } /** 结算记录列表行(yii_ledger_log) */ export function mapSettlementRow(item) { if (!item) return {} const isIncrease = item.merged ? (item.type_txt === '增加' || Number(item.amount) >= 0) : item.type === 1 return { id: item.id, orderNo: item.order_no || (item.order_id ? '订单#' + item.order_id : '-'), orderTypeText: item.order_type_txt || '', feeTypeText: item.fee_type_txt || '-', amountText: formatMoney(item.amount), amountClass: isIncrease ? 'text-success' : 'text-danger', typeText: item.type_txt || '-', content: item.content || '', createdAt: formatDateTime(item.created_at), merged: !!item.merged, orderId: item.order_id, orderType: item.order_type, _raw: item, } } export function ledgerTypeClass(item) { return item && item.type === 1 ? 'inc' : 'dec' } /** 商品订单状态(对齐 PC product-order) */ export function orderStatusText(status) { const m = { 0: '待支付', 1: '待发货', 2: '待收货', 3: '待评价', 4: '已退款', 5: '退款中', 6: '已收货', 7: '确认收货', 8: '拒绝退款', 9: '已取消', } return m[status] != null ? m[status] : '-' } export function deliveryMethodText(dm) { if (dm === 0) return '快递到家' if (dm === 1) return '药店自提' return '-' } export function orderOnlineText(isOnline) { if (isOnline === 1) return '在线问诊' if (isOnline === 2) return '在线复诊' return '线下就诊' } export function prescriptionTypeText(pt) { const m = { 1: '中药', 2: '西药', 3: '保健食品', 5: '产品服务包', 6: '非药品', 7: '医疗器械', } return m[pt] != null ? m[pt] : '其他' } export function orderTypeText(ot) { const m = { 1: '处方订单', 2: '预约购药订单', 3: '商城处方订单', } return m[ot] != null ? m[ot] : '其他' } export function erpSyncText(v) { if (v === 1) return '已同步' return '未同步' } export function prescriptionStatusText(status) { const m = { 0: '待审核', 1: '已审核', 2: '已驳回', 3: '已过期' } return m[status] != null ? m[status] : '-' } export function freeShippingText(v) { if (v === 1) return '包邮' return '不包邮' } function pickReceiverMobile(item) { const addr = item.address if (addr && typeof addr === 'object' && addr.mobile) return addr.mobile return item.patient_mobile || '' } function buildProductSummary(items, prescriptionType, max = 2) { if (!Array.isArray(items) || !items.length) return '' return items.slice(0, max).map(p => formatOrderProductLine(p, prescriptionType)).join(';') } function pickAddrName(item) { const addr = item.address if (addr && typeof addr === 'object' && addr.name) return addr.name if (typeof addr === 'string') { try { const o = JSON.parse(addr) return o.name || '' } catch (e) { return '' } } return item.patient || item.express_name || '-' } /** 订单列表卡片 */ export function mapOrderListRow(item) { if (!item) return {} const store = item.store || {} const user = item.user || {} const pt = item.prescription_type return { id: item.id, orderNo: item.order_no || '-', totalPayPrice: formatMoney(item.total_pay_price), itemsPrice: formatMoney(item.items_price), transExpenses: formatMoney(item.trans_expenses), registerPrice: item.register_id != null && item.register_price != null ? formatMoney(item.register_price) : '', registerOrderNo: item.register_order_no || '', statusText: orderStatusText(item.status), statusClass: 'tag-status', prescriptionTypeText: prescriptionTypeText(pt), prescriptionTypeClass: 'tag-type', orderTypeText: orderTypeText(item.order_type), onlineText: orderOnlineText(item.is_online), erpStatusText: erpSyncText(item.is_sync_erp), freeShippingText: freeShippingText(item.is_free_shipping), receiverName: pickAddrName(item), receiverMobile: pickReceiverMobile(item), deliveryText: deliveryMethodText(item.delivery_method), deliveryClass: 'tag-delivery', userNickname: user.nickname || '-', patientName: (item.user_patient && item.user_patient.name) || item.patient || '-', upId: Number(item.up_id || (item.user_patient && item.user_patient.id) || 0), payTime: formatDateTime(item.pay_time), createdAt: formatDateTime(item.created_at), storeName: store.name || '-', productSummary: buildProductSummary(item.product_order_items, pt), pId: item.p_id, canViewPrescription: !!(item.p_id && item.order_type !== 2 && item.order_type !== 3), _raw: item, } } /** * 列表卡片瘦字段:只保留 UI 需要的标量,丢弃处方 content / 明细整包, * 避免微信小程序 setData 体积过大(曾出现 ~1.5MB 告警) * @param {Object} raw 接口订单行 * @returns {Object} */ export function toOrderCardRow(raw) { if (!raw) return { _wxKey: '0', id: 0 } const d = mapOrderListRow(raw) const id = raw.id const status = raw.status // 样式用:已完成/取消给语义 class,其余用状态码 let statusKey = status != null ? String(status) : 'default' if (status === 6 || status === 7) statusKey = 'done' else if (status === 9) statusKey = 'cancel' const payText = (d.totalPayPrice || '').replace('¥', '').trim() return { _wxKey: id != null && id !== '' ? String(id) : 'ord0', id, status, statusKey, orderNo: d.orderNo, storeName: d.storeName, statusText: d.statusText, productSummary: d.productSummary || '药品订单', prescriptionTypeText: d.prescriptionTypeText, deliveryText: d.deliveryText, patientName: d.patientName, userNickname: d.userNickname, receiverName: d.receiverName, receiverMobile: d.receiverMobile, createdAt: d.createdAt, totalPayPrice: d.totalPayPrice, payAmountText: payText, pId: d.pId, canViewPrescription: d.canViewPrescription, upId: d.upId, } } /** 物流详情(对齐 PC express-detail/detail-by-order) */ export function mapExpressDetail(data) { if (!data || typeof data !== 'object') { return { hasData: false, companyName: '', expressNo: '', stateText: '', tracks: [] } } const rawDetail = data.detail const tracks = Array.isArray(rawDetail) ? rawDetail.map(d => ({ status: d.status || '-', time: d.detail_at || '', detail: d.detail || '', })) : [] return { hasData: !!(data.express_no || data.express_company_name || tracks.length), companyName: data.express_company_name || '-', expressNo: data.express_no || '-', stateText: data.state_txt || '-', tracks, } } /** 订单详情商品行 */ export function mapOrderProductItem(p, prescriptionType) { if (!p) return {} const drug = p.drug || {} const sourceInfo = drug.source_info || {} const manufacturer = sourceInfo.name || drug.source || '暂无' const dosage = p.dosage > 0 ? p.dosage : 1 const qty = prescriptionType === 1 ? '*' + ((p.number != null ? p.number : 0) * dosage) : '×' + (p.number != null ? p.number : 0) const isTcm = prescriptionType === 1 const unitName = (drug.unit && drug.unit.name) || (p.unit && p.unit.name) || p.unit_name || 'g' return { id: p.id, drugName: p.drug_name || drug.drug_name || '药品', drugNumber: drug.drug_number || '', imageUrl: resolveDrugImage(p.drug_image || drug.image), specification: drug.specification || (isTcm ? unitName : '暂无'), manufacturer, qty, price: isTcm ? (p.price != null && p.price !== '' ? p.price + ' 元/' + unitName : '—') : formatMoney(p.price), buyPrice: p.buy_price != null && p.buy_price !== '' ? p.buy_price + ' 元/' + unitName : '—', isTcm, } } /** 订单详情处方块 */ export function mapOrderPrescription(info) { const pres = info && info.prescription const content = pres && pres.content if (!content || info.order_type === 2 || info.order_type === 3) return null const doctor = content.doctor || {} const depart = doctor.depart || {} const title = doctor.title || {} return { prescriptionNo: content.prescription_no || '-', diagnose: content.clinical_diagnose || '-', doctorOrder: formatDoctorOrder(pres), doctorName: doctor.name || '-', departName: depart.name || '-', titleName: title.name || '-', } } export function mapOrderDetailDisplay(info) { if (!info || !info.id) return {} const freeShip = info.is_free_shipping === 1 || info.free_ship === 1 const canView = !!(info.p_id && info.order_type !== 2 && info.order_type !== 3) const presStatus = info.prescription && info.prescription.status != null ? info.prescription.status : null return { orderTypeText: orderTypeText(info.order_type), marketPrice: formatMoney(info.market_price), freeShippingText: freeShip ? '是' : '否', cancelRemark: info.cancel_remark || '无', showPrescription: mapOrderPrescription(info), prescriptionId: info.p_id, canViewPrescription: canView, prescriptionStatusText: canView && presStatus != null ? prescriptionStatusText(presStatus) : '', statusText: orderStatusText(info.status), prescriptionTypeText: prescriptionTypeText(info.prescription_type), deliveryText: deliveryMethodText(info.delivery_method), } } function parseRecipeContent(raw) { if (!raw) return null if (typeof raw === 'object') return raw try { return JSON.parse(raw) } catch (e) { return null } } /** 完整处方详情(对齐 PC PrescriptionDetail.vue) */ export function mapPrescriptionDetailView(item) { if (!item) return null const content = item.content || {} const patient = content.patient || {} const doctor = content.doctor || {} const depart = doctor.depart || {} const title = doctor.title || {} const pt = item.prescription_type const recipes = [] const repice = content.repice || content.recipe || [] const list = Array.isArray(repice) ? repice : [] if (pt === 1) { list.forEach((recipe) => { const drugs = parseRecipeContent(recipe.content) const drugLines = Array.isArray(drugs) ? drugs.map(d => { const name = d.name || d.drug_name || '—' const num = d.number != null ? d.number : '' const way = (d.use_way && d.use_way.name) || d.useWay || '煎服' const unit = (d.unit && d.unit.name) || (d.use_unit && d.use_unit.name) || 'g' return { name, qty: num !== '' ? num + ' /' + unit : '', usage: way, specification: d.specification || '', } }) : [] recipes.push({ type: 'tcm', drugs: drugLines, usage: recipe.consumption != null && recipe.dosage != null ? `每日${recipe.consumption}次,共${recipe.dosage}剂` : '', process: [recipe.process_rule_note, recipe.process_rule].filter(Boolean).join(','), }) }) } else { list.forEach((recipe) => { const d = parseRecipeContent(recipe.content) if (!d) return const unitName = (d.unit && d.unit.name) || d.unit || '' recipes.push({ type: 'west', drugs: [{ name: d.name || d.drug_name || '—', qty: (d.number != null ? d.number : '') + unitName, usage: d.useWay || (d.use_way && d.use_way.name) || '', specification: d.specification || '', }], usage: '', process: '', }) }) } const tcm = item.online_tcm_print || {} return { prescriptionNo: item.prescription_no || content.prescription_no || '-', createdAt: item.created_at || '-', patientName: patient.name || '-', patientSex: patient.sex === 1 ? '男' : patient.sex === 2 ? '女' : '-', patientAge: patient.age != null ? String(patient.age) : '-', category: content.category || '-', diagnose: content.clinical_diagnose || '-', doctorOrder: formatDoctorOrder(item), doctorName: doctor.name || '-', departName: depart.name || '-', titleName: title.name || '-', tcmSyndrome: tcm.show && tcm.tcm_syndrome ? tcm.tcm_syndrome : '', tcmMethod: tcm.show && tcm.tcm_method ? tcm.tcm_method : '', tcmDisease: tcm.show && tcm.tcm_disease ? tcm.tcm_disease : '', recipes, prescriptionType: pt, } } /** 订单商品行展示 */ export function formatOrderProductLine(p, prescriptionType) { if (!p) return '-' const name = p.drug_name || (p.drug && p.drug.drug_name) || '药品' const num = p.number != null ? p.number : '' if (prescriptionType === 1) { const dosage = p.dosage > 0 ? p.dosage : 1 return name + ' ×' + (num * dosage) } return name + ' ×' + num } export function resolveDrugImage(url) { if (!url) return DEFAULT_DRUG_IMAGE const s = String(url) if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s return DEFAULT_DRUG_IMAGE } /** 仓库 1=下架 2=上架 */ export function warehouseStatusText(status) { if (status === 2) return '上架' if (status === 1) return '下架' return '-' } export function mapWarehouseRow(item, warehouseType = 'store') { if (!item) return {} const drug = item.drug || {} const storeDrug = drug.drug_store_drug || {} const suggestPrice = storeDrug.price != null ? storeDrug.price : drug.price const isPlatform = warehouseType === 'platform' const supplyRaw = isPlatform ? (item.market_price ?? item.buy_price) : (item.buy_price ?? item.market_price) return { id: item.id, drugName: drug.drug_name || '-', imageUrl: resolveDrugImage(drug.image), buyPrice: formatMoney(supplyRaw), price: formatMoney(item.price), suggestPrice: formatMoney(suggestPrice), stock: item.stock != null ? item.stock : '-', statusText: warehouseStatusText(item.status), isOnShelf: item.status === 2, pinyin: drug.pinyin || '-', _raw: item, } } function mapReconciliationCategory(rec, prefix) { const sales = rec[prefix + '_sales'] const salesPrice = rec[prefix + '_sales_price'] const supplyPrice = rec[prefix + '_supply_price'] return { sales: sales != null ? String(sales) : '-', salesPrice: formatMoney(salesPrice), supplyPrice: formatMoney(supplyPrice), } } export function mapReconciliationStoreRow(item) { if (!item) return {} const rec = item.reconciliation || {} return { id: item.id, name: item.name || '-', totalSales: formatMoney(rec.total_sales_price), totalSupply: formatMoney(rec.total_supply_price), herbalSalesPrice: formatMoney(rec.herbal_sales_price), medicineSalesPrice: formatMoney(rec.medicine_sales_price), registrationPrice: formatMoney(rec.registration_price), herbal: mapReconciliationCategory(rec, 'herbal'), medicine: mapReconciliationCategory(rec, 'medicine'), servicePackage: mapReconciliationCategory(rec, 'service_package'), otherFees: { express: formatMoney(rec.express_price), process: formatMoney(rec.process_price), treatment: formatMoney(rec.treatment_price), }, _raw: item, } } /** 订单追溯对账汇总(summary 字段,对齐 mapReconciliationStoreRow 结构) */ export function mapReconciliationOrderSummary(summary) { if (!summary) return null return { totalSales: formatMoney(summary.total_sales_price), totalSupply: formatMoney(summary.total_supply_price), registrationPrice: formatMoney(summary.registration_price), registerOrderNo: summary.register_order_no || '', herbal: mapReconciliationCategory(summary, 'herbal'), medicine: mapReconciliationCategory(summary, 'medicine'), servicePackage: mapReconciliationCategory(summary, 'service_package'), otherFees: { express: formatMoney(summary.express_price), process: formatMoney(summary.process_price), treatment: formatMoney(summary.treatment_price), }, _raw: summary, } } export function mapReconciliationDrugRow(item) { if (!item) return {} return { drugId: item.drug_id, drugName: item.drug_name || '-', drugNumber: item.drug_number || '', typeText: item.type_txt || '-', number: item.number != null ? item.number : '-', marketPrice: formatMoney(item.market_price), totalSales: formatMoney(item.total_sales_price), totalSupply: formatMoney(item.total_supply_price), orderNo: item.order_no || '', _raw: item, } } export function formatPricePlain(v) { if (v === null || v === undefined || v === '') return '-' return '¥' + Number(v).toFixed(2) } /** 汇总项:隐藏全零噪音 */ export function filterReconciliationStatItems(items) { return items.filter(s => { if (s.key === 'total_sales_price' || s.key === 'total_supply_price') return true if (s.isCount) { const n = Number(s.raw) return !Number.isNaN(n) && n !== 0 } const v = s.raw if (v === null || v === undefined || v === '') return false const n = Number(v) return !Number.isNaN(n) && n !== 0 }) } /** 诊所对账汇总(对齐 PC setStoreStatistics) */ export function mapReconciliationStoreCount(count) { if (!count) return [] const items = [ { key: 'total_sales_price', label: '总销售金额', value: formatPricePlain(count.total_sales_price), raw: count.total_sales_price }, { key: 'total_supply_price', label: '总供货金额', value: formatPricePlain(count.total_supply_price), raw: count.total_supply_price }, { key: 'herbal_sales', label: '草药销量', value: count.herbal_sales != null ? String(count.herbal_sales) : '-', raw: count.herbal_sales, isCount: true }, { key: 'herbal_sales_price', label: '草药销售金额', value: formatPricePlain(count.herbal_sales_price), raw: count.herbal_sales_price }, { key: 'herbal_supply_price', label: '草药供货金额', value: formatPricePlain(count.herbal_supply_price), raw: count.herbal_supply_price }, { key: 'medicine_sales', label: '成药销量', value: count.medicine_sales != null ? String(count.medicine_sales) : '-', raw: count.medicine_sales, isCount: true }, { key: 'medicine_sales_price', label: '成药销售金额', value: formatPricePlain(count.medicine_sales_price), raw: count.medicine_sales_price }, { key: 'medicine_supply_price', label: '成药供货金额', value: formatPricePlain(count.medicine_supply_price), raw: count.medicine_supply_price }, { key: 'express_price', label: '快递费', value: formatPricePlain(count.express_price), raw: count.express_price }, { key: 'process_price', label: '加工费', value: formatPricePlain(count.process_price), raw: count.process_price }, { key: 'treatment_price', label: '诊疗费', value: formatPricePlain(count.treatment_price), raw: count.treatment_price }, { key: 'outpatient_price', label: '门诊收入', value: formatPricePlain(count.outpatient_price), raw: count.outpatient_price }, { key: 'registration_price', label: '挂号费', value: formatPricePlain(count.registration_price), raw: count.registration_price }, ] return filterReconciliationStatItems(items) } /** 药品对账汇总(对齐 PC setDrugStatistics) */ export function mapReconciliationDrugCount(count) { if (!count) return [] return [ { key: 'total_sales_price', label: '总销售金额', value: formatPricePlain(count.total_sales_price) }, { key: 'total_supply_price', label: '总供货金额', value: formatPricePlain(count.total_supply_price) }, { key: 'number', label: '销量', value: count.number != null ? String(count.number) : '-' }, ] }