Compare commits
5 Commits
7728cc456a
...
79de0c59ab
Author | SHA1 | Date | |
---|---|---|---|
79de0c59ab | |||
0b8897ecc4 | |||
95ae012aab | |||
88ac93c477 | |||
7a73b09b4c |
@ -242,5 +242,8 @@ export enum DICT_TYPE {
|
||||
AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度
|
||||
AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式
|
||||
AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气
|
||||
AI_WRITE_LANGUAGE = 'ai_write_language' // AI 写作语言
|
||||
AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言
|
||||
|
||||
// ========== 通用模块 ==========
|
||||
ZERO_OR_ONE = 'zero_or_one'
|
||||
}
|
||||
|
@ -0,0 +1,126 @@
|
||||
<!-- 商品发布 - 库存价格 -->
|
||||
<template>
|
||||
<el-form ref="formRef" :disabled="isDetail" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form-item label="付费会员专属" >
|
||||
<el-switch
|
||||
v-model="formData.onlyPaidMemberView"
|
||||
:active-value="1"
|
||||
:inactive-value="0" />
|
||||
<el-text class="mx-1" size="small">开启后仅付费会员可以看见并购买此商品</el-text>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品推荐">
|
||||
<el-checkbox
|
||||
v-model="formData.recommendHot"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
热卖单品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendBenefit"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
促销单品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendBest"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
精品推荐
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendNew"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
首发新品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendGood"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
优品推荐
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
<!-- 商品属性添加 Form 表单 -->
|
||||
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import {
|
||||
getPropertyList,
|
||||
PropertyAndValues,
|
||||
RuleConfig,
|
||||
SkuList
|
||||
} from '@/views/mall/product/spu/components/index'
|
||||
import ProductAttributes from './ProductAttributes.vue'
|
||||
import ProductPropertyAddForm from './ProductPropertyAddForm.vue'
|
||||
import type { Spu } from '@/api/mall/product/spu'
|
||||
|
||||
defineOptions({ name: 'ProductSpuSkuForm' })
|
||||
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
propFormData: {
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||
})
|
||||
const attributesAddFormRef = ref() // 添加商品属性表单
|
||||
const formRef = ref() // 表单 Ref
|
||||
const propertyList = ref<PropertyAndValues[]>([]) // 商品属性列表
|
||||
const skuListRef = ref() // 商品属性列表 Ref
|
||||
const formData = reactive<Spu>({
|
||||
recommendHot: 0, // 热卖推荐
|
||||
recommendBenefit: 0, // 优惠推荐
|
||||
recommendBest: 0, // 精品推荐
|
||||
recommendNew: 0, // 新品推荐
|
||||
recommendGood: 0, // 优品推荐
|
||||
onlyPaidMemberView: 0 // 仅限付费会员可见
|
||||
})
|
||||
const rules = reactive({
|
||||
// specType: [required],
|
||||
// subCommissionType: [required]
|
||||
})
|
||||
|
||||
/** 将传进来的值赋值给 formData */
|
||||
watch(
|
||||
() => props.propFormData,
|
||||
(data) => {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
copyValueToTarget(formData, data)
|
||||
// 将 SKU 的属性,整理成 PropertyAndValues 数组
|
||||
propertyList.value = getPropertyList(data)
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
/** 表单校验 */
|
||||
const emit = defineEmits(['update:activeName'])
|
||||
const validate = async () => {
|
||||
if (!formRef) return
|
||||
try {
|
||||
// 校验通过更新数据
|
||||
Object.assign(props.propFormData, formData)
|
||||
} catch (e) {
|
||||
throw e // 目的截断之后的校验
|
||||
}
|
||||
}
|
||||
defineExpose({ validate })
|
||||
|
||||
</script>
|
@ -17,43 +17,6 @@
|
||||
<el-radio :label="true">多规格</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品推荐">
|
||||
<el-checkbox
|
||||
v-model="formData.recommendHot"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
热卖单品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendBenefit"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
促销单品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendBest"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
精品推荐
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendNew"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
新品单品
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="formData.recommendGood"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
name="productRecommend">
|
||||
优品推荐
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<!-- 多规格添加-->
|
||||
<el-form-item v-if="!formData.specType">
|
||||
<SkuList
|
||||
@ -146,11 +109,6 @@ const skuListRef = ref() // 商品属性列表 Ref
|
||||
const formData = reactive<Spu>({
|
||||
specType: false, // 商品规格
|
||||
subCommissionType: false, // 分销类型
|
||||
recommendHot: 0, // 热卖推荐
|
||||
recommendBenefit: 0, // 优惠推荐
|
||||
recommendBest: 0, // 精品推荐
|
||||
recommendNew: 0, // 新品推荐
|
||||
recommendGood: 0, // 优品推荐
|
||||
skus: []
|
||||
})
|
||||
const rules = reactive({
|
||||
|
@ -33,6 +33,14 @@
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="营销设置" name="marketing">
|
||||
<MarketingForm
|
||||
ref="marketingRef"
|
||||
v-model:activeName="activeName"
|
||||
:is-detail="isDetail"
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="其它设置" name="other">
|
||||
<OtherForm
|
||||
ref="otherRef"
|
||||
@ -41,6 +49,7 @@
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
<el-form>
|
||||
<el-form-item style="float: right">
|
||||
@ -61,6 +70,7 @@ import DescriptionForm from './DescriptionForm.vue'
|
||||
import OtherForm from './OtherForm.vue'
|
||||
import SkuForm from './SkuForm.vue'
|
||||
import DeliveryForm from './DeliveryForm.vue'
|
||||
import MarketingForm from './MarketingForm.vue'
|
||||
import { convertToInteger, floatToFixed2, formatToFraction } from '@/utils'
|
||||
|
||||
defineOptions({ name: 'ProductSpuForm' })
|
||||
@ -79,6 +89,7 @@ const skuRef = ref() // 商品规格 Ref
|
||||
const deliveryRef = ref() // 物流设置 Ref
|
||||
const descriptionRef = ref() // 商品详情 Ref
|
||||
const otherRef = ref() // 其他设置 Ref
|
||||
const marketingRef = ref() // 营销设置 Ref
|
||||
// SPU 表单数据
|
||||
const formData = ref<ProductSpuApi.Spu>({
|
||||
name: '', // 商品名称
|
||||
@ -97,6 +108,7 @@ const formData = ref<ProductSpuApi.Spu>({
|
||||
recommendBest: 0, // 精品推荐
|
||||
recommendNew: 0, // 新品推荐
|
||||
recommendGood: 0, // 优品推荐
|
||||
onlyPaidMemberView: 0, // 仅限付费会员可见
|
||||
skus: [
|
||||
{
|
||||
price: 0, // 商品价格
|
||||
@ -164,6 +176,7 @@ const submitForm = async () => {
|
||||
await unref(deliveryRef)?.validate()
|
||||
await unref(descriptionRef)?.validate()
|
||||
await unref(otherRef)?.validate()
|
||||
await unref(marketingRef)?.validate()
|
||||
// 深拷贝一份, 这样最终 server 端不满足,不需要影响原始数据
|
||||
const deepCopyFormData = cloneDeep(unref(formData.value)) as ProductSpuApi.Spu
|
||||
deepCopyFormData.skus!.forEach((item) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!-- 商品中心 - 商品列表 -->
|
||||
<template>
|
||||
<doc-alert title="【商品】商品 SPU 与 SKU" url="https://doc.iocoder.cn/mall/product-spu-sku/" />
|
||||
<!-- <doc-alert title="【商品】商品 SPU 与 SKU" url="https://doc.iocoder.cn/mall/product-spu-sku/" /> -->
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<ContentWrap>
|
||||
@ -9,7 +9,7 @@
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
class="-mb-15px"
|
||||
label-width="68px"
|
||||
label-width="auto"
|
||||
>
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
<el-input
|
||||
@ -31,6 +31,16 @@
|
||||
placeholder="请选择商品分类"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="仅付费会员可见" prop="isPaidMember">
|
||||
<el-select v-model="queryParams.isPaidMember" style="width: 100px" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.ZERO_OR_ONE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
@ -234,6 +244,7 @@
|
||||
import { TabsPaneContext } from 'element-plus'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { defaultProps, handleTree, treeToString } from '@/utils/tree'
|
||||
import { ProductSpuStatusEnum } from '@/utils/constants'
|
||||
import { fenToYuan } from '@/utils'
|
||||
@ -286,7 +297,8 @@ const queryParams = ref({
|
||||
tabType: 0,
|
||||
name: '',
|
||||
categoryId: undefined,
|
||||
createTime: undefined
|
||||
createTime: undefined,
|
||||
isPaidMember: undefined
|
||||
}) // 查询参数
|
||||
const queryFormRef = ref() // 搜索的表单Ref
|
||||
|
||||
|
@ -173,7 +173,7 @@
|
||||
v-if="checkPermi(['member:user:update-balance'])"
|
||||
command="handleUpdateBlance"
|
||||
>
|
||||
修改余额(WIP)
|
||||
修改余额
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
@ -51,8 +51,12 @@ public class ProductSpuPageReqVO extends PageParam {
|
||||
@Schema(description = "商品分类编号", example = "1")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description = "是否是付费会员", example = "1")
|
||||
private Integer isPaidMember;
|
||||
|
||||
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
|
||||
}
|
||||
|
@ -85,6 +85,10 @@ public class ProductSpuRespVO {
|
||||
@Schema(description = "是否优品推荐")
|
||||
@ExcelProperty("是否优品推荐")
|
||||
private Integer recommendGood;
|
||||
|
||||
@Schema(description = "是否仅付费会员可见")
|
||||
@ExcelProperty("是否仅付费会员可见")
|
||||
private Integer onlyPaidMemberView;
|
||||
// ========== SKU 相关字段 =========
|
||||
|
||||
@Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
|
@ -118,4 +118,8 @@ public class ProductSpuSaveReqVO {
|
||||
@Schema(description = "是否优品推荐")
|
||||
@Valid
|
||||
private Integer recommendGood;
|
||||
|
||||
@Schema(description = "是否仅付费会员可见")
|
||||
@Valid
|
||||
private Integer onlyPaidMemberView;
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ public class AppProductSpuPageReqVO extends PageParam {
|
||||
@Schema(description = "排序方式", example = "true")
|
||||
private Boolean sortAsc;
|
||||
|
||||
@Schema(description = "是否是付费会员", example = "1")
|
||||
private Integer isPaidMember;
|
||||
|
||||
@AssertTrue(message = "排序字段不合法")
|
||||
@JsonIgnore
|
||||
public boolean isSortFieldValid() {
|
||||
|
@ -23,4 +23,6 @@ public class AppProductSpuRecommendPageReqVo extends PageParam {
|
||||
private Integer recommendNew;
|
||||
@Schema(description = "优品推荐", example = "1")
|
||||
private Integer recommendGood;
|
||||
@Schema(description = "是否是付费会员", example = "1")
|
||||
private Integer isPaidMember;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -115,6 +116,11 @@ public class ProductSpuDO extends BaseDO {
|
||||
*/
|
||||
private Integer recommendGood;
|
||||
|
||||
/**
|
||||
* 是否仅付费会员可见
|
||||
*/
|
||||
private Integer onlyPaidMemberView;
|
||||
|
||||
// ========== SKU 相关字段 =========
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,7 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
||||
.eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
|
||||
.betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(ProductSpuDO::getSort)
|
||||
.eqIfPresent(ProductSpuDO::getOnlyPaidMemberView, reqVO.getIsPaidMember())
|
||||
.orderByDesc(ProductSpuDO::getId);
|
||||
appendTabQuery(tabType, queryWrapper);
|
||||
return selectPage(reqVO, queryWrapper);
|
||||
@ -61,7 +62,9 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
||||
.inIfPresent(ProductSpuDO::getCategoryId, categoryIds);
|
||||
// 上架状态 且有库存
|
||||
query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
|
||||
|
||||
if (pageReqVO.getIsPaidMember() == null || pageReqVO.getIsPaidMember() == 0) {
|
||||
query.eq(ProductSpuDO::getOnlyPaidMemberView, 0);
|
||||
}
|
||||
// 排序逻辑
|
||||
if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
|
||||
query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC",
|
||||
|
@ -186,6 +186,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||
if (recommendGood != null && recommendGood != 0){
|
||||
wrapperX.eq(ProductSpuDO::getRecommendGood, recommendGood);
|
||||
}
|
||||
if (pageVo.getIsPaidMember() == null || pageVo.getIsPaidMember() == 0){
|
||||
wrapperX.eq(ProductSpuDO::getOnlyPaidMemberView, 0);
|
||||
}
|
||||
wrapperX.eq(ProductSpuDO::getStatus, 1);
|
||||
wrapperX.last(" ORDER BY (sales_count + virtual_sales_count) DESC, sort DESC, id DESC");
|
||||
return productSpuMapper.selectList(wrapperX);
|
||||
|
Loading…
Reference in New Issue
Block a user