21
This commit is contained in:
parent
6d7d4b099c
commit
1bebd937bc
112
TASK6_IMPLEMENTATION_SUMMARY.md
Normal file
112
TASK6_IMPLEMENTATION_SUMMARY.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Task 6: 商城商品详情页Banner图配置 - 实施完成
|
||||
|
||||
## 概述
|
||||
为商城类型盒子添加独立的商品详情页Banner图字段 `imgurl_banner`,解决当前 `imgurl_detail` 同时用于顶部Banner和底部详情图的问题。
|
||||
|
||||
## 字段用途说明
|
||||
- `imgurl` → 列表页封面图(小图)
|
||||
- `imgurl_banner` → 详情页顶部Banner图(新增)
|
||||
- `imgurl_detail` → 详情页底部详情图
|
||||
|
||||
## 已完成的修改
|
||||
|
||||
### 1. 数据库 ✅
|
||||
**文件**: `server/HoneyBox/scripts/add_imgurl_banner.sql`
|
||||
- 添加 `imgurl_banner` 字段(NVARCHAR(500) NULL)
|
||||
- 包含字段存在性检查,避免重复添加
|
||||
|
||||
**执行方式**:
|
||||
```bash
|
||||
# 在 SQL Server Management Studio 或命令行执行
|
||||
sqlcmd -S localhost -d honey_box -i server/HoneyBox/scripts/add_imgurl_banner.sql
|
||||
```
|
||||
|
||||
### 2. 后端实体 ✅
|
||||
**文件**: `server/HoneyBox/src/HoneyBox.Model/Entities/Good.cs`
|
||||
- 添加 `ImgUrlBanner` 属性(string?)
|
||||
|
||||
### 3. 后端 DTO ✅
|
||||
**文件**: `server/HoneyBox/src/HoneyBox.Model/Models/Goods/GoodsModels.cs`
|
||||
- `GoodsInfoDto` 添加 `imgurl_banner` 字段
|
||||
- 使用 `[JsonPropertyName("imgurl_banner")]` 保持 snake_case 格式
|
||||
|
||||
### 4. 后台管理配置 ✅
|
||||
**文件**: `server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/goods/config/typeFieldConfig.ts`
|
||||
- `GoodsTypeFieldConfig` 接口添加 `showBannerImage` 字段
|
||||
- 商城类型(type=10)配置 `showBannerImage: true`
|
||||
- 其他类型保持 `showBannerImage: false`
|
||||
|
||||
### 5. 后台管理 - 新增对话框 ✅
|
||||
**文件**: `server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/goods/components/GoodsAddDialog.vue`
|
||||
- 添加 Banner 图上传组件(仅商城类型显示)
|
||||
- 添加表单验证规则
|
||||
- 添加到提交数据中
|
||||
|
||||
### 6. 后台管理 - 编辑对话框 ✅
|
||||
**文件**: `server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/goods/components/GoodsEditDialog.vue`
|
||||
- 添加 Banner 图上传组件(仅商城类型显示)
|
||||
- 添加表单验证规则
|
||||
- 加载和保存 Banner 图数据
|
||||
|
||||
### 7. 小程序前端 ✅
|
||||
**文件**: `honey_box/pages/mall/detail.vue`
|
||||
- 修改顶部 Banner 图片源:从 `imgurl_detail || imgurl` 改为 `imgurl_banner || imgurl`
|
||||
- 底部详情图继续使用 `imgurl_detail`
|
||||
|
||||
## 数据库迁移 SQL
|
||||
|
||||
```sql
|
||||
-- 为 goods 表添加 imgurl_banner 字段
|
||||
-- 用于商城详情页顶部 banner 图
|
||||
|
||||
USE honey_box;
|
||||
GO
|
||||
|
||||
-- 添加 imgurl_banner 字段
|
||||
IF NOT EXISTS (
|
||||
SELECT * FROM sys.columns
|
||||
WHERE object_id = OBJECT_ID(N'dbo.goods')
|
||||
AND name = 'imgurl_banner'
|
||||
)
|
||||
BEGIN
|
||||
ALTER TABLE dbo.goods
|
||||
ADD imgurl_banner NVARCHAR(500) NULL;
|
||||
|
||||
PRINT 'Column imgurl_banner added successfully.';
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
PRINT 'Column imgurl_banner already exists.';
|
||||
END
|
||||
GO
|
||||
|
||||
PRINT 'Migration completed.';
|
||||
GO
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 后台管理操作
|
||||
1. 进入"商品管理" → "盒子管理"
|
||||
2. 新增或编辑商城类型(type=10)的盒子
|
||||
3. 会看到三个图片上传字段:
|
||||
- **盒子封面图**:列表页显示的小图
|
||||
- **盒子详情图**:详情页底部的详情图
|
||||
- **商品详情页Banner图**:详情页顶部的大图(新增)
|
||||
4. 上传对应图片后保存
|
||||
|
||||
### 前端显示逻辑
|
||||
- 详情页顶部:优先显示 `imgurl_banner`,如果没有则显示 `imgurl`(封面图)
|
||||
- 详情页底部:显示 `imgurl_detail`(详情图)
|
||||
|
||||
## 注意事项
|
||||
1. 只有商城类型(type=10)的盒子会显示 Banner 图上传字段
|
||||
2. Banner 图字段为可选(NULL),不影响现有数据
|
||||
3. 如果不上传 Banner 图,前端会自动使用封面图作为兜底
|
||||
4. Mapster 会自动映射新字段,无需额外配置
|
||||
|
||||
## 测试建议
|
||||
1. 执行 SQL 脚本添加字段
|
||||
2. 重启后端服务(如果需要)
|
||||
3. 在后台管理中编辑一个商城类型盒子,上传 Banner 图
|
||||
4. 在小程序中查看该商品详情页,确认顶部显示 Banner 图,底部显示详情图
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<view class="detail-content-wrap">
|
||||
<!-- 商品主图 -->
|
||||
<view class="goods-banner">
|
||||
<image :src="goodsInfo.imgurl_detail || goodsInfo.imgurl" mode="widthFix" class="banner-img"></image>
|
||||
<image :src="goodsInfo.imgurl_banner || goodsInfo.imgurl" mode="widthFix" class="banner-img"></image>
|
||||
</view>
|
||||
|
||||
<!-- 价格区域 -->
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@
|
|||
// 下拉刷新的配置(可选, 绝大部分情况无需配置)
|
||||
downOption: {
|
||||
auto: false,
|
||||
bgColor: '#ffffff', // 下拉区域背景色
|
||||
textColor: '#666666', // 下拉文字颜色
|
||||
},
|
||||
// 上拉加载的配置(可选, 绝大部分情况无需配置)
|
||||
upOption: {
|
||||
|
|
|
|||
30
server/HoneyBox/scripts/add_imgurl_banner.sql
Normal file
30
server/HoneyBox/scripts/add_imgurl_banner.sql
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
-- 为 goods 表添加 imgurl_banner 字段
|
||||
-- 用于商城详情页顶部 banner 图
|
||||
|
||||
USE honey_box;
|
||||
GO
|
||||
|
||||
-- 添加 imgurl_banner 字段
|
||||
IF NOT EXISTS (
|
||||
SELECT * FROM sys.columns
|
||||
WHERE object_id = OBJECT_ID(N'dbo.goods')
|
||||
AND name = 'imgurl_banner'
|
||||
)
|
||||
BEGIN
|
||||
ALTER TABLE dbo.goods
|
||||
ADD imgurl_banner NVARCHAR(500) NULL;
|
||||
|
||||
PRINT 'Column imgurl_banner added successfully.';
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
PRINT 'Column imgurl_banner already exists.';
|
||||
END
|
||||
GO
|
||||
|
||||
-- 可选:将现有的 imgurl 复制到 imgurl_banner 作为初始值
|
||||
-- UPDATE dbo.goods SET imgurl_banner = imgurl WHERE imgurl_banner IS NULL AND imgurl IS NOT NULL;
|
||||
-- GO
|
||||
|
||||
PRINT 'Migration completed.';
|
||||
GO
|
||||
|
|
@ -327,7 +327,7 @@
|
|||
|
||||
<!-- 图片上传 -->
|
||||
<el-divider v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage" content-position="left">图片上传</el-divider>
|
||||
<el-row :gutter="20" v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage">
|
||||
<el-row :gutter="20" v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage || fieldConfig.showBannerImage">
|
||||
<el-col :span="12" v-if="fieldConfig.showCoverImage">
|
||||
<el-form-item label="盒子封面图" prop="imgUrl">
|
||||
<ImageUpload
|
||||
|
|
@ -347,6 +347,18 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" v-if="fieldConfig.showBannerImage">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品详情页Banner图" prop="imgUrlBanner">
|
||||
<ImageUpload
|
||||
v-model="formData.imgUrlBanner"
|
||||
placeholder="点击上传Banner图"
|
||||
tip="支持 jpg、png、gif、webp 格式,最大 10MB"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
|
|
@ -433,6 +445,7 @@ const formData = reactive({
|
|||
unlockAmount: 0,
|
||||
imgUrl: '',
|
||||
imgUrlDetail: '',
|
||||
imgUrlBanner: '',
|
||||
categoryId: 0,
|
||||
couponPro: 0,
|
||||
})
|
||||
|
|
@ -457,6 +470,9 @@ const formRules = computed<FormRules>(() => {
|
|||
if (fieldConfig.value.showDetailImage) {
|
||||
rules.imgUrlDetail = [{ required: true, message: '请上传盒子详情图', trigger: 'change' }]
|
||||
}
|
||||
if (fieldConfig.value.showBannerImage) {
|
||||
rules.imgUrlBanner = [{ required: true, message: '请上传商品详情页Banner图', trigger: 'change' }]
|
||||
}
|
||||
|
||||
// 福利屋时间验证
|
||||
if (fieldConfig.value.showTimeConfig) {
|
||||
|
|
@ -551,6 +567,7 @@ const resetForm = () => {
|
|||
formData.unlockAmount = 0
|
||||
formData.imgUrl = ''
|
||||
formData.imgUrlDetail = ''
|
||||
formData.imgUrlBanner = ''
|
||||
formData.categoryId = 0
|
||||
formData.couponPro = 0
|
||||
formRef.value?.resetFields()
|
||||
|
|
@ -598,6 +615,7 @@ const handleSubmit = async () => {
|
|||
type: formData.type,
|
||||
imgUrl: formData.imgUrl,
|
||||
imgUrlDetail: formData.imgUrlDetail,
|
||||
imgUrlBanner: formData.imgUrlBanner || undefined,
|
||||
stock: formData.stock,
|
||||
sort: formData.sort,
|
||||
dailyLimit: formData.dailyLimit,
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@
|
|||
|
||||
<!-- 图片上传 -->
|
||||
<el-divider v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage" content-position="left">图片上传</el-divider>
|
||||
<el-row :gutter="20" v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage">
|
||||
<el-row :gutter="20" v-if="fieldConfig.showCoverImage || fieldConfig.showDetailImage || fieldConfig.showBannerImage">
|
||||
<el-col :span="12" v-if="fieldConfig.showCoverImage">
|
||||
<el-form-item label="盒子封面图" prop="imgUrl">
|
||||
<ImageUpload
|
||||
|
|
@ -357,6 +357,18 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" v-if="fieldConfig.showBannerImage">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品详情页Banner图" prop="imgUrlBanner">
|
||||
<ImageUpload
|
||||
v-model="formData.imgUrlBanner"
|
||||
placeholder="点击上传Banner图"
|
||||
tip="支持 jpg、png、gif、webp 格式,最大 10MB"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
|
|
@ -451,6 +463,7 @@ const formData = reactive({
|
|||
unlockAmount: 0,
|
||||
imgUrl: '',
|
||||
imgUrlDetail: '',
|
||||
imgUrlBanner: '',
|
||||
categoryId: 0,
|
||||
couponPro: 0,
|
||||
})
|
||||
|
|
@ -474,6 +487,9 @@ const formRules = computed<FormRules>(() => {
|
|||
if (fieldConfig.value.showDetailImage) {
|
||||
rules.imgUrlDetail = [{ required: true, message: '请上传盒子详情图', trigger: 'change' }]
|
||||
}
|
||||
if (fieldConfig.value.showBannerImage) {
|
||||
rules.imgUrlBanner = [{ required: true, message: '请上传商品详情页Banner图', trigger: 'change' }]
|
||||
}
|
||||
|
||||
// 福利屋时间验证
|
||||
if (fieldConfig.value.showTimeConfig) {
|
||||
|
|
@ -521,6 +537,7 @@ const loadGoodsDetail = async () => {
|
|||
formData.lingzhuFan = detail.lingzhuFan
|
||||
formData.imgUrl = detail.imgUrl
|
||||
formData.imgUrlDetail = detail.imgUrlDetail
|
||||
formData.imgUrlBanner = detail.imgUrlBanner || ''
|
||||
formData.categoryId = detail.categoryId
|
||||
formData.couponPro = detail.couponPro
|
||||
formData.unlockAmount = (detail as any).unlockAmount || 0
|
||||
|
|
@ -600,6 +617,7 @@ const handleSubmit = async () => {
|
|||
type: formData.type,
|
||||
imgUrl: formData.imgUrl,
|
||||
imgUrlDetail: formData.imgUrlDetail,
|
||||
imgUrlBanner: formData.imgUrlBanner || undefined,
|
||||
stock: formData.stock,
|
||||
sort: formData.sort,
|
||||
dailyLimit: formData.dailyLimit,
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ export interface GoodsTypeFieldConfig {
|
|||
showUnlockAmount: boolean // 显示解锁金额
|
||||
showCoverImage: boolean // 显示盒子封面图
|
||||
showDetailImage: boolean // 显示盒子详情图
|
||||
showBannerImage: boolean // 显示商品详情页Banner图
|
||||
showPrice: boolean // 显示盒子价格
|
||||
showShouZhe: boolean // 显示首抽五折
|
||||
}
|
||||
|
|
@ -128,6 +129,7 @@ export const defaultFieldConfig: GoodsTypeFieldConfig = {
|
|||
showUnlockAmount: true,
|
||||
showCoverImage: true,
|
||||
showDetailImage: true,
|
||||
showBannerImage: false,
|
||||
showPrice: true,
|
||||
showShouZhe: true,
|
||||
}
|
||||
|
|
@ -150,7 +152,7 @@ export const GoodsTypeFieldConfigs: Record<number, GoodsTypeFieldConfig> = {
|
|||
showLianji: false, showTimeConfig: false, showAutoXiajia: false,
|
||||
showCoupon: false, showIntegral: false, showDescription: false,
|
||||
showQuanjuXiangou: false, showShowIs: false, showUnlockAmount: true,
|
||||
showCoverImage: true, showDetailImage: true,
|
||||
showCoverImage: true, showDetailImage: true, showBannerImage: false,
|
||||
showPrice: true, showShouZhe: true,
|
||||
},
|
||||
// 无限赏:不需要套数、锁箱,需要首抽五折
|
||||
|
|
@ -160,17 +162,17 @@ export const GoodsTypeFieldConfigs: Record<number, GoodsTypeFieldConfig> = {
|
|||
showLianji: false, showTimeConfig: false, showAutoXiajia: false,
|
||||
showCoupon: false, showIntegral: false, showDescription: false,
|
||||
showQuanjuXiangou: false, showShowIs: false, showUnlockAmount: true,
|
||||
showCoverImage: true, showDetailImage: true,
|
||||
showCoverImage: true, showDetailImage: true, showBannerImage: false,
|
||||
showPrice: true, showShouZhe: true,
|
||||
},
|
||||
// 商城赏:套数、盒子描述、详情图
|
||||
// 商城赏:套数、盒子描述、详情图、Banner图
|
||||
[GoodsType.ShangChengShang]: {
|
||||
showStock: true, showLock: false, showDailyLimit: false,
|
||||
showRage: false, showItemCard: false, showLingzhu: false,
|
||||
showLianji: false, showTimeConfig: false, showAutoXiajia: false,
|
||||
showCoupon: false, showIntegral: false, showDescription: true,
|
||||
showQuanjuXiangou: false, showShowIs: false, showUnlockAmount: true,
|
||||
showCoverImage: true, showDetailImage: true,
|
||||
showCoverImage: true, showDetailImage: true, showBannerImage: true,
|
||||
showPrice: true, showShouZhe: false,
|
||||
},
|
||||
// 福利屋:时间配置、盒子描述,不需要封面图、详情图、价格、首抽五折
|
||||
|
|
@ -180,7 +182,7 @@ export const GoodsTypeFieldConfigs: Record<number, GoodsTypeFieldConfig> = {
|
|||
showLianji: false, showTimeConfig: true, showAutoXiajia: false,
|
||||
showCoupon: false, showIntegral: false, showDescription: true,
|
||||
showQuanjuXiangou: false, showShowIs: false, showUnlockAmount: false,
|
||||
showCoverImage: false, showDetailImage: false,
|
||||
showCoverImage: false, showDetailImage: false, showBannerImage: false,
|
||||
showPrice: false, showShouZhe: false,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ public partial class Good
|
|||
/// </summary>
|
||||
public string ImgUrlDetail { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 商品详情页Banner图片URL(商城类型专用)
|
||||
/// </summary>
|
||||
public string? ImgUrlBanner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品价格
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -299,6 +299,9 @@ public class GoodsInfoDto
|
|||
[JsonPropertyName("imgurl_detail")]
|
||||
public string ImgUrlDetail { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("imgurl_banner")]
|
||||
public string? ImgUrlBanner { get; set; }
|
||||
|
||||
[JsonPropertyName("price")]
|
||||
public string Price { get; set; } = "0";
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user