修改价格套餐样式结构
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 价格套餐 · 纯函数与数据工厂
|
||||
*
|
||||
* 只做数据转换,不依赖组件实例 / 字典 / 接口,
|
||||
* create.vue、detail.vue 及 set/components 下的组件共用。
|
||||
*/
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
|
||||
/** 计价类型枚举 */
|
||||
export const SET_TYPE = {
|
||||
FIXED: 'FIXED',
|
||||
DISCOUNT: 'DISCOUNT'
|
||||
}
|
||||
|
||||
/** 套餐状态枚举:D 草稿 / A 审核中 / E 生效中 / R 驳回 / S 已停用 */
|
||||
export const SET_STATUS = {
|
||||
DRAFT: 'D',
|
||||
AUDIT: 'A',
|
||||
EFFECTIVE: 'E',
|
||||
REJECT: 'R',
|
||||
STOPPED: 'S'
|
||||
}
|
||||
|
||||
const STATUS_LABEL = {
|
||||
D: '草稿',
|
||||
A: '审核中',
|
||||
E: '生效中',
|
||||
R: '驳回',
|
||||
S: '已停用'
|
||||
}
|
||||
|
||||
const STATUS_TAG = {
|
||||
D: 'warning',
|
||||
A: 'primary',
|
||||
E: 'success',
|
||||
R: 'danger',
|
||||
S: 'info'
|
||||
}
|
||||
|
||||
/** 默认取值方式 */
|
||||
export const DEFAULT_ROUND_MODE = 'HALF_UP'
|
||||
|
||||
/** 状态文案(已过期优先) */
|
||||
export function setStatusLabel(set) {
|
||||
if (set && set.expired) return '已过期'
|
||||
return STATUS_LABEL[set && set.status] || (set && set.status) || '-'
|
||||
}
|
||||
|
||||
/** 状态标签色(已过期优先) */
|
||||
export function setStatusTagType(set) {
|
||||
if (set && set.expired) return 'danger'
|
||||
return STATUS_TAG[set && set.status] || 'info'
|
||||
}
|
||||
|
||||
/** 明细 / 客户是否可维护:草稿、驳回、生效中 */
|
||||
export function isChildEditable(status) {
|
||||
return [SET_STATUS.DRAFT, SET_STATUS.REJECT, SET_STATUS.EFFECTIVE].includes(status)
|
||||
}
|
||||
|
||||
/** 日期显示 yyyy-MM-dd */
|
||||
export function formatDate(val) {
|
||||
return val ? parseTime(val, '{y}-{m}-{d}') : ''
|
||||
}
|
||||
|
||||
/** 有效期区间文案,结束为空表示长期 */
|
||||
export function formatDateRange(begin, end) {
|
||||
return `${formatDate(begin) || '-'} ~ ${end ? formatDate(end) : '长期'}`
|
||||
}
|
||||
|
||||
/** 是否固定价模式 */
|
||||
export function isFixedType(setType) {
|
||||
return setType === SET_TYPE.FIXED
|
||||
}
|
||||
|
||||
/** 是否折扣模式 */
|
||||
export function isDiscountType(setType) {
|
||||
return setType === SET_TYPE.DISCOUNT
|
||||
}
|
||||
|
||||
/** 计价类型展示文案 */
|
||||
export function setTypeLabel(setType) {
|
||||
return isFixedType(setType) ? 'FIXED 固定价' : 'DISCOUNT 折扣'
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字转字符串,抹掉浮点误差尾巴
|
||||
* @param {number|string} v
|
||||
* @returns {string} 0.1 + 0.2 -> '0.3'
|
||||
*/
|
||||
export function trimNum(v) {
|
||||
if (v == null || v === '') return ''
|
||||
const n = Number(v)
|
||||
if (Number.isNaN(n)) return String(v)
|
||||
return String(parseFloat(n.toFixed(6)))
|
||||
}
|
||||
|
||||
/** 重量段展示文案:1≤W≤2 */
|
||||
export function formatWeightLabel(min, max) {
|
||||
return `${trimNum(min)}≤W≤${trimNum(max)}`
|
||||
}
|
||||
|
||||
/** 国家唯一键:优先国家三字码,其次国家名称 */
|
||||
export function countryKeyOf(row) {
|
||||
if (!row) return ''
|
||||
if (row.countryCode) return row.countryCode
|
||||
if (row.countryName) return 'N:' + row.countryName
|
||||
return ''
|
||||
}
|
||||
|
||||
/** 明细行的国家 与 产品国家配置行 是否指向同一国家 */
|
||||
export function matchCountry(detail, item) {
|
||||
if (detail.countryCode && item.countryCode) {
|
||||
return detail.countryCode === item.countryCode
|
||||
}
|
||||
return !!detail.countryName && item.countryName === detail.countryName
|
||||
}
|
||||
|
||||
/**
|
||||
* 国家下拉选项(按产品的国家配置去重)
|
||||
* @param {Array} rows bms_product_country 行
|
||||
* @returns {Array<{key, code, name, label}>}
|
||||
*/
|
||||
export function buildCountryOptions(rows) {
|
||||
const map = new Map()
|
||||
;(rows || []).forEach(item => {
|
||||
const key = countryKeyOf(item)
|
||||
if (!key || map.has(key)) return
|
||||
map.set(key, {
|
||||
key,
|
||||
code: item.countryCode || undefined,
|
||||
name: item.countryName,
|
||||
label: item.countryCode ? `${item.countryName} ${item.countryCode}` : item.countryName
|
||||
})
|
||||
})
|
||||
return [...map.values()]
|
||||
}
|
||||
|
||||
/**
|
||||
* 重量段下拉选项(按已选国家过滤去重)
|
||||
* @param {Array} rows bms_product_country 行
|
||||
* @param {Object} row 当前明细行(含国家)
|
||||
* @returns {Array<{value, label, detailId, freightPrice, registrationFee}>}
|
||||
*/
|
||||
export function buildWeightOptions(rows, row) {
|
||||
const map = new Map()
|
||||
;(rows || []).filter(item => matchCountry(row, item)).forEach(item => {
|
||||
if (item.weightMin == null && item.weightMax == null) return
|
||||
const value = formatWeightLabel(item.weightMin, item.weightMax)
|
||||
if (map.has(value)) return
|
||||
map.set(value, {
|
||||
value,
|
||||
label: value,
|
||||
detailId: item.detailId,
|
||||
freightPrice: item.freightPrice,
|
||||
registrationFee: item.registrationFee
|
||||
})
|
||||
})
|
||||
return [...map.values()]
|
||||
}
|
||||
|
||||
/** 附加费金额展示:RATE 转百分比,其余带币种 */
|
||||
export function formatChargeValue(row) {
|
||||
if (!row || row.chargeValue == null) return '-'
|
||||
const v = Number(row.chargeValue)
|
||||
if (row.chargeType === 'RATE') return (v * 100).toFixed(2) + '%'
|
||||
return v + ' ' + (row.currency || 'CNY')
|
||||
}
|
||||
|
||||
/** 附加费作用范围文案 */
|
||||
export function surchargeScopeLabel(s) {
|
||||
if (s.detailId == null) return '产品级'
|
||||
const w = s.weightMin != null && s.weightMax != null ? `${s.weightMin}-${s.weightMax}kg` : '-'
|
||||
return `${s.countryName || '-'} · ${w}`
|
||||
}
|
||||
|
||||
/** 附加费标签文案 */
|
||||
export function surchargeTagLabel(s) {
|
||||
return `${s.scName} ${formatChargeValue(s)}`
|
||||
}
|
||||
|
||||
/** 新增一条空明细行 */
|
||||
export function createEmptyDetailRow() {
|
||||
return {
|
||||
productCode: undefined,
|
||||
productName: undefined,
|
||||
countryCode: undefined,
|
||||
countryName: undefined,
|
||||
_countryKey: undefined,
|
||||
weightLabel: undefined,
|
||||
productCountryId: undefined,
|
||||
fvValue: undefined,
|
||||
fvRegistrationFee: undefined,
|
||||
discountValue: undefined,
|
||||
roundMode: DEFAULT_ROUND_MODE
|
||||
}
|
||||
}
|
||||
|
||||
/** 明细行 -> 可编辑行(补齐取值方式与国家键) */
|
||||
export function toEditableDetailRow(row) {
|
||||
return {
|
||||
...row,
|
||||
roundMode: row.roundMode || DEFAULT_ROUND_MODE,
|
||||
_countryKey: countryKeyOf(row)
|
||||
}
|
||||
}
|
||||
|
||||
/** 新增一条空客户绑定行 */
|
||||
export function createEmptyCustomerRow({ effectiveDate, expireDate, seq = 1 } = {}) {
|
||||
return {
|
||||
customerId: undefined,
|
||||
customerCode: undefined,
|
||||
customerName: '',
|
||||
bindPriority: seq,
|
||||
prBegindate: effectiveDate,
|
||||
prEnddate: expireDate
|
||||
}
|
||||
}
|
||||
|
||||
/** 新建套餐的基本信息默认值 */
|
||||
export function createEmptyBasicInfo() {
|
||||
return {
|
||||
priceSetName: '',
|
||||
setType: SET_TYPE.FIXED,
|
||||
defaultDiscount: 88,
|
||||
effectiveDate: undefined,
|
||||
expireDate: undefined,
|
||||
priceSetNote: ''
|
||||
}
|
||||
}
|
||||
|
||||
/** 明细行 -> 提交后端的 payload */
|
||||
export function toDetailPayload(d) {
|
||||
return {
|
||||
productCode: d.productCode,
|
||||
productName: d.productName,
|
||||
countryCode: d.countryCode || undefined,
|
||||
countryName: d.countryName || undefined,
|
||||
weightLabel: d.weightLabel || undefined,
|
||||
productCountryId: d.productCountryId || undefined,
|
||||
fvValue: d.fvValue,
|
||||
fvRegistrationFee: d.fvRegistrationFee,
|
||||
discountValue: d.discountValue,
|
||||
roundMode: d.roundMode || DEFAULT_ROUND_MODE
|
||||
}
|
||||
}
|
||||
|
||||
/** 客户绑定行 -> 提交后端的 payload */
|
||||
export function toCustomerPayload(c) {
|
||||
return { ...c }
|
||||
}
|
||||
Reference in New Issue
Block a user