diff --git a/src/api/mall/product/spu.ts b/src/api/mall/product/spu.ts
index e0d4ec83..b6bec97e 100644
--- a/src/api/mall/product/spu.ts
+++ b/src/api/mall/product/spu.ts
@@ -88,3 +88,8 @@ export const deleteSpu = (id: number) => {
export const exportSpu = async (params) => {
return await request.download({ url: '/product/spu/export', params })
}
+
+// 获得商品 SPU 精简列表
+export const getSpuSimpleList = async () => {
+ return request.get({ url: '/product/spu/get-simple-list' })
+}
diff --git a/src/api/mall/promotion/coupon.ts b/src/api/mall/promotion/coupon.ts
new file mode 100755
index 00000000..565b86f7
--- /dev/null
+++ b/src/api/mall/promotion/coupon.ts
@@ -0,0 +1,18 @@
+import request from '@/config/axios'
+
+// TODO @dhb52:vo 缺少
+
+// 删除优惠劵
+export const deleteCoupon = async (id: number) => {
+ return request.delete({
+ url: `/promotion/coupon/delete?id=${id}`
+ })
+}
+
+// 获得优惠劵分页
+export const getCouponPage = async (params: PageParam) => {
+ return request.get({
+ url: '/promotion/coupon/page',
+ params: params
+ })
+}
diff --git a/src/api/mall/promotion/couponTemplate.ts b/src/api/mall/promotion/couponTemplate.ts
new file mode 100755
index 00000000..6a58876e
--- /dev/null
+++ b/src/api/mall/promotion/couponTemplate.ts
@@ -0,0 +1,83 @@
+import request from '@/config/axios'
+
+export interface CouponTemplateVO {
+ id: number
+ name: string
+ status: number
+ totalCount: number
+ takeLimitCount: number
+ takeType: number
+ usePrice: number
+ productScope: number
+ productSpuIds: string
+ validityType: number
+ validStartTime: Date
+ validEndTime: Date
+ fixedStartTerm: number
+ fixedEndTerm: number
+ discountType: number
+ discountPercent: number
+ discountPrice: number
+ discountLimitPrice: number
+ takeCount: number
+ useCount: number
+}
+
+// 创建优惠劵模板
+export function createCouponTemplate(data: CouponTemplateVO) {
+ return request.post({
+ url: '/promotion/coupon-template/create',
+ data: data
+ })
+}
+
+// 更新优惠劵模板
+export function updateCouponTemplate(data: CouponTemplateVO) {
+ return request.put({
+ url: '/promotion/coupon-template/update',
+ data: data
+ })
+}
+
+// 更新优惠劵模板的状态
+export function updateCouponTemplateStatus(id: number, status: [0, 1]) {
+ const data = {
+ id,
+ status
+ }
+ return request.put({
+ url: '/promotion/coupon-template/update-status',
+ data: data
+ })
+}
+
+// 删除优惠劵模板
+export function deleteCouponTemplate(id: number) {
+ return request.delete({
+ url: '/promotion/coupon-template/delete?id=' + id
+ })
+}
+
+// 获得优惠劵模板
+export function getCouponTemplate(id: number) {
+ return request.get({
+ url: '/promotion/coupon-template/get?id=' + id
+ })
+}
+
+// 获得优惠劵模板分页
+export function getCouponTemplatePage(params: PageParam) {
+ return request.get({
+ url: '/promotion/coupon-template/page',
+ params: params
+ })
+}
+
+// 导出优惠劵模板 Excel
+export function exportCouponTemplateExcel(params: PageParam) {
+ return request.get({
+ url: '/promotion/coupon-template/export-excel',
+ params: params,
+ responseType: 'blob'
+ })
+}
diff --git a/src/api/mall/trade/delivery/expressTemplate/index.ts b/src/api/mall/trade/delivery/expressTemplate/index.ts
index 53f2cdeb..9ed23bc1 100644
--- a/src/api/mall/trade/delivery/expressTemplate/index.ts
+++ b/src/api/mall/trade/delivery/expressTemplate/index.ts
@@ -52,8 +52,3 @@ export const updateDeliveryExpressTemplate = async (data: DeliveryExpressTemplat
export const deleteDeliveryExpressTemplate = async (id: number) => {
return await request.delete({ url: '/trade/delivery/express-template/delete?id=' + id })
}
-
-// 导出快递运费模板 Excel
-export const exportDeliveryExpressTemplateApi = async (params) => {
- return await request.download({ url: '/trade/delivery/express-template/export-excel', params })
-}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index e37b6abc..b2914f9e 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -222,7 +222,7 @@ export const PayRefundStatusEnum = {
}
/**
- * 商品SPU枚举类
+ * 商品 SPU 状态
*/
export const ProductSpuStatusEnum = {
RECYCLE: {
@@ -238,3 +238,59 @@ export const ProductSpuStatusEnum = {
name: '上架'
}
}
+
+/**
+ * 优惠劵模板的有限期类型的枚举
+ */
+export const CouponTemplateValidityTypeEnum = {
+ DATE: {
+ type: 1,
+ name: '固定日期可用'
+ },
+ TERM: {
+ type: 2,
+ name: '领取之后可用'
+ }
+}
+
+/**
+ * 营销的商品范围枚举
+ */
+export const PromotionProductScopeEnum = {
+ ALL: {
+ scope: 1,
+ name: '全部商品参与'
+ },
+ SPU: {
+ scope: 2,
+ name: '指定商品参与'
+ }
+}
+
+/**
+ * 营销的条件类型枚举
+ */
+export const PromotionConditionTypeEnum = {
+ PRICE: {
+ type: 10,
+ name: '满 N 元'
+ },
+ COUNT: {
+ type: 20,
+ name: '满 N 件'
+ }
+}
+
+/**
+ * 优惠类型枚举
+ */
+export const PromotionDiscountTypeEnum = {
+ PRICE: {
+ type: 1,
+ name: '满减'
+ },
+ PERCENT: {
+ type: 2,
+ name: '折扣'
+ }
+}
diff --git a/src/utils/dict.ts b/src/utils/dict.ts
index c742274f..73913b91 100644
--- a/src/utils/dict.ts
+++ b/src/utils/dict.ts
@@ -146,9 +146,12 @@ export enum DICT_TYPE {
MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型
- // ========== MALL 模块 ==========
- PRODUCT_UNIT = 'product_unit', // 商品单位
- PRODUCT_SPU_STATUS = 'product_spu_status', //商品状态
- // ========== MALL 交易模块 ==========
- EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode' //快递的计费方式
+ // ========== MALL - PROMOTION 模块 ==========
+ PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型
+ PROMOTION_PRODUCT_SCOPE = 'promotion_product_scope', // 营销的商品范围
+ PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE = 'promotion_coupon_template_validity_type', // 优惠劵模板的有限期类型
+ PROMOTION_COUPON_STATUS = 'promotion_coupon_status', // 优惠劵的状态
+ PROMOTION_COUPON_TAKE_TYPE = 'promotion_coupon_take_type', // 优惠劵的领取方式
+ PROMOTION_ACTIVITY_STATUS = 'promotion_activity_status', // 优惠活动的状态
+ PROMOTION_CONDITION_TYPE = 'promotion_condition_type' // 营销的条件类型枚举
}
diff --git a/src/utils/tree.ts b/src/utils/tree.ts
index 65a9345c..c8503f54 100644
--- a/src/utils/tree.ts
+++ b/src/utils/tree.ts
@@ -306,11 +306,14 @@ export const handleTree2 = (data, id, parentId, children, rootId) => {
})
return treeData !== '' ? treeData : data
}
+
/**
+ * 校验选中的节点,是否为指定 level
*
* @param tree 要操作的树结构数据
* @param nodeId 需要判断在什么层级的数据
* @param level 检查的级别, 默认检查到二级
+ * @return true 是;false 否
*/
export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => {
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
diff --git a/src/views/mall/product/spu/components/BasicInfoForm.vue b/src/views/mall/product/spu/components/BasicInfoForm.vue
index 00a82a87..b8ae405c 100644
--- a/src/views/mall/product/spu/components/BasicInfoForm.vue
+++ b/src/views/mall/product/spu/components/BasicInfoForm.vue
@@ -1,4 +1,5 @@
+
@@ -126,8 +127,8 @@
-
-
+
+
{{ categoryString(row.categoryId) }}
@@ -163,6 +164,10 @@
/>
+
+
+
+
diff --git a/src/views/mall/promotion/couponTemplate/index.vue b/src/views/mall/promotion/couponTemplate/index.vue
new file mode 100755
index 00000000..b63e93e1
--- /dev/null
+++ b/src/views/mall/promotion/couponTemplate/index.vue
@@ -0,0 +1,614 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+ 重置
+
+
+
+
+
+
+
+ 新增
+
+
+ 会员优惠劵
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 修改
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dict.label }}
+
+
+
+
+ 元
+
+
+
+ 折
+
+
+
+ 元
+
+
+
+ 元
+
+
+
+ 直接领取
+ 指定发放
+
+
+
+
+ 张
+
+
+
+ 张
+
+
+
+ {{ dict.label }}
+
+
+
+
+
+
+ 第
+
+ 至
+
+ 天有效
+
+
+
+ {{ dict.label }}
+
+
+
+
+
+ {{ item.name }}
+ ¥{{ (item.minPrice / 100.0).toFixed(2) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue b/src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue
index 5b25422d..6c9ff296 100644
--- a/src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue
+++ b/src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue
@@ -89,7 +89,7 @@
-
+
{
dialogVisible.value = true
@@ -204,9 +207,9 @@ const open = async (type: string, id?: number) => {
}
item.freePrice = fenToYuan(item.freePrice)
})
- //已选的区域节点
+ // 已选的区域节点
const areaIds = chargeAreaIds.concat(freeAreaIds)
- //区域节点,懒加载方式。 已选节点需要缓存展示
+ // 区域节点,懒加载方式。已选节点需要缓存展示
areaCache.value = await getAreaListByIds(areaIds.join(','))
}
} finally {
@@ -226,8 +229,9 @@ const submitForm = async () => {
formLoading.value = true
try {
const data = formData.value as DeliveryExpressTemplateApi.DeliveryExpressTemplateVO
+ // 前端价格以元展示,提交到后端。用分计算
+ // TODO @jason:不能直接这样改,要复制出来改。不然后端操作失败,数据已经被改了
data.templateCharge.forEach((item) => {
- //前端价格以元展示,提交到后端。用分计算
item.startPrice = yuanToFen(item.startPrice)
item.extraPrice = yuanToFen(item.extraPrice)
})
@@ -248,6 +252,7 @@ const submitForm = async () => {
formLoading.value = false
}
}
+
/** 重置表单 */
const resetForm = () => {
formData.value = {
@@ -269,6 +274,7 @@ const resetForm = () => {
columnTitle.value = columnTitleMap.get(1)
formRef.value?.resetFields()
}
+
/** 配送计费方法改变 */
const changeChargeMode = (chargeMode: number) => {
columnTitle.value = columnTitleMap.get(chargeMode)
@@ -276,6 +282,24 @@ const changeChargeMode = (chargeMode: number) => {
const defaultArea = [{ id: 1, name: '全国', disabled: false }]
/** 初始化数据 */
+// TODO @jason:是不是不用写这样一个初始化方法,columnTitleMap 直接就可以了呀
+// const columnTitleMap = {
+// '1': {
+// startCountTitle: '首件',
+// extraCountTitle: '续件',
+// freeCountTitle: '包邮件数'
+// },
+// '2': {
+// startCountTitle: '首件重量(kg)',
+// extraCountTitle: '续件重量(kg)',
+// freeCountTitle: '包邮重量(kg)'
+// },
+// '3': {
+// startCountTitle: '首件体积(m³)',
+// extraCountTitle: '续件体积(m³)',
+// freeCountTitle: '包邮体积(m³)'
+// }
+// }
const initData = async () => {
// TODO 从服务端全量加载数据, 后面看懒加载是不是可以从前端获取数据。 目前从后端获取数据
// formLoading.value = true
@@ -286,7 +310,7 @@ const initData = async () => {
// } finally {
// formLoading.value = false
// }
- //表头标题和计费方式的映射
+ // 表头标题和计费方式的映射
columnTitleMap.set(1, {
startCountTitle: '首件',
extraCountTitle: '续件',
@@ -320,6 +344,7 @@ const loadChargeArea = async (node, resolve) => {
const item = data[0]
if (areaIds.includes(item.id)) {
// TODO 禁止选中的区域有些问题, 导致修改时候不能重新选择 不知道如何处理。 暂时注释掉 @芋艿 有空瞅瞅
+ // TODO @jason:先不做这个功能哈。
//item.disabled = true
}
resolve(data)
@@ -357,10 +382,11 @@ const loadFreeArea = async (node, resolve) => {
} else {
const id = node.data.id
const data = await getChildrenArea(id)
- //已选区域需要禁止再次选择
+ // 已选区域需要禁止再次选择
data.forEach((item) => {
if (areaIds.includes(item.id)) {
// TODO 禁止选中的区域有些问题, 导致修改时候不能重新选择 不知道如何处理。 暂时注释掉 @芋艿 有空瞅瞅
+ // TODO @jason:先不做这个功能哈。
//item.disabled = true
}
})
@@ -378,11 +404,13 @@ const addChargeArea = () => {
extraPrice: 1
})
}
+
/** 删除计费区域 */
const deleteChargeArea = (index) => {
const data = formData.value
data.templateCharge.splice(index, 1)
}
+
/** 添加包邮区域 */
const addFreeArea = () => {
const data = formData.value
@@ -392,6 +420,7 @@ const addFreeArea = () => {
freePrice: 1
})
}
+
/** 删除包邮区域 */
const deleteFreeArea = (index) => {
const data = formData.value
diff --git a/src/views/mall/trade/delivery/expressTemplate/index.vue b/src/views/mall/trade/delivery/expressTemplate/index.vue
index e9f670f5..9acb5db9 100644
--- a/src/views/mall/trade/delivery/expressTemplate/index.vue
+++ b/src/views/mall/trade/delivery/expressTemplate/index.vue
@@ -110,6 +110,7 @@ const queryParams = reactive({
chargeMode: undefined
})
const queryFormRef = ref() // 搜索的表单
+
/** 查询列表 */
const getList = async () => {
loading.value = true
diff --git a/src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue b/src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue
index 937c2a48..cb9358ad 100644
--- a/src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue
+++ b/src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue
@@ -51,7 +51,7 @@
-
+
@@ -99,7 +99,7 @@
- 获取
+ 获取
@@ -125,6 +125,7 @@ import { getAreaTree } from '@/api/system/area'
import * as ConfigApi from '@/api/infra/config'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
+
const dialogVisible = ref(false) // 弹窗的是否展示
const mapDialogVisible = ref(false) // 地图弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
@@ -160,14 +161,15 @@ const formRules = reactive({
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
-const cascaderProps = {
+const areaTreeProps = {
children: 'children',
label: 'name',
value: 'id',
emitPath: false
}
const areaList = ref() // 区域树
-const tencentLbsUrl = ref('') //腾讯位置服务 url
+const tencentLbsUrl = ref('') // 腾讯位置服务 url
+
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
@@ -196,7 +198,6 @@ const submitForm = async () => {
// 提交请求
formLoading.value = true
try {
- console.log('formData.value', formData.value)
const data = formData.value as DeliveryPickUpStoreApi.DeliveryPickUpStoreVO
if (formType.value === 'create') {
await DeliveryPickUpStoreApi.createDeliveryPickUpStore(data)
@@ -222,7 +223,7 @@ const resetForm = () => {
logo: '',
detailAddress: '',
introduction: '',
- areaId: 1,
+ areaId: undefined,
openingTime: undefined,
closingTime: undefined,
latitude: undefined,
@@ -232,11 +233,7 @@ const resetForm = () => {
formRef.value?.resetFields()
}
-//查找位置
-const searchLocation = async () => {
- mapDialogVisible.value = true
-}
-// 选择经纬度
+/** 选择经纬度 */
const selectAddress = function (loc: any): void {
if (loc.latlng && loc.latlng.lat) {
formData.value.latitude = loc.latlng.lat
@@ -246,6 +243,7 @@ const selectAddress = function (loc: any): void {
}
mapDialogVisible.value = false
}
+
/** 初始化数据 */
const initData = async () => {
formLoading.value = true
@@ -255,6 +253,7 @@ const initData = async () => {
} finally {
formLoading.value = false
}
+ // TODO @jason:要不创建一个 initTencentLbsMap
window.selectAddress = selectAddress
window.addEventListener(
'message',
@@ -262,7 +261,7 @@ const initData = async () => {
// 接收位置信息,用户选择确认位置点后选点组件会触发该事件,回传用户的位置信息
let loc = event.data
if (loc && loc.module === 'locationPicker') {
- // 防止其他应用也会向该页面post信息,需判断module是否为'locationPicker'
+ // 防止其他应用也会向该页面 post 信息,需判断 module 是否为 'locationPicker'
window.parent.selectAddress(loc)
}
},
diff --git a/src/views/mall/trade/delivery/pickUpStore/index.vue b/src/views/mall/trade/delivery/pickUpStore/index.vue
index d163af10..c8963442 100644
--- a/src/views/mall/trade/delivery/pickUpStore/index.vue
+++ b/src/views/mall/trade/delivery/pickUpStore/index.vue
@@ -121,6 +121,7 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
+
const total = ref(0) // 列表的总页数
const loading = ref(true) // 列表的加载中
const exportLoading = ref(false) // 导出的加载中
@@ -134,6 +135,7 @@ const queryParams = reactive({
createTime: []
})
const queryFormRef = ref() // 搜索的表单
+
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
@@ -153,7 +155,7 @@ const handleDelete = async (id: number) => {
} catch {}
}
-//** 查询列表 */
+/** 查询列表 */
const getList = async () => {
loading.value = true
try {