|
@@ -2,26 +2,26 @@
|
|
|
<div class="layout_container wxmall-package">
|
|
|
<header class="round-header">
|
|
|
<span>上架时间:</span>
|
|
|
- <CyDateRange />
|
|
|
+ <CyDateRange/>
|
|
|
<span class="ml-12">
|
|
|
套餐状态:
|
|
|
</span>
|
|
|
<el-select v-model="inquiry.state" clearable class="w-80">
|
|
|
- <el-option label="已上架" value="ACTIVATED" />
|
|
|
- <el-option label="已下架" value="DEACTIVATED" />
|
|
|
+ <el-option label="已上架" value="ACTIVATED"/>
|
|
|
+ <el-option label="已下架" value="DEACTIVATED"/>
|
|
|
</el-select>
|
|
|
- <el-divider direction="vertical" />
|
|
|
+ <el-divider direction="vertical"/>
|
|
|
<el-button icon="Search" type="primary" @click="queryPackages">查询</el-button>
|
|
|
<el-button icon="Plus" color="green" @click="beforeAddPackage">上架</el-button>
|
|
|
</header>
|
|
|
<div class="layout_main layout_el-table">
|
|
|
<el-table :data="packageList" stripe>
|
|
|
- <el-table-column prop="name" label="套餐名称" />
|
|
|
- <el-table-column prop="originPrice" label="套餐原价" />
|
|
|
- <el-table-column prop="discountPrice" label="套餐优惠价" />
|
|
|
- <el-table-column prop="description" label="套餐描述" />
|
|
|
- <el-table-column prop="createTime" label="创建时间" />
|
|
|
- <el-table-column prop="createStaffName" label="创建人" />
|
|
|
+ <el-table-column prop="name" label="套餐名称"/>
|
|
|
+ <el-table-column prop="originPrice" label="套餐原价"/>
|
|
|
+ <el-table-column prop="discountPrice" label="套餐优惠价"/>
|
|
|
+ <el-table-column prop="description" label="套餐描述"/>
|
|
|
+ <el-table-column prop="createTime" label="创建时间"/>
|
|
|
+ <el-table-column prop="createStaffName" label="创建人"/>
|
|
|
<el-table-column label="状态">
|
|
|
<template #default="{row}">
|
|
|
<el-switch
|
|
@@ -95,8 +95,10 @@
|
|
|
:auto-upload="false"
|
|
|
:on-success="onSubmitSuccess"
|
|
|
>
|
|
|
- <el-image v-if="imageUrl" fit="cover" :src="imageUrl" class="avatar-image" />
|
|
|
- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
|
|
+ <el-image v-if="imageUrl" fit="cover" :src="imageUrl" class="avatar-image"/>
|
|
|
+ <el-icon v-else class="avatar-uploader-icon">
|
|
|
+ <Plus/>
|
|
|
+ </el-icon>
|
|
|
<template #tip>
|
|
|
<div class="gray-text">
|
|
|
请选择小于 200Kb 的 jpg/png 格式的图片。
|
|
@@ -121,31 +123,49 @@
|
|
|
<el-input v-model="item.hisName" readonly @click="displaySearchPanel(index)"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="原价">
|
|
|
- <el-input disabled v-model="item.originPrice" type="number" class="w-60" />
|
|
|
+ <el-input disabled v-model="item.originPrice" type="number" class="w-60"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="优惠价" required>
|
|
|
- <el-input v-model="item.discountPrice" type="number" class="w-60" />
|
|
|
+ <el-input v-model="item.discountPrice" type="number" class="w-60"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="数量" required>
|
|
|
- <el-input v-model.number="item.quantity" class="w-60" />
|
|
|
+ <el-input v-model.number="item.quantity" class="w-60"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item v-if="!disableEdit">
|
|
|
<el-button
|
|
|
v-if="index === packageItemList.length - 1"
|
|
|
icon="Plus"
|
|
|
type="success"
|
|
|
+ title="添加条目"
|
|
|
@click="addNewItemLine(index)"
|
|
|
>
|
|
|
- 添加
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
+ :disabled="packageItemList.length === 1"
|
|
|
icon="Minus"
|
|
|
type="danger"
|
|
|
+ title="删除本条"
|
|
|
@click="deleteItemLine(index)"
|
|
|
>
|
|
|
- 删除
|
|
|
</el-button>
|
|
|
</el-form-item>
|
|
|
+ <div style="margin: -16px 0 12px 20px;">
|
|
|
+ <el-tag v-if="item.genderRestriction" type="warning" style="margin-right: 8px">
|
|
|
+ 限 {{item.genderRestriction === 1 ? '男' : '女'}}性
|
|
|
+ </el-tag>
|
|
|
+ <el-tag v-if="item.minAgeRestriction" style="margin-right: 8px">
|
|
|
+ 最小 {{item.minAgeRestriction}}岁
|
|
|
+ </el-tag>
|
|
|
+ <el-tag v-if="item.maxAgeRestriction" style="margin-right: 8px">
|
|
|
+ 最大 {{item.maxAgeRestriction}}岁
|
|
|
+ </el-tag>
|
|
|
+ <el-tag v-if="item.genderConflict" type="danger" style="margin-right: 8px">
|
|
|
+ 限定性别与其他项目冲突
|
|
|
+ </el-tag>
|
|
|
+ <el-tag v-if="item.ageConflict" type="danger">
|
|
|
+ 年龄限制与其他项目冲突
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer>
|
|
@@ -174,7 +194,7 @@
|
|
|
<script setup>
|
|
|
import {
|
|
|
getPackagesByCondition,
|
|
|
- getOriginalPrice,
|
|
|
+ getOriginPrice,
|
|
|
getPackageDetail,
|
|
|
createNewPackage2,
|
|
|
updatePackageState
|
|
@@ -199,6 +219,7 @@ const inquiry = reactive({
|
|
|
})
|
|
|
|
|
|
const packageList = ref([])
|
|
|
+
|
|
|
function queryPackages() {
|
|
|
inquiry.start = dateRange.value.start
|
|
|
inquiry.end = dateRange.value.end
|
|
@@ -214,8 +235,8 @@ function changePackageState(row) {
|
|
|
}
|
|
|
|
|
|
const packageMainRules = reactive({
|
|
|
- name: [ { required: true, message: '请输入套餐名称', trigger: 'blur' } ],
|
|
|
- description: [ { required: true, message: '请输入套餐描述', trigger: 'blur' } ],
|
|
|
+ name: [{required: true, message: '请输入套餐名称', trigger: 'blur'}],
|
|
|
+ description: [{required: true, message: '请输入套餐描述', trigger: 'blur'}],
|
|
|
})
|
|
|
|
|
|
const mode = ref('see')
|
|
@@ -236,10 +257,12 @@ const mainPackage = ref({})
|
|
|
const uploadRef = ref()
|
|
|
const fileList = ref([])
|
|
|
const imageUrl = ref('');
|
|
|
+
|
|
|
function beforeAddPackage() {
|
|
|
mode.value = 'add';
|
|
|
showCreation.value = true
|
|
|
}
|
|
|
+
|
|
|
function handleSelectImage({raw}) {
|
|
|
if (raw.type !== "image/jpeg" && raw.type !== "image/png") {
|
|
|
ElMessage.error("请选择 jpg/png 格式的图片!");
|
|
@@ -253,6 +276,7 @@ function handleSelectImage({raw}) {
|
|
|
}
|
|
|
imageUrl.value = URL.createObjectURL(raw);
|
|
|
}
|
|
|
+
|
|
|
function handleExceed(files) {
|
|
|
uploadRef.value.clearFiles();
|
|
|
const file = files[0];
|
|
@@ -263,25 +287,70 @@ function handleExceed(files) {
|
|
|
const packageItemList = ref([{quantity: 1}])
|
|
|
const showSearch = ref(false)
|
|
|
const currentIndex = ref(0)
|
|
|
+
|
|
|
function displaySearchPanel(index) {
|
|
|
currentIndex.value = index
|
|
|
showSearch.value = true
|
|
|
}
|
|
|
+
|
|
|
async function handleClickSearchItem(val) {
|
|
|
- packageItemList.value[currentIndex.value].hisCode = val.code
|
|
|
- packageItemList.value[currentIndex.value].hisName = val.name
|
|
|
- packageItemList.value[currentIndex.value].type = val.type
|
|
|
+ const targetItem = packageItemList.value[currentIndex.value]
|
|
|
+ targetItem.hisCode = val.code
|
|
|
+ targetItem.hisName = val.name
|
|
|
+ targetItem.type = val.type
|
|
|
if (val.type === 'ZL') {
|
|
|
- packageItemList.value[currentIndex.value].originPrice = val.price
|
|
|
- packageItemList.value[currentIndex.value].discountPrice = val.price
|
|
|
+ targetItem.originPrice = val.price
|
|
|
+ targetItem.discountPrice = val.price
|
|
|
} else {
|
|
|
- await getOriginalPrice(val.type, val.code).then(price => {
|
|
|
- packageItemList.value[currentIndex.value].originPrice = price
|
|
|
- packageItemList.value[currentIndex.value].discountPrice = price
|
|
|
+ targetItem.genderRestriction = val.genderRestriction
|
|
|
+ targetItem.minAgeRestriction = val.minAgeRestriction
|
|
|
+ targetItem.maxAgeRestriction = val.maxAgeRestriction
|
|
|
+ await getOriginPrice(val.type, val.code).then(price => {
|
|
|
+ targetItem.originPrice = price
|
|
|
+ targetItem.discountPrice = price
|
|
|
})
|
|
|
}
|
|
|
showSearch.value = false;
|
|
|
+ checkConflict()
|
|
|
}
|
|
|
+
|
|
|
+function checkConflict() {
|
|
|
+ let maleRestriction = false
|
|
|
+ let femaleRestriction = false
|
|
|
+ let minAgeRestriction = -1
|
|
|
+ let maxAgeRestriction = 1000
|
|
|
+ packageItemList.value.forEach(item => {
|
|
|
+ if (item.genderRestriction === 1) {
|
|
|
+ maleRestriction = true
|
|
|
+ } else if (item.genderRestriction === 2) {
|
|
|
+ femaleRestriction = true
|
|
|
+ }
|
|
|
+ if (item.minAgeRestriction && item.minAgeRestriction > minAgeRestriction) {
|
|
|
+ minAgeRestriction = item.minAgeRestriction
|
|
|
+ }
|
|
|
+ if (item.maxAgeRestriction && item.maxAgeRestriction < maxAgeRestriction) {
|
|
|
+ maxAgeRestriction = item.maxAgeRestriction
|
|
|
+ }
|
|
|
+ })
|
|
|
+ packageItemList.value.forEach(item => {
|
|
|
+ if (maleRestriction && femaleRestriction) {
|
|
|
+ if (item.genderRestriction) {
|
|
|
+ item.genderConflict = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ item.genderConflict = false
|
|
|
+ }
|
|
|
+ if (minAgeRestriction > maxAgeRestriction) {
|
|
|
+ if (item.minAgeRestriction || item.maxAgeRestriction) {
|
|
|
+ item.ageConflict = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ item.ageConflict = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
function addNewItemLine(index) {
|
|
|
let item = packageItemList.value[index]
|
|
|
if (!isValidItem(item)) {
|
|
@@ -289,8 +358,10 @@ function addNewItemLine(index) {
|
|
|
}
|
|
|
packageItemList.value.push({quantity: 1});
|
|
|
}
|
|
|
+
|
|
|
function deleteItemLine(index) {
|
|
|
packageItemList.value.splice(index, 1);
|
|
|
+ checkConflict()
|
|
|
}
|
|
|
|
|
|
function isValidItem(item) {
|
|
@@ -298,8 +369,10 @@ function isValidItem(item) {
|
|
|
ElMessage.error('请先填写项目名称')
|
|
|
return false
|
|
|
}
|
|
|
- if (!item.discountPrice || item.discountPrice < 0) {
|
|
|
- ElMessage.error('项目优惠价不能小于 0')
|
|
|
+ if (item.discountPrice === null
|
|
|
+ || item.discountPrice === undefined
|
|
|
+ || item.discountPrice === '') {
|
|
|
+ ElMessage.error('项目优惠价不能为空')
|
|
|
return false
|
|
|
}
|
|
|
if (!item.quantity || item.quantity < 1) {
|
|
@@ -308,6 +381,7 @@ function isValidItem(item) {
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
const addedItemCode = ref([])
|
|
|
|
|
|
const header = {
|
|
@@ -317,6 +391,7 @@ const creation = ref({
|
|
|
mainPackageJson: null,
|
|
|
packageItemListJson: null
|
|
|
})
|
|
|
+
|
|
|
function submitUpload() {
|
|
|
addedItemCode.value = []
|
|
|
if (!mainPackage.value.name) {
|
|
@@ -337,6 +412,10 @@ function submitUpload() {
|
|
|
}
|
|
|
for (let i = 0; i < packageItemList.value.length; i++) {
|
|
|
let item = packageItemList.value[i]
|
|
|
+ if (item.genderConflict || item.ageConflict) {
|
|
|
+ ElMessage.error('请先解决冲突项')
|
|
|
+ return
|
|
|
+ }
|
|
|
if (addedItemCode.value.indexOf(item.hisCode) !== -1) {
|
|
|
ElMessage.error('请勿添加重复项')
|
|
|
return
|
|
@@ -409,12 +488,15 @@ function beforeEditPackage(id) {
|
|
|
.ml-12 {
|
|
|
margin-left: 12px;
|
|
|
}
|
|
|
+
|
|
|
.w-80 {
|
|
|
width: 80px;
|
|
|
}
|
|
|
+
|
|
|
.w-60 {
|
|
|
width: 60px;
|
|
|
}
|
|
|
+
|
|
|
.gray-text {
|
|
|
color: gray;
|
|
|
}
|
|
@@ -428,9 +510,11 @@ function beforeEditPackage(id) {
|
|
|
overflow: hidden;
|
|
|
transition: var(--el-transition-duration-fast);
|
|
|
}
|
|
|
+
|
|
|
.el-upload:hover {
|
|
|
border-color: var(--el-color-primary);
|
|
|
}
|
|
|
+
|
|
|
.avatar-uploader-icon {
|
|
|
font-size: 28px;
|
|
|
color: #8c939d;
|
|
@@ -438,6 +522,7 @@ function beforeEditPackage(id) {
|
|
|
height: 100px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
+
|
|
|
.avatar-image {
|
|
|
width: 100px;
|
|
|
height: 100px;
|