feat(shop): 实时修复今日数据及优化商城设置与商品列表展示
- 修复 dashboard 今日数据统计,改为实时计算订单、销售额、用户数与优惠券使用量 - 统计数据写入 cmsStatistics 表,新增 couponUsedCount 状态与 getter - dashboard 页面移除原有按日期查询逻辑,优惠券使用数改为响应式读取 - 商城设置 Logo 上传改为直接调用 OSS 接口上传,移除图片库选择组件 - 新增商品列表中市场价和会员价列,数据为空时显示 "-" - 同步更新商品列表导出功能,包含新增的价格列与列宽配置 - 商品列表商品图片添加 OSS 压缩访问支持 - 调整商品分类搜索框与关键词输入框宽度以优化布局
This commit is contained in:
@@ -35,6 +35,29 @@
|
|||||||
- `src/views/shop/shopOrder/useOrderNotify.ts` 增加 `onNewOrder` 回调参数,检测到新订单触发提醒(叮声+语音)时同时调用回调。
|
- `src/views/shop/shopOrder/useOrderNotify.ts` 增加 `onNewOrder` 回调参数,检测到新订单触发提醒(叮声+语音)时同时调用回调。
|
||||||
- `src/views/shop/shopOrder/index.vue` 调用 `useOrderNotify({ onNewOrder: () => reload() })`,使新订单提醒时自动刷新表格数据,保持数据同步。
|
- `src/views/shop/shopOrder/index.vue` 调用 `useOrderNotify({ onNewOrder: () => reload() })`,使新订单提醒时自动刷新表格数据,保持数据同步。
|
||||||
|
|
||||||
|
## 2026-07-14 实时统计 Dashboard 今日数据
|
||||||
|
|
||||||
|
### 问题
|
||||||
|
用户再次反馈 `/shop/dashboard` 的「今日数据概况」与「待处理事项」全部显示为 0,且已确认存在今日订单/用户数据。根本原因是 `cmsStatistics` 统计表未写入今日数据,而前端仍依赖该表读取 todaySales/todayOrders/todayUsers;另外 dashboard 中直接按日期查询时使用了 `YYYY-MM-DD` 格式,缺少时间部分,导致时间范围不匹配。
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- `src/store/modules/statistics.ts`:
|
||||||
|
- 引入 `dayjs` 与 `listShopOrder`。
|
||||||
|
- 在 `fetchStatistics` 中实时调用 `listShopOrder({ createTimeStart, createTimeEnd })` 获取今日订单列表,直接计算 `todayOrders`、`todaySales`(仅已付款订单)、`couponUsedCount`。
|
||||||
|
- 调用 `pageUsers({ createTimeStart, createTimeEnd })` 获取 `todayUsers`。
|
||||||
|
- 将今日数据同步写入 `cmsStatistics` 表(若存在记录),同时新增 `couponUsedCount` store 状态与 getter。
|
||||||
|
- `src/views/shop/dashboard/index.vue`:
|
||||||
|
- 移除原来使用 `createTimeStart/End: today`(仅日期)查询今日订单并作为优惠券使用数的占位逻辑。
|
||||||
|
- `couponUsedCount` 改为从 `statisticsStore.couponUsedCount` 读取。
|
||||||
|
- 今日销售额使用 `formatMoney` 保留两位小数显示。
|
||||||
|
|
||||||
|
### 验证
|
||||||
|
- `pnpm run build` 成功。
|
||||||
|
- `vue-tsc --noEmit` 在改动文件中未引入新错误。
|
||||||
|
|
||||||
|
### 备注
|
||||||
|
- 待发货/退款仍使用 `statusFilter=1` 与 `statusFilter=6`;若后续出现货到付款订单未计入待发货,需再检查订单 `payStatus` 在后端是否被正确标记为已付款。
|
||||||
|
|
||||||
## 2026-07-14 订单列表商品图片接入 OSS 压缩
|
## 2026-07-14 订单列表商品图片接入 OSS 压缩
|
||||||
|
|
||||||
### 改动内容
|
### 改动内容
|
||||||
@@ -47,3 +70,34 @@
|
|||||||
|
|
||||||
### 待办
|
### 待办
|
||||||
- 用户提到后端也需要此方法,但当前工作区只有前端代码,后端实现需在后端项目补充。
|
- 用户提到后端也需要此方法,但当前工作区只有前端代码,后端实现需在后端项目补充。
|
||||||
|
|
||||||
|
## 2026-07-14 商城设置 Logo 改为直传
|
||||||
|
|
||||||
|
### 修改文件
|
||||||
|
- `src/views/shop/shopSetting/components/basic.vue`
|
||||||
|
|
||||||
|
### 修改内容
|
||||||
|
- 将商城 Logo 上传方式从 `SelectFile` 图片库选择改为 `a-upload` + `uploadOss` 直接上传,与商品编辑弹窗的商品图片上传方式保持一致。
|
||||||
|
- 已上传图片使用 `a-image` 预览,下方提供"上传"按钮覆盖替换。
|
||||||
|
- 删除不再使用的 `SelectFile` 导入、`logoList` 变量、`chooseImage`/`onDeleteImage` 回调。
|
||||||
|
- 使用 `ele-admin-pro` 的 `messageLoading` 保持上传加载提示与商品编辑弹窗一致。
|
||||||
|
|
||||||
|
## 2026-07-14 商品列表增加三价格展示
|
||||||
|
|
||||||
|
### 改动文件
|
||||||
|
- `src/views/shop/shopGoods/index.vue`
|
||||||
|
|
||||||
|
### 列表页列配置
|
||||||
|
- 原来只显示一列「价格」(`price`)
|
||||||
|
- 新增「市场价」列 (`salePrice`),数据为空时显示 `-`
|
||||||
|
- 新增「会员价」列 (`dealerPrice`),数据为空时显示 `-`
|
||||||
|
- 三列均设置 `width: 110`、`align: 'center'`、`customRender` 带 `¥` 前缀
|
||||||
|
|
||||||
|
### 导出功能同步更新
|
||||||
|
- 导出表头增加「市场价」「会员价」两列
|
||||||
|
- 数据行对应增加 `goods.salePrice` 和 `goods.dealerPrice` 输出
|
||||||
|
- 列宽配置同步增加两列 `{ wch: 12 }`
|
||||||
|
|
||||||
|
### 备注
|
||||||
|
- 编辑表单 `shopGoodsEdit.vue` 已支持三个价格编辑(价格/市场价/会员价),无需修改
|
||||||
|
- 数据模型字段映射:价格=price, 市场价=salePrice, 会员价=dealerPrice
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
* 统计数据 store
|
* 统计数据 store
|
||||||
*/
|
*/
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { pageUsers } from '@/api/system/user';
|
import { pageUsers } from '@/api/system/user';
|
||||||
import { pageShopOrder, shopOrderTotal } from '@/api/shop/shopOrder';
|
import { pageShopOrder, shopOrderTotal, listShopOrder } from '@/api/shop/shopOrder';
|
||||||
import {
|
import {
|
||||||
addCmsStatistics,
|
addCmsStatistics,
|
||||||
listCmsStatistics,
|
listCmsStatistics,
|
||||||
@@ -23,6 +24,8 @@ export interface StatisticsState {
|
|||||||
cacheExpiry: number;
|
cacheExpiry: number;
|
||||||
// 自动刷新定时器
|
// 自动刷新定时器
|
||||||
refreshTimer: number | null;
|
refreshTimer: number | null;
|
||||||
|
// 今日使用优惠券数量
|
||||||
|
couponUsedCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useStatisticsStore = defineStore('statistics', {
|
export const useStatisticsStore = defineStore('statistics', {
|
||||||
@@ -32,7 +35,8 @@ export const useStatisticsStore = defineStore('statistics', {
|
|||||||
lastUpdateTime: null,
|
lastUpdateTime: null,
|
||||||
// 默认缓存5分钟
|
// 默认缓存5分钟
|
||||||
cacheExpiry: 5 * 60 * 1000,
|
cacheExpiry: 5 * 60 * 1000,
|
||||||
refreshTimer: null
|
refreshTimer: null,
|
||||||
|
couponUsedCount: 0
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
@@ -85,6 +89,13 @@ export const useStatisticsStore = defineStore('statistics', {
|
|||||||
return safeNumber(state.statistics?.todayUsers);
|
return safeNumber(state.statistics?.todayUsers);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取今日使用优惠券数量
|
||||||
|
*/
|
||||||
|
couponUsedCount: (state): number => {
|
||||||
|
return safeNumber(state.couponUsedCount);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查缓存是否有效
|
* 检查缓存是否有效
|
||||||
*/
|
*/
|
||||||
@@ -183,38 +194,49 @@ export const useStatisticsStore = defineStore('statistics', {
|
|||||||
return 0;
|
return 0;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// 安全获取今日销售额
|
// 实时计算今日数据(不依赖可能未更新的统计表)
|
||||||
const todaySales = (() => {
|
const todayStart = dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss');
|
||||||
if (statisticsData && statisticsData.length > 0) {
|
const todayEnd = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
|
||||||
const stats = statisticsData[0];
|
|
||||||
if (stats.todaySales !== undefined && stats.todaySales !== null) {
|
|
||||||
return safeNumber(stats.todaySales);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
})();
|
|
||||||
|
|
||||||
// 安全获取今日订单数
|
// 安全获取今日订单列表、销售额和优惠券使用量
|
||||||
const todayOrders = (() => {
|
let todayOrders = 0;
|
||||||
if (statisticsData && statisticsData.length > 0) {
|
let todaySales = 0;
|
||||||
const stats = statisticsData[0];
|
let couponUsedCount = 0;
|
||||||
if (stats.todayOrders !== undefined && stats.todayOrders !== null) {
|
try {
|
||||||
return safeNumber(stats.todayOrders);
|
const todayOrderList = await listShopOrder({
|
||||||
|
createTimeStart: todayStart,
|
||||||
|
createTimeEnd: todayEnd
|
||||||
|
});
|
||||||
|
if (Array.isArray(todayOrderList)) {
|
||||||
|
todayOrders = todayOrderList.length;
|
||||||
|
todaySales = todayOrderList.reduce((acc, order) => {
|
||||||
|
return acc + (order.payStatus ? safeNumber(order.payPrice) : 0);
|
||||||
|
}, 0);
|
||||||
|
couponUsedCount = todayOrderList.filter((order) => {
|
||||||
|
const couponType = order.couponType;
|
||||||
|
return couponType !== undefined && couponType !== null && couponType !== 0;
|
||||||
|
}).length;
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ 获取今日订单列表失败:', e);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
})();
|
|
||||||
|
|
||||||
// 安全获取今日新增用户
|
// 安全获取今日新增用户
|
||||||
const todayUsers = (() => {
|
let todayUsers = 0;
|
||||||
if (statisticsData && statisticsData.length > 0) {
|
try {
|
||||||
const stats = statisticsData[0];
|
const todayUsersResult = await pageUsers({
|
||||||
if (stats.todayUsers !== undefined && stats.todayUsers !== null) {
|
page: 1,
|
||||||
return safeNumber(stats.todayUsers);
|
limit: 1,
|
||||||
|
createTimeStart: todayStart,
|
||||||
|
createTimeEnd: todayEnd
|
||||||
|
});
|
||||||
|
if (todayUsersResult && typeof todayUsersResult === 'object' && 'count' in todayUsersResult) {
|
||||||
|
todayUsers = safeNumber(todayUsersResult.count);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ 获取今日新增用户失败:', e);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
})();
|
|
||||||
const totalSales = (() => {
|
const totalSales = (() => {
|
||||||
if (!total) {
|
if (!total) {
|
||||||
console.warn('⚠️ 订单总额API返回空数据');
|
console.warn('⚠️ 订单总额API返回空数据');
|
||||||
@@ -244,7 +266,10 @@ export const useStatisticsStore = defineStore('statistics', {
|
|||||||
id: existingStatistics.id,
|
id: existingStatistics.id,
|
||||||
userCount: userCount,
|
userCount: userCount,
|
||||||
orderCount: orderCount,
|
orderCount: orderCount,
|
||||||
totalSales: totalSales
|
totalSales: totalSales,
|
||||||
|
todaySales: todaySales,
|
||||||
|
todayOrders: todayOrders,
|
||||||
|
todayUsers: todayUsers
|
||||||
};
|
};
|
||||||
|
|
||||||
// 异步更新数据库
|
// 异步更新数据库
|
||||||
@@ -293,6 +318,7 @@ export const useStatisticsStore = defineStore('statistics', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.statistics = statistics;
|
this.statistics = statistics;
|
||||||
|
this.couponUsedCount = couponUsedCount;
|
||||||
this.lastUpdateTime = Date.now();
|
this.lastUpdateTime = Date.now();
|
||||||
|
|
||||||
return statistics;
|
return statistics;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
<div class="today-stat">
|
<div class="today-stat">
|
||||||
<div class="today-stat-icon">💰</div>
|
<div class="today-stat-icon">💰</div>
|
||||||
<div class="today-stat-info">
|
<div class="today-stat-info">
|
||||||
<div class="today-stat-value">{{ todayStats.salesAmount || '0.00' }}</div>
|
<div class="today-stat-value">{{ formatMoney(todayStats.salesAmount) }}</div>
|
||||||
<div class="today-stat-label">今日销售额(元)</div>
|
<div class="today-stat-label">今日销售额(元)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -267,7 +267,7 @@ const coreStats = computed(() => [
|
|||||||
// 待处理事项数据
|
// 待处理事项数据
|
||||||
const pendingShipmentCount = ref(0);
|
const pendingShipmentCount = ref(0);
|
||||||
const pendingRefundCount = ref(0);
|
const pendingRefundCount = ref(0);
|
||||||
const couponUsedCount = ref(0);
|
const couponUsedCount = computed(() => statisticsStore.couponUsedCount);
|
||||||
|
|
||||||
// 待处理事项(使用computed确保响应式更新)
|
// 待处理事项(使用computed确保响应式更新)
|
||||||
const todoItems = computed(() => [
|
const todoItems = computed(() => [
|
||||||
@@ -301,6 +301,12 @@ const navigateTo = (path: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 金额格式化(保留两位小数)
|
||||||
|
const formatMoney = (value?: number | string) => {
|
||||||
|
const num = Number(value);
|
||||||
|
return Number.isFinite(num) ? num.toFixed(2) : '0.00';
|
||||||
|
};
|
||||||
|
|
||||||
// 清除缓存
|
// 清除缓存
|
||||||
const handleClearCache = () => {
|
const handleClearCache = () => {
|
||||||
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId')).then(
|
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId')).then(
|
||||||
@@ -358,22 +364,6 @@ const loadData = async () => {
|
|||||||
pendingRefundCount.value = 0;
|
pendingRefundCount.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
// 获取今日订单总数(用于计算优惠券使用率)
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
|
||||||
const todayOrderResult = await pageShopOrder({
|
|
||||||
createTimeStart: today,
|
|
||||||
createTimeEnd: today,
|
|
||||||
page: 1,
|
|
||||||
limit: 1
|
|
||||||
});
|
|
||||||
// 暂时使用今日订单数作为优惠券使用参考
|
|
||||||
couponUsedCount.value = todayOrderResult?.count || 0;
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('获取今日订单数失败:', e);
|
|
||||||
couponUsedCount.value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载数据失败:', error);
|
console.error('加载数据失败:', error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
allow-clear
|
allow-clear
|
||||||
:tree-data="navigationList"
|
:tree-data="navigationList"
|
||||||
tree-default-expand-all
|
tree-default-expand-all
|
||||||
style="width: 240px"
|
style="width: 180px"
|
||||||
:listHeight="700"
|
:listHeight="700"
|
||||||
placeholder="请选择分类"
|
placeholder="请选择分类"
|
||||||
:value="where.categoryId || undefined"
|
:value="where.categoryId || undefined"
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
<a-input-search
|
<a-input-search
|
||||||
allow-clear
|
allow-clear
|
||||||
placeholder="请输入关键词"
|
placeholder="请输入关键词"
|
||||||
style="width: 360px"
|
style="width: 220px"
|
||||||
v-model:value="where.keywords"
|
v-model:value="where.keywords"
|
||||||
@pressEnter="reload"
|
@pressEnter="reload"
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<template v-if="column.key === 'name'">
|
<template v-if="column.key === 'name'">
|
||||||
<a-space class="flex items-center cursor-pointer">
|
<a-space class="flex items-center cursor-pointer">
|
||||||
<a-image
|
<a-image
|
||||||
:src="record.image"
|
:src="getCompressedImageUrl(record.image)"
|
||||||
v-if="record.image"
|
v-if="record.image"
|
||||||
:preview="false"
|
:preview="false"
|
||||||
:width="50"
|
:width="50"
|
||||||
@@ -132,6 +132,7 @@
|
|||||||
} from '@/api/shop/shopGoods';
|
} from '@/api/shop/shopGoods';
|
||||||
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
|
import { getCompressedImageUrl } from '@/utils/image';
|
||||||
import { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model';
|
import { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model';
|
||||||
import { listShopGoodsCategory } from '@/api/shop/shopGoodsCategory';
|
import { listShopGoodsCategory } from '@/api/shop/shopGoodsCategory';
|
||||||
import { utils, writeFile } from 'xlsx';
|
import { utils, writeFile } from 'xlsx';
|
||||||
@@ -199,13 +200,30 @@
|
|||||||
key: 'code',
|
key: 'code',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '市场价',
|
||||||
|
dataIndex: 'salePrice',
|
||||||
|
key: 'salePrice',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }) => (text ? `¥${text}` : '-')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '价格',
|
title: '价格',
|
||||||
dataIndex: 'price',
|
dataIndex: 'price',
|
||||||
key: 'price',
|
key: 'price',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
customRender: ({ text }) => `¥${text}`
|
customRender: ({ text }) => `¥${text}`
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '会员价',
|
||||||
|
dataIndex: 'dealerPrice',
|
||||||
|
key: 'dealerPrice',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }) => (text ? `¥${text}` : '-')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '销量',
|
title: '销量',
|
||||||
dataIndex: 'sales',
|
dataIndex: 'sales',
|
||||||
@@ -347,6 +365,8 @@
|
|||||||
'商品ID',
|
'商品ID',
|
||||||
'商品名称',
|
'商品名称',
|
||||||
'价格',
|
'价格',
|
||||||
|
'市场价',
|
||||||
|
'会员价',
|
||||||
'销量',
|
'销量',
|
||||||
'库存',
|
'库存',
|
||||||
'状态',
|
'状态',
|
||||||
@@ -368,6 +388,8 @@
|
|||||||
`${goods.goodsId || ''}`,
|
`${goods.goodsId || ''}`,
|
||||||
`${goods.name || ''}`,
|
`${goods.name || ''}`,
|
||||||
`¥${goods.price || 0}`,
|
`¥${goods.price || 0}`,
|
||||||
|
`${goods.salePrice ? `¥${goods.salePrice}` : ''}`,
|
||||||
|
`${goods.dealerPrice ? `¥${goods.dealerPrice}` : ''}`,
|
||||||
`${goods.sales || 0}`,
|
`${goods.sales || 0}`,
|
||||||
`${goods.stock || 0}`,
|
`${goods.stock || 0}`,
|
||||||
statusMap[goods.status || 0] || '',
|
statusMap[goods.status || 0] || '',
|
||||||
@@ -388,6 +410,8 @@
|
|||||||
{ wch: 10 },
|
{ wch: 10 },
|
||||||
{ wch: 30 },
|
{ wch: 30 },
|
||||||
{ wch: 12 },
|
{ wch: 12 },
|
||||||
|
{ wch: 12 },
|
||||||
|
{ wch: 12 },
|
||||||
{ wch: 10 },
|
{ wch: 10 },
|
||||||
{ wch: 10 },
|
{ wch: 10 },
|
||||||
{ wch: 12 },
|
{ wch: 12 },
|
||||||
|
|||||||
@@ -16,13 +16,27 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="商城Logo" name="shopLogo">
|
<a-form-item label="商城Logo" name="shopLogo">
|
||||||
<SelectFile
|
<a-image
|
||||||
:placeholder="'请选择商城Logo'"
|
v-if="form.shopLogo"
|
||||||
:limit="1"
|
width="100px"
|
||||||
:data="logoList"
|
height="100px"
|
||||||
@done="chooseImage"
|
:src="form.shopLogo"
|
||||||
@del="onDeleteImage"
|
style="margin-right: 10px; border-radius: 6px;"
|
||||||
/>
|
/>
|
||||||
|
<a-upload
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="onUploadLogo"
|
||||||
|
>
|
||||||
|
<a-button class="ele-btn-icon">
|
||||||
|
<template #icon>
|
||||||
|
<UploadOutlined/>
|
||||||
|
</template>
|
||||||
|
<span>上传</span>
|
||||||
|
</a-button>
|
||||||
|
</a-upload>
|
||||||
|
<div class="ele-text-placeholder" style="margin-top: 6px;">
|
||||||
|
建议上传 400x400 像素的正方形 Logo,图片大小不超过 10MB。
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="商城描述" name="shopDesc">
|
<a-form-item label="商城描述" name="shopDesc">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
@@ -59,7 +73,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, watch, onMounted } from 'vue';
|
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { reactive, ref, onMounted } from 'vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
@@ -67,8 +82,8 @@ import { FormInstance } from 'ant-design-vue/es/form';
|
|||||||
import useFormData from '@/utils/use-form-data';
|
import useFormData from '@/utils/use-form-data';
|
||||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
import { uploadOss } from '@/api/system/file';
|
||||||
import { FileRecord } from '@/api/system/file/model';
|
import { messageLoading } from 'ele-admin-pro';
|
||||||
|
|
||||||
const category = 'basic';
|
const category = 'basic';
|
||||||
|
|
||||||
@@ -77,7 +92,6 @@ const { styleResponsive } = storeToRefs(themeStore);
|
|||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const formRef = ref<FormInstance | null>(null);
|
const formRef = ref<FormInstance | null>(null);
|
||||||
const logoList = ref<ItemType[]>([]);
|
|
||||||
|
|
||||||
const { form, assignFields } = useFormData<ShopSetting>({
|
const { form, assignFields } = useFormData<ShopSetting>({
|
||||||
shopName: '',
|
shopName: '',
|
||||||
@@ -99,16 +113,27 @@ const rules = reactive({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
// 选择图片
|
// 上传 Logo
|
||||||
const chooseImage = (data: FileRecord) => {
|
const onUploadLogo = (item: any) => {
|
||||||
logoList.value.push({ uid: data.id, url: data.path, status: 'done' });
|
const { file } = item;
|
||||||
form.shopLogo = data.path;
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
};
|
message.error('图片大小不能超过 10MB');
|
||||||
|
return;
|
||||||
// 删除图片
|
}
|
||||||
const onDeleteImage = (index: number) => {
|
const hide = messageLoading({
|
||||||
logoList.value.splice(index, 1);
|
content: '上传中..',
|
||||||
form.shopLogo = '';
|
duration: 0,
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
uploadOss(file)
|
||||||
|
.then((res) => {
|
||||||
|
hide();
|
||||||
|
form.shopLogo = res.path;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message || '上传失败');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
@@ -119,11 +144,6 @@ const load = async () => {
|
|||||||
// 布尔值转换(后端可能返回字符串 '1'/'0'/'true'/'false')
|
// 布尔值转换(后端可能返回字符串 '1'/'0'/'true'/'false')
|
||||||
const raw = (values as any).shopEnabled;
|
const raw = (values as any).shopEnabled;
|
||||||
form.shopEnabled = raw === true || raw === 'true' || raw === '1' || raw === 1;
|
form.shopEnabled = raw === true || raw === 'true' || raw === '1' || raw === 1;
|
||||||
// 回显 Logo
|
|
||||||
logoList.value = [];
|
|
||||||
if (form.shopLogo) {
|
|
||||||
logoList.value.push({ uid: 1, url: form.shopLogo as string, status: '' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
// 未配置时忽略
|
// 未配置时忽略
|
||||||
|
|||||||
Reference in New Issue
Block a user