[fix]促销相关模块修改,规格修改,优化代码

This commit is contained in:
黄少君
2024-02-22 18:41:03 +08:00
parent 64191373f0
commit 099a40740d
16 changed files with 139 additions and 64 deletions

View File

@ -33,6 +33,7 @@
border
style="width: 100%"
row-key="id"
@select="handleSelectionSelect"
@selection-change="handleSelectionChange"
>
<el-table-column
@ -77,7 +78,7 @@
</template>
<script setup lang="ts">
import { uniqBy } from 'lodash-es'
import { uniqBy, findIndex } from 'lodash-es'
import * as CouponApi from '@/api/mall/product/discountCoupon/index'
import { dateFormatter } from '@/utils/formatTime'
const loading = ref(true) // 列表的加载中
@ -101,12 +102,11 @@ const props = defineProps({
});
const { selectedItems } = toRefs(props);
watchEffect(() => {
console.log(dialogVisible.value,'dialogVisible')
if(!dialogVisible.value){
multipleSelection.value = []
}
})
// watchEffect(() => {
// if(!dialogVisible.value){
// multipleSelection.value = []
// }
// })
// 获取优惠券列表
const getList = async () => {
loading.value = true
@ -115,7 +115,7 @@ const getList = async () => {
list.value = data.list
total.value = data.total
for(let i=0;i<data.list.length;i++){
if(selectedItems.value.some(item => item.id === data.list[i].id) && !multipleSelection.value.some(item => item.id === data.list[i].id)){
if(findIndex(multipleSelection.value,['id', data.list[i].id]) >=0){
tableRef.value!.toggleRowSelection(data.list[i],true)
}
}
@ -135,16 +135,26 @@ const resetQuery = () => {
handleQuery()
}
// 多选选择
const handleSelectionSelect = (selection, row)=>{
// 取消选中而且selectedItems包含row
const selectedIndex = findIndex(selectedItems.value, row)
if(findIndex(selection, row) < 0 && selectedIndex >=0){
selectedItems.value = selectedItems.value.splice(selectedIndex,1)
}
}
// 多选改变
const handleSelectionChange = (val) => {
multipleSelection.value = uniqBy(val,'id')
console.log(multipleSelection.value,'multipleSelection.value')
multipleSelection.value = uniqBy(val.concat(selectedItems.value),'id')
}
/** 打开弹窗 */
const open = async () => {
multipleSelection.value = selectedItems.value
getList()
dialogVisible.value = true
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗

View File

@ -17,6 +17,7 @@ export interface SkuResp {
sku?: string
image?: string
price: number
discount: number
stock: number
}
// 新增活动

18
src/types/member.ts Normal file
View File

@ -0,0 +1,18 @@
// 会员积分规则
interface RuleListItem {
attribute1: string,
enable: boolean,
integral: number,
type: string,
typeName: string
}
export interface FormData {
integralName: string,
integralEnable: string,
integralDeductionRule: number,
ruleList: RuleListItem[],
integral: number,
attribute1: string | undefined,
checkInScore: number
}

View File

@ -22,7 +22,7 @@
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMISSION_STATUS)"
:key="dict.value"
:key="String(dict.value)"
:label="dict.label"
:value="dict.value"
/>
@ -97,9 +97,9 @@ import OrderDetail from "./components/OrderDetail.vue";
interface QueryParams {
pageNo: number
pageSize: number
status?: number | null
orderId?: number | null
createTime: Date[]
status?: number
orderId?: number
createTime: any
}
const detailRef = ref()
const loading = ref<boolean>(true);
@ -108,9 +108,9 @@ const list = ref<DistributorList[]>([]);
const queryParams: QueryParams = reactive({
pageNo: 1,
pageSize: 10,
status: null,
status: undefined,
createTime: [],
orderId: null
orderId: undefined
})
const queryFormRef = ref() // 搜索的表单
/** 查询列表 */

View File

@ -215,7 +215,7 @@ const formValidate = ref({
distributionPurchase: 0,
distributionProductSettlement: 1,
distributionWagesSettlement: 0,
distributionLevel: null
distributionLevel: undefined
})
const manyFormValidate = ref([])
@ -351,7 +351,7 @@ const switchingRules = () => {
formValidate.value.distributionProductSettlement = 1
formValidate.value.distributionPurchase = 0
formValidate.value.distributionWagesSettlement = 0
formValidate.value.distributionLevel = null
formValidate.value.distributionLevel = undefined
}
console.log(formValidate.value.distributionRule, 'distributionRule')
}
@ -402,7 +402,7 @@ const resetForm = () => {
distributionPurchase: 0,
distributionProductSettlement: 1,
distributionWagesSettlement: 0,
distributionLevel: null
distributionLevel: undefined
}
attrs.value = []
formRef.value?.resetFields()

View File

@ -105,7 +105,7 @@ const queryParams = reactive({
isShow: 1,
stock: 1,
cateId: 0,
isDistribution: null
isDistribution: undefined
})
const distributionStatus = ref([
{

View File

@ -141,7 +141,6 @@ const submitForm = async () => {
formLoading.value = false
}
}
let arr = []
/** 重置表单 */
@ -152,11 +151,11 @@ const resetForm = () => {
ruleValue: []
}
formRef.value?.resetFields()
arr = []
formData.value.ruleValue = []
}
const handleRemove = (index) => {
formData.value.ruleValue.splice(index, 1);
arr.splice(index, 1);
formData.value.ruleValue.splice(index, 1);
}
const handleRemove2 = (item, index) => {
item.splice(index, 1);
@ -193,8 +192,7 @@ const createAttrName = () => {
value: attrsName.value,
detail: [attrsVal.value]
}
arr.push(data)
formData.value.ruleValue = arr
formData.value.ruleValue.push(data)
var hash = {}
formData.value.ruleValue = formData.value.ruleValue.reduce(function (item, next) {
/* eslint-disable */

View File

@ -11,10 +11,11 @@
:modal="false"
>
<div class="flex batch" v-if="!visitDetail">
<el-button :type="isInventory === 0 ? 'primary' : ''" @click="showPriceSet(0)">批量设置价格</el-button>
<el-button :type="isInventory === 0 ? 'primary' : ''" @click="showPriceSet(0)">批量设置{{marketingType === 3 ? '折扣' : '价格'}}</el-button>
<el-button :type="isInventory === 1 ? 'primary' : ''" @click="showPriceSet(1)">批量设置库存</el-button>
<div class="price-box flex" v-if="bulkSetPrice">
<el-input-number class="value-class" v-model="setPrice" :min="0" controls-position="right" />
<el-input-number class="value-class" v-if="marketingType === 3 && isInventory === 0" v-model="setPrice" :min="0" :max="9.9" :step="1" :precision="1" controls-position="right"/>
<el-input-number v-else class="value-class" v-model="setPrice" :min="0" controls-position="right" />
<el-button
type="primary"
@click="priceSetting"
@ -48,7 +49,7 @@
</el-table-column>
<el-table-column
prop="originalPrice"
label="价格"
:label="marketingType === 3 ? '折扣' : '价格'"
/>
<el-table-column
prop="originalStock"
@ -57,12 +58,24 @@
<el-table-column :label="activityTit" width="200" align="center">
<template #default="scope">
<el-input-number
v-if="marketingType === 3"
:placeholder="`请输入${activityTit}`"
v-model="scope.row.discount"
:min="0"
:max="9.9"
:step="1"
:precision="1"
controls-position="right"
:disabled="visitDetail"
/>
<el-input-number
v-else
:placeholder="`请输入${activityTit}`"
v-model="scope.row.price"
:min="0"
:max="marketingType === 3 ? 9.9 : scope.row.originalPrice"
:max="scope.row.originalPrice"
:step="1"
:precision="marketingType === 3 ? 1 : 2"
:precision="2"
controls-position="right"
:disabled="visitDetail"
/>
@ -130,10 +143,10 @@ const emit = defineEmits(['changeSpecification'])
const saveIdList = () => {
for(let item of multipleSelection.value) {
// 检查 item 中的 price 和 stock 字段
let checkFields = ['price', 'stock'];
let checkFields = marketingType.value === 3 ? ['discount', 'stock'] : ['price', 'stock'];
for (let field of checkFields) {
if (!(field in item) || item[field] <= 0) {
message.error(`所选规格${item.sku}活动价格与库存必须大于0`)
message.error(`所选规格${item.sku}活动${marketingType.value === 3 ? '折扣' : '价格'}与库存必须大于0`)
return false;
}
}
@ -144,6 +157,7 @@ const saveIdList = () => {
let newSku = {...sku}; // 创建一个新的 sku 对象来避免直接修改原始数据
newSku['stock'] = 0
newSku['price'] = 0
newSku['discount'] = 0
return newSku;
} else {
return sku; // 如果 sku 的 id 在 selectionIds 中存在,或者 sku 没有 price 字段,就原样返回 sku
@ -161,8 +175,14 @@ const open = async (item: ActivityProduct, disabled, type) => {
clear()
if (item.skus.length) {
listData.forEach((i) => {
if (i.price !== 0 && i.price !== null) {
idList.value.push(i.skuId)
if (marketingType.value === 3) {
if (i.discount !== 0 && i.discount !== null) {
idList.value.push(i.skuId)
}
} else {
if (i.price !== 0 && i.price !== null) {
idList.value.push(i.skuId)
}
}
})
}
@ -203,7 +223,11 @@ const priceSetting = (): void => {
if (isInventory.value) {
item.stock = setPrice.value;
} else {
item.price = setPrice.value;
if (marketingType.value === 3) {
item.discount = setPrice.value;
} else {
item.price = setPrice.value;
}
}
}
});

View File

@ -94,16 +94,18 @@
prop="originalStock"
label="库存"
/>
<el-table-column label="折扣价" width="180" align="center">
<el-table-column label="折扣价(折)" width="180" align="center">
<template #default="scope">
<div class="set-specification" v-if="scope.row.specType === 1">
<el-button @click="setSpecifications(scope.row)">设置规格信息</el-button>
</div>
<el-input-number
v-else
v-model="scope.row.skus[0].price"
v-model="scope.row.skus[0].discount"
:min="0"
:max="9.9"
:step="1"
:precision="1"
controls-position="right"
/>
</template>
@ -136,9 +138,9 @@
max-height="300"
>
<el-table-column prop="sku" label="规格名" :show-overflow-tooltip="true" />
<el-table-column label="价格" width="68" align="center">
<el-table-column label="折扣" width="68" align="center">
<template #default="skuScope">
<span>{{ skuScope.row.price ? skuScope.row.price : 0 }}</span>
<span>{{ skuScope.row.discount ? skuScope.row.discount : 0 }}</span>
</template>
</el-table-column>
<el-table-column label="库存" width="68" align="center">
@ -150,7 +152,7 @@
</div>
<template #reference>
<el-form label-width="100px" :model="formData">
<el-button class="m-2">查看价格与库存</el-button>
<el-button class="m-2">查看折扣与库存</el-button>
</el-form>
</template>
</el-popover>
@ -193,7 +195,7 @@ const dialogVisible = ref<boolean>(false) // 弹窗的是否展示
const dialogTitle = ref<string>('') // 弹窗的标题
const formLoading = ref<boolean>(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref<string>('') // 表单的类型create - 新增update - 修改
const timeData = ref<string[]>([])
const timeData = ref<any>([])
const multiple = ref()
const selectProductRef = ref()
const setProductRef = ref()
@ -211,9 +213,9 @@ const initForm = (): CreateActivity => {
startTime: null, // 活动开始时间
endTime: null, // 活动结束时间
ifLimit: 1, // 是否限购
limitNumber: null, // 限购几件/人
limitNumber: undefined, // 限购几件/人
ifEnable: 1, // 活动预热 1-停用 2-启用
enableTime: null, // 预热时间 (分钟)
enableTime: undefined, // 预热时间 (分钟)
remark: '', // 备注
id: null,
details: []
@ -283,7 +285,7 @@ const submitForm = async () => {
for (let item of selectProductList.value) {
// 根据商品类型选择对应的规格列表
if (item.skus) {
let validSkus = item.skus.filter(sku => sku.price > 0);
let validSkus = item.skus.filter(sku => sku.discount > 0);
formData.value.details = formData.value.details.concat(validSkus);
}
}
@ -327,13 +329,13 @@ const validateForm = () => {
}
// 判断限购数量
if (ifLimit.value && formData.value.limitNumber !== null && formData.value.limitNumber <= 0) {
if (ifLimit.value && formData.value.limitNumber && formData.value.limitNumber <= 0) {
message.error('限购数量必须大于0件')
return false;
}
// 判断预热时间
if (preheat.value && formData.value.enableTime !== null && formData.value.enableTime <= 0) {
if (preheat.value && formData.value.enableTime && formData.value.enableTime <= 0) {
message.error('预热时间必须大于0分钟')
return false;
}
@ -349,14 +351,14 @@ const validateDetails = () => {
}
for (let product of selectProductList.value) {
if (product.specType === 1) {
let hasValidPrice = product.skus.some(sku => sku.price > 0);
let hasValidPrice = product.skus.some(sku => sku.discount > 0);
if (!hasValidPrice) {
message.error(`所选商品${product.storeName}未选择规格参与活动`)
return false;
}
} else {
if (product.skus[0].price <=0 || product.skus[0].stock <=0) {
message.error(`${product.storeName}该商品折扣或库存必须大于0`)
if (product.skus[0].discount <=0 || product.skus[0].stock <=0) {
message.error(`${product.storeName}该商品折扣或库存必须大于0`)
return false;
}
}

View File

@ -22,7 +22,7 @@
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.GROUP_STATUS)"
:key="dict.value"
:key="String(dict.value)"
:label="dict.label"
:value="dict.value"
/>
@ -149,7 +149,7 @@ interface QueryParams {
pageSize: number
state?: number | null;
campaignName?: string;
createTime: Date[]
createTime: any
status: string
}

View File

@ -22,7 +22,7 @@
<el-select v-model="queryParams.state" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ACTIVITY_STATUS)"
:key="dict.value"
:key="String(dict.value)"
:label="dict.label"
:value="dict.value"
/>
@ -151,7 +151,7 @@ const queryParams: QueryParams = reactive({
name: "",
type: 1,
createTime: [],
state: null
state: undefined
})
/** 查询列表 */

View File

@ -22,7 +22,7 @@
<el-select v-model="queryParams.state" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ACTIVITY_STATUS)"
:key="dict.value"
:key="String(dict.value)"
:label="dict.label"
:value="dict.value"
/>
@ -161,7 +161,7 @@ const queryParams: QueryParams = reactive({
name: "",
type: 2,
createTime: [],
state: null
state: undefined
})
const queryFormRef = ref() // 搜索的表单

View File

@ -193,7 +193,7 @@ const dialogVisible = ref<boolean>(false) // 弹窗的是否展示
const dialogTitle = ref<string>('') // 弹窗的标题
const formLoading = ref<boolean>(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref<string>('') // 表单的类型create - 新增update - 修改
const timeData = ref<string[]>([])
const timeData = ref<any>([])
const multiple = ref()
const selectProductRef = ref()
const setProductRef = ref()
@ -211,9 +211,9 @@ const initForm = (): CreateActivity => {
startTime: null, // 活动开始时间
endTime: null, // 活动结束时间
ifLimit: 1, // 是否限购
limitNumber: null, // 限购几件/人
limitNumber: undefined, // 限购几件/人
ifEnable: 1, // 活动预热 1-停用 2-启用
enableTime: null, // 预热时间 (分钟)
enableTime: undefined, // 预热时间 (分钟)
remark: '', // 备注
id: null,
details: []
@ -327,13 +327,13 @@ const validateForm = () => {
}
// 判断限购数量
if (ifLimit.value && formData.value.limitNumber !== null && formData.value.limitNumber <= 0) {
if (ifLimit.value && formData.value.limitNumber && formData.value.limitNumber <= 0) {
message.error('限购数量必须大于0件')
return false;
}
// 判断预热时间
if (preheat.value && formData.value.enableTime !== null && formData.value.enableTime <= 0) {
if (preheat.value && formData.value.enableTime && formData.value.enableTime <= 0) {
message.error('预热时间必须大于0分钟')
return false;
}

View File

@ -1,6 +1,11 @@
<script setup lang="ts">
import * as IntegralRuleApi from '@/api/member/integralRule'
import * as DictDataApi from '@/api/system/dict/dict.data'
import { FormData } from "@/types/member"
import { useI18n } from 'vue-i18n'
import { onMounted } from 'vue'
import { ref, reactive } from "vue"
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@ -12,7 +17,7 @@ const queryParams = reactive({
dictType: 'integral_config'
})
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formData = ref({
const formData = ref<FormData>({
integralName: '', // 自定义积分名称
integralEnable: '1', // 积分是否开启抵扣
integralDeductionRule: 0, // 积分抵扣规则值
@ -29,7 +34,7 @@ const formRef = ref() // 表单 Ref
/** 提交表单 */
const submitForm = async () => {
// 校验表单
if (!formRef) return
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
// 提交请求

View File

@ -75,6 +75,7 @@
<script setup lang="ts" name="IntegralRule">
import { dateFormatter } from '@/utils/formatTime'
import { ref, reactive } from "vue";
import type { TabsPaneContext } from 'element-plus'
import * as UserBillApi from '@/api/member/userBill'
import IntegralRuleForm from "@/views/member/integralRule/IntegralRuleForm.vue";
@ -82,7 +83,15 @@ import IntegralRuleForm from "@/views/member/integralRule/IntegralRuleForm.vue";
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
interface QueryParams {
pageNo: number
pageSize: number
nickname: string
category: string
createTime: any
}
const queryParams: QueryParams = reactive({
pageNo: 1,
pageSize: 10,
nickname: '',

View File

@ -110,6 +110,7 @@
<script setup lang="ts" name="SignInRecord">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ref, reactive } from "vue"
import * as SignInRecordApi from '@/api/member/signInRecord'
import SignInRecordForm from './SignInRecordForm.vue'
const message = useMessage() // 消息弹窗
@ -118,7 +119,14 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
interface QueryParams {
pageNo: number,
pageSize: number,
userId: string | null,
integral: number | null,
createTime: any
}
const queryParams = reactive<QueryParams>({
pageNo: 1,
pageSize: 10,
userId: null,