mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-06-24 11:00:22 +08:00
feat: 新增全局布局样式并提升组件响应式表现
- 在 global-layout.scss 中引入全局布局样式,统一页面宽度与对齐方式 - 更新多个组件与页面以优化响应式,包括宽度、间距及 flex 布局等调整 - 在 API 请求中增加 loading 状态管理,改善用户体验 - 优化领券中心与商品详情页,提升功能与 UI 一致性
This commit is contained in:
@@ -232,17 +232,12 @@
|
||||
|
||||
<script>
|
||||
import { saveShopCoupon, getShopCoupon, editShopCoupon } from "@/api/promotion";
|
||||
import {
|
||||
savePlatformCoupon,
|
||||
getPlatformCoupon,
|
||||
editPlatformCoupon,
|
||||
} from "@/api/promotion";
|
||||
import { getGoodsCategoryAll } from "@/api/goods";
|
||||
import { regular } from "@/utils";
|
||||
import skuSelect from "@/views/lili-dialog";
|
||||
|
||||
export default {
|
||||
name: "edit-platform-coupon",
|
||||
name: "add-coupon",
|
||||
components: {
|
||||
skuSelect,
|
||||
},
|
||||
@@ -360,7 +355,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getCoupon() {
|
||||
getPlatformCoupon(this.id).then((res) => {
|
||||
getShopCoupon(this.id).then((res) => {
|
||||
let data = res.result;
|
||||
if (!data.promotionGoodsList) data.promotionGoodsList = [];
|
||||
this.rangeTimeType = data.rangeDayType === "DYNAMICTIME" ? 0 : 1;
|
||||
@@ -453,7 +448,7 @@ export default {
|
||||
if (this.modalType === 0) {
|
||||
delete params.id;
|
||||
|
||||
savePlatformCoupon(params).then((res) => {
|
||||
saveShopCoupon(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("优惠券发送成功");
|
||||
@@ -464,7 +459,7 @@ export default {
|
||||
delete params.consumeLimit;
|
||||
delete params.updateTime;
|
||||
|
||||
editPlatformCoupon(params).then((res) => {
|
||||
editShopCoupon(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("优惠券修改成功");
|
||||
@@ -476,7 +471,7 @@ export default {
|
||||
});
|
||||
},
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "add-platform-coupon");
|
||||
this.$store.commit("removeTag", "add-coupon");
|
||||
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
|
||||
this.$router.go(-1);
|
||||
},
|
||||
@@ -535,7 +530,7 @@ export default {
|
||||
this.form.promotionGoodsList = list;
|
||||
},
|
||||
async getCagetoryList() {
|
||||
let data = await getCategoryTree();
|
||||
let data = await getGoodsCategoryAll();
|
||||
this.goodsCategoryList = data.result;
|
||||
this.goodsCategoryList = this.goodsCategoryList.map((item) => {
|
||||
if (item.children) {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<div class="operation padding-row" v-if="getType !== 'ACTIVITY'">
|
||||
<el-button type="primary" @click="add">添加优惠券</el-button>
|
||||
<el-button @click="delAll">批量关闭</el-button>
|
||||
<el-button type="info" @click="receivePage()">优惠券领取记录</el-button>
|
||||
<el-button type="warning" @click="receivePage()">优惠券领取记录</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
@@ -182,11 +182,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getShopCouponList, updateCouponStatus } from "@/api/promotion";
|
||||
import {
|
||||
getPlatformCouponList,
|
||||
updatePlatformCouponStatus,
|
||||
deletePlatformCoupon,
|
||||
getShopCouponList,
|
||||
updateCouponStatus,
|
||||
deleteShopCoupon,
|
||||
} from "@/api/promotion";
|
||||
import { formatPromotionCouponValidityHtml } from "@/utils/promotions";
|
||||
|
||||
@@ -223,6 +222,7 @@ export default {
|
||||
selectDate: [],
|
||||
showActionColumn: true,
|
||||
showStatusColumn: true,
|
||||
isSyncingSelection: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -233,6 +233,8 @@ export default {
|
||||
},
|
||||
selectedList: {
|
||||
handler(val) {
|
||||
if (this.isSyncingSelection) return;
|
||||
if (this.isSameSelection(val, this.selectList)) return;
|
||||
this.$nextTick(() => {
|
||||
this.syncTableSelection(val);
|
||||
});
|
||||
@@ -312,15 +314,31 @@ export default {
|
||||
};
|
||||
return map[type] || "";
|
||||
},
|
||||
isSameSelection(next, current) {
|
||||
const a = next || [];
|
||||
const b = current || [];
|
||||
if (a.length !== b.length) return false;
|
||||
const nextIds = a.map((item) => item.id).sort().join(",");
|
||||
const currentIds = b.map((item) => item.id).sort().join(",");
|
||||
return nextIds === currentIds;
|
||||
},
|
||||
syncTableSelection(selected) {
|
||||
const table = this.$refs.table;
|
||||
if (!table) return;
|
||||
const nextList = selected ? [...selected] : [];
|
||||
this.isSyncingSelection = true;
|
||||
table.clearSelection();
|
||||
if (!selected || !selected.length) return;
|
||||
this.data.forEach((row) => {
|
||||
if (selected.some((item) => item.id === row.id)) {
|
||||
table.toggleRowSelection(row, true);
|
||||
}
|
||||
if (nextList.length) {
|
||||
this.data.forEach((row) => {
|
||||
if (nextList.some((item) => item.id === row.id)) {
|
||||
table.toggleRowSelection(row, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.selectList = nextList;
|
||||
this.selectCount = nextList.length;
|
||||
this.$nextTick(() => {
|
||||
this.isSyncingSelection = false;
|
||||
});
|
||||
},
|
||||
check() {
|
||||
@@ -337,7 +355,7 @@ export default {
|
||||
this.getDataList();
|
||||
},
|
||||
add() {
|
||||
this.$router.push({ name: "add-platform-coupon" });
|
||||
this.$router.push({ name: "add-coupon" });
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
@@ -357,6 +375,7 @@ export default {
|
||||
this.$refs.table?.clearSelection();
|
||||
},
|
||||
changeSelect(e) {
|
||||
if (this.isSyncingSelection) return;
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
if (this.getType === "ACTIVITY") this.check();
|
||||
@@ -370,7 +389,7 @@ export default {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
getPlatformCouponList(this.searchForm)
|
||||
getShopCouponList(this.searchForm)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
@@ -388,7 +407,7 @@ export default {
|
||||
},
|
||||
see(v, only) {
|
||||
const data = only ? { onlyView: true, id: v.id } : { id: v.id };
|
||||
this.$router.push({ name: "edit-platform-coupon", query: data });
|
||||
this.$router.push({ name: "add-coupon", query: data });
|
||||
},
|
||||
close(v) {
|
||||
this.$Modal.confirm({
|
||||
@@ -396,7 +415,7 @@ export default {
|
||||
content: "确认要关闭此优惠券么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
updatePlatformCouponStatus({
|
||||
updateCouponStatus({
|
||||
couponIds: v.id,
|
||||
effectiveDays: 0,
|
||||
})
|
||||
@@ -419,7 +438,7 @@ export default {
|
||||
content: "确认要删除此优惠券么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
deletePlatformCoupon(v.id)
|
||||
deleteShopCoupon(v.id)
|
||||
.then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
@@ -444,7 +463,7 @@ export default {
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
const ids = this.selectList.map((e) => e.id);
|
||||
updatePlatformCouponStatus({
|
||||
updateCouponStatus({
|
||||
couponIds: ids.toString(),
|
||||
promotionStatus: "CLOSE",
|
||||
}).then((res) => {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card>
|
||||
<el-form ref="form" :model="form" label-width="120px">
|
||||
<el-form ref="form" :model="form" label-width="120px" :rules="formRule">
|
||||
<div class="base-info-item">
|
||||
<h4>基本信息</h4>
|
||||
<div class="form-item-view">
|
||||
<el-form-item label="活动名称" prop="promotionName">
|
||||
<el-input
|
||||
v-model="form.promotionName"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
placeholder="活动名称"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
@@ -18,7 +18,7 @@
|
||||
<el-date-picker
|
||||
type="datetimerange"
|
||||
v-model="form.rangeTime"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
@@ -30,7 +30,7 @@
|
||||
<el-form-item label="活动描述" prop="description">
|
||||
<el-input
|
||||
v-model="form.description"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
clearable
|
||||
@@ -44,17 +44,17 @@
|
||||
<el-form-item label="优惠门槛" prop="fullMoney">
|
||||
<el-input
|
||||
v-model="form.fullMoney"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
placeholder="优惠门槛"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<span class="describe">消费达到当前金额可以参与优惠</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="赠送优惠券">
|
||||
<el-radio-group v-model="form.discountType">
|
||||
<el-radio-button value="fullMinusFlag" disabled>减现金</el-radio-button>
|
||||
<el-radio-button value="fullRateFlag" disabled>打折</el-radio-button>
|
||||
<el-form-item label="优惠方式">
|
||||
<el-radio-group v-model="form.discountType" :disabled="fieldDisabled">
|
||||
<el-radio-button value="fullMinusFlag">减现金</el-radio-button>
|
||||
<el-radio-button value="fullRateFlag">打折</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -63,7 +63,7 @@
|
||||
prop="fullMinus"
|
||||
>
|
||||
<el-input
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
v-model="form.fullMinus"
|
||||
placeholder="优惠金额"
|
||||
clearable
|
||||
@@ -76,26 +76,27 @@
|
||||
prop="fullRate"
|
||||
>
|
||||
<el-input-number
|
||||
:disabled="fieldDisabled"
|
||||
v-model="form.fullRate"
|
||||
placeholder="优惠折扣"
|
||||
:max="9.9"
|
||||
:min="0.1"
|
||||
:max="9.9"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
v-model="form.fullRate"
|
||||
style="width: 260px"
|
||||
/>
|
||||
<span class="describe">优惠折扣为0-10之间数字,可有一位小数</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="额外赠送">
|
||||
<el-checkbox v-model="form.freeFreightFlag" disabled>免邮费</el-checkbox>
|
||||
<el-checkbox v-model="form.couponFlag" disabled>送优惠券</el-checkbox>
|
||||
<el-checkbox v-model="form.giftFlag" disabled>送赠品</el-checkbox>
|
||||
<el-checkbox v-model="form.pointFlag" disabled>送积分</el-checkbox>
|
||||
<el-checkbox v-model="form.freeFreightFlag" :disabled="fieldDisabled">免邮费</el-checkbox>
|
||||
<el-checkbox v-model="form.couponFlag" :disabled="fieldDisabled">送优惠券</el-checkbox>
|
||||
<el-checkbox v-model="form.giftFlag" :disabled="fieldDisabled">送赠品</el-checkbox>
|
||||
<el-checkbox v-model="form.pointFlag" :disabled="fieldDisabled">送积分</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.couponFlag" label="赠送优惠券" prop="couponId">
|
||||
<el-select
|
||||
v-model="form.couponId"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
:disabled="fieldDisabled"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="getCouponList"
|
||||
@@ -118,7 +119,7 @@
|
||||
remote
|
||||
:remote-method="getGiftList"
|
||||
placeholder="输入赠品名称搜索"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
:loading="giftLoading"
|
||||
style="width: 260px"
|
||||
>
|
||||
@@ -134,23 +135,36 @@
|
||||
<el-input
|
||||
v-model="form.point"
|
||||
type="number"
|
||||
disabled
|
||||
:disabled="fieldDisabled"
|
||||
style="width: 260px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用范围" prop="scopeType">
|
||||
<el-radio-group v-model="form.scopeType">
|
||||
<el-radio-button value="ALL" disabled>全品类</el-radio-button>
|
||||
<el-radio-button value="PORTION_GOODS" disabled>指定商品</el-radio-button>
|
||||
<el-radio-group v-model="form.scopeType" :disabled="fieldDisabled">
|
||||
<el-radio-button value="ALL">全品类</el-radio-button>
|
||||
<el-radio-button value="PORTION_GOODS">指定商品</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
style="width: 100%"
|
||||
v-if="form.scopeType == 'PORTION_GOODS'"
|
||||
>
|
||||
<el-table border :data="form.promotionGoodsList" style="width: 100%">
|
||||
<el-table-column type="selection" width="60" align="center" />
|
||||
<el-form-item style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
|
||||
<div v-if="!fieldDisabled" style="display: flex; margin-bottom: 10px">
|
||||
<el-button type="primary" @click="openSkuList">选择商品</el-button>
|
||||
<el-button type="danger" plain style="margin-left: 10px" @click="delSelectGoods">
|
||||
批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
border
|
||||
:data="form.promotionGoodsList"
|
||||
style="width: 100%"
|
||||
@selection-change="changeSelect"
|
||||
>
|
||||
<el-table-column
|
||||
v-if="!fieldDisabled"
|
||||
type="selection"
|
||||
width="60"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column label="商品名称" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
@@ -190,40 +204,95 @@
|
||||
<span v-if="row">{{ row.quantity }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="!fieldDisabled" label="操作" width="100" align="center">
|
||||
<template #default="{ $index }">
|
||||
<a class="link-text" @click="delGoods($index)">删除</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
|
||||
<div>
|
||||
<el-button @click="$router.push({ name: 'promotions/full-discount' })">返回</el-button>
|
||||
<el-button @click="closeCurrentPage">返回</el-button>
|
||||
<el-button
|
||||
v-if="!fieldDisabled"
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<liliDialog ref="liliDialog" @selectedGoodsData="selectedGoodsData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getPlatformCouponList, getFullDiscountById } from "@/api/promotion";
|
||||
import {
|
||||
getShopCouponList,
|
||||
getFullDiscountById,
|
||||
newFullDiscount,
|
||||
editFullDiscount,
|
||||
} from "@/api/promotion";
|
||||
import { getGoodsSkuListDataSeller } from "@/api/goods";
|
||||
import { regular } from "@/utils";
|
||||
import vueQr from "vue-qr";
|
||||
|
||||
export default {
|
||||
name: "add-full-discount",
|
||||
components: {
|
||||
"vue-qr": vueQr,
|
||||
},
|
||||
data() {
|
||||
const checkWeight = (rule, value, callback) => {
|
||||
if (!value && typeof value !== "number") {
|
||||
callback(new Error("优惠门槛不能为空"));
|
||||
} else if (!regular.money.test(value)) {
|
||||
callback(new Error("请输入正整数或者两位小数"));
|
||||
} else if (parseFloat(value) > 99999999) {
|
||||
callback(new Error("优惠门槛设置超过上限值"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const checkDiscount = (rule, value, callback) => {
|
||||
if (value === null || value === undefined || value === "") {
|
||||
callback(new Error("请填写优惠折扣"));
|
||||
} else if (value < 0.1 || value > 9.9) {
|
||||
callback(new Error("请输入0-10的数字,可有一位小数"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
form: {
|
||||
discountType: "fullMinusFlag",
|
||||
scopeType: "ALL",
|
||||
promotionGoodsList: [],
|
||||
promotionStatus: "NEW",
|
||||
},
|
||||
id: this.$route.query.id,
|
||||
submitLoading: false,
|
||||
selectedGoods: [],
|
||||
couponList: [],
|
||||
giftList: [],
|
||||
giftLoading: false,
|
||||
couponLoading: false,
|
||||
formRule: {
|
||||
promotionName: [{ required: true, message: "活动名称不能为空" }],
|
||||
rangeTime: [{ required: true, message: "请选择活动时间" }],
|
||||
description: [{ required: true, message: "请填写活动描述" }],
|
||||
fullMoney: [{ required: true, validator: checkWeight }],
|
||||
fullMinus: [
|
||||
{ required: true, message: "请填写优惠金额" },
|
||||
{ pattern: regular.money, message: "请输入正确金额" },
|
||||
],
|
||||
fullRate: [{ required: true, validator: checkDiscount }],
|
||||
},
|
||||
options: {
|
||||
disabledDate(date) {
|
||||
return date && date.valueOf() < Date.now() - 86400000;
|
||||
@@ -231,7 +300,12 @@ export default {
|
||||
},
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
computed: {
|
||||
fieldDisabled() {
|
||||
return !!this.id && this.form.promotionStatus !== "NEW";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.id) {
|
||||
this.getDetail();
|
||||
}
|
||||
@@ -239,36 +313,149 @@ export default {
|
||||
this.getGiftList();
|
||||
},
|
||||
methods: {
|
||||
closeCurrentPage() {
|
||||
this.$router.back();
|
||||
},
|
||||
openSkuList() {
|
||||
this.$refs.liliDialog.open("goods");
|
||||
const data = JSON.parse(JSON.stringify(this.form.promotionGoodsList));
|
||||
data.forEach((e) => {
|
||||
e.id = e.skuId;
|
||||
});
|
||||
this.$refs.liliDialog.goodsData = data;
|
||||
},
|
||||
getDetail() {
|
||||
getFullDiscountById(this.id).then((res) => {
|
||||
let data = res.result;
|
||||
if (!data.scopeType === "ALL") {
|
||||
const data = res.result;
|
||||
if (data.scopeType === "ALL") {
|
||||
data.promotionGoodsList = [];
|
||||
}
|
||||
if (data.fullMinusFlag) {
|
||||
data.discountType = "fullMinusFlag";
|
||||
delete data.fullMinusFlag;
|
||||
} else {
|
||||
data.discountType = "fullMinusFlag";
|
||||
data.discountType = "fullRateFlag";
|
||||
delete data.fullRateFlag;
|
||||
}
|
||||
data.rangeTime = [];
|
||||
data.rangeTime.push(new Date(data.startTime), new Date(data.endTime));
|
||||
|
||||
data.rangeTime = [new Date(data.startTime), new Date(data.endTime)];
|
||||
if (data.fullRate !== null && data.fullRate !== undefined && data.fullRate !== "") {
|
||||
data.fullRate = parseFloat(Number(data.fullRate).toFixed(1));
|
||||
}
|
||||
this.form = data;
|
||||
});
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return;
|
||||
const params = JSON.parse(JSON.stringify(this.form));
|
||||
params.startTime = this.$filters.unixToDate(this.form.rangeTime[0] / 1000);
|
||||
params.endTime = this.$filters.unixToDate(this.form.rangeTime[1] / 1000);
|
||||
|
||||
if (params.couponFlag && !params.couponId) {
|
||||
this.$Message.warning("请选择优惠券");
|
||||
return;
|
||||
}
|
||||
if (params.giftFlag && !params.giftId) {
|
||||
this.$Message.warning("请选择赠品");
|
||||
return;
|
||||
}
|
||||
if (params.pointFlag && !params.point) {
|
||||
this.$Message.warning("请填写积分");
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
params.scopeType === "PORTION_GOODS" &&
|
||||
(!params.promotionGoodsList || params.promotionGoodsList.length === 0)
|
||||
) {
|
||||
this.$Message.warning("请选择指定商品");
|
||||
return;
|
||||
}
|
||||
if (params.scopeType === "ALL") {
|
||||
delete params.promotionGoodsList;
|
||||
params.number = -1;
|
||||
} else {
|
||||
const scopeId = [];
|
||||
params.number = 1;
|
||||
params.promotionGoodsList.forEach((e) => {
|
||||
e.startTime = params.startTime;
|
||||
e.endTime = params.endTime;
|
||||
scopeId.push(e.skuId);
|
||||
});
|
||||
params.scopeId = scopeId.toString();
|
||||
}
|
||||
if (params.discountType === "fullMinusFlag") {
|
||||
params.fullMinusFlag = true;
|
||||
} else {
|
||||
params.fullRateFlag = true;
|
||||
}
|
||||
delete params.discountType;
|
||||
delete params.rangeTime;
|
||||
if (!this.id) {
|
||||
delete params.id;
|
||||
} else {
|
||||
delete params.updateTime;
|
||||
}
|
||||
|
||||
this.submitLoading = true;
|
||||
const request = this.id ? editFullDiscount(params) : newFullDiscount(params);
|
||||
request.then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success(this.id ? "编辑活动成功" : "添加活动成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectedGoods = e;
|
||||
},
|
||||
delSelectGoods() {
|
||||
if (this.selectedGoods.length <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除所选商品吗?",
|
||||
onOk: () => {
|
||||
const ids = this.selectedGoods.map((e) => e.skuId || e.id);
|
||||
this.form.promotionGoodsList = this.form.promotionGoodsList.filter(
|
||||
(item) => !ids.includes(item.skuId)
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
delGoods(index) {
|
||||
this.form.promotionGoodsList.splice(index, 1);
|
||||
},
|
||||
selectedGoodsData(item) {
|
||||
const list = [];
|
||||
item.forEach((e) => {
|
||||
list.push({
|
||||
goodsName: e.goodsName,
|
||||
price: e.price,
|
||||
quantity: e.quantity,
|
||||
storeId: e.storeId,
|
||||
storeName: e.storeName,
|
||||
thumbnail: e.thumbnail,
|
||||
skuId: e.id,
|
||||
goodsId: e.goodsId,
|
||||
});
|
||||
});
|
||||
this.form.promotionGoodsList = list;
|
||||
},
|
||||
getCouponList(query) {
|
||||
let params = {
|
||||
const params = {
|
||||
pageSize: 20,
|
||||
pageNumber: 1,
|
||||
getType: "ACTIVITY",
|
||||
storeId: "",
|
||||
couponName: query,
|
||||
promotionStatus: "START",
|
||||
};
|
||||
this.couponLoading = true;
|
||||
getPlatformCouponList(params).then((res) => {
|
||||
getShopCouponList(params).then((res) => {
|
||||
this.couponLoading = false;
|
||||
if (res.success) {
|
||||
this.couponList = res.result.records;
|
||||
@@ -276,16 +463,16 @@ export default {
|
||||
});
|
||||
},
|
||||
getGiftList(query) {
|
||||
let params = {
|
||||
const params = {
|
||||
pageSize: 20,
|
||||
pageNumber: 1,
|
||||
id: query === this.form.giftId ? this.form.giftId : null,
|
||||
goodsName: query === this.form.giftId ? null : query,
|
||||
marketEnable: "UPPER",
|
||||
authFlag: "PASS"
|
||||
authFlag: "PASS",
|
||||
};
|
||||
this.giftLoading = true;
|
||||
getGoodsSkuData(params).then((res) => {
|
||||
getGoodsSkuListDataSeller(params).then((res) => {
|
||||
this.giftLoading = false;
|
||||
if (res.success) {
|
||||
this.giftList = res.result.records;
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
</el-card>
|
||||
|
||||
<el-card>
|
||||
<div class="operation padding-row">
|
||||
<el-button type="primary" @click="add">新增</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
@@ -71,10 +74,12 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="140" fixed="right">
|
||||
<el-table-column label="操作" align="center" width="160" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a class="link-text" @click="view(row)">查看</a>
|
||||
<a class="link-text" @click="goDetail(row)">
|
||||
{{ row.promotionStatus === "NEW" ? "编辑" : "查看" }}
|
||||
</a>
|
||||
<template v-if="row.promotionStatus === 'NEW' || row.promotionStatus === 'START'">
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="openOrClose(row)">关闭</a>
|
||||
@@ -189,7 +194,10 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
view(row) {
|
||||
add() {
|
||||
this.$router.push({ name: "full-discount-detail" });
|
||||
},
|
||||
goDetail(row) {
|
||||
this.$router.push({ name: "full-discount-detail", query: { id: row.id } });
|
||||
},
|
||||
},
|
||||
@@ -214,4 +222,12 @@ export default {
|
||||
.mt_10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.operation {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.padding-row {
|
||||
padding: 0 0 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,179 +1,195 @@
|
||||
<template>
|
||||
<div class="pintuan-goods">
|
||||
<div class="new-pintuan">
|
||||
<el-card>
|
||||
<h4>活动详情</h4>
|
||||
<el-table border :data="data" style="width: 100%; margin: 10px 0">
|
||||
<el-table-column prop="promotionName" label="活动名称" min-width="120" />
|
||||
<el-table-column prop="startTime" label="活动开始时间" min-width="120" />
|
||||
<el-table-column prop="endTime" label="活动结束时间" min-width="120" />
|
||||
<el-table-column prop="requiredNum" label="成团人数" min-width="90" />
|
||||
<el-table-column prop="limitNum" label="限购数量" min-width="90" />
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row" :type="promotionStatusTagType(row.promotionStatus)">
|
||||
{{ promotionStatusText(row.promotionStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<h4>商品信息</h4>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
class="operation"
|
||||
:data="goodsData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="商品名称" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a class="link-text mr_10" @click="linkTo(row.goodsId, row.skuId)">{{ row.goodsName }}</a>
|
||||
<el-popover trigger="hover" title="扫码在手机中查看" placement="top" width="180">
|
||||
<template #reference>
|
||||
<img
|
||||
src="../../../assets/qrcode.svg"
|
||||
style="vertical-align: middle"
|
||||
class="hover-pointer"
|
||||
width="20"
|
||||
height="20"
|
||||
alt="qrcode"
|
||||
/>
|
||||
</template>
|
||||
<vue-qr
|
||||
:text="wapLinkTo(row.goodsId, row.skuId)"
|
||||
:margin="0"
|
||||
color-dark="#000"
|
||||
color-light="#fff"
|
||||
:size="150"
|
||||
/>
|
||||
</el-popover>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="库存" min-width="80" />
|
||||
<el-table-column label="拼团价格" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.price, "¥") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="page operation mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
<el-form ref="form" :model="form" label-width="130px" :rules="formValidate">
|
||||
<el-form-item label="活动名称" prop="promotionName">
|
||||
<el-input
|
||||
v-model="form.promotionName"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
maxlength="25"
|
||||
placeholder="请输入活动名称"
|
||||
/>
|
||||
<div class="form-tip">
|
||||
活动名称将显示在店铺拼团活动列表中,供商家管理使用,最多输入25个字符
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="rangeTime">
|
||||
<el-date-picker
|
||||
v-model="form.rangeTime"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
placeholder="请选择"
|
||||
:disabled-date="options.disabledDate"
|
||||
style="width: 360px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="成团人数" prop="requiredNum">
|
||||
<el-input v-model="form.requiredNum" style="width: 260px" placeholder="请输入成团人数">
|
||||
<template #append>人</template>
|
||||
</el-input>
|
||||
<span class="form-tip inline-tip">成团人数最少为2人,最多不超过10人。</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="限购数量" prop="limitNum">
|
||||
<el-input v-model="form.limitNum" type="number" style="width: 260px" placeholder="请输入限购数量">
|
||||
<template #append>件/人</template>
|
||||
</el-input>
|
||||
<span class="form-tip inline-tip">若设置为0,则为不限制购买数量。</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="虚拟成团" prop="fictitious">
|
||||
<el-radio-group v-model="form.fictitious">
|
||||
<el-radio-button :value="1">开启</el-radio-button>
|
||||
<el-radio-button :value="0">关闭</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div class="form-tip">
|
||||
开启虚拟成团后,24小时内人数未满的团,系统将会模拟匿名买家凑满人数,使该团成团。您只需要对真实拼团买家发货。建议合理开启,以提高成团率。
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="拼团规则" prop="pintuanRule">
|
||||
<el-input
|
||||
v-model="form.pintuanRule"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
clearable
|
||||
maxlength="255"
|
||||
style="width: 260px"
|
||||
placeholder="请输入拼团规则"
|
||||
/>
|
||||
<div class="form-tip">拼团规则字数不能超过255字,将在WAP拼团详情页中显示</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="closeCurrentPage">返回</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getPintuanGoodsList, getPintuanDetail } from "@/api/promotion.js";
|
||||
import vueQr from "vue-qr";
|
||||
import { savePintuan, editPintuan, getPintuanDetail } from "@/api/promotion";
|
||||
|
||||
export default {
|
||||
components: { vueQr },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
id: this.$route.query.id,
|
||||
form: {
|
||||
promotionName: "",
|
||||
promotionTitle: "",
|
||||
pintuanRule: "",
|
||||
requiredNum: "",
|
||||
fictitious: 0,
|
||||
limitNum: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
rangeTime: [],
|
||||
},
|
||||
formValidate: {
|
||||
promotionName: [{ required: true, message: "活动名称不能为空", trigger: "blur" }],
|
||||
requiredNum: [
|
||||
{ required: true, message: "成团人数不能为空", trigger: "blur" },
|
||||
{
|
||||
pattern: /^([2-9]|10)?$/,
|
||||
message: "成团人数不合法",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
limitNum: [
|
||||
{ required: true, message: "限购数量不能为空", trigger: "blur" },
|
||||
{
|
||||
pattern: /^(0|[1-9]\d?|100)$/,
|
||||
message: "限购数量不合法",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
rangeTime: [{ required: true, message: "请选择活动时间", trigger: "change" }],
|
||||
},
|
||||
submitLoading: false,
|
||||
options: {
|
||||
disabledDate(date) {
|
||||
return date && date.valueOf() < Date.now() - 86400000;
|
||||
},
|
||||
},
|
||||
data: [],
|
||||
total: 0,
|
||||
goodsData: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (this.id) {
|
||||
this.getDetail();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
promotionStatusText(status) {
|
||||
const map = {
|
||||
NEW: "未开始",
|
||||
START: "已开始",
|
||||
END: "已结束",
|
||||
CLOSE: "已关闭",
|
||||
};
|
||||
return map[status] || "未知";
|
||||
closeCurrentPage() {
|
||||
this.$router.back();
|
||||
},
|
||||
promotionStatusTagType(status) {
|
||||
const map = {
|
||||
NEW: "info",
|
||||
START: "success",
|
||||
END: "danger",
|
||||
CLOSE: "danger",
|
||||
};
|
||||
return map[status] || "danger";
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
this.getPintuanMsg();
|
||||
},
|
||||
changePage() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePageSize() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.getDataList();
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
this.searchForm.pintuanId = this.$route.query.id;
|
||||
getPintuanGoodsList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.goodsData = res.result.records;
|
||||
this.total = res.result.total;
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.submitLoading = true;
|
||||
const params = JSON.parse(JSON.stringify(this.form));
|
||||
params.fictitious = !!params.fictitious;
|
||||
params.startTime = this.$filters.unixToDate(this.form.rangeTime[0] / 1000);
|
||||
params.endTime = this.$filters.unixToDate(this.form.rangeTime[1] / 1000);
|
||||
|
||||
if (!params.startTime || !params.endTime) {
|
||||
this.$Message.error("活动时间不能为空");
|
||||
this.submitLoading = false;
|
||||
return;
|
||||
}
|
||||
if (new Date(params.startTime).getTime() < Date.now()) {
|
||||
this.$Message.error("拼团活动开始时间不能小于当前时间");
|
||||
this.submitLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
delete params.rangeTime;
|
||||
if (!this.id) {
|
||||
delete params.id;
|
||||
savePintuan(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("拼团活动添加成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (params.promotionGoodsList === "") delete params.promotionGoodsList;
|
||||
editPintuan(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("编辑成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getPintuanMsg() {
|
||||
getPintuanDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success) this.data.push(res.result);
|
||||
getDetail() {
|
||||
getPintuanDetail(this.id).then((res) => {
|
||||
if (res.success) {
|
||||
const data = res.result;
|
||||
data.rangeTime = [new Date(data.startTime), new Date(data.endTime)];
|
||||
this.form = data;
|
||||
this.form.fictitious = data.fictitious ? 1 : 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
h4 {
|
||||
margin: 20px 0;
|
||||
padding: 0 10px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
border-left: 3px solid red;
|
||||
.form-tip {
|
||||
color: #cccccc;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.link-text {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mr_10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.hover-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mt_10 {
|
||||
margin-top: 10px;
|
||||
.inline-tip {
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<h4>活动详情</h4>
|
||||
<el-table border :data="data" style="width: 100%; margin: 10px 0">
|
||||
<el-table-column prop="promotionName" label="活动名称" min-width="120" />
|
||||
<el-table-column prop="startTime" label="活动开始时间" min-width="120" />
|
||||
<el-table-column prop="endTime" label="活动结束时间" min-width="120" />
|
||||
<el-table-column prop="startTime" label="活动开始时间" min-width="160" />
|
||||
<el-table-column prop="endTime" label="活动结束时间" min-width="160" />
|
||||
<el-table-column prop="requiredNum" label="成团人数" min-width="90" />
|
||||
<el-table-column prop="limitNum" label="限购数量" min-width="90" />
|
||||
<el-table-column label="状态" min-width="100">
|
||||
@@ -17,75 +17,130 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<h4>商品信息</h4>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
class="operation"
|
||||
:data="goodsData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="商品名称" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a class="link-text mr_10" @click="linkTo(row.goodsId, row.skuId)">{{ row.goodsName }}</a>
|
||||
<el-popover trigger="hover" title="扫码在手机中查看" placement="top" width="180">
|
||||
<template #reference>
|
||||
<img
|
||||
src="../../../assets/qrcode.svg"
|
||||
style="vertical-align: middle"
|
||||
class="hover-pointer"
|
||||
width="20"
|
||||
height="20"
|
||||
alt="qrcode"
|
||||
/>
|
||||
</template>
|
||||
<vue-qr
|
||||
:text="wapLinkTo(row.goodsId, row.skuId)"
|
||||
:margin="0"
|
||||
color-dark="#000"
|
||||
color-light="#fff"
|
||||
:size="150"
|
||||
/>
|
||||
</el-popover>
|
||||
<h4>活动商品</h4>
|
||||
<template v-if="!readonly">
|
||||
<div class="operation">
|
||||
<el-button type="primary" @click="openSkuList">选择商品</el-button>
|
||||
<el-button @click="delAll">批量删除</el-button>
|
||||
<el-button @click="getDataList">刷新</el-button>
|
||||
</div>
|
||||
<el-alert v-if="selectCount > 0" type="info" show-icon :closable="false" class="select-alert">
|
||||
已选择 <span>{{ selectCount }}</span> 项
|
||||
<a class="select-clear" @click="clearSelectAll">清空</a>
|
||||
</el-alert>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="goodsData"
|
||||
style="width: 100%"
|
||||
@selection-change="changeSelect"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="quantity" label="库存" width="90" />
|
||||
<el-table-column label="拼团价格" width="160">
|
||||
<template #default="{ row, $index }">
|
||||
<el-input-number
|
||||
v-if="row"
|
||||
v-model="row.price"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
@change="(val) => updateGoodsPrice($index, val)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="库存" min-width="80" />
|
||||
<el-table-column label="拼团价格" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.price, "¥") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center">
|
||||
<template #default="{ $index }">
|
||||
<a class="link-text" @click="delGoods($index)">删除</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<div class="page operation mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="goodsData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="商品名称" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a class="link-text mr_10" @click="linkTo(row.goodsId, row.skuId)">{{ row.goodsName }}</a>
|
||||
<el-popover trigger="hover" title="扫码在手机中查看" placement="top" width="180">
|
||||
<template #reference>
|
||||
<img
|
||||
src="../../../assets/qrcode.svg"
|
||||
class="hover-pointer qrcode-icon"
|
||||
width="20"
|
||||
height="20"
|
||||
alt="qrcode"
|
||||
/>
|
||||
</template>
|
||||
<vue-qr
|
||||
:text="wapLinkTo(row.goodsId, row.skuId)"
|
||||
:margin="0"
|
||||
color-dark="#000"
|
||||
color-light="#fff"
|
||||
:size="150"
|
||||
/>
|
||||
</el-popover>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="库存" width="90" />
|
||||
<el-table-column label="拼团价格" width="120">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.price, "¥") }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="foot-btn">
|
||||
<el-button @click="closeCurrentPage">返回</el-button>
|
||||
<el-button v-if="!readonly" type="primary" :loading="submitLoading" @click="save">
|
||||
提交
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<liliDialog ref="liliDialog" @selectedGoodsData="selectedGoodsData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getPintuanGoodsList, getPintuanDetail, editPintuan } from "@/api/promotion.js";
|
||||
import liliDialog from "@/views/lili-dialog";
|
||||
import vueQr from "vue-qr";
|
||||
|
||||
export default {
|
||||
components: { vueQr },
|
||||
components: { liliDialog, vueQr },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
promotionStatus: "",
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
@@ -93,8 +148,15 @@ export default {
|
||||
data: [],
|
||||
total: 0,
|
||||
goodsData: [],
|
||||
selectList: [],
|
||||
selectCount: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
readonly() {
|
||||
return this.$route.query.status === "view" || this.promotionStatus !== "NEW";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
promotionStatusText(status) {
|
||||
const map = {
|
||||
@@ -114,8 +176,10 @@ export default {
|
||||
};
|
||||
return map[status] || "danger";
|
||||
},
|
||||
closeCurrentPage() {
|
||||
this.$router.back();
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
this.getPintuanMsg();
|
||||
},
|
||||
changePage() {
|
||||
@@ -125,20 +189,119 @@ export default {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.getDataList();
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
this.searchForm.pintuanId = this.$route.query.id;
|
||||
getPintuanGoodsList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.goodsData = res.result.records;
|
||||
this.total = res.result.total;
|
||||
getPintuanMsg() {
|
||||
getPintuanDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.data = [res.result];
|
||||
this.promotionStatus = res.result.promotionStatus;
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
getPintuanMsg() {
|
||||
getPintuanDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success) this.data.push(res.result);
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
const params = {
|
||||
pintuanId: this.$route.query.id,
|
||||
pageNumber: this.readonly ? this.searchForm.pageNumber : 1,
|
||||
pageSize: this.readonly ? this.searchForm.pageSize : 1000,
|
||||
};
|
||||
getPintuanGoodsList(params).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result) {
|
||||
this.goodsData = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
openSkuList() {
|
||||
const data = JSON.parse(JSON.stringify(this.goodsData));
|
||||
data.forEach((e) => {
|
||||
e.id = e.skuId;
|
||||
});
|
||||
this.$refs.liliDialog.goodsData = data;
|
||||
this.$refs.liliDialog.open("goods");
|
||||
},
|
||||
selectedGoodsData(selected) {
|
||||
const existingMap = new Map(this.goodsData.map((item) => [item.skuId, item]));
|
||||
this.goodsData = selected.map((item) => {
|
||||
const existed = existingMap.get(item.id);
|
||||
if (existed) {
|
||||
return existed;
|
||||
}
|
||||
return {
|
||||
goodsName: item.goodsName,
|
||||
price: item.price,
|
||||
originalPrice: item.price,
|
||||
quantity: item.quantity,
|
||||
storeId: item.storeId,
|
||||
sellerName: item.sellerName,
|
||||
thumbnail: item.thumbnail,
|
||||
skuId: item.id,
|
||||
categoryPath: item.categoryPath,
|
||||
goodsId: item.goodsId,
|
||||
goodsType: item.goodsType,
|
||||
};
|
||||
});
|
||||
this.clearSelectAll();
|
||||
},
|
||||
updateGoodsPrice(index, value) {
|
||||
if (this.goodsData[index]) {
|
||||
this.goodsData[index].price = value;
|
||||
}
|
||||
},
|
||||
changeSelect(selection) {
|
||||
this.selectList = selection;
|
||||
this.selectCount = selection.length;
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table?.clearSelection();
|
||||
this.selectList = [];
|
||||
this.selectCount = 0;
|
||||
},
|
||||
delGoods(index) {
|
||||
this.goodsData.splice(index, 1);
|
||||
this.selectCount = 0;
|
||||
},
|
||||
delAll() {
|
||||
if (this.selectCount <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: `您确认要删除所选 ${this.selectCount} 项数据?`,
|
||||
onOk: () => {
|
||||
const ids = this.selectList.map((e) => e.skuId);
|
||||
this.goodsData = this.goodsData.filter((item) => !ids.includes(item.skuId));
|
||||
this.clearSelectAll();
|
||||
},
|
||||
});
|
||||
},
|
||||
save() {
|
||||
if (!this.goodsData.length) {
|
||||
this.$Message.warning("请选择活动商品");
|
||||
return;
|
||||
}
|
||||
for (const item of this.goodsData) {
|
||||
if (item.price === "" || item.price === null || item.price === undefined) {
|
||||
this.$Message.warning(`请填写【${item.goodsName}】的价格`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const params = JSON.parse(JSON.stringify(this.data[0]));
|
||||
params.promotionGoodsList = this.goodsData.map((item) => ({
|
||||
...item,
|
||||
promotionId: params.id,
|
||||
startTime: params.startTime,
|
||||
endTime: params.endTime,
|
||||
}));
|
||||
this.submitLoading = true;
|
||||
editPintuan(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改拼团商品成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -159,6 +322,22 @@ h4 {
|
||||
border-left: 3px solid red;
|
||||
}
|
||||
|
||||
.operation {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.select-alert {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.select-clear {
|
||||
margin-left: 12px;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.link-text {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
@@ -173,6 +352,16 @@ h4 {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.qrcode-icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.foot-btn {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mt_10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
</el-card>
|
||||
|
||||
<el-card>
|
||||
<div class="operation padding-row mb_10">
|
||||
<el-button type="primary" @click="newAct">添加</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
@@ -71,13 +74,23 @@
|
||||
<el-table-column prop="storeName" label="所属店铺" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="startTime" label="活动开始时间" width="180" />
|
||||
<el-table-column prop="endTime" label="活动结束时间" width="180" />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<el-table-column label="操作" width="220" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a class="link-text" @click="view(row)">查看</a>
|
||||
<template v-if="row.promotionStatus === 'START' || row.promotionStatus === 'NEW'">
|
||||
<template v-if="row.promotionStatus === 'NEW'">
|
||||
<a class="link-text" @click="edit(row)">编辑</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="close(row)">关闭</a>
|
||||
<a class="link-text" @click="manage(row, 'manager')">管理</a>
|
||||
</template>
|
||||
<template v-else-if="row.promotionStatus !== 'CLOSE'">
|
||||
<a class="link-text" @click="manage(row, 'view')">查看</a>
|
||||
<template v-if="row.promotionStatus === 'START'">
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="close(row)">关闭</a>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a class="link-text" @click="open(row)">开启</a>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
@@ -101,7 +114,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getPintuanList, deletePintuan, editPintuanStatus } from "@/api/promotion";
|
||||
import { getPintuanList, editPintuanStatus } from "@/api/promotion";
|
||||
export default {
|
||||
name: "pintuan",
|
||||
data() {
|
||||
@@ -176,8 +189,37 @@ export default {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
view(v) {
|
||||
this.$router.push({ name: "pintuan-goods", query: { id: v.id } });
|
||||
newAct() {
|
||||
this.$router.push({ name: "pintuan-edit" });
|
||||
},
|
||||
edit(v) {
|
||||
this.$router.push({ name: "pintuan-edit", query: { id: v.id } });
|
||||
},
|
||||
manage(v, status) {
|
||||
this.$router.push({ name: "pintuan-goods", query: { id: v.id, status } });
|
||||
},
|
||||
open(v) {
|
||||
const sTime = new Date();
|
||||
sTime.setMinutes(sTime.getMinutes() + 10);
|
||||
const eTime = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1);
|
||||
const params = {
|
||||
startTime: sTime.getTime(),
|
||||
endTime: eTime.getTime(),
|
||||
};
|
||||
this.$Modal.confirm({
|
||||
title: "确认开启",
|
||||
content: "您确认要开启此拼团活动?(默认为当前时间后十分钟至当天结束)",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
editPintuanStatus(v.id, params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("开启活动成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
close(v) {
|
||||
this.$Modal.confirm({
|
||||
@@ -185,10 +227,10 @@ export default {
|
||||
content: "您确认要关闭此拼团活动?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
updatePintuanStatus(v.id).then((res) => {
|
||||
editPintuanStatus(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.$Message.success("关闭活动成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
@@ -206,4 +248,19 @@ export default {
|
||||
.mt_10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mb_10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.link-text {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.op-split {
|
||||
margin: 0 8px;
|
||||
color: #dcdee2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,58 +25,155 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
class="operation"
|
||||
:data="goodsList"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="商品价格" width="110">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.originalPrice, "¥") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" width="90">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.quantity }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="活动价格" width="100">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.price, "¥") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="storeName" label="商家名称" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="活动场次" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row">{{ row.timeLine + ":00" }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<a v-if="row" class="link-text" @click="delGoods($index, row)">删除</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template v-if="!readonly">
|
||||
<div class="operation">
|
||||
<el-button type="primary" @click="openSkuList">选择商品</el-button>
|
||||
</div>
|
||||
<el-tabs v-model="tabCurrent" type="card" class="operation">
|
||||
<el-tab-pane
|
||||
v-for="(tab, tabIndex) in goodsList"
|
||||
:key="tabIndex"
|
||||
:label="tab.hour"
|
||||
:name="String(tabIndex)"
|
||||
>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="tab.list"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="商品价格" width="110">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.originalPrice, "¥") }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-input-number
|
||||
v-if="row"
|
||||
v-model="row.quantity"
|
||||
:min="1"
|
||||
:disabled="row.promotionApplyStatus === 'PASS'"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
@change="(val) => updateGoodsField(tabIndex, $index, 'quantity', val)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="活动价格" width="140">
|
||||
<template #default="{ row, $index }">
|
||||
<el-input-number
|
||||
v-if="row"
|
||||
v-model="row.price"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
:disabled="row.promotionApplyStatus === 'PASS'"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
@change="(val) => updateGoodsField(tabIndex, $index, 'price', val)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="120">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<el-tag :type="applyStatusTagType(row.promotionApplyStatus)" size="small">
|
||||
{{ applyStatusText(row.promotionApplyStatus) }}
|
||||
</el-tag>
|
||||
<a
|
||||
v-if="row.promotionApplyStatus === 'REFUSE' && row.failReason"
|
||||
class="reason link-text"
|
||||
@click="showReason(row.failReason)"
|
||||
>
|
||||
拒绝原因
|
||||
</a>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<a v-if="row" class="link-text" @click="delGoods(tabIndex, $index, row)">删除</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
class="operation"
|
||||
:data="readonlyGoodsList"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="商品价格" width="110">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.originalPrice, "¥") }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" width="90">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.quantity }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="活动价格" width="100">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" :style="{ color: $mainColor }">
|
||||
{{ $filters.unitPrice(row.price, "¥") }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="活动场次" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row">{{ row.timeLine }}:00</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row" :type="applyStatusTagType(row.promotionApplyStatus)" size="small">
|
||||
{{ applyStatusText(row.promotionApplyStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="foot-btn">
|
||||
<el-button @click="closeCurrentPage">返回</el-button>
|
||||
<el-button
|
||||
v-if="!readonly"
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="save"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<liliDialog ref="liliDialog" @selectedGoodsData="selectedGoodsData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -84,14 +181,21 @@
|
||||
import {
|
||||
seckillGoodsList,
|
||||
seckillDetail,
|
||||
setSeckillGoods,
|
||||
delSeckillGoods,
|
||||
} from "@/api/promotion.js";
|
||||
import liliDialog from "@/views/lili-dialog";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
liliDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabCurrent: "0",
|
||||
promotionStatus: "",
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
@@ -99,85 +203,220 @@ export default {
|
||||
total: 0,
|
||||
data: [],
|
||||
goodsList: [],
|
||||
readonlyGoodsList: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
readonly() {
|
||||
return this.$route.query.mode === "view" || this.promotionStatus !== "NEW";
|
||||
},
|
||||
tabIndex() {
|
||||
return Number(this.tabCurrent) || 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
seckillStatusText(status) {
|
||||
const map = {
|
||||
NEW: "新建",
|
||||
START: "开始",
|
||||
END: "结束",
|
||||
CLOSE: "废弃",
|
||||
NEW: "未开始",
|
||||
START: "已开始",
|
||||
END: "已结束",
|
||||
CLOSE: "已关闭",
|
||||
};
|
||||
return map[status] || status || "-";
|
||||
},
|
||||
seckillStatusTagType(status) {
|
||||
const map = {
|
||||
NEW: "danger",
|
||||
NEW: "info",
|
||||
START: "success",
|
||||
END: "danger",
|
||||
CLOSE: "danger",
|
||||
};
|
||||
return map[status] || "danger";
|
||||
},
|
||||
applyStatusText(status) {
|
||||
const map = {
|
||||
APPLY: "申请中",
|
||||
PASS: "已通过",
|
||||
REFUSE: "已拒绝",
|
||||
};
|
||||
return map[status] || "未申请";
|
||||
},
|
||||
applyStatusTagType(status) {
|
||||
const map = {
|
||||
APPLY: "warning",
|
||||
PASS: "success",
|
||||
REFUSE: "danger",
|
||||
};
|
||||
return map[status] || "info";
|
||||
},
|
||||
closeCurrentPage() {
|
||||
this.$router.back();
|
||||
},
|
||||
init() {
|
||||
this.getSeckillMsg();
|
||||
},
|
||||
changePage() {
|
||||
this.getDataList();
|
||||
this.getReadonlyGoodsList();
|
||||
},
|
||||
changePageSize() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.getDataList();
|
||||
this.getReadonlyGoodsList();
|
||||
},
|
||||
getDataList() {
|
||||
getSeckillMsg() {
|
||||
seckillDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.data = [res.result];
|
||||
this.promotionStatus = res.result.promotionStatus;
|
||||
if (this.readonly) {
|
||||
this.getReadonlyGoodsList();
|
||||
} else {
|
||||
this.getManageGoodsList();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getManageGoodsList() {
|
||||
if (!this.data[0]?.hours) {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
const hourValues = this.data[0].hours.split(",");
|
||||
const hourLabels = this.unixHours(this.data[0].hours);
|
||||
this.goodsList = hourLabels.map((hour, index) => ({
|
||||
hour,
|
||||
timeLine: hourValues[index],
|
||||
list: [],
|
||||
}));
|
||||
|
||||
seckillGoodsList({
|
||||
seckillId: this.$route.query.id,
|
||||
pageNumber: 1,
|
||||
pageSize: 1000,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result?.records?.length) {
|
||||
res.result.records.forEach((item) => {
|
||||
const slot = this.goodsList.find(
|
||||
(g) => String(g.timeLine) === String(item.timeLine)
|
||||
);
|
||||
if (slot) {
|
||||
slot.list.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getReadonlyGoodsList() {
|
||||
this.loading = true;
|
||||
this.searchForm.seckillId = this.$route.query.id;
|
||||
seckillGoodsList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result) {
|
||||
this.goodsList = res.result.records;
|
||||
this.total = res.result.total;
|
||||
this.readonlyGoodsList = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
getSeckillMsg() {
|
||||
seckillDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.data = [];
|
||||
this.data.push(res.result);
|
||||
this.promotionStatus = res.result.promotionStatus;
|
||||
this.getDataList();
|
||||
openSkuList() {
|
||||
const existing = this.goodsList[this.tabIndex]?.list || [];
|
||||
this.$refs.liliDialog.goodsData = existing.map((item) => ({
|
||||
...item,
|
||||
id: item.skuId || item.id,
|
||||
}));
|
||||
this.$refs.liliDialog.open("goods");
|
||||
},
|
||||
selectedGoodsData(selected) {
|
||||
const timeLine = this.goodsList[this.tabIndex]?.timeLine;
|
||||
if (timeLine === undefined) {
|
||||
return;
|
||||
}
|
||||
const existingMap = new Map(
|
||||
(this.goodsList[this.tabIndex].list || []).map((item) => [item.skuId, item])
|
||||
);
|
||||
const list = selected.map((item) => {
|
||||
const existed = existingMap.get(item.id);
|
||||
if (existed) {
|
||||
return existed;
|
||||
}
|
||||
return {
|
||||
goodsName: item.goodsName,
|
||||
price: item.price,
|
||||
originalPrice: item.price,
|
||||
promotionApplyStatus: item.promotionApplyStatus || "",
|
||||
quantity: item.quantity,
|
||||
seckillId: this.$route.query.id,
|
||||
storeId: item.storeId,
|
||||
storeName: item.storeName,
|
||||
skuId: item.id,
|
||||
timeLine,
|
||||
};
|
||||
});
|
||||
this.goodsList[this.tabIndex].list = list;
|
||||
},
|
||||
updateGoodsField(tabIndex, index, field, value) {
|
||||
if (this.goodsList[tabIndex]?.list?.[index]) {
|
||||
this.goodsList[tabIndex].list[index][field] = value;
|
||||
}
|
||||
},
|
||||
delGoods(tabIndex, index, row) {
|
||||
if (row.promotionApplyStatus === "PASS") {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除该商品吗?删除后不可恢复",
|
||||
onOk: () => {
|
||||
delSeckillGoods({
|
||||
seckillId: row.seckillId,
|
||||
id: row.id,
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
this.goodsList[tabIndex].list.splice(index, 1);
|
||||
this.$Message.success("删除成功");
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.goodsList[tabIndex].list.splice(index, 1);
|
||||
this.$Message.success("删除成功");
|
||||
},
|
||||
save() {
|
||||
const applyVos = [];
|
||||
this.goodsList.forEach((slot) => {
|
||||
slot.list.forEach((item) => {
|
||||
applyVos.push(item);
|
||||
});
|
||||
});
|
||||
if (!applyVos.length) {
|
||||
this.$Message.warning("请先选择活动商品");
|
||||
return;
|
||||
}
|
||||
this.submitLoading = true;
|
||||
setSeckillGoods({
|
||||
seckillId: this.$route.query.id,
|
||||
applyVos,
|
||||
}).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res?.success) {
|
||||
this.$Message.success("提交活动商品成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
},
|
||||
delGoods(index, row) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除该商品吗?删除后不可恢复",
|
||||
onOk: () => {
|
||||
const params = {
|
||||
seckillId: row.seckillId,
|
||||
id: row.id,
|
||||
};
|
||||
delSeckillGoods(params).then((res) => {
|
||||
if (res.success) {
|
||||
this.goodsList.splice(index, 1);
|
||||
this.$Message.success("删除成功!");
|
||||
}
|
||||
});
|
||||
},
|
||||
showReason(reason) {
|
||||
this.$Modal.info({
|
||||
title: "拒绝原因",
|
||||
content: reason,
|
||||
});
|
||||
},
|
||||
unixDate(time) {
|
||||
return this.$filters.unixToDate(new Date(time) / 1000);
|
||||
},
|
||||
unixHours(item) {
|
||||
const hourArr = item.split(",");
|
||||
for (let i = 0; i < hourArr.length; i++) {
|
||||
hourArr[i] += ":00";
|
||||
if (!item) {
|
||||
return [];
|
||||
}
|
||||
return hourArr;
|
||||
return item.split(",").map((hour) => `${hour}:00`);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
@@ -188,7 +427,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.operation {
|
||||
margin: 10px 0;
|
||||
margin: 16px 0 10px;
|
||||
}
|
||||
|
||||
.hour-tag {
|
||||
@@ -202,6 +441,18 @@ export default {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.reason {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.foot-btn {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mt_10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@@ -47,102 +47,74 @@
|
||||
</el-card>
|
||||
|
||||
<el-card>
|
||||
<el-tabs v-model="activeTab" class="mt_10">
|
||||
<el-tab-pane label="秒杀活动列表" name="list">
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="data"
|
||||
class="mt_10"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="promotionName"
|
||||
label="活动名称"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="startTime" label="开始时间" width="180" />
|
||||
<el-table-column prop="applyEndTime" label="申请截止时间" width="180" />
|
||||
<el-table-column label="活动状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row" :type="promotionStatusTagType(row.promotionStatus)">
|
||||
{{ promotionStatusText(row.promotionStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="seckillRule"
|
||||
label="申请规则"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a
|
||||
v-if="row.promotionStatus === 'CLOSE' || row.promotionStatus === 'NEW'"
|
||||
class="link-text"
|
||||
@click="edit(row)"
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
<a v-else class="link-text" @click="manage(row)">查看</a>
|
||||
<span v-if="row.promotionStatus" class="op-split">|</span>
|
||||
<a
|
||||
v-if="row.promotionStatus == 'NEW'"
|
||||
class="link-text"
|
||||
@click="manage(row)"
|
||||
>
|
||||
管理
|
||||
</a>
|
||||
<span v-if="row.promotionStatus == 'NEW'" class="op-split">|</span>
|
||||
<a
|
||||
v-if="row.promotionStatus == 'START' || row.promotionStatus == 'NEW'"
|
||||
class="link-text"
|
||||
@click="off(row)"
|
||||
>
|
||||
关闭
|
||||
</a>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="data"
|
||||
class="mt_10"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="promotionName"
|
||||
label="活动名称"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="startTime" label="开始时间" width="180" />
|
||||
<el-table-column prop="applyEndTime" label="申请截止时间" width="180" />
|
||||
<el-table-column label="活动状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row" :type="promotionStatusTagType(row.promotionStatus)">
|
||||
{{ promotionStatusText(row.promotionStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="seckillRule"
|
||||
label="申请规则"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row">
|
||||
<a
|
||||
v-if="row.promotionStatus === 'NEW'"
|
||||
class="link-text"
|
||||
@click="manage(row)"
|
||||
>
|
||||
管理
|
||||
</a>
|
||||
<a v-else class="link-text" @click="view(row)">查看</a>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="秒杀活动设置" name="setup" lazy>
|
||||
<setupSeckill />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { seckillList } from "@/api/promotion";
|
||||
import setupSeckill from "@/views/promotion/seckill/seckill-setup";
|
||||
|
||||
export default {
|
||||
name: "seckill",
|
||||
components: {
|
||||
setupSeckill,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: "list",
|
||||
selectDate: [],
|
||||
loading: true,
|
||||
searchForm: {
|
||||
@@ -191,40 +163,12 @@ export default {
|
||||
this.searchForm.pageSize = 20;
|
||||
this.getDataList();
|
||||
},
|
||||
edit(v) {
|
||||
this.$router.push({ name: "manager-seckill-add", query: { id: v.id } });
|
||||
view(v) {
|
||||
this.$router.push({ name: "seckill-goods", query: { id: v.id, mode: "view" } });
|
||||
},
|
||||
manage(v) {
|
||||
this.$router.push({ name: "seckill-goods", query: { id: v.id } });
|
||||
},
|
||||
off(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content: "您确定要下架该活动吗?",
|
||||
onOk: () => {
|
||||
updateSeckillStatus(v.id).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("下架成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
expire(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content: "您确定要作废该活动吗?",
|
||||
onOk: () => {
|
||||
delSeckill(v.id).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("作废成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
|
||||
@@ -234,7 +178,7 @@ export default {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
getSeckillList(this.searchForm)
|
||||
seckillList(this.searchForm)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
|
||||
Reference in New Issue
Block a user