feat: 删除不再使用的格式化数字工具函数,优化 SKU 列表组件的逻辑和结构
parent
4fafb39efc
commit
3326c25a0d
|
@ -1,38 +0,0 @@
|
||||||
/**
|
|
||||||
* 将一个整数转换为分数保留两位小数
|
|
||||||
* @param num
|
|
||||||
*/
|
|
||||||
export const formatToFraction = (num: number | string | undefined): string => {
|
|
||||||
if (typeof num === 'undefined') return '0.00';
|
|
||||||
const parsedNumber = typeof num === 'string' ? parseFloat(num) : num;
|
|
||||||
return (parsedNumber / 100.0).toFixed(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将一个数转换为 1.00 这样
|
|
||||||
* 数据呈现的时候使用
|
|
||||||
*
|
|
||||||
* @param num 整数
|
|
||||||
*/
|
|
||||||
// TODO @芋艿:看看怎么融合掉
|
|
||||||
export const floatToFixed2 = (num: number | string | undefined): string => {
|
|
||||||
let str = '0.00';
|
|
||||||
if (typeof num === 'undefined') {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
const f = formatToFraction(num);
|
|
||||||
const decimalPart = f.toString().split('.')[1];
|
|
||||||
const len = decimalPart ? decimalPart.length : 0;
|
|
||||||
switch (len) {
|
|
||||||
case 0:
|
|
||||||
str = f.toString() + '.00';
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
str = f.toString() + '0';
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
str = f.toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 情况一:添加/修改 -->
|
<!-- 情况一:添加/修改 -->
|
||||||
<el-table
|
<el-table
|
||||||
v-if="!isDetail && !isActivityComponent"
|
v-if="!isActivityComponent"
|
||||||
:data="isBatch ? skuList : formData!.skus!"
|
:data="isBatch ? skuList : formData!.skus!"
|
||||||
border
|
border
|
||||||
class="tabNumWidth"
|
class="tabNumWidth"
|
||||||
|
@ -164,89 +164,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 情况二:详情 -->
|
<!-- 情况二:作为活动组件 -->
|
||||||
<el-table
|
|
||||||
v-if="isDetail"
|
|
||||||
ref="activitySkuListRef"
|
|
||||||
:data="formData!.skus!"
|
|
||||||
border
|
|
||||||
max-height="500"
|
|
||||||
size="small"
|
|
||||||
style="width: 99%"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
>
|
|
||||||
<el-table-column v-if="isComponent" type="selection" width="45" />
|
|
||||||
<el-table-column align="center" label="图片" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-image v-if="row.picUrl" :src="row.picUrl" class="h-50px w-50px" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<template v-if="formData!.specType && !isBatch">
|
|
||||||
<!-- 根据商品属性动态添加 -->
|
|
||||||
<el-table-column
|
|
||||||
v-for="(item, index) in tableHeaders"
|
|
||||||
:key="index"
|
|
||||||
:label="item.label"
|
|
||||||
align="center"
|
|
||||||
min-width="80"
|
|
||||||
>
|
|
||||||
<template #default="{ row }">
|
|
||||||
<span style="font-weight: bold; color: #40aaff">
|
|
||||||
{{ row.properties?.[index]?.valueName }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</template>
|
|
||||||
<el-table-column align="center" label="商品条码" min-width="100">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.barCode }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="销售价(元)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.price }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="市场价(元)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.marketPrice }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="成本价(元)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.costPrice }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="库存" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.stock }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="重量(kg)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.weight }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="体积(m^3)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.volume }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<template v-if="formData!.subCommissionType">
|
|
||||||
<el-table-column align="center" label="一级返佣(元)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.firstBrokeragePrice }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column align="center" label="二级返佣(元)" min-width="80">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.secondBrokeragePrice }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</template>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<!-- 情况三:作为活动组件 -->
|
|
||||||
<el-table
|
<el-table
|
||||||
v-if="isActivityComponent"
|
v-if="isActivityComponent"
|
||||||
:data="formData!.skus!"
|
:data="formData!.skus!"
|
||||||
|
@ -307,7 +225,8 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { copyValueToTarget, formatToFraction } from '#/utils';
|
import { copyValueToTarget } from '#/utils';
|
||||||
|
import { formatToFraction } from '@vben/utils';
|
||||||
import type { PropertyAndValues, RuleConfig } from './model';
|
import type { PropertyAndValues, RuleConfig } from './model';
|
||||||
import UploadImg from '#/components/upload/image-upload.vue';
|
import UploadImg from '#/components/upload/image-upload.vue';
|
||||||
import { ElTable, ElInput, ElMessage } from 'element-plus';
|
import { ElTable, ElInput, ElMessage } from 'element-plus';
|
||||||
|
@ -335,10 +254,6 @@ const props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
}, // 是否作为批量操作组件
|
}, // 是否作为批量操作组件
|
||||||
isDetail: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
}, // 是否作为 sku 详情组件
|
|
||||||
isComponent: {
|
isComponent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref, unref } from 'vue';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import { floatToFixed2, formatToFraction } from '#/utils';
|
import { floatToFixed2, formatToFraction, convertToInteger } from '@vben/utils';
|
||||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import InfoForm from '../components/info-form.vue';
|
import InfoForm from '../components/info-form.vue';
|
||||||
import DeliveryForm from '../components/delivery-form.vue';
|
import DeliveryForm from '../components/delivery-form.vue';
|
||||||
|
@ -50,7 +52,7 @@ const formData = ref<MallSpuApi.Spu>({
|
||||||
|
|
||||||
const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
const isDetail = ref(false); // 是否查看详情
|
const isDetail = ref(false); // 是否查看详情
|
||||||
const { push, currentRoute } = useRouter(); // 路由
|
const { push } = useRouter(); // 路由
|
||||||
const { params, name } = useRoute(); // 查询参数
|
const { params, name } = useRoute(); // 查询参数
|
||||||
/** 获得详情 */
|
/** 获得详情 */
|
||||||
const getDetail = async () => {
|
const getDetail = async () => {
|
||||||
|
@ -87,6 +89,59 @@ const getDetail = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const infoRef = ref<InstanceType<typeof InfoForm>>();
|
||||||
|
const skuRef = ref<InstanceType<typeof SkuForm>>();
|
||||||
|
const deliveryRef = ref<InstanceType<typeof DeliveryForm>>();
|
||||||
|
const descriptionRef = ref<InstanceType<typeof DescriptionForm>>();
|
||||||
|
const otherRef = ref<InstanceType<typeof OtherForm>>();
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true;
|
||||||
|
try {
|
||||||
|
// 校验各表单
|
||||||
|
await unref(infoRef)?.validate();
|
||||||
|
await unref(skuRef)?.validate();
|
||||||
|
await unref(deliveryRef)?.validate();
|
||||||
|
await unref(descriptionRef)?.validate();
|
||||||
|
await unref(otherRef)?.validate();
|
||||||
|
// 深拷贝一份, 这样最终 server 端不满足,不需要影响原始数据
|
||||||
|
const deepCopyFormData = cloneDeep(unref(formData.value)) as MallSpuApi.Spu;
|
||||||
|
deepCopyFormData.skus!.forEach((item) => {
|
||||||
|
// 给sku name赋值
|
||||||
|
item.name = deepCopyFormData.name;
|
||||||
|
// sku相关价格元转分
|
||||||
|
item.price = convertToInteger(item.price);
|
||||||
|
item.marketPrice = convertToInteger(item.marketPrice);
|
||||||
|
item.costPrice = convertToInteger(item.costPrice);
|
||||||
|
item.firstBrokeragePrice = convertToInteger(item.firstBrokeragePrice);
|
||||||
|
item.secondBrokeragePrice = convertToInteger(item.secondBrokeragePrice);
|
||||||
|
});
|
||||||
|
// 处理轮播图列表
|
||||||
|
const newSliderPicUrls: any[] = [];
|
||||||
|
deepCopyFormData.sliderPicUrls!.forEach((item: any) => {
|
||||||
|
// 如果是前端选的图
|
||||||
|
typeof item === 'object'
|
||||||
|
? newSliderPicUrls.push(item.url)
|
||||||
|
: newSliderPicUrls.push(item);
|
||||||
|
});
|
||||||
|
deepCopyFormData.sliderPicUrls = newSliderPicUrls;
|
||||||
|
// 校验都通过后提交表单
|
||||||
|
const data = deepCopyFormData as MallSpuApi.Spu;
|
||||||
|
const id = params.id as unknown as number;
|
||||||
|
if (!id) {
|
||||||
|
await ProductSpuApi.createSpu(data);
|
||||||
|
ElMessage.success('创建成功');
|
||||||
|
} else {
|
||||||
|
await ProductSpuApi.updateSpu(data);
|
||||||
|
ElMessage.success('更新成功');
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** 关闭按钮 */
|
/** 关闭按钮 */
|
||||||
const close = () => {
|
const close = () => {
|
||||||
push({ name: 'ProductSpu' });
|
push({ name: 'ProductSpu' });
|
||||||
|
@ -102,26 +157,44 @@ onMounted(async () => {
|
||||||
<Page :auto-content-height="true">
|
<Page :auto-content-height="true">
|
||||||
<ElTabs v-model="activeTab">
|
<ElTabs v-model="activeTab">
|
||||||
<ElTabPane label="基础设置" name="info">
|
<ElTabPane label="基础设置" name="info">
|
||||||
<InfoForm :propFormData="formData" v-model:activeName="activeName" />
|
<InfoForm
|
||||||
|
:propFormData="formData"
|
||||||
|
v-model:activeName="activeName"
|
||||||
|
ref="infoRef"
|
||||||
|
/>
|
||||||
</ElTabPane>
|
</ElTabPane>
|
||||||
<ElTabPane label="价格库存" name="sku">
|
<ElTabPane label="价格库存" name="sku">
|
||||||
<SkuForm :propFormData="formData" v-model:activeName="activeName" />
|
<SkuForm
|
||||||
|
:propFormData="formData"
|
||||||
|
v-model:activeName="activeName"
|
||||||
|
ref="skuRef"
|
||||||
|
/>
|
||||||
</ElTabPane>
|
</ElTabPane>
|
||||||
<ElTabPane label="物流设置" name="delivery">
|
<ElTabPane label="物流设置" name="delivery">
|
||||||
<DeliveryForm
|
<DeliveryForm
|
||||||
:propFormData="formData"
|
:propFormData="formData"
|
||||||
v-model:activeName="activeName"
|
v-model:activeName="activeName"
|
||||||
|
ref="deliveryRef"
|
||||||
/>
|
/>
|
||||||
</ElTabPane>
|
</ElTabPane>
|
||||||
<ElTabPane label="商品详情" name="description">
|
<ElTabPane label="商品详情" name="description">
|
||||||
<DescriptionForm
|
<DescriptionForm
|
||||||
:propFormData="formData"
|
:propFormData="formData"
|
||||||
v-model:activeName="activeName"
|
v-model:activeName="activeName"
|
||||||
|
ref="descriptionRef"
|
||||||
/>
|
/>
|
||||||
</ElTabPane>
|
</ElTabPane>
|
||||||
<ElTabPane label="其它设置" name="other">
|
<ElTabPane label="其它设置" name="other">
|
||||||
<OtherForm :propFormData="formData" v-model:activeName="activeName" />
|
<OtherForm
|
||||||
|
:propFormData="formData"
|
||||||
|
v-model:activeName="activeName"
|
||||||
|
ref="otherRef"
|
||||||
|
/>
|
||||||
</ElTabPane>
|
</ElTabPane>
|
||||||
</ElTabs>
|
</ElTabs>
|
||||||
|
<ElButton type="primary" :loading="formLoading" @click="submitForm"
|
||||||
|
>保存</ElButton
|
||||||
|
>
|
||||||
|
<ElButton @click="close">返回</ElButton>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue