123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- <template>
- <div class="order-detail-card-container">
- <InfoCard title="基本信息">
- <div class="order-detail-card-content">
- <div class="order-detail-card-item" v-for="(item, index) in basicInfoItems" :key="index">
- {{ item.label }}:{{ getFilteredValue(orderData[item.key], item.filter) || '-' }}
- </div>
- </div>
- </InfoCard>
- <InfoCard title="产品信息">
- <div class="order-detail-card-content">
- <div class="order-detail-card-item" v-for="(item, index) in productInfoTotalItems" :key="index">
- <div v-if="item.key === 'pure_amount'">
- {{ item.label }}:¥{{ formatNumber(orderData[item.key]) || '-' }}
- </div>
- <div v-else-if="item.key === 'commission'">
- {{ item.label }}:¥{{ formatNumber(orderData[item.key]) || '0.00' }}
- </div>
- <div v-else-if="item.key === 'zero_type'">
- <span v-if="shouldRenderItem(item)">
- {{ item.label }}:{{ getFilteredValue(orderData[item.key], item.filter) || '-' }}
- </span>
- </div>
- <div v-else>{{ item.label }}:{{ getFilteredValue(orderData[item.key], item.filter ) || '-' }}</div>
- </div>
- </div>
- <div class="order-detail-product-list">
- <ProductCard
- v-for="(product, index) in productData"
- :key="product.id"
- :title="setProductTitle(product, index)"
- :subtitle="product.auto !== 1 ? '该产品暂不支持系统自动开通权限,请联系运维开通': ''"
- >
- <div class="order-detail-product-content">
- <div class="grouped-items">
- <div
- v-for="(item, index) in productInfoItems"
- :key="index"
- :class="`item-span-${item.span}`" >
- <div
- class="order-detail-card-item"
- v-if="shouldRenderItem(item, product)"
- >
- <div v-if="item.key === 'linkedOrder'" class="linkedOrder">
- {{ item.label }}:
- <TableCard :span-method="objectSpanMethod" v-if="product[item.key].length" :table-data="product[item.key]" :columns="linkOrderColumns">
- </TableCard>
- <span v-else>-</span>
- </div>
- <div v-else-if="item.key === 'subAccountCount'">
- <span v-html="getValidityPeriodHtml(product, item)"></span>
- </div>
- <div v-else-if="item.key === 'mainAccountCount'">
- <span v-html="getValidityPeriodHtml(product, item)"></span>
- </div>
- <div v-else-if="item.key ==='rate'">
- {{ item.label }}:
- <span :class="{'no_open_root': product.original_price === '0.00'}">{{ getFilteredValue(product[item.key], item.filter) || '-' }}</span>
- </div>
- <div v-else-if="item.key === 'final_price' || item.key === 'original_price'">
- {{ item.label }}:¥{{ getFilteredValue(product[item.key], item.filter) || '-' }}
- </div>
- <div v-else-if="item.key === 'validity_period'">
- <span v-html="getValidityPeriodHtml(product, item)"></span>
- </div>
- <div v-else-if="item.key === 'supServicelds'">
- {{ item.label }}:{{ getFilteredValue(product[item.key], item.filter) || '-' }}
- </div>
- <div v-else-if="item.key === 'service_starttime'">
- {{ item.label }}:
- <span :class="{'no_open_root':!product.is_service_open}" >{{ product.is_service_open? (product.service_starttime || '-') : '暂未开通' }}</span>
- </div>
- <div v-else-if="item.key === 'service_endtime'">
- {{ item.label }}:
- <span :class="{'no_open_root': !product.is_service_open}" >{{ product.is_service_open ? (product.service_endtime || '-') : '暂未开通' }}</span>
- </div>
- <div v-else-if="item.key ==='phone'">
- {{ item.label }}:{{ orderData.user_phone || '-' }}
- </div>
- <div v-else>{{ item.label }}:{{ getFilteredValue(product[item.key], item.filter) || '-' }}</div>
- </div>
- </div>
- </div>
- </div>
- </ProductCard>
- </div>
- </InfoCard>
- <InfoCard title="其他信息">
- <div class="order-detail-card-content">
- <div class="order-detail-card-item" v-for="(item, index) in otherInfoItems" :key="index">
- {{ item.label }}:{{ getFilteredValue(orderData[item.key], item.filter) || '-' }}
- </div>
- </div>
- </InfoCard>
- </div>
- </template>
- <script>
- import InfoCard from '../../ui/InfoCard.vue';
- import ProductCard from '../../ui/ProductCard.vue';
- import { paymentTypeOptions } from '../../data/options.js';
- import { div, calcDiscountRate, roundToTwoDecimals } from '@/utils/number/';
- import TableCard from '../../ui/TableCard.vue';
- export default {
- name: 'OrderDetailCard',
- components: {
- InfoCard,
- ProductCard,
- TableCard
- },
- props: {
- orderDetail: {
- type: Object,
- default: () => {}
- }
- },
- data() {
- return {
- orderDetailInfo: {},
- basicInfoItems: [
- { label: '创建人', key: 'create_person' },
- { label: '创建时间', key: 'create_time' },
- { label: '最近更新人', key: 'last_update_person' },
- { label: '最近更新时间', key: 'autoUpdate' },
- { label: '订单审核状态', key: 'audit_status', filter: 'orderCoursed' },
- { label: '订单状态', key: 'order_status', filter: 'orderStatus' }
- ],
- otherInfoItems: [
- { label: '约定支付方式', key: 'pay_way' },
- { label: '下单渠道', key: 'order_channel_new' },
- { label: '付款户名', key: 'payment_user'},
- { label: '订单备注', key: 'remark' },
- ],
- productInfoTotalItems: [
- { label: '合同金额合计', key: 'final_price_total' },
- { label: '标准售价合计', key: 'original_price_total'},
- { label: '折扣率', key: 'rate_total' },
- { label: '渠道佣金', key: 'commission'},
- { label: '净合同金额合计', key: 'pure_amount'},
- { label: '0元订单类型', key: 'zero_type', condition: () => this.orderData.final_price_total === '0.00' },
- ],
- productInfoItems: [
- { label: '活动产品', key: 'activity_code', span: 1, condition: (product) => product.activity_code },
- { label: '付费类型', key: 'service_type', filter: 'orderServiceType', span: 3},
- { label: '升级内容', key: 'supServicelds', span: 3, condition: (product) => product.supServicelds },
- { label: '产品规格', key: 'productName', span: 3},
- { label: '服务列表', key: 'bigServiceNames', span: 1, condition: (product) => product.productName && product.productName.includes('自定义') && product.product_code === 'dyh001'},
- { label: '有效周期', key: 'validity_period', span: 1},
- { label: '合同金额', key: 'final_price', span: 3},
- { label: '标准售价', key: 'original_price', span: 3},
- { label: '折扣率', key: 'rate', span: 3},
- { label: '子账号数量', key: 'subAccountCount', span: 1, condition: (product) => product.product_type === 'VIP订阅' && product.buyAccountCount && product.giftAccountCount },
- { label: '主账号数量', key: 'mainAccountCount', span: 1, condition: (product) => product.product_type === 'VIP订阅' },
- { label: '关联订单', key: 'linkedOrder', span: 1},
- { label: '开通权益手机号', key: 'phone', span: 3},
- { label: '服务开始时间', key: 'service_starttime', span: 3},
- { label: '服务结束时间', key: 'service_endtime', span: 3}
- ],
- orderData: {},
- productData: [],
- linkOrderColumns: [
- {
- prop: 'name',
- label: '产品类型及规格',
- width: 154
- },
- {
- prop: 'empowerCount',
- label: '账号数量',
- width: 80
- },
- {
- prop: 'serviceEndTime',
- label: '到期时间',
- width: 102
- },
- {
- prop: 'buySubject',
- label: '购买主体',
- width: 80
- },
- {
- prop:'order_code',
- label: '订单编号',
- width: 154
- },
- {
- prop:'service_type',
- label: '付费类型',
- width: 80
- },
- {
- prop:'create_time',
- label: '创建时间',
- width: 102
- }
- ]
- }
- },
- watch: {
- orderDetail: {
- handler(newVal) {
- this.orderDetailInfo = newVal || {};
- this.init();
- },
- deep: true,
- immediate: true
- }
- },
- // async mounted() {
- // this.orderDetailInfo = await this.orderDetail || {}
- // this.init()
- // },
- computed: {},
- methods: {
- init() {
- this.orderData = this.orderDetailInfo?.orderData || {}
- let productData = this.orderDetailInfo?.productData || []
- if(productData.length > 0) {
- productData = productData.map(product => {
- try {
- const parsedFilter = this.parseProductFilter(product);
- const rate = this.calculateDiscountRate(product);
- const validityPeriod = this.calculateValidityPeriod(
- parsedFilter.buy_cycle,
- parsedFilter.buy_type,
- parsedFilter.give_cycle,
- parsedFilter.give_type,
- product
- );
- const subAccountCount = this.buildSubAccountCount(product);
- const mainAccountCount = this.buildMainAccountCount(product);
- const linkedOrder = this.processLinkedOrder(product);
- const finalPrice = this.formatNumber(product.final_price);
- const originalPrice = this.formatNumber(product.original_price);
- return {
- ...product,
- filter: parsedFilter,
- rate,
- validity_period: validityPeriod,
- subAccountCount,
- mainAccountCount,
- linkedOrder,
- final_price: finalPrice,
- original_price: originalPrice
- };
- } catch (error) {
- console.error('产品信息初始化失败:', error);
- return product;
- }
- });
- }
- this.setTotalAmounts(productData);
- this.productData = productData;
- },
- parseProductFilter(product) {
- let parsedFilter = {};
- if (typeof product.filter === 'string') {
- try {
- parsedFilter = JSON.parse(product.filter || '{}');
- } catch {
- parsedFilter = {};
- }
- } else {
- parsedFilter = product.filter || {};
- }
- return parsedFilter;
- },
- // 计算折扣率
- calculateDiscountRate(product) {
- let rate = '无法计算';
- if (product.original_price && Number(product.original_price) !== 0) {
- rate = (calcDiscountRate(product.final_price, product.original_price)) + '%';
- }
- return rate;
- },
- // 构造子账号数量字符串。
- buildSubAccountCount(product) {
- if (product.product_type === 'VIP订阅') {
- const buyCount = Number(product.buyAccountCount) || 0;
- const giftCount = Number(product.giftAccountCount) || 0;
- const countTotal = buyCount + giftCount;
- return `付费${buyCount}个,赠送${giftCount}个,合计:<span class="color_main">${countTotal}</span>个`;
- }
- return '';
- },
- // 构造主账号数量字符串。
- buildMainAccountCount(product) {
- if (product.product_type === 'VIP订阅') {
- return `付费1个,合计<span class="color_main">1</span>个`;
- }
- return '';
- },
- // 处理关联订单数据。
- processLinkedOrder(product) {
- if (product.linkedOrder && Object.keys(product.linkedOrder).length > 0) {
- const orderList = [product.linkedOrder];
- return this.flattenLinkOrderList(orderList);
- }
- return [];
- },
- // 设置合同金额合计和标准售价合计,以及计算折扣率总和。
- setTotalAmounts(productData) {
- const totalFinalPrice = productData.reduce((acc, cur) => acc + Number(cur.final_price), 0).toFixed(2);
- const totalOriginalPrice = productData.reduce((acc, cur) => acc + Number(cur.original_price), 0).toFixed(2);
- const rateTotal = div(totalFinalPrice, totalOriginalPrice) ? (div(totalFinalPrice, totalOriginalPrice) * 100).toFixed(2) + '%' : '无法计算';
- this.orderData.final_price_total = '¥' + totalFinalPrice;
- this.orderData.original_price_total = '¥' + totalOriginalPrice;
- this.orderData.rate_total = rateTotal;
- },
- flattenLinkOrderList(linkOrderList) {
- const result = [];
- if (!linkOrderList || linkOrderList.length === 0) return result;
- linkOrderList.forEach(item => {
- const { orderArr, ...rest } = item; // 拆分 orderArr 和其他字段
- if (!orderArr || orderArr.length === 0) return;
- orderArr.forEach(order => {
- result.push({
- ...rest, // 非 orderArr 的字段(如 name, empowerCount 等)
- ...order // orderArr 中的字段(如 order_code, service_type 等)
- });
- });
- });
- return result;
- },
- shouldRenderItem(item, product) {
- if (item.condition && typeof item.condition === 'function') {
- const conditionResult = item.condition(product)
- if(!conditionResult) {
- // item.span = 0
- }
- return conditionResult
- }
- return true;
- },
- calculateValidityPeriod(buyCycle, buyType, giveCycle, giveType, product) {
- let totalMonths = 0;
- let buyText = '';
- let giveText = '';
- const TIME_MAP = {
- '1': '天',
- '2': '月',
- '3': '年',
- '4': '季度'
- }
- // 安全地将字符串转为整数,默认为 0
- const parseCycle = (cycle) => {
- const num = parseInt(cycle);
- return isNaN(num) ? 0 : num;
- };
- // 计算周期并返回文本和月份数
- const processCycle = (cycle, type) => {
- const textValue = TIME_MAP[type] || '';
- const value = parseCycle(cycle);
- let months = 0;
- let text = '';
- if (textValue.includes('月')) {
- months += value;
- text = `${value}个月`;
- } else if (textValue.includes('年')) {
- months += value * 12;
- text = `${value}年`;
- } else if (textValue.includes('季度')) {
- months += value * 3;
- text = `${value}季度`;
- } else if (textValue.includes('天')) {
- months += value / 30; // 注意:此处为近似值
- text = `${value}天`;
- }
- return { months, text };
- };
- const buyResult = processCycle(buyCycle, buyType);
- const giveResult = processCycle(giveCycle, giveType);
- totalMonths = buyResult.months + giveResult.months;
- buyText = buyResult.text;
- giveText = giveResult.text;
- const returned_open = product.returned_open === '1' ? '(全额回款当日开通)' : '';
- if(totalMonths === 0) return '-'
- return `付费${buyText},赠送${giveText},合计<span class="color_main">${totalMonths.toFixed(0)}</span>个月${returned_open}`;
- },
- getValidityPeriodHtml(product, item) {
- const label = item.label;
- const value = product[item.key] || '-';
- return `${label}:${value}`;
- },
- // 替代过滤器的通用方法
- getFilteredValue(value, filterName) {
- if (!filterName) return value || '-';
- return this[filterName](value);
- },
- setProductTitle(product, index) {
- const tactics = product.tactics === '2' ? '【赠送】' : '【售卖】';
- return `${index + 1}.${tactics}${product.product_type}`;
- },
- // 格式化数字,保留两位小数
- formatNumber(num, x = 2) {
- if(!num) return 0.00
- const newnum = Number(num) / 100;
- return roundToTwoDecimals(newnum, x)
- },
- orderCoursed(val) {
- if (val == 0) {
- return '待提交'
- } else if (val == 1) {
- return '待一审'
- } else if (val == 2) {
- return '待二审'
- } else if (val == 4) {
- return '待三审'
- } else if (val == 3) {
- return '已通过'
- } else if (val == -2 || val == -3 || val == -4) {
- return '已退回'
- }
- },
- orderServiceType(val) {
- const matchedOption = paymentTypeOptions.find(option => option.value === val);
- return matchedOption ? matchedOption.label : val; // 如果未找到匹配项,返回原始值
- },
- orderStatus(val) {
- if (!val || val == 0) {
- return '未完成'
- } else if (val == 1) {
- return '已完成'
- } else if (val == -1) {
- return '逻辑删除'
- } else if (val == -2) {
- return '已取消'
- } else if (val == -3) {
- return '已退款'
- } else if (val == -3) {
- return '已退款'
- }
- },
- objectSpanMethod({ row, column, rowIndex, columnIndex }) {
- if (columnIndex <= 3) {
- if (rowIndex % 2 === 0) {
- return {
- rowspan: 2,
- colspan: 1
- };
- } else {
- return {
- rowspan: 0,
- colspan: 0
- };
- }
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .order-detail-card-container {
- background: #F2F2F4;
- ::v-deep {
- .info-card {
- margin-bottom: 16px;
- }
- }
- .order-detail-card-content {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- margin-bottom: 6px;
- }
- .grouped-items {
- display: flex;
- flex-wrap: wrap;
- margin-bottom: 10px;
- .item-span-1 {
- width: 100%;
- }
- .item-span-3 {
- min-width: 255px;
- }
- }
- .order-detail-product-content {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- margin-bottom: 6px;
- padding: 0 24px;
- }
- .order-detail-card-item {
- min-width: 255px;
- margin-right: 32px;
- margin-bottom: 10px;
- font-size: 14px;
- line-height: 22px;
- color: $gray_10;
- .linkedOrder {
- display: flex;
- align-items: flex-start;
- }
- }
- .no_open_root {
- color: #F56500;
- }
- ::v-deep {
- .color_main {
- color: #2ABED1;
- }
- }
- }
- </style>
|