Files
guilixu-admin/src/views/shop/shopSetting/components/order.vue
T
gxwebsoft a284a83b86 feat(dashboard): 新增后台今日数据概况及仪表盘页面
- 新增 shopOrderTotalAll 和 shopOrderOverview 接口,支持含未支付口径数据统计
- 新增 ShopOrderOverview 类型定义,包含今日销售额、订单数、新增用户数和优惠券使用数
- 新增后台专用仪表盘页面,展示用户数、订单数、总营业额和系统运行天数等核心数据
- 仪表盘页面实现新订单提醒功能,支持声音和语音播报
- 提供待付款、待发货订单数和退款申请动态展示,带点击跳转功能
- 新增今日数据概况区域,显示销售额、订单数、新增用户和优惠券使用情况
- 集成订阅和续费功能,支持支付二维码扫码支付及状态轮询
- 基本信息展示系统版本、授权状态以及订阅到期提醒和续费入口
- 快速入口模块方便访问订单管理、商品管理、优惠券管理等功能页
- 实现数据自动刷新机制,包括统计数据和含未支付订单的特殊统计
- 优化了界面样式和交互体验,提升了后台管理的可用性和操作便捷性
2026-08-01 22:10:28 +08:00

179 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<a-card :bordered="false">
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
>
<a-form-item label="自动确认收货天数" name="orderAutoConfirmDays">
<a-input-number
v-model:value="form.orderAutoConfirmDays"
:min="1"
:max="365"
placeholder="请输入天数"
style="width: 200px"
/>
<span style="margin-left: 8px; color: #888">天</span>
</a-form-item>
<a-form-item label="未付款自动关闭" name="orderAutoCloseMins">
<a-input-number
v-model:value="form.orderAutoCloseMins"
:min="0"
:max="10080"
placeholder="0 表示不自动取消"
style="width: 200px"
/>
<span style="margin-left: 8px; color: #888">分钟(0 表示不自动取消)</span>
</a-form-item>
<a-form-item label="自动好评天数" name="orderAutoCommentDays">
<a-input-number
v-model:value="form.orderAutoCommentDays"
:min="1"
:max="365"
placeholder="请输入天数"
style="width: 200px"
/>
<span style="margin-left: 8px; color: #888">天</span>
</a-form-item>
<a-form-item label="免运费金额" name="orderFreightFreeAmount">
<a-input-number
v-model:value="form.orderFreightFreeAmount"
:min="0"
:precision="2"
placeholder="0 表示不免运费"
style="width: 200px"
/>
<span style="margin-left: 8px; color: #888">元(0 表示不免运费)</span>
</a-form-item>
<a-form-item label="允许退款" name="orderRefundEnabled">
<a-switch
v-model:checked="form.orderRefundEnabled"
checked-children="是"
un-checked-children="否"
/>
</a-form-item>
<a-form-item label="销量累加方式" name="salesAccumulateType">
<a-radio-group v-model:value="form.salesAccumulateType">
<a-radio :value="10">支付成功后累加(默认)</a-radio>
<a-radio :value="20">下单成功后累加</a-radio>
</a-radio-group>
<div style="color: #888; font-size: 12px; margin-top: 4px">
支付累加:用户付款后才计入销量;下单累加:生成订单即计入销量(取消订单会回滚)。
</div>
</a-form-item>
<a-form-item label="保存">
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
</a-form-item>
</a-form>
</a-card>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { FormInstance } from 'ant-design-vue/es/form';
import useFormData from '@/utils/use-form-data';
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
import type { ShopSetting } from '@/api/shop/shopSetting/model';
const category = 'order';
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const loading = ref(false);
const formRef = ref<FormInstance | null>(null);
const { form, assignFields } = useFormData<ShopSetting>({
orderAutoConfirmDays: 7,
orderAutoCloseMins: 30,
orderAutoCommentDays: 15,
orderFreightFreeAmount: 0,
orderRefundEnabled: true,
salesAccumulateType: 10
});
const rules = reactive({
orderAutoConfirmDays: [
{
required: true,
message: '请输入自动确认收货天数',
type: 'number',
trigger: 'blur'
}
],
orderAutoCloseMins: [
{
required: true,
message: '请输入未付款自动关闭分钟数(0 表示不自动取消)',
type: 'number',
trigger: 'blur'
}
],
orderAutoCommentDays: [
{
required: true,
message: '请输入自动好评天数',
type: 'number',
trigger: 'blur'
}
]
});
const load = async () => {
try {
const values = await getShopSettingCategoryValues(category);
if (values && Object.keys(values).length > 0) {
assignFields(values);
// 布尔值转换
const raw = (values as any).orderRefundEnabled;
form.orderRefundEnabled = raw === true || raw === 'true' || raw === '1' || raw === 1;
// 数值字段转换(后端返回字符串时)
if (values.orderAutoConfirmDays !== undefined) {
form.orderAutoConfirmDays = Number(values.orderAutoConfirmDays);
}
if (values.orderAutoCloseMins !== undefined) {
form.orderAutoCloseMins = Number(values.orderAutoCloseMins);
}
if (values.orderAutoCommentDays !== undefined) {
form.orderAutoCommentDays = Number(values.orderAutoCommentDays);
}
if (values.orderFreightFreeAmount !== undefined) {
form.orderFreightFreeAmount = Number(values.orderFreightFreeAmount);
}
if (values.salesAccumulateType !== undefined) {
form.salesAccumulateType = Number(values.salesAccumulateType);
}
}
} catch (e: any) {
// 未配置时忽略
}
};
const save = () => {
if (!formRef.value) return;
formRef.value
.validate()
.then(() => {
loading.value = true;
batchSaveShopSetting(category, form as Record<string, unknown>)
.then(() => {
message.success('保存成功');
})
.catch((e) => {
message.error(e.message);
})
.finally(() => {
loading.value = false;
});
})
.catch(() => {});
};
onMounted(load);
</script>