This commit is contained in:
hw
2025-11-20 16:31:23 +08:00
96 changed files with 969 additions and 1361 deletions

View File

@@ -9,7 +9,7 @@ export function useFormSchema(): VbenFormSchema[] {
{
fieldName: 'file',
label: '文件上传',
component: 'FileUpload',
component: 'Upload',
componentProps: {
placeholder: '请选择要上传的文件',
},

View File

@@ -1,19 +1,19 @@
<script lang="ts" setup>
import type { UploadFile, UploadRawFile } from 'element-plus';
import { useVbenModal } from '@vben/common-ui';
import { isEmpty } from '@vben/utils';
import { ElMessage, ElUpload } from 'element-plus';
import { useVbenForm } from '#/adapter/form';
import { useUpload } from '#/components/upload/use-upload';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
const [Modal, modalApi] = useVbenModal({
showConfirmButton: false,
showCancelButton: false,
});
const [Form] = useVbenForm({
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
@@ -25,20 +25,77 @@ const [Form] = useVbenForm({
layout: 'horizontal',
schema: useFormSchema().map((item) => ({ ...item, label: '' })), // 去除label
showDefaultActions: false,
handleValuesChange: (values) => {
if (isEmpty(values)) {
});
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
const { valid } = await formApi.validate();
if (!valid) {
return;
}
// 上传成功关闭 modal
modalApi.close();
emit('success');
modalApi.lock();
// 提交表单
const data = await formApi.getValues();
try {
await useUpload().httpRequest(data.file);
// 关闭并提示
await modalApi.close();
emit('success');
ElMessage.success($t('ui.actionMessage.operationSuccess'));
} finally {
modalApi.unlock();
}
},
});
/** 文件变化处理 */
function handleChange(uploadFile: UploadFile) {
if (uploadFile.raw) {
formApi.setFieldValue('file', uploadFile.raw);
}
}
/** 文件数量超出限制 */
function handleExceed() {
ElMessage.warning('最多只能上传一个文件!');
}
/** 上传前校验:不自动上传,仅保存文件 */
function beforeUpload(_rawFile: UploadRawFile) {
return false;
}
</script>
<template>
<!-- TODO @puhui999这个看看怎么和 antd file/modules/form.vue UI保持一致一点哈 -->
<Modal title="上传文件">
<Form class="mx-4" />
<Modal title="上传图片">
<Form class="mx-4">
<template #file>
<div class="w-full">
<ElUpload
:auto-upload="false"
:limit="1"
:on-change="handleChange"
:on-exceed="handleExceed"
:before-upload="beforeUpload"
accept=".jpg,.png,.gif,.webp"
drag
>
<div
class="flex min-h-[200px] flex-col items-center justify-center py-8"
>
<span
class="icon-[mdi--cloud-upload-outline] mb-4 text-6xl text-gray-400"
></span>
<div class="text-base text-gray-600">
点击或拖拽文件到此区域上传
</div>
<div class="mt-2 text-sm text-gray-400">
支持 .jpg.png.gif.webp 格式图片文件
</div>
</div>
</ElUpload>
</div>
</template>
</Form>
</Modal>
</template>

View File

@@ -19,7 +19,7 @@ import MemberTerminalCard from './modules/terminal-card.vue';
defineOptions({ name: 'MemberStatistics' });
const loading = ref(true); // 加载中
const summary = ref<MallMemberStatisticsApi.Summary>(); // 会员统计数据
const summary = ref<MallMemberStatisticsApi.SummaryRespVO>(); // 会员统计数据
/** 查询会员统计 */
async function loadMemberSummary() {

View File

@@ -18,9 +18,9 @@ import { getAreaChartOptions, getAreaTableColumns } from './area-chart-options';
defineOptions({ name: 'MemberAreaCard' });
const loading = ref(true);
const areaStatisticsList = shallowRef<MallMemberStatisticsApi.AreaStatistics[]>(
[],
);
const areaStatisticsList = shallowRef<
MallMemberStatisticsApi.AreaStatisticsRespVO[]
>([]);
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
@@ -49,7 +49,7 @@ async function loadMemberAreaStatisticsList() {
try {
const list = await getMemberAreaStatisticsList();
areaStatisticsList.value = list.map(
(item: MallMemberStatisticsApi.AreaStatistics) => ({
(item: MallMemberStatisticsApi.AreaStatisticsRespVO) => ({
...item,
areaName: areaReplace(item.areaName),
}),

View File

@@ -5,7 +5,7 @@ import { fenToYuan } from '@vben/utils';
/** 会员地域分布图表配置 */
export function getAreaChartOptions(
data: MallMemberStatisticsApi.AreaStatistics[],
data: MallMemberStatisticsApi.AreaStatisticsRespVO[],
): any {
if (!data || data.length === 0) {
return {

View File

@@ -31,7 +31,7 @@ async function loadMemberSexStatisticsList() {
dictDataList.push({ label: '未知', value: null } as any);
const chartData = dictDataList.map((dictData: any) => {
const userCount = list.find(
(item: MallMemberStatisticsApi.SexStatistics) =>
(item: MallMemberStatisticsApi.SexStatisticsRespVO) =>
item.sex === dictData.value,
)?.userCount;
return {

View File

@@ -37,7 +37,7 @@ defineOptions({ name: 'ProductSummaryCard' });
const trendLoading = ref(true); // 商品状态加载中
const exportLoading = ref(false); // 导出的加载中
const trendSummary =
ref<DataComparisonRespVO<MallProductStatisticsApi.ProductStatistics>>(); // 商品状况统计数据
ref<DataComparisonRespVO<MallProductStatisticsApi.ProductStatisticsRespVO>>(); // 商品状况统计数据
const searchTimes = ref<string[]>([]);
const chartRef = ref<EchartsUIType>();

View File

@@ -18,7 +18,7 @@ defineOptions({ name: 'TradeStatistics' });
const loading = ref(true); // 加载中
const summary =
ref<DataComparisonRespVO<MallTradeStatisticsApi.TradeSummary>>(); // 交易统计数据
ref<DataComparisonRespVO<MallTradeStatisticsApi.TradeSummaryRespVO>>(); // 交易统计数据
/** 计算环比百分比 */
function calculateRelativeRate(value?: number, reference?: number): string {

View File

@@ -37,7 +37,7 @@ defineOptions({ name: 'TradeTrendCard' });
const trendLoading = ref(true); // 交易状态加载中
const exportLoading = ref(false); // 导出的加载中
const trendSummary =
ref<DataComparisonRespVO<MallTradeStatisticsApi.TradeTrendSummary>>(); // 交易状况统计数据
ref<DataComparisonRespVO<MallTradeStatisticsApi.TradeTrendSummaryRespVO>>(); // 交易状况统计数据
const searchTimes = ref<string[]>([]);
const chartRef = ref<EchartsUIType>();

View File

@@ -4,7 +4,7 @@ import { fenToYuan } from '@vben/utils';
/** 交易趋势折线图配置 */
export function getTradeTrendChartOptions(
data: MallTradeStatisticsApi.TradeTrendSummary[],
data: MallTradeStatisticsApi.TradeTrendSummaryRespVO[],
): any {
// 处理数据:将分转换为元
const processedData = data.map((item) => ({

View File

@@ -39,7 +39,7 @@ const [Modal, modalApi] = useVbenModal({
// 提交表单
try {
const data =
(await formApi.getValues()) as MallAfterSaleApi.DisagreeRequest;
(await formApi.getValues()) as MallAfterSaleApi.AfterSaleDisagreeReqVO;
await disagreeAfterSale(data);
// 关闭并提示
await modalApi.close();

View File

@@ -32,13 +32,15 @@ function handleCreate() {
}
/** 编辑快递模板 */
function handleEdit(row: MallDeliveryExpressTemplateApi.ExpressTemplate) {
function handleEdit(
row: MallDeliveryExpressTemplateApi.DeliveryExpressTemplate,
) {
formModalApi.setData(row).open();
}
/** 删除快递模板 */
async function handleDelete(
row: MallDeliveryExpressTemplateApi.ExpressTemplate,
row: MallDeliveryExpressTemplateApi.DeliveryExpressTemplate,
) {
const loadingInstance = ElLoading.service({
text: $t('ui.actionMessage.deleting', [row.name]),
@@ -79,7 +81,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
refresh: true,
search: true,
},
} as VxeTableGridOptions<MallDeliveryExpressTemplateApi.ExpressTemplate>,
} as VxeTableGridOptions<MallDeliveryExpressTemplateApi.DeliveryExpressTemplate>,
});
</script>

View File

@@ -11,7 +11,7 @@ import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { CHARGE_MODE_TITLE_MAP, useChargesColumns } from '../data';
interface Props {
items?: MallDeliveryExpressTemplateApi.TemplateCharge[];
items?: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateCharge[];
chargeMode?: number;
areaTree?: SystemAreaApi.Area[];
}

View File

@@ -23,7 +23,7 @@ import ChargeItemForm from './charge-item-form.vue';
import FreeItemForm from './free-item-form.vue';
const emit = defineEmits(['success']);
const formData = ref<MallDeliveryExpressTemplateApi.ExpressTemplate>();
const formData = ref<MallDeliveryExpressTemplateApi.DeliveryExpressTemplate>();
const chargeItemFormRef = ref<InstanceType<typeof ChargeItemForm>>();
const freeItemFormRef = ref<InstanceType<typeof FreeItemForm>>();
const areaTree = ref<SystemAreaApi.Area[]>([]);
@@ -55,10 +55,10 @@ const [Form, formApi] = useVbenForm({
/** 更新运费设置 */
const handleUpdateCharges = async (
charges: MallDeliveryExpressTemplateApi.TemplateCharge[],
charges: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateCharge[],
) => {
formData.value =
await formApi.getValues<MallDeliveryExpressTemplateApi.ExpressTemplate>();
await formApi.getValues<MallDeliveryExpressTemplateApi.DeliveryExpressTemplate>();
formData.value.charges = charges;
await formApi.setValues({
charges,
@@ -67,10 +67,10 @@ const handleUpdateCharges = async (
/** 更新包邮设置 */
const handleUpdateFrees = async (
frees: MallDeliveryExpressTemplateApi.TemplateFree[],
frees: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateFree[],
) => {
formData.value =
await formApi.getValues<MallDeliveryExpressTemplateApi.ExpressTemplate>();
await formApi.getValues<MallDeliveryExpressTemplateApi.DeliveryExpressTemplate>();
formData.value.frees = frees;
await formApi.setValues({
frees,
@@ -102,17 +102,19 @@ const [Modal, modalApi] = useVbenModal({
// 提交表单
const data = cloneDeep(
await formApi.getValues(),
) as MallDeliveryExpressTemplateApi.ExpressTemplate;
) as MallDeliveryExpressTemplateApi.DeliveryExpressTemplate;
try {
// 转换金额单位
data.charges?.forEach(
(item: MallDeliveryExpressTemplateApi.TemplateCharge) => {
(
item: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateCharge,
) => {
item.startPrice = yuanToFen(item.startPrice);
item.extraPrice = yuanToFen(item.extraPrice);
},
);
data.frees?.forEach(
(item: MallDeliveryExpressTemplateApi.TemplateFree) => {
(item: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateFree) => {
item.freePrice = yuanToFen(item.freePrice);
},
);
@@ -134,7 +136,7 @@ const [Modal, modalApi] = useVbenModal({
}
// 加载数据
const data =
modalApi.getData<MallDeliveryExpressTemplateApi.ExpressTemplate>();
modalApi.getData<MallDeliveryExpressTemplateApi.DeliveryExpressTemplate>();
if (!data || !data.id) {
return;
}
@@ -143,13 +145,15 @@ const [Modal, modalApi] = useVbenModal({
formData.value = await getDeliveryExpressTemplate(data.id);
// 转换金额单位
formData.value.charges?.forEach(
(item: MallDeliveryExpressTemplateApi.TemplateCharge) => {
(
item: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateCharge,
) => {
item.startPrice = Number.parseFloat(fenToYuan(item.startPrice));
item.extraPrice = Number.parseFloat(fenToYuan(item.extraPrice));
},
);
formData.value.frees?.forEach(
(item: MallDeliveryExpressTemplateApi.TemplateFree) => {
(item: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateFree) => {
item.freePrice = Number.parseFloat(fenToYuan(item.freePrice));
},
);

View File

@@ -11,7 +11,7 @@ import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { FREE_MODE_TITLE_MAP, useFreesColumns } from '../data';
interface Props {
items?: MallDeliveryExpressTemplateApi.TemplateFree[];
items?: MallDeliveryExpressTemplateApi.DeliveryExpressTemplateFree[];
chargeMode?: number;
areaTree?: SystemAreaApi.Area[];
}

View File

@@ -38,17 +38,19 @@ function handleCreate() {
}
/** 编辑门店 */
function handleEdit(row: MallDeliveryPickUpStoreApi.PickUpStore) {
function handleEdit(row: MallDeliveryPickUpStoreApi.DeliveryPickUpStore) {
formModalApi.setData(row).open();
}
/** 绑定店员 */
function handleBind(row: MallDeliveryPickUpStoreApi.PickUpStore) {
function handleBind(row: MallDeliveryPickUpStoreApi.DeliveryPickUpStore) {
bindFormModalApi.setData(row).open();
}
/** 删除门店 */
async function handleDelete(row: MallDeliveryPickUpStoreApi.PickUpStore) {
async function handleDelete(
row: MallDeliveryPickUpStoreApi.DeliveryPickUpStore,
) {
const loadingInstance = ElLoading.service({
text: $t('ui.actionMessage.deleting', [row.name]),
});
@@ -88,7 +90,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
refresh: true,
search: true,
},
} as VxeTableGridOptions<MallDeliveryPickUpStoreApi.PickUpStore>,
} as VxeTableGridOptions<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>,
});
</script>

View File

@@ -17,7 +17,7 @@ import { $t } from '#/locales';
import { useBindFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MallDeliveryPickUpStoreApi.PickUpStore>();
const formData = ref<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>();
const [Form, formApi] = useVbenForm({
commonConfig: {

View File

@@ -6,7 +6,7 @@ import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import dayjs from 'dayjs';
import { ElButton, ElMessage } from 'element-plus';
import { ElButton, ElDialog, ElMessage } from 'element-plus';
import { useVbenForm } from '#/adapter/form';
import { getTradeConfig } from '#/api/mall/trade/config';
@@ -20,7 +20,7 @@ import { $t } from '#/locales';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MallDeliveryPickUpStoreApi.PickUpStore>();
const formData = ref<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>();
const getTitle = computed(() => {
return formData.value?.id
? $t('ui.actionTitle.edit', ['门店'])
@@ -94,7 +94,7 @@ const [Modal, modalApi] = useVbenModal({
modalApi.lock();
// 提交表单
const data =
(await formApi.getValues()) as MallDeliveryPickUpStoreApi.PickUpStore;
(await formApi.getValues()) as MallDeliveryPickUpStoreApi.DeliveryPickUpStore;
try {
await (formData.value?.id
? updateDeliveryPickUpStore(data)
@@ -113,7 +113,8 @@ const [Modal, modalApi] = useVbenModal({
return;
}
// 加载数据
const data = modalApi.getData<MallDeliveryPickUpStoreApi.PickUpStore>();
const data =
modalApi.getData<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>();
if (!data || !data.id) {
// 初始化地图
await initTencentLbsMap();
@@ -146,16 +147,11 @@ const [Modal, modalApi] = useVbenModal({
</Modal>
<!-- 地图弹窗 -->
<el-dialog
v-model="mapVisible"
title="获取经纬度"
:width="800"
:footer="null"
>
<ElDialog v-model="mapVisible" title="获取经纬度" :width="800" :footer="null">
<iframe
v-if="mapVisible && tencentLbsUrl"
:src="tencentLbsUrl"
class="h-[600px] w-full border-0"
></iframe>
</el-dialog>
</ElDialog>
</template>

View File

@@ -12,7 +12,7 @@ import { getAreaTree } from '#/api/system/area';
import { getRangePickerDefaultProps } from '#/utils';
/** 关联数据 */
let pickUpStoreList: MallDeliveryPickUpStoreApi.PickUpStore[] = [];
let pickUpStoreList: MallDeliveryPickUpStoreApi.DeliveryPickUpStore[] = [];
getSimpleDeliveryPickUpStoreList().then((data) => {
pickUpStoreList = data;
});

View File

@@ -51,11 +51,11 @@ const orderId = ref(0);
const order = ref<MallOrderApi.Order>({
logs: [],
});
const deliveryExpressList = ref<MallDeliveryExpressApi.SimpleDeliveryExpress[]>(
[],
);
const deliveryExpressList = ref<MallDeliveryExpressApi.DeliveryExpress[]>([]);
const expressTrackList = ref<any[]>([]);
const pickUpStore = ref<MallDeliveryPickUpStoreApi.PickUpStore | undefined>();
const pickUpStore = ref<
MallDeliveryPickUpStoreApi.DeliveryPickUpStore | undefined
>();
const [OrderInfoDescriptions] = useDescription({
title: '订单信息',

View File

@@ -40,7 +40,7 @@ const [Modal, modalApi] = useVbenModal({
// 提交表单
const data = await formApi.getValues();
try {
await updateOrderAddress(data as MallOrderApi.AddressRequest);
await updateOrderAddress(data as MallOrderApi.OrderUpdateAddressReqVO);
// 关闭并提示
await modalApi.close();
emit('success');

View File

@@ -50,7 +50,7 @@ const [Modal, modalApi] = useVbenModal({
data.logisticsNo = '';
}
try {
await deliveryOrder(data as MallOrderApi.DeliveryRequest);
await deliveryOrder(data as MallOrderApi.OrderUpdateDeliveryReqVO);
// 关闭并提示
await modalApi.close();
emit('success');

View File

@@ -15,7 +15,7 @@ import { useRemarkFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<MallOrderApi.DeliveryRequest>();
const formData = ref<MallOrderApi.OrderUpdateDeliveryReqVO>();
const [Form, formApi] = useVbenForm({
commonConfig: {
@@ -38,7 +38,8 @@ const [Modal, modalApi] = useVbenModal({
}
modalApi.lock();
// 提交表单
const data = (await formApi.getValues()) as MallOrderApi.RemarkRequest;
const data =
(await formApi.getValues()) as MallOrderApi.OrderUpdateRemarkReqVO;
try {
await updateOrderRemark(data);
// 关闭并提示