适配重构促销

This commit is contained in:
paulGao
2021-12-11 13:50:58 +08:00
parent fd1d32d431
commit edef393535
40 changed files with 2532 additions and 1486 deletions

View File

@@ -0,0 +1,177 @@
<template>
<div>
<div class="content-goods-publish">
<Form ref="form" :label-width="70">
<div class="base-info-item">
<h4>优惠券活动详情</h4>
<div class="form-item-view">
<FormItem label="活动名称">
<span>{{ couponActivity.promotionName }}</span>
</FormItem>
<FormItem label="活动类型">
<span v-if="couponActivity.couponActivityType === 'REGISTERED'"
>新人发券</span
>
<spin v-else>精确发券</spin>
</FormItem>
<FormItem
label="活动范围"
v-if="couponActivity.couponActivityType === 'SPECIFY'"
>
<span v-if="couponActivity.activityScope === 'ALL'">全部会员</span>
<spin v-else>指定会员</spin>
</FormItem>
<FormItem label="活动时间">
<span>{{ couponActivity.startTime }}{{ couponActivity.endTime }}</span>
</FormItem>
<FormItem label="活动状态">
<span v-if="couponActivity.promotionStatus === 'NEW'">未开始</span>
<span v-if="couponActivity.promotionStatus === 'START'">已开始</span>
<span v-if="couponActivity.promotionStatus === 'END'">已结束</span>
<span v-if="couponActivity.promotionStatus === 'CLOSE'">已关闭</span>
</FormItem>
</div>
<h4>优惠券列表</h4>
<Table :columns="couponColumn" :data="couponData" ref="table"> </Table>
<template v-if="couponActivity.activityScopeInfo && memberData.length > 0">
<h4 class="mt_10">会员列表列表</h4>
<Table :columns="memberColumn" :data="memberData"></Table>
</template>
</div>
</Form>
</div>
<div class="footer">
<Button type="primary" @click="back">返回活动列表</Button>
</div>
</div>
</template>
<script>
import { getCouponActivity } from "@/api/promotion";
export default {
name: "coupon-activity-info",
data() {
return {
id: this.$route.query.id, //表单id
couponActivity: {}, //券活动
couponColumn: [
{
title: "优惠券名称",
key: "couponName",
},
{
title: "优惠券金额",
key: "price",
render: (h, params) => {
let text = "未知";
if (params.row.couponType === "DISCOUNT") {
text = params.row.couponDiscount + "折";
} else if (params.row.couponType === "PRICE") {
text = "¥" + params.row.price;
}
return h("div", [text]);
},
},
{
title: "优惠券类型",
key: "couponType",
render: (h, params) => {
let text = "未知";
if (params.row.couponType == "DISCOUNT") {
text = "打折";
} else if (params.row.couponType == "PRICE") {
text = "减免现金";
}
return h("div", [text]);
},
},
{
title: "赠送数量",
key: "num",
},
],
couponData: [],
memberColumn: [
{
title: "会员id",
key: "id",
},
{
title: "昵称",
key: "nickName",
},
],
memberData: [],
};
},
mounted() {
this.getCouponActivity();
},
methods: {
//获取优惠券活动
getCouponActivity() {
getCouponActivity(this.id).then((res) => {
this.couponActivity = res.result;
this.couponData = this.couponActivity.couponActivityItems;
this.memberData = JSON.parse(this.couponActivity.activityScopeInfo);
});
},
back() {
this.$store.commit("removeTag", "coupon-activity");
this.$router.go(-1);
},
},
};
</script>
<style lang="scss" scoped>
/*选择商品品类*/
.content-goods-publish {
padding: 15px;
margin: 0 auto;
text-align: center;
border: 1px solid #ddd;
background: none repeat 0 0 #fff;
height: 100%;
margin-bottom: 20px;
}
div.base-info-item {
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.form-item-view {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
padding-left: 40px;
.shop-category-text {
font-size: 12px;
}
}
}
/** 底部步骤 */
.footer {
width: 88.7%;
padding: 10px;
background-color: #ffc;
position: fixed;
bottom: 0px;
left: 10%;
text-align: center;
z-index: 9999;
}
</style>

View File

@@ -0,0 +1,400 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<h4>活动信息</h4>
<div class="form-item-view">
<FormItem label="活动名称" prop="promotionName">
<Input
type="text"
v-model="form.promotionName"
placeholder="请填写活动名称"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动时间">
<DatePicker
type="datetimerange"
:options="options"
v-model="rangeTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择活动时间"
style="width: 260px"
>
</DatePicker>
</FormItem>
<FormItem label="优惠券活动类型" prop="couponActivityType">
<RadioGroup
type="button"
button-style="solid"
v-model="form.couponActivityType"
>
<Radio label="REGISTERED">新人发券</Radio>
<Radio label="SPECIFY">精确发券</Radio>
</RadioGroup>
</FormItem>
<FormItem
label="活动范围"
prop="activityScope"
v-if="form.couponActivityType === 'SPECIFY'"
>
<RadioGroup type="button" button-style="solid" v-model="form.activityScope">
<Radio label="ALL">全部会员</Radio>
<Radio label="DESIGNATED">指定会员</Radio>
</RadioGroup>
</FormItem>
<FormItem
label="选择会员"
prop="scopeType"
v-if="
form.couponActivityType === 'SPECIFY' &&
form.activityScope === 'DESIGNATED'
"
>
<Button type="primary" icon="ios-add" @click="addVip" ghost
>选择会员</Button
>
<div style="margin-top: 24px" v-if="form.activityScope == 'DESIGNATED'">
<Table border :columns="userColumns" :data="this.selectedMember"> </Table>
</div>
</FormItem>
</div>
<h4>配置优惠券</h4>
<div class="form-item-view">
<FormItem label="选择优惠券" prop="scopeType">
<Button type="primary" :loading="submitLoading" @click="showSelector"
>选择优惠券</Button
>
</FormItem>
<FormItem label="赠送配置" prop="scopeType">
<Table border :columns="columns" :data="this.selectCouponList">
<template slot="sendNum" slot-scope="scope">
<Input
type="text"
v-model="form.couponActivityItems[scope.index].num"
placeholder="赠送数量"
/>
<Input
type="text"
v-model="form.couponActivityItems[scope.index].couponId"
v-show="false"
/>
</template>
</Table>
</FormItem>
<div>
<Button type="text" @click="closeCurrentPage">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
>提交</Button
>
</div>
</div>
</div>
</Form>
</Card>
<Modal
@on-ok="
() => {
this.showCouponSelect = false;
}
"
@on-cancel="
() => {
this.showCouponSelect = false;
}
"
v-model="showCouponSelect"
width="80%"
>
<couponTemplate
:checked="true"
:selectedList="selectCouponList"
getType="ACTIVITY"
promotionStatus="START"
@selected="selectedCoupon"
/>
</Modal>
<Modal width="1200" v-model="checkUserList">
<userList
v-if="checkUserList"
@callback="callbackSelectUser"
:selectedList="selectedMember"
ref="memberLayout"
/>
</Modal>
</div>
</template>
<script>
import couponTemplate from "@/views/promotions/coupon/coupon";
import userList from "@/views/member/list/index";
import { saveActivityCoupon } from "@/api/promotion";
import { promotionsScopeTypeRender } from "@/utils/promotions";
export default {
name: "add-coupon-activity",
components: {
couponTemplate,
userList,
},
data() {
return {
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
showCouponSelect: false, //显示优惠券选择框
rangeTime: "", //时间区间
checkUserList: false, //会员选择器
selectedMember: [], //选择的会员
form: {
promotionName: "", //活动名称
activityScope: "ALL", //活动范围 ,默认全体发券
couponActivityType: "REGISTERED", //触发活动方式 默认新人赠券
startTime: "", //开始时间
endTime: "", //结束时间
memberDTOS: [], //指定会员范围
couponActivityItems: [], //优惠券列表
},
submitLoading: false, // 添加或编辑提交状态
selectCouponList: [], //选择的优惠券列表
formRule: {
promotionName: [{ required: true, message: "活动名称不能为空" }],
rangeTime: [{ required: true, message: "请选择活动有效期" }],
description: [{ required: true, message: "请输入范围描述" }],
},
// 用户表格
userColumns: [
{
title: "用户名称",
key: "nickName",
minWidth: 120,
},
{
title: "手机号",
key: "mobile",
render: (h, params) => {
return h("div", params.row.mobile || "暂未填写");
},
},
{
title: "最后登录时间",
key: "lastLoginDate",
},
{
title: "操作",
key: "action",
minWidth: 50,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
size: "small",
type: "error",
ghost: true,
},
on: {
click: () => {
this.delUser(params.index);
},
},
},
"删除"
);
},
},
],
//优惠券表格
columns: [
{
title: "优惠券名称",
key: "couponName",
minWidth: 120,
},
{
title: "品类描述",
key: "scopeType",
width: 120,
render: (h, params) => {
return promotionsScopeTypeRender(h, params);
},
},
{
title: "面额/折扣",
key: "couponName",
minWidth: 120,
render: (h, params) => {
if (params.row.price) {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
} else {
return h("div", params.row.couponDiscount + "折");
}
},
},
{
title: "赠送数量",
type: "template",
slot: "sendNum",
minWidth: 120,
},
{
title: "操作",
key: "action",
minWidth: 50,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
size: "small",
type: "error",
ghost: true,
},
on: {
click: () => {
this.delCoupon(params.index);
},
},
},
"删除"
);
},
},
],
};
},
methods: {
// 返回已选择的用户
callbackSelectUser(val) {
// 每次将返回的数据回调判断
let findUser = this.selectedMember.find((item) => {
return item.id === val.id;
});
// 如果没有则添加
if (!findUser) {
this.selectedMember.push(val);
} else {
// 有重复数据就删除
this.selectedMember.map((item, index) => {
if (item.id === findUser.id) {
this.selectedMember.splice(index, 1);
}
});
}
this.reSelectMember();
},
// 删除选择的会员
delUser(index) {
this.selectedMember.splice(index, 1);
this.reSelectMember();
},
//更新选择的会员
reSelectMember() {
this.form.memberDTOS = this.selectedMember.map((item) => {
return {
nickName: item.nickName,
id: item.id,
};
});
},
/**
* 返回优惠券*/
selectedCoupon(val) {
this.selectCouponList = val;
this.reSelectCoupon();
},
// 删除选择的优惠券
delCoupon(index) {
this.selectCouponList.splice(index, 1);
this.reSelectCoupon();
},
reSelectCoupon() {
// 清空原有数据
this.form.couponActivityItems = this.selectCouponList.map((item) => {
return {
num: 0,
couponId: item.id,
};
});
},
// 添加指定用户
addVip() {
this.checkUserList = true;
this.$nextTick(() => {
this.$refs.memberLayout.selectedMember = true;
});
},
//显示优惠券选择框
showSelector() {
this.showCouponSelect = true;
},
/** 保存平台优惠券 */
handleSubmit() {
this.form.startTime = this.$options.filters.unixToDate(this.rangeTime[0] / 1000);
this.form.endTime = this.$options.filters.unixToDate(this.rangeTime[1] / 1000);
this.$refs.form.validate((valid) => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.form));
this.submitLoading = true;
// 添加 避免编辑后传入id等数据 记得删除
delete params.id;
saveActivityCoupon(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("优惠券活动创建成功");
this.closeCurrentPage();
}
});
}
});
},
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "add-platform-coupon");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
},
};
</script>
<style lang="scss" scpoed>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
.effectiveDays {
font-size: 12px;
color: #999;
> * {
margin: 0 4px;
}
}
</style>

View File

@@ -0,0 +1,233 @@
<template>
<div class="search">
<Card>
<Row class="operation padding-row">
<Button @click="add" type="primary">添加活动</Button>
</Row>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
sortable="custom"
>
<template slot-scope="{ row }" slot="action">
<Button type="info" size="small" style="margin-right: 10px" @click="info(row)">
查看
</Button>
<Button
v-if="
(!checked && row.promotionStatus === 'START') ||
row.promotionStatus === 'NEW'
"
type="error"
size="small"
style="margin-right: 10px"
@click="remove(row)"
>关闭
</Button>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getCouponActivityList, closeActivity } from "@/api/promotion";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
name: "coupon-activity",
components: {},
data() {
return {
loading: true, // 表单加载状态
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalTitle: "", // 添加或编辑标题
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
},
form: {
// 添加或编辑表单对象初始化数据
promotionName: "",
},
// 表单验证规则
formValidate: {
promotionName: [{ required: true, message: "不能为空", trigger: "blur" }],
},
submitLoading: false, // 添加或编辑提交状态
selectList: [], // 多选数据
selectCount: 0, // 多选计数
columns: [
// 表头
{
title: "活动名称",
key: "promotionName",
minWidth: 120,
},
{
title: "活动类型",
key: "couponActivityType",
minWidth: 120,
render: (h, params) => {
if (params.row.couponActivityType === "REGISTERED") {
return h("div", ["注册赠券"]);
} else {
return h("div", ["精确发券"]);
}
},
},
{
title: "活动范围",
key: "activityScope",
minWidth: 120,
render: (h, params) => {
let text = "未知";
if (params.row.activityScope === "DESIGNATED") {
text = "指定会员";
} else {
text = "全部会员";
}
return h("div", [text]);
},
},
{
title: "活动时间",
minWidth: 150,
render: (h, params) => {
if (params.row.startTime && params.row.endTime) {
return h("div", {
domProps: {
innerHTML: params.row.startTime + "<br/>" + params.row.endTime,
},
});
}
},
},
{
title: "状态",
minWidth: 80,
key: "promotionStatus",
fixed: "right",
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
{
title: "操作",
slot: "action",
align: "center",
fixed: "right",
minWidth: 100,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
};
},
props: {
// 是否为选中模式
checked: {
type: Boolean,
default: false,
},
},
methods: {
//获取数据 初始化
init() {
this.getDataList();
},
//增加券活动
add() {
this.$router.push({ name: "add-coupon-activity" });
},
//查看详情
info(v) {
this.$router.push({ name: "coupon-activity-info", query: { id: v.id } });
},
// 分页 修改页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 修改页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
//搜索活动
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
//数据获取
getDataList() {
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
getCouponActivityList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
this.loading = false;
},
//跳转编辑
edit(v) {
this.$router.push({ name: "edit-platform-coupon", query: { id: v.id } });
},
//停止活动
remove(v) {
this.$Modal.confirm({
title: "确认关闭",
content: "确认要关闭此优惠券活动么?关闭活动只能重新创建",
loading: true,
onOk: () => {
// 删除
closeActivity(v.id)
.then((res) => {
if (res.success) {
this.$Message.success("优惠券活动已关闭");
this.getDataList();
this.$Modal.remove();
}
})
.catch(() => {});
},
});
},
},
mounted() {
this.init();
},
};
</script>

View File

@@ -0,0 +1,672 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<h4>基本信息</h4>
<div class="form-item-view">
<FormItem label="活动名称" prop="promotionName">
<Input
:disabled="disabled"
type="text"
v-model="form.promotionName"
placeholder="活动名称"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="优惠券名称" prop="couponName">
<Input
:disabled="disabled"
type="text"
v-model="form.couponName"
placeholder="优惠券名称"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="优惠券类型" prop="couponType">
<Select :disabled="disabled" v-model="form.couponType" style="width: 260px">
<Option value="DISCOUNT">打折</Option>
<Option value="PRICE">减免现金</Option>
</Select>
</FormItem>
<FormItem
label="折扣"
prop="couponDiscount"
v-if="form.couponType == 'DISCOUNT'"
>
<Input
:disabled="disabled"
type="number"
v-model="form.couponDiscount"
placeholder="折扣"
clearable
style="width: 260px"
/>
<span class="describe">请输入0-10之间数字可以输入一位小数</span>
</FormItem>
<FormItem label="面额" prop="price" v-if="form.couponType == 'PRICE'">
<Input
:disabled="disabled"
type="text"
v-model="form.price"
placeholder="面额"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动类型" prop="getType">
<Select :disabled="disabled" v-model="form.getType" style="width: 260px">
<Option value="FREE">免费领取</Option>
<Option value="ACTIVITY">活动赠送</Option>
</Select>
</FormItem>
<FormItem label="店铺承担比例" prop="storeCommission">
<Input
:disabled="disabled"
v-model="form.storeCommission"
placeholder="店铺承担比例"
style="width: 260px"
>
<span slot="append">%</span>
</Input>
<span class="describe">店铺承担比例输入0-100之间数值</span>
</FormItem>
<FormItem label="发放数量" prop="publishNum" v-if="form.getType === 'FREE'">
<Input
:disabled="disabled"
v-model="form.publishNum"
placeholder="发放数量"
style="width: 260px"
/>
<div class="tips">如果发放数量为0时,则代表不限制发放数量</div>
</FormItem>
<FormItem
label="领取数量限制"
prop="couponLimitNum"
v-if="form.getType === 'FREE'"
>
<Input
:disabled="disabled"
v-model="form.couponLimitNum"
placeholder="领取限制"
clearable
style="width: 260px"
/>
<div class="tips">如果领取数量为0时,则代表不限制领取数量</div>
</FormItem>
<FormItem label="范围描述" prop="description">
<Input
:disabled="disabled"
v-model="form.description"
type="textarea"
:rows="4"
maxlength="50"
show-word-limit
clearable
style="width: 260px"
/>
</FormItem>
</div>
<h4>使用限制</h4>
<div class="form-item-view">
<FormItem label="消费门槛" prop="consumeThreshold">
<Input
:disabled="disabled"
type="text"
v-model="form.consumeThreshold"
placeholder="消费门槛"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="有效期" prop="rangeTime">
<div v-if="form.getType == 'ACTIVITY'">
<RadioGroup v-model="rangeTimeType">
<Radio :disabled="disabled" :label="1">起止时间</Radio>
<Radio :disabled="disabled" :label="0">固定时间</Radio>
</RadioGroup>
</div>
<div v-if="rangeTimeType == 1">
<DatePicker
:disabled="disabled"
type="datetimerange"
v-model="form.rangeTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
:options="options"
style="width: 260px"
>
</DatePicker>
</div>
<div class="effectiveDays" v-if="rangeTimeType == 0">
领取当天开始
<InputNumber
v-model="form.effectiveDays"
:min="1"
style="width: 100px"
:max="365"
/>
天内有效(1-365间的整数)
</div>
</FormItem>
<FormItem label="使用范围" prop="scopeType">
<RadioGroup type="button" button-style="solid" v-model="form.scopeType">
<Radio :disabled="disabled" label="ALL">全品类</Radio>
<Radio :disabled="disabled" label="PORTION_GOODS">指定商品</Radio>
<Radio :disabled="disabled" label="PORTION_GOODS_CATEGORY"
>部分商品分类</Radio
>
</RadioGroup>
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<div style="display: flex; margin-bottom: 10px">
<Button :disabled="disabled" type="primary" @click="openSkuList"
>选择商品</Button
>
<Button
:disabled="disabled"
type="error"
ghost
style="margin-left: 10px"
@click="delSelectGoods"
>批量删除</Button
>
</div>
<Table
border
:columns="columns"
:data="form.promotionGoodsList"
@on-selection-change="changeSelect"
>
<template slot-scope="{ row }" slot="QRCode">
<img
:src="row.QRCode || '../../../assets/lili.png'"
width="50px"
height="50px"
alt=""
/>
</template>
</Table>
</FormItem>
<FormItem v-if="form.scopeType == 'PORTION_GOODS_CATEGORY'">
<Cascader
:disabled="disabled"
:data="goodsCategoryList"
style="width: 260px"
v-model="form.scopeIdGoods"
></Cascader>
</FormItem>
<div>
<Button :disabled="disabled" type="text" @click="closeCurrentPage"
>返回</Button
>
<Button
:disabled="disabled"
type="primary"
:loading="submitLoading"
@click="handleSubmit"
>提交</Button
>
</div>
</div>
</div>
</Form>
</Card>
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
</div>
</template>
<script>
import {
savePlatformCoupon,
getPlatformCoupon,
editPlatformCoupon,
} from "@/api/promotion";
import { getCategoryTree } from "@/api/goods";
import { regular } from "@/utils";
import skuSelect from "@/views/lili-dialog";
export default {
name: "edit-platform-coupon",
components: {
skuSelect,
},
watch: {
"form.getType": {
handler(val) {
if (val == "FREE") {
this.rangeTimeType = 1;
}
},
deep: true,
},
$route(e) {
// 监听路由,参数变化调取接口
this.id = e.query.id;
if (this.id) {
this.getCoupon();
} else {
this.$refs.form.resetFields();
}
},
},
data() {
const checkPrice = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("面额不能为空"));
} else if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("面额设置超过上限值"));
} else {
callback();
}
};
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();
}
};
return {
disabled: this.$route.query.onlyView,
rangeTimeType: 1, // 当前时间类型
modalType: 0, // 是否编辑
form: {
/** 店铺承担比例 */
storeCommission: 0,
/** 发行数量 */
publishNum: 0,
/** 运费承担者 */
scopeType: "ALL",
/** 限领数量 */
couponLimitNum: 1,
/** 活动类型 */
couponType: "PRICE",
/** 优惠券名称 */
couponName: "",
promotionName: "",
getType: "FREE",
promotionGoodsList: [],
scopeIdGoods: [],
rangeDayType: "",
},
id: this.$route.query.id, // 优惠券id
submitLoading: false, // 添加或编辑提交状态
selectedGoods: [], // 已选商品列表,便于删除
goodsCategoryList: [], // 商品分类列表
formRule: {
promotionName: [{ required: true, message: "活动名称不能为空" }],
couponName: [{ required: true, message: "优惠券名称不能为空" }],
price: [{ required: true, message: "请输入面额" }, { validator: checkPrice }],
rangeTime: [{ required: true, message: "请选择优惠券有效期" }],
consumeThreshold: [
{ required: true, message: "请输入消费门槛" },
{ validator: checkWeight },
],
couponDiscount: [
{ required: true, message: "请输入折扣" },
{
pattern: regular.discount,
message: "请输入0-10的数字,可有一位小数",
},
],
storeCommission: [
{ required: true, message: "请输入店铺承担比例" },
{ pattern: regular.rate, message: "请输入0-100的正整数" },
],
publishNum: [
{ required: true, message: "请输入发放数量" },
{ pattern: regular.Integer, message: "请输入正整数" },
],
couponLimitNum: [
{ required: true, message: "领取限制不能为空" },
{ pattern: regular.Integer, message: "请输入正整数" },
],
description: [{ required: true, message: "请输入范围描述" }],
},
columns: [
{
type: "selection",
width: 60,
align: "center",
},
{
title: "商品名称",
key: "goodsName",
minWidth: 120,
},
{
title: "商品价格",
key: "price",
minWidth: 40,
render: (h, params) => {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
},
},
{
title: "库存",
key: "quantity",
minWidth: 40,
},
{
title: "操作",
key: "action",
minWidth: 50,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
size: "small",
type: "error",
ghost: true,
},
on: {
click: () => {
this.delGoods(params.index);
},
},
},
"删除"
);
},
},
],
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
};
},
async mounted() {
await this.getCagetoryList();
// 如果id不为空则查询信息
if (this.id) {
this.getCoupon();
this.modalType = 1;
}
},
methods: {
// 获取优惠券数据
getCoupon() {
getPlatformCoupon(this.id).then((res) => {
let data = res.result;
if (!data.promotionGoodsList) data.promotionGoodsList = [];
this.rangeTimeType = data.rangeDayType === "DYNAMICTIME" ? 0 : 1;
if (data.scopeType == "PORTION_GOODS_CATEGORY") {
let prevCascader = data.scopeId.split(",");
function next(params, prev) {
for (let i = 0; i < params.length; i++) {
const item = params[i];
if (item.children) {
next(item.children, [...prev, item]);
} else {
if (prevCascader.includes(item.id)) {
prevCascader = prevCascader.map((key) => {
if (key === item.id) {
let result = prev.map((item) => item.id);
return [...result, item.id];
} else {
return key;
}
});
} else {
i === params.length - 1 && (prev = []);
}
}
}
}
next(this.goodsCategoryList, []);
data.scopeIdGoods = prevCascader;
}
data.rangeTime = [];
if (data.startTime && data.endTime) {
data.rangeTime.push(new Date(data.startTime), new Date(data.endTime));
}
this.form = data;
});
},
/** 保存平台优惠券 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.form));
// 判断当前活动类型
params.getType != "ACTIVITY" ? delete params.effectiveDays : "";
//判断当前时间类型
if (this.rangeTimeType == 1) {
params.rangeDayType = "FIXEDTIME";
params.startTime = this.$options.filters.unixToDate(
this.form.rangeTime[0] / 1000
);
params.endTime = this.$options.filters.unixToDate(
this.form.rangeTime[1] / 1000
);
delete params.effectiveDays;
} else {
params.rangeDayType = "DYNAMICTIME";
delete params.rangeTime;
}
let scopeId = [];
if (
params.scopeType == "PORTION_GOODS" &&
(!params.promotionGoodsList || params.promotionGoodsList.length == 0)
) {
this.$Modal.warning({ title: "提示", content: "请选择指定商品" });
return;
}
if (
params.scopeType == "PORTION_GOODS_CATEGORY" &&
(!params.scopeIdGoods || params.scopeIdGoods.length == 0)
) {
this.$Modal.warning({ title: "提示", content: "请选择商品分类" });
return;
}
if (params.scopeType == "PORTION_GOODS") {
//指定商品
params.promotionGoodsList.forEach((item) => {
scopeId.push(item.skuId);
});
params.scopeId = scopeId.toString();
} else if (params.scopeType == "ALL") {
delete params.promotionGoodsList;
} else if (params.scopeType == "PORTION_GOODS_CATEGORY") {
//部分商品分类
scopeId = this.filterCategoryId(params.scopeIdGoods, []);
params.scopeId = scopeId.toString();
delete params.promotionGoodsList;
}
delete params.scopeIdGoods;
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete params.id;
savePlatformCoupon(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("优惠券发送成功");
this.closeCurrentPage();
}
});
} else {
// 编辑
delete params.consumeLimit;
delete params.updateTime;
editPlatformCoupon(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("优惠券修改成功");
this.closeCurrentPage();
}
});
}
}
});
},
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "add-platform-coupon");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
openSkuList() {
// 显示商品选择器
this.$refs.skuSelect.open("goods");
let data = JSON.parse(JSON.stringify(this.form.promotionGoodsList));
data.forEach((e) => {
e.id = e.skuId;
});
this.$refs.skuSelect.goodsData = data;
},
changeSelect(e) {
// 已选商品批量选择
this.selectedGoods = e;
},
delSelectGoods() {
// 多选删除商品
if (this.selectedGoods.length <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选商品吗?",
onOk: () => {
let ids = [];
this.selectedGoods.forEach(function (e) {
ids.push(e.id);
});
this.form.promotionGoodsList = this.form.promotionGoodsList.filter((item) => {
return !ids.includes(item.id);
});
},
});
},
delGoods(index) {
// 删除商品
this.form.promotionGoodsList.splice(index, 1);
},
selectedGoodsData(item) {
// 回显已选商品
let list = [];
item.forEach((e) => {
list.push({
goodsName: e.goodsName,
price: e.price,
originalPrice: e.price,
quantity: e.quantity,
storeId: e.storeId,
storeName: e.storeName,
skuId: e.id,
categoryPath: e.categoryPath,
thumbnail: e.small,
goodsType: e.goodsType,
goodsId: e.goodsId,
originPrice: e.price,
});
});
this.form.promotionGoodsList = list;
},
async getCagetoryList() {
// 获取全部商品分类
let data = await getCategoryTree();
this.goodsCategoryList = data.result;
// 过滤出可显示的值
this.goodsCategoryList = this.goodsCategoryList.map((item) => {
if (item.children) {
item.children = item.children.map((child) => {
if (child.children) {
child.children = child.children.map((son) => {
return {
value: son.id,
label: son.name,
};
});
return {
value: child.id,
label: child.name,
children: child.children,
};
} else {
return {
value: child.id,
label: child.name,
};
}
});
}
return { value: item.id, label: item.name, children: item.children };
});
},
filterCategoryId(list, idArr) {
// 递归获取分类id
list.forEach((e) => {
if (e instanceof Array) {
this.filterCategoryId(e, idArr);
} else {
if (!idArr.includes(e)) idArr.push(e);
}
});
return idArr;
},
},
};
</script>
<style lang="scss" scpoed>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
.effectiveDays {
font-size: 12px;
color: #999;
> * {
margin: 0 4px;
}
}
.tips {
font-size: 12px;
color: #999;
}
</style>

View File

@@ -0,0 +1,460 @@
<template>
<div class="search">
<Card>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form mb_10"
>
<Form-item label="活动名称" prop="couponName">
<Input
type="text"
v-model="searchForm.couponName"
placeholder="请输入活动名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 200px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 200px"
></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn"
>搜索</Button
>
</Form>
<Row class="operation padding-row" v-if="getType !== 'ACTIVITY'">
<Button @click="add" type="primary">添加优惠券</Button>
<Button @click="delAll">批量关闭</Button>
</Row>
<Table
v-if="refreshTable"
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
@on-selection-change="changeSelect"
>
<template slot-scope="{ row }" slot="action">
<Button
v-if="row.promotionStatus !== 'START'"
type="info"
size="small"
@click="see(row)"
>编辑
</Button>
<Button v-else type="default" size="small" @click="see(row, 'onlyView')"
>查看
</Button>
<Button
class="ml_5"
v-if="row.promotionStatus === 'START' || row.promotionStatus === 'NEW'"
type="error"
size="small"
@click="close(row)"
>关闭
</Button>
<Button
class="ml_5"
v-if="row.promotionStatus === 'CLOSE'"
type="error"
size="small"
@click="remove(row)"
>删除
</Button>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import {
getPlatformCouponList,
updatePlatformCouponStatus,
deletePlatformCoupon,
} from "@/api/promotion";
import { promotionsStatusRender, promotionsScopeTypeRender } from "@/utils/promotions";
export default {
name: "coupon",
data() {
return {
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
getType: "", // 默认排序方式
},
selectList: [], // 多选数据
selectCount: 0, // 多选计数
columns: [
// 表头
{
type: "selection",
width: 60,
align: "center",
fixed: "left",
},
{
title: "活动名称",
key: "promotionName",
minWidth: 100,
fixed: "left",
},
{
title: "优惠券名称",
key: "couponName",
minWidth: 100,
tooltip: true,
},
{
title: "面额/折扣",
key: "price",
width: 100,
render: (h, params) => {
if (params.row.price) {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
} else {
return h("div", params.row.couponDiscount + "折");
}
},
},
{
title: "已领取数量/总数量",
key: "publishNum",
width: 130,
render: (h, params) => {
return h(
"div",
params.row.receivedNum +
"/" +
(params.row.publishNum === 0 ? "不限制" : params.row.publishNum)
);
},
},
{
title: "优惠券类型",
key: "couponType",
width: 120,
render: (h, params) => {
let text = "";
if (params.row.couponType === "DISCOUNT") {
return h("Tag", { props: { color: "blue" } }, "打折");
} else if (params.row.couponType === "PRICE") {
return h("Tag", { props: { color: "geekblue" } }, "减免现金");
} else {
return h("Tag", { props: { color: "purple" } }, "未知");
}
},
},
{
title: "品类描述",
key: "scopeType",
width: 120,
render: (h, params) => {
return promotionsScopeTypeRender(h, params);
},
},
{
title: "活动时间",
width: 150,
render: (h, params) => {
if (
params?.row?.getType === "ACTIVITY" &&
params?.row?.rangeDayType === "DYNAMICTIME"
) {
return h("div", "长期有效");
} else if (params?.row?.startTime && params?.row?.endTime) {
return h("div", {
domProps: {
innerHTML: params.row.startTime + "<br/>" + params.row.endTime,
},
});
}
},
},
{
title: "状态",
width: 100,
key: "promotionStatus",
fixed: "right",
render: (h, params) => {
return promotionsStatusRender(h, params);
},
minWidth: 70,
},
{
title: "操作",
slot: "action",
align: "center",
fixed: "right",
width: 130,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
refreshTable: true, // 修改选中状态后刷新表格
selectDate: [], //选中的信息
};
},
props: {
//优惠券类型 查询参数
getType: {
type: String,
default: "",
},
promotionStatus: {
type: String,
default: "",
},
//已选择优惠券
selectedList: {
type: Array,
default: () => {
return [];
},
},
},
watch: {
$route(to, from) {
if (to.fullPath == "/promotions/manager-coupon") {
this.init();
}
},
// 选中优惠券 父级传值
selectedList: {
handler(val) {
// 判断是否是父级回调给自己已选择优惠券
if (val.length) {
this.selectList = val;
this.data.forEach((item) => {
item._checked = false;
if (this.selectList.length) {
this.selectList.forEach((child) => {
if (item.id == child.id) {
item._checked = true;
}
});
}
});
} else {
this.data.forEach((item) => {
item._checked = false;
});
}
this.refreshTable = false;
this.$nextTick(() => {
this.refreshTable = true;
});
},
deep: true,
},
},
methods: {
check() {
// 选中的优惠券
this.$emit("selected", this.selectList);
},
// 初始化数据
init() {
this.getDataList();
},
add() {
// 跳转添加页面
this.$router.push({ name: "add-platform-coupon" });
},
info(v) {
// 查看优惠券
this.$router.push({ name: "platform-coupon-info", query: { id: v.id } });
},
changePage(v) {
// 改变页码
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
// 改变页数
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
clearSelectAll() {
// 清除选中状态
this.$refs.table.selectAll(false);
},
/**
* 选择优惠券
*/
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
if (this.getType === "ACTIVITY") this.check();
},
getDataList() {
// 获取数据
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
getPlatformCouponList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
this.total = this.data.length;
this.loading = false;
},
see(v, only) {
// 跳转编辑页面
let data;
only ? (data = { onlyView: true, id: v.id }) : (data = { id: v.id });
this.$router.push({ name: "edit-platform-coupon", query: data });
},
close(v) {
// 下架优惠券
this.$Modal.confirm({
title: "确认关闭",
// 记得确认修改此处
content: "确认要关闭此优惠券么?",
loading: true,
onOk: () => {
// 删除
updatePlatformCouponStatus({
couponIds: v.id,
effectiveDays: 0,
})
.then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("优惠券已关闭");
this.getDataList();
}
})
.catch(() => {
this.$Modal;
});
},
});
},
remove(v) {
// 下架优惠券
this.$Modal.confirm({
title: "确认删除",
// 记得确认修改此处
content: "确认要删除此优惠券么?",
loading: true,
onOk: () => {
// 删除
deletePlatformCoupon(v.id)
.then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("优惠券已删除");
this.getDataList();
}
})
.catch(() => {
this.$Modal;
});
},
});
},
delAll() {
// 批量下架
if (this.selectCount <= 0) {
this.$Message.warning("您还未选择要下架的优惠券");
return;
}
this.$Modal.confirm({
title: "确认下架",
content: "您确认要下架所选的 " + this.selectCount + " 条数据?",
loading: true,
onOk: () => {
let ids = [];
this.selectList.forEach(function (e) {
ids.push(e.id);
});
let params = {
couponIds: ids.toString(),
promotionStatus: "CLOSE",
};
// 批量删除
updatePlatformCouponStatus(params).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("下架成功");
this.clearSelectAll();
this.getDataList();
}
});
},
});
},
},
mounted() {
//如果作为组件方式,传入了类型值,则搜索参数附加类型
if (this.getType) {
this.searchForm.getType = this.getType;
this.columns.pop();
}
if (this.promotionStatus) {
this.searchForm.promotionStatus = this.promotionStatus;
this.columns.pop();
}
this.init();
},
};
</script>

View File

@@ -0,0 +1,310 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120">
<div class="base-info-item">
<h4>基本信息</h4>
<div class="form-item-view">
<FormItem label="活动名称" prop="promotionName">
<Input
type="text"
v-model="form.promotionName"
disabled
placeholder="活动名称"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动时间" prop="rangeTime">
<DatePicker
type="datetimerange"
v-model="form.rangeTime"
disabled
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
:options="options"
style="width: 320px"
>
</DatePicker>
</FormItem>
<FormItem label="活动描述" prop="description">
<Input
v-model="form.description"
disabled
type="textarea"
:rows="4"
clearable
style="width: 260px"
/>
</FormItem>
</div>
<h4>优惠设置</h4>
<div class="form-item-view">
<FormItem label="优惠门槛" prop="fullMoney">
<Input
type="text"
v-model="form.fullMoney"
disabled
placeholder="优惠门槛"
clearable
style="width: 260px"
/>
<span class="describe">消费达到当前金额可以参与优惠</span>
</FormItem>
<FormItem label="优惠方式">
<RadioGroup type="button" button-style="solid" v-model="form.discountType">
<Radio label="isFullMinus" disabled>减现金</Radio>
<Radio label="isFullRate" disabled>打折</Radio>
</RadioGroup>
</FormItem>
<FormItem
v-if="form.discountType == 'isFullMinus'"
label="优惠金额"
prop="fullMinus"
>
<Input
type="text"
disabled
v-model="form.fullMinus"
placeholder="优惠金额"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem
v-if="form.discountType == 'isFullRate'"
label="优惠折扣"
prop="fullRate"
>
<Input
type="text"
v-model="form.fullRate"
placeholder="优惠折扣"
disabled
clearable
style="width: 260px"
/>
<span class="describe">优惠折扣为0-10之间数字可有一位小数</span>
</FormItem>
<FormItem label="额外赠送">
<Checkbox v-model="form.isFreeFreight" disabled>免邮费</Checkbox>&nbsp;
<Checkbox v-model="form.isCoupon" disabled>送优惠券</Checkbox>&nbsp;
<Checkbox v-model="form.isGift" disabled>送赠品</Checkbox>&nbsp;
<Checkbox v-model="form.isPoint" disabled>送积分</Checkbox>
</FormItem>
<FormItem v-if="form.isCoupon" label="赠送优惠券" prop="couponId">
<Select
v-model="form.couponId"
filterable
:remote-method="getCouponList"
placeholder="输入优惠券名称搜索"
disabled
:loading="couponLoading"
style="width: 260px"
>
<Option v-for="item in couponList" :value="item.id" :key="item.id">{{
item.couponName
}}</Option>
</Select>
</FormItem>
<FormItem v-if="form.isGift" label="赠品" prop="giftId">
<Select
v-model="form.giftId"
filterable
:remote-method="getGiftList"
placeholder="输入赠品名称搜索"
disabled
:loading="giftLoading"
style="width: 260px"
>
<Option v-for="item in giftList" :value="item.id" :key="item.id">{{
item.goodsName
}}</Option>
</Select>
</FormItem>
<FormItem v-if="form.isPoint" label="赠积分" prop="point">
<Input v-model="form.point" type="number" disabled style="width: 260px" />
</FormItem>
<FormItem label="使用范围" prop="scopeType">
<RadioGroup type="button" button-style="solid" v-model="form.scopeType">
<Radio label="ALL" disabled>全品类</Radio>
<Radio label="PORTION_GOODS" disabled>指定商品</Radio>
</RadioGroup>
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<Table border :columns="columns" :data="form.promotionGoodsList">
<template slot-scope="{ row }" slot="goodsName">
<div>
<a class="mr_10" @click="linkTo(row.goodsId, row.skuId)">{{
row.goodsName
}}</a>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<vue-qr
:text="wapLinkTo(row.goodsId, row.skuId)"
:margin="0"
colorDark="#000"
colorLight="#fff"
:size="150"
></vue-qr>
</div>
<img
src="../../../assets/qrcode.svg"
style="vertical-align: middle"
class="hover-pointer"
width="20"
height="20"
alt=""
/>
</Poptip>
</div>
</template>
</Table>
</FormItem>
<div>
<Button @click="$router.push({ name: 'fullCut' })">返回</Button>
</div>
</div>
</div>
</Form>
</Card>
</div>
</template>
<script>
import { getPlatformCouponList, getFullDiscountById } from "@/api/promotion";
import { getGoodsSkuData } from "@/api/goods";
import vueQr from "vue-qr";
export default {
name: "add-full-discount",
components: {
"vue-qr": vueQr,
},
data() {
return {
form: {
// 表单
discountType: "isFullMinus",
scopeType: "ALL",
promotionGoodsList: [],
},
id: this.$route.query.id, // 活动id
couponList: [], // 优惠券列表
giftList: [], // 赠品列表
giftLoading: false, // 赠品加载状态
columns: [
{
type: "selection",
width: 60,
align: "center",
},
{
title: "商品名称",
slot: "goodsName",
minWidth: 120,
},
{
title: "商品价格",
key: "price",
minWidth: 40,
render: (h, params) => {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
},
},
{
title: "库存",
key: "quantity",
minWidth: 40,
},
],
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
};
},
async mounted() {
if (this.id) {
this.getDetail();
}
this.getCouponList();
this.getGiftList();
},
methods: {
getDetail() {
// 获取活动详情
getFullDiscountById(this.id).then((res) => {
let data = res.result;
if (!data.scopeType === "ALL") {
data.promotionGoodsList = [];
}
if (data.isFullMinus) {
data.discountType = "isFullMinus";
delete data.isFullMinus;
} else {
data.discountType = "isFullMinus";
delete data.isFullRate;
}
data.rangeTime = [];
data.rangeTime.push(new Date(data.startTime), new Date(data.endTime));
this.form = data;
});
},
getCouponList(query) {
// 优惠券列表
let params = {
pageSize: 10,
pageNumber: 0,
couponName: query,
promotionStatus: "START",
};
this.couponLoading = true;
getPlatformCouponList(params).then((res) => {
this.couponLoading = false;
if (res.success) {
this.couponList = res.result.records;
}
});
},
getGiftList(query) {
// 赠品列表
let params = {
pageSize: 10,
pageNumber: 1,
goodsName: query,
};
this.giftLoading = true;
getGoodsSkuData(params).then((res) => {
this.giftLoading = false;
if (res.success) {
this.giftList = res.result.records;
}
});
},
},
};
</script>
<style lang="scss" scoped>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
</style>

View File

@@ -0,0 +1,246 @@
<template>
<div class="full-cut">
<Card>
<Row>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="活动名称" prop="promotionName">
<Input
type="text"
v-model="searchForm.promotionName"
placeholder="请输入活动名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 200px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 200px"
>
</DatePicker>
</Form-item>
<Button
@click="handleSearch"
type="primary"
class="search-btn"
icon="ios-search"
>搜索</Button
>
</Form>
</Row>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
sortable="custom"
>
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
</template>
<template slot-scope="{ row }" slot="promotionType">
{{ row.isFullMinus ? "满减" : "满折" }}
</template>
<template slot-scope="{ row }" slot="hours">
<Tag v-for="item in unixHours(row.hours)" :key="item">{{ item }}</Tag>
</template>
<template slot-scope="{ row }" slot="action">
<div>
<Button type="info" size="small" @click="view(row)">查看</Button>
<Button
type="error"
v-if="row.promotionStatus === 'START'"
style="margin-left: 5px"
size="small"
@click="openOrClose(row)"
>关闭</Button
>
<Button
type="success"
v-if="row.promotionStatus === 'CLOSE' || row.promotionStatus === 'NEW'"
style="margin-left: 5px"
size="small"
@click="openOrClose(row)"
>开启</Button
>
</div>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getFullDiscountList, updateFullDiscount } from "@/api/promotion.js";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
data() {
return {
selectDate: [],
total: 0,
loading: false, // 表单加载状态
searchForm: {
// 请求参数
pageNumber: 1,
pageSize: 10,
sort: "startTime",
order: "desc",
},
columns: [
// 表头
{
title: "活动名称",
key: "promotionName",
minWidth: 120,
},
{
title: "开始时间",
key: "startTime",
width: 170,
},
{
title: "结束时间",
key: "endTime",
width: 170,
},
{
title: "店铺名称",
key: "storeName",
minWidth: 60,
},
{
title: "活动类型",
slot: "promotionType",
minWidth: 60,
},
{
title: "活动状态",
key: "promotionStatus",
minWidth: 60,
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
{
title: "操作",
slot: "action",
align: "center",
width: 140,
},
],
data: [], // 列表数据
};
},
methods: {
// 初始化数据
init() {
this.getDataList();
},
// 开启或关闭活动
openOrClose(row) {
let name = "开启";
let status = "START";
if (row.promotionStatus === "START") {
name = "关闭";
status = "CLOSE";
}
this.$Modal.confirm({
title: "提示",
// 记得确认修改此处
content: `确认${name}此活动吗?需要一定时间才能生效,请耐心等待`,
loading: true,
onOk: () => {
// 删除
updateFullDiscount(row.id, status).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success(`${name}成功`);
this.getDataList();
}
});
},
});
},
changePage(v) {
// 改变页数
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
// 改变页码
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
// 获取列表数据
getDataList() {
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
getFullDiscountList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
view(row) {
// 查看
this.$router.push({ name: "full-discount-detail", query: { id: row.id } });
},
},
mounted() {
this.init();
},
};
</script>

View File

@@ -0,0 +1,380 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<div class="form-item-view">
<h4>商品信息</h4>
<FormItem label="选择商品" prop="scopeType">
<Button type="primary" @click="openSkuList">选择商品</Button>
<!-- <Button type="error" ghost style="margin-left: 10px" @click="delSelectGoods">批量删除
</Button> -->
</FormItem>
<FormItem astyle="width: 100%">
<Table
border
:columns="columns"
:data="form.promotionGoodsList"
@on-selection-change="changeSelect"
>
<template slot-scope="{ row }" slot="skuId">
<div>{{ row.skuId }}</div>
</template>
<template slot-scope="{ index }" slot="settlementPrice">
<InputNumber
:min="0"
v-model="form.promotionGoodsList[index].settlementPrice"
/>
</template>
<template slot-scope="{ index }" slot="lowestPrice">
<InputNumber
:min="0"
v-model="form.promotionGoodsList[index].lowestPrice"
/>
</template>
<template slot-scope="{ index }" slot="highestPrice">
<InputNumber
:min="0"
v-model="form.promotionGoodsList[index].highestPrice"
/>
</template>
<template slot-scope="{ index }" slot="stock">
<InputNumber :min="0" v-model="form.promotionGoodsList[index].stock" />
</template>
</Table>
</FormItem>
<FormItem label="活动时间" prop="rangeTime">
<DatePicker
type="datetimerange"
v-model="form.rangeTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
:options="options"
style="width: 260px"
>
</DatePicker>
</FormItem>
<div>
<Button type="text" @click="closeCurrentPage">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
>提交</Button
>
</div>
</div>
</div>
</Form>
</Card>
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
</div>
</template>
<script>
import { saveKanJiaActivityGoods } from "@/api/promotion";
import { regular } from "@/utils";
import skuSelect from "@/views/lili-dialog";
export default {
name: "add-kanjia-activity-goods",
components: {
skuSelect,
},
watch: {},
data() {
return {
modalType: 0, // 是否编辑
form: {
promotionGoodsList: [], // 活动商品列表
},
id: this.$route.query.id, // 砍价活动id
submitLoading: false, // 添加或编辑提交状态
selectedGoods: [], // 已选商品列表,便于删除
promotionGoodsList: [], // 活动商品列表
formRule: {
rangeTime: [{ required: true, message: "请选择活动时间" }],
},
columns: [
{
type: "selection",
width: 60,
align: "center",
},
{
title: "商品名称",
key: "goodsName",
tooltip: true,
minWidth: 100,
},
{
title: "商品价格",
key: "price",
width: 120,
render: (h, params) => {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
},
},
{
title: "库存",
key: "quantity",
width: 100,
},
{
title: "结算价格",
slot: "settlementPrice",
width: 110,
},
{
title: "最低砍",
slot: "lowestPrice",
width: 110,
},
{
title: "最高砍",
slot: "highestPrice",
width: 110,
},
{
title: "活动库存",
slot: "stock",
width: 110,
},
{
title: "操作",
key: "action",
align: "center",
width: 100,
render: (h, params) => {
return h(
"Button",
{
props: {
size: "small",
type: "error",
ghost: true,
},
on: {
click: () => {
this.delGoods(params.index);
},
},
},
"删除"
);
},
},
],
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
};
},
async mounted() {
// 如果id不为空则查询信息
if (this.id) {
this.getCoupon();
this.modalType = 1;
}
},
methods: {
openSkuList() {
// 显示商品选择器
this.$refs.skuSelect.open("goods");
let data = JSON.parse(JSON.stringify(this.promotionGoodsList));
data.forEach((e) => {
e.id = e.skuId;
});
this.$refs.skuSelect.goodsData = data;
},
/** 保存砍价活动 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.form));
if (this.form.rangeTime[0] === "" || this.form.rangeTime[0] === "") {
this.$Message.error("请选择活动时间");
return;
}
params.startTime = this.$options.filters.unixToDate(
this.form.rangeTime[0] / 1000
);
params.endTime = this.$options.filters.unixToDate(
this.form.rangeTime[1] / 1000
);
delete params.rangeTime;
let checkResult = true;
//如果添加活动的时候选择了商品 则对选择的商品参数做一些校验
if (this.form.promotionGoodsList.length > 0) {
this.form.promotionGoodsList.forEach((res) => {
//校验库存参数
if (res.stock <= 0 || res.stock > res.quantity) {
checkResult = false;
this.$Message.error("活动库存不能为0且不能超过商品库存");
return;
}
// 结算价格金额格式校验
if (!regular.money.test(res.settlementPrice)) {
checkResult = false;
this.$Message.error("结算价格金额格式不正确");
return;
}
// 结算价格金额格式校验
if (res.settlementPrice < 0 || res.settlementPrice > res.price) {
checkResult = false;
this.$Message.error("结算价格金额不能为0且不能超过商品价格");
return;
}
//最高砍价校验
if (!regular.money.test(res.highestPrice)) {
checkResult = false;
this.$Message.error("最高可砍金额格式错误");
return;
}
if (res.highestPrice <= 0 || res.highestPrice > res.price) {
checkResult = false;
this.$Message.error("最高可砍金额不能为0且不能超过商品价格");
return;
}
//最低砍价校验
if (!regular.money.test(res.lowestPrice)) {
checkResult = false;
this.$Message.error("最低可砍金额格式错误");
return;
}
if (res.lowestPrice <= 0 || res.lowestPrice > res.price) {
checkResult = false;
this.$Message.error("最低可砍金额不能为0");
return;
}
//校验最高最低砍价金额
if (parseInt(res.lowestPrice) > parseInt(res.highestPrice)) {
checkResult = false;
this.$Message.error("最低砍价金额不能大于最高砍价金额");
return;
}
});
}
if (!checkResult) {
return;
}
this.submitLoading = true;
saveKanJiaActivityGoods(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("砍价活动修改成功");
this.closeCurrentPage();
}
});
}
});
},
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "add-kan-jia-goods");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
openSkuList() {
// 显示商品选择器
this.$refs.skuSelect.open("goods");
let data = JSON.parse(JSON.stringify(this.form.promotionGoodsList));
data.forEach((e) => {
e.id = e.skuId;
});
this.$refs.skuSelect.goodsData = data;
},
changeSelect(e) {
// 已选商品批量选择
this.selectedGoods = e;
},
// delSelectGoods() {
// // 多选删除商品
// if (this.selectedGoods.length <= 0) {
// this.$Message.warning("您还未选择要删除的数据");
// return;
// }
// this.$Modal.confirm({
// title: "确认删除",
// content: "您确认要删除所选商品吗?",
// onOk: () => {
// let ids = [];
// this.selectedGoods.forEach(function (e) {
// ids.push(e.id);
// });
// this.form.promotionGoodsList = this.form.promotionGoodsList.filter(
// (item) => {
// return !ids.includes(item.id);
// }
// );
// },
// });
// },
delGoods(index) {
// 删除商品
this.form.promotionGoodsList.splice(index, 1);
},
selectedGoodsData(item) {
// 回显已选商品
let list = [];
item.forEach((e) => {
list.push({
settlementPrice: e.settlementPrice || 0,
purchasePrice: 0,
lowestPrice: e.lowestPrice || 0,
highestPrice: e.highestPrice || 0,
stock: e.stock || 0,
goodsName: e.goodsName,
price: e.price,
originalPrice: e.price,
quantity: e.quantity,
storeId: e.storeId,
storeName: e.storeName,
skuId: e.id,
});
});
console.warn(list);
this.form.promotionGoodsList = list;
},
},
};
</script>
<style lang="scss" scpoed>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
.effectiveDays {
font-size: 12px;
color: #999;
> * {
margin: 0 4px;
}
}
.tips {
font-size: 12px;
color: #999;
}
</style>

View File

@@ -0,0 +1,313 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<div class="form-item-view">
<h4>商品信息</h4>
<FormItem label="商品名称">
<div>{{ form.goodsName }}</div>
</FormItem>
<FormItem label="SKU编码">
<div>{{ form.skuId }}</div>
</FormItem>
<FormItem label="店铺名称">
<div>{{ form.goodsSku.storeName }}</div>
</FormItem>
<FormItem label="商品价格">
<div>{{ form.goodsSku.price | unitPrice('¥') }}</div>
</FormItem>
<FormItem label="商品库存">
<div>{{ form.goodsSku.quantity }}</div>
</FormItem>
<FormItem label="结算价格" prop="settlementPrice">
<Input
:disabled="onlyView"
type="number"
v-model="form.settlementPrice"
placeholder="请填写结算价格"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="最低可砍" prop="lowestPrice">
<Input
:disabled="onlyView"
type="number"
v-model="form.lowestPrice"
placeholder="请填写最低可砍金额"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="最高可砍" prop="highestPrice">
<Input
:disabled="onlyView"
type="number"
v-model="form.highestPrice"
placeholder="请填写最高可砍金额"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动库存" prop="stock">
<Input
:disabled="onlyView"
type="number"
v-model="form.stock"
placeholder="请填写活动库存"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动时间" prop="rangeTime">
<DatePicker
:disabled="onlyView"
type="datetimerange"
v-model="form.rangeTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
:options="options"
style="width: 300px"
>
</DatePicker>
</FormItem>
<div>
<Button type="text" @click="closeCurrentPage">返回</Button>
<Button type="primary" v-if="!onlyView" :loading="submitLoading" @click="handleSubmit">提交</Button>
</div>
</div>
</div>
</Form>
</Card>
</div>
</template>
<script>
import {
getKanJiaActivityGoodsById,
editKanJiaActivityGoods,
} from "@/api/promotion";
import {regular} from "@/utils";
export default {
name: "editKanjiaActivityGoods",
watch: {},
data() {
const checkSettlementPrice = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("结算金额不能为空"));
} else if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("结算金额设置超过上限值"));
} else {
callback();
}
};
const checkPurchasePrice = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("最低购买金额不能为空"));
} else if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("最低购买金额设置超过上限值"));
} else {
callback();
}
};
const checkLowestPrice = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("最低可砍金额不能为空"));
} else if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("最低可砍金额设置超过上限值"));
} else {
callback();
}
};
const checkHighestPrice = (rule, value, callback) => {
if (!value && value !== 0) {
return callback(new Error("最高可砍金额不能为空"));
} else if (!regular.money.test(value)) {
callback(new Error("请输入正整数或者两位小数"));
} else if (parseFloat(value) > 99999999) {
callback(new Error("最高可砍金额设置超过上限值"));
} else {
callback();
}
};
return {
modalType: 0, // 是否编辑
form: {
purchasePrice:0,
goodsSku: {},
},
id: this.$route.query.id, // 砍价活动id
onlyView:this.$route.query.onlyView, // 是否为只读
submitLoading: false, // 添加或编辑提交状态
formRule: {
settlementPrice: [
{required: true, message: "请输入结算金额"},
{validator: checkSettlementPrice},
],
lowestPrice: [
{required: true, message: "请输入最低可砍金额"},
{validator: checkLowestPrice},
],
highestPrice: [
{required: true, message: "请输入最高可砍金额"},
{validator: checkHighestPrice},
],
rangeTime: [{required: true, message: "请选择活动时间"}],
stock: [{required: true, message: "请输入活动库存"}],
},
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
};
},
async mounted() {
// 如果id不为空则查询信息
if (this.id) {
this.getKanJiaActivityGoods();
this.modalType = 1;
}
},
methods: {
getKanJiaActivityGoods() {
getKanJiaActivityGoodsById(this.id).then((res) => {
this.form = res.result;
this.form.rangeTime = [];
this.form.rangeTime.push(new Date(this.form.startTime), new Date(this.form.endTime));
});
},
/** 保存砍价活动 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.form));
if (this.form.rangeTime[0] === '' || this.form.rangeTime[0] === '') {
this.$Message.error("请选择活动时间");
return
}
params.startTime = this.$options.filters.unixToDate(
this.form.rangeTime[0] / 1000
);
params.endTime = this.$options.filters.unixToDate(
this.form.rangeTime[1] / 1000
);
delete params.rangeTime
console.warn(params)
//校验库存参数
if (params.stock <= 0 || params.stock > params.goodsSku.quantity) {
this.$Message.error("活动库存不能为0且不能超过商品库存");
return
}
// 结算价格金额格式校验
if (!regular.money.test(params.settlementPrice)) {
this.$Message.error("结算价格金额格式不正确");
return
}
// 结算价格金额格式校验
if (params.settlementPrice < 0 || params.settlementPrice > params.price) {
this.$Message.error("结算价格金额不能为0且不能超过商品价格");
return
}
//最高砍价校验
if (!regular.money.test(params.highestPrice)) {
this.$Message.error("最高可砍金额格式错误");
return
}
if (params.highestPrice <= 0 || params.highestPrice > params.price) {
this.$Message.error("最高可砍金额不能为0且不能超过商品价格");
return
}
//最低砍价校验
if (!regular.money.test(params.lowestPrice)) {
this.$Message.error("最低可砍金额格式错误");
return
}
if (params.lowestPrice <= 0 || params.lowestPrice > params.price) {
this.$Message.error("最低可砍金额不能为0");
return
}
//校验最高最低砍价金额
if (params.lowestPrice > params.highestPrice) {
this.$Message.error("最低砍价金额不能大于最高砍价金额");
return
}
this.submitLoading = true;
// 添加 避免编辑后传入id等数据 记得删除
editKanJiaActivityGoods(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("砍价活动修改成功");
this.closeCurrentPage();
}
});
}
});
},
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "add-kan-jia-goods");
localStorage.pageOpenedList = JSON.stringify(
this.$store.state.app.pageOpenedList
);
this.$router.go(-1);
},
},
};
</script>
<style lang="scss" scpoed>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
.effectiveDays {
font-size: 12px;
color: #999;
> * {
margin: 0 4px;
}
}
.tips {
font-size: 12px;
color: #999;
}
</style>

View File

@@ -0,0 +1,373 @@
<template>
<div class="search">
<Card>
<Row>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="商品名称" prop="goodsName">
<Input
type="text"
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 200px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 200px"
>
</DatePicker>
</Form-item>
<Button
@click="handleSearch"
type="primary"
icon="ios-search"
class="search-btn"
>搜索</Button
>
</Form>
</Row>
<Row class="operation padding-row">
<Button @click="add" type="primary">添加砍价</Button>
</Row>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
sortable="custom"
@on-sort-change="changeSort"
>
<template slot-scope="{ row }" slot="goodsName">
<div>
<a class="mr_10" @click="linkTo(row.goodsId, row.skuId)">{{
row.goodsName
}}</a>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<vue-qr
:text="wapLinkTo(row.goodsId, row.skuId)"
:margin="0"
colorDark="#000"
colorLight="#fff"
:size="150"
></vue-qr>
</div>
<img
src="../../../assets/qrcode.svg"
style="vertical-align: middle"
class="hover-pointer"
width="20"
height="20"
alt=""
/>
</Poptip>
</div>
</template>
<template slot-scope="{ row }" slot="startTime">
<div>{{ row.startTime }}</div>
<div>{{ row.endTime }}</div>
</template>
<template slot-scope="{ row }" slot="quantity">
<div>{{ row.stock }}</div>
</template>
<template slot-scope="{ row }" slot="action">
<Button
v-if="row.promotionStatus != 'NEW'"
size="small"
style="margin-right: 10px"
@click="edit(row, 'onlyView')"
>查看
</Button>
<Button
v-if="row.promotionStatus === 'NEW'"
type="info"
size="small"
style="margin-right: 10px"
@click="edit(row)"
>编辑
</Button>
<Button
v-if="row.promotionStatus === 'NEW' || row.promotionStatus === 'END'"
type="error"
size="small"
style="margin-right: 10px"
@click="delAll(row)"
>删除
</Button>
</template>
</Table>
<Row type="flex" justify="end" class="page">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getKanJiaGoodsList, delKanJiaGoods } from "@/api/promotion";
import { promotionsStatusRender } from "@/utils/promotions";
import vueQr from "vue-qr";
export default {
name: "coupon",
components: {
"vue-qr": vueQr,
},
data() {
return {
selectDate: [], //选中的数据
loading: true, // 表单加载状态
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalTitle: "", // 添加或编辑标题
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
goodsName: "",
},
form: {
// 添加或编辑表单对象初始化数据
},
// 表单验证规则
formValidate: {},
submitLoading: false, // 添加或编辑提交状态
selectList: [], // 多选数据
selectCount: 0, // 多选计数
columns: [
{
title: "商品名称",
slot: "goodsName",
minWidth: 150,
tooltip: true,
},
{
title: "库存数量",
slot: "quantity",
width: 100,
},
{
title: "剩余活动库存",
key: "stock",
width: 110,
},
{
title: "最低购买金额",
key: "lowestPrice",
minWidth: 110,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.lowestPrice, "¥")
);
},
},
{
title: "每人最低砍",
key: "lowestPrice",
minWidth: 100,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.lowestPrice, "¥")
);
},
},
{
title: "每人最高砍",
key: "highestPrice",
minWidth: 100,
tooltip: true,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.highestPrice, "¥")
);
},
},
{
title: "结算价格",
key: "settlementPrice",
minWidth: 100,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.settlementPrice, "¥")
);
},
},
{
title: "活动开始时间",
slot: "startTime",
minWidth: 150,
},
{
title: "状态",
key: "promotionStatus",
render: (h, params) => {
return promotionsStatusRender(h, params);
},
width: 100,
},
{
title: "操作",
slot: "action",
align: "center",
fixed: "right",
width: 150,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
selectCoupon: [], //本级选中的优惠券
};
},
props: {},
watch: {
$route(to, from) {
if (to.fullPath == "/promotions/manager-coupon") {
this.init();
}
},
},
methods: {
check() {
// this.selectCoupon.push(this.selectList)
this.$emit("selected", this.selectCoupon);
},
init() {
this.getDataList();
},
// 添加砍价活动跳转
add() {
this.$router.push({ name: "add-kanJia-activity-goods" });
},
info(v) {
this.$router.push({ name: "platform-coupon-info", query: { id: v.id } });
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
// this.clearSelectAll();
},
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
this.searchForm.pageNumber = 0;
this.searchForm.pageSize = 10;
this.getDataList();
},
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order === "normal") {
this.searchForm.order = "";
}
this.getDataList();
},
clearSelectAll() {
this.$refs.table.selectAll(false);
},
getDataList() {
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
// 带多条件搜索参数获取表单数据 请自行修改接口
getKanJiaGoodsList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
this.total = this.data.length;
this.loading = false;
},
edit(v, type) {
let data = {
id: v.id,
};
type ? (data.onlyView = true) : "";
this.$router.push({
name: "edit-kanJia-activity-goods",
query: data,
});
},
delAll(row) {
this.$Modal.confirm({
title: "确认删除",
content: "确认需要删除此砍价商品",
loading: true,
onOk: () => {
let ids = [];
this.selectList.forEach(function (e) {
ids.push(e.id);
});
// 批量删除
delKanJiaGoods(row.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.getDataList();
}
});
},
});
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss">
@import "@/styles/table-common.scss";
</style>

View File

@@ -0,0 +1,306 @@
<template>
<div>
<Card>
<Form :model="liveForm" ref="liveForm" :rules="liveRulesForm" :label-width="120">
<FormItem label="直播标题" prop="name">
<Input disabled v-model="liveForm.name" style="width:460px"></Input>
<div class="tips">直播间名字最短3个汉字最长17个汉字1个汉字相当于2个字符</div>
</FormItem>
<FormItem label="主播昵称" prop="anchorName">
<Input disabled v-model="liveForm.anchorName" style="width:360px"></Input>
<div class="tips">主播昵称最短2个汉字最长15个汉字1个汉字相当于2个字符</div>
</FormItem>
<FormItem label="直播时间" prop="startTime">
<DatePicker disabled format="yyyy-MM-dd HH:mm" type="datetimerange" v-model="times" @on-change="handleChangeTime" :options="optionsTime" placeholder="直播计划开始时间-直播计划结束时间" style="width: 300px">
</DatePicker>
<div class="tips">直播开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后</div>
</FormItem>
<FormItem label="主播微信号" prop="anchorWechat">
<Input disabled v-model="liveForm.anchorWechat" style="width:360px" placeholder="主播微信号"></Input>
<div class="tips">主播微信号如果未实名认证需要先前往小程序直播小程序进行<a target="_black" href="https://res.wx.qq.com/op_res/9rSix1dhHfK4rR049JL0PHJ7TpOvkuZ3mE0z7Ou_Etvjf-w1J_jVX0rZqeStLfwh">实名验证</a></div>
</FormItem>
<!-- 分享卡片 -->
<FormItem label="分享卡片封面" prop="feedsImg">
<div class="upload-list" v-if="liveForm.feedsImg">
<template>
<img :src="liveForm.feedsImg">
<div class="upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(liveForm.feedsImg)"></Icon>
</div>
</template>
</div>
<Upload v-if="liveForm.feedsImg.length ==0" ref="upload" :show-upload-list="false" :on-success="handleFeedsImgSuccess" :default-file-list="defaultImgList" :format="['jpg','jpeg','png']"
:on-format-error="handleFormatError" :max-size="1024" :on-exceeded-size="handleMaxSize" type="drag" :action="action" :headers="accessToken" style="display: inline-block;width:58px;">
<div style="width: 58px;height:58px;line-height: 58px;">
<Icon type="ios-camera" size="20"></Icon>
</div>
</Upload>
<div class="tips">
直播间分享图图片规则建议像素800*640大小不超过1M
</div>
</FormItem>
<!-- 直播间背景墙 -->
<FormItem label="直播间背景墙" prop="coverImg">
<div class="upload-list" v-if="liveForm.coverImg">
<template>
<img :src="liveForm.coverImg">
<div class="upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(liveForm.coverImg)"></Icon>
</div>
</template>
</div>
<Upload v-if="liveForm.coverImg.length ==0" ref="upload" :show-upload-list="false" :on-success="handleCoverImgSuccess" :default-file-list="defaultImgList" :format="['jpg','jpeg','png']"
:on-format-error="handleFormatError" :max-size="1024" :on-exceeded-size="handleMaxSize" type="drag" :action="action" :headers="accessToken" style="display: inline-block;width:58px;">
<div style="width: 58px;height:58px;line-height: 58px;">
<Icon type="ios-camera" size="20"></Icon>
</div>
</Upload>
<div class="tips"> 直播间背景图图片规则建议像素1080*1920大小不超过1M</div>
</FormItem>
<!-- 直播间背景墙 -->
<FormItem label="直播间分享图" prop="shareImg">
<div class="upload-list" v-if="liveForm.shareImg">
<template>
<img :src="liveForm.shareImg">
<div class="upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(liveForm.shareImg)"></Icon>
</div>
</template>
</div>
<Upload v-if="liveForm.shareImg.length ==0" ref="upload" :show-upload-list="false" :on-success="handleShareImgSuccess" :default-file-list="defaultImgList" :format="['jpg','jpeg','png']"
:on-format-error="handleFormatError" :max-size="1024" :on-exceeded-size="handleMaxSize" type="drag" :action="action" :headers="accessToken" style="display: inline-block;width:58px;">
<div style="width: 58px;height:58px;line-height: 58px;">
<Icon type="ios-camera" size="20"></Icon>
</div>
</Upload>
<div class="tips"> 直播间分享图图片规则建议像素800*640大小不超过1M</div>
</FormItem>
<FormItem label="商品" v-if="$route.query.id">
<Table class="goods-table" :columns="liveColumns" :data="liveData">
<template slot-scope="{ row,index }" slot="goodsName">
<div class="flex-goods">
<Badge v-if="index == 0 || index ==1" color="volcano"></Badge>
<img class="thumbnail" :src="row.thumbnail || row.goodsImage">
{{ row.goodsName || row.name }}
</div>
</template>
<template slot-scope="{ row }" class="price" slot="price">
<div>
<div v-if="row.priceType == 1">{{row.price | unitPrice('')}}</div>
<div v-if="row.priceType == 2">{{row.price | unitPrice('')}}{{row.price2 | unitPrice('')}}</div>
<div v-if="row.priceType == 3">{{row.price | unitPrice('¥')}}<span class="original-price">{{row.price2 | unitPrice('')}}</span></div>
</div>
</template>
<template slot-scope="{ row }" slot="quantity">
<div>{{row.quantity}}</div>
</template>
</Table>
<div class="tips">
直播间商品中前两个商品将自动被选为封面伴随直播间在直播列表中显示
</div>
</FormItem>
<FormItem>
<Button type="primary" @click="createLives()">保存</Button>
</FormItem>
</Form>
</Card>
<!-- 浏览图片 -->
<Modal title="查看图片" v-model="imageVisible">
<img :src="imageSrc" v-if="imageVisible" style="width: 100%">
</Modal>
</div>
</template>
<script>
import { getLiveInfo } from "@/api/promotion";
export default {
data() {
return {
imageVisible: false, //查看图片的dailog
imageSrc: "", //查看图片的路径
liveForm: {
name: "", //直播标题
anchorName: "", //主播昵称
anchorWechat: "", //主播微信号
feedsImg: "", //分享卡片封面
coverImg: "", //直播间背景墙
shareImg: "", //分享图
startTime: "",
},
times: [], //接收直播时间数据
// 直播商品表格表头
liveColumns: [
{
title: "商品",
slot: "goodsName",
},
{
title: "价格",
slot: "price",
},
{
title: "库存",
slot: "quantity",
width: 100,
},
{
title: "操作",
slot: "action",
width: 250,
},
],
liveData: [], //直播商品集合
commodityList: "", //商品集合
};
},
mounted() {
/**
* 如果query.id有值说明是查看详情
* liveStatus 可以判断当前直播状态 从而区分数据 是否是未开始、已开启、已关闭、
*/
if (this.$route.query.id) {
// 获取直播间详情
this.getLiveDetail();
}
this.accessToken = {
accessToken: this.getStore("accessToken"),
};
},
methods: {
/**
* 上传图片查看图片
*/
handleView(src) {
this.imageVisible = true;
this.imageSrc = src;
},
// 上传文件超过大小限制
handleMaxSize(file) {
this.$Notice.warning({
title: "文件大小过大",
desc: "所选文件大小过大, 不得超过 1M.",
});
},
/**
* 获取直播间详情
*/
async getLiveDetail() {
let result = await getLiveInfo(this.$route.query.id);
// 将数据回调到liveform里面
if (result.success) {
let data = result.result;
for (let key in data) {
this.liveForm[key] = data[key];
}
// 将选择的商品回调给表格
this.liveData = data.commodityList;
this.commodityList = data.commodityList;
// 将时间格式化
this.$set(
this.times,
[0],
this.$options.filters.unixToDate(data.startTime, "yyyy-MM-dd hh:mm")
);
this.$set(
this.times,
[1],
this.$options.filters.unixToDate(data.endTime, "yyyy-MM-dd hh:mm")
);
this.liveStatus = data.status;
}
},
},
};
</script>
<style lang="scss" scoped>
.action {
display: flex;
/deep/ .ivu-btn {
margin: 0 5px !important;
}
}
.original-price {
margin-left: 10px;
color: #999;
text-decoration: line-through;
}
.thumbnail {
width: 50px;
height: 50px;
border-radius: 0.4em;
}
.flex-goods {
margin: 10px;
display: flex;
align-items: center;
> img {
margin-right: 10px;
}
}
.tips {
color: #999;
font-size: 12px;
}
.goods-table {
width: 1000px;
margin: 10px 0;
}
.upload-list {
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
margin-right: 4px;
}
.upload-list img {
width: 100%;
height: 100%;
}
.upload-list-cover {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.6);
}
.upload-list:hover .upload-list-cover {
display: block;
}
.upload-list-cover i {
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
</style>

View File

@@ -0,0 +1,256 @@
<template>
<div>
<Card>
<Tabs v-model="searchForm.status">
<!-- 标签栏 -->
<TabPane
v-for="(item, index) in tabs"
:key="index"
:name="item.status"
:label="item.title"
>
</TabPane>
</Tabs>
<Table :columns="liveColumns" :data="liveData"></Table>
<Row type="flex" style="margin: 20px" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePageNumber"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getLiveList, whetherStar } from "@/api/promotion.js";
export default {
data() {
return {
// 查询数据的总数
total: 0,
// 查询的form
searchForm: {
pageSize: 10,
pageNumber: 1,
status: "NEW",
},
// 直播tab选项栏
tabs: [
{
title: "直播中",
status: "START",
},
{
title: "未开始",
status: "NEW",
},
{
title: "已结束",
status: "END",
},
],
liveColumns: [
{
title: "直播标题",
key: "name",
},
{
title: "主播昵称",
key: "anchorName",
},
{
title: "直播开始时间",
key: "createTime",
render: (h, params) => {
return h("span", this.$options.filters.unixToDate(params.row.startTime));
},
},
{
title: "直播结束时间",
key: "endTime",
render: (h, params) => {
return h(
"span",
this.$options.filters.unixToDate(params.row.endTime)
);
},
},
{
title: "是否推荐",
align: "center",
render: (h, params) => {
return h("div", [
h(
"i-switch",
{
// 数据库0 enabled,1 disabled
props: {
type: "primary",
size: "large",
value: params.row.recommend == true,
},
on: {
"on-change": () => {
this.star(params.row, params.index);
},
},
},
[
h("span", {
slot: "open",
domProps: {
innerHTML: "是",
},
}),
h("span", {
slot: "close",
domProps: {
innerHTML: "否",
},
}),
]
),
]);
},
},
{
title: "直播状态",
render: (h, params) => {
if (params.row.status == "NEW") {
return h("div", [h("tag", { props: { color: "blue" } }, "未开始")]);
} else if (params.row.status == "START") {
return h("div", [h("tag", { props: { color: "green" } }, "直播中")]);
} else {
return h("div", [h("tag", { props: { color: "volcano" } }, "已结束")]);
}
},
},
{
title: "操作",
key: "action",
render: (h, params) => {
return h(
"div",
{
style: {
display: "flex",
},
},
[
h(
"Button",
{
props: {
type: "error",
size: "small",
},
style: {
marginRight: "5px",
},
on: {
click: () => {
this.getLiveDetail(params.row);
},
},
},
"查看"
),
]
);
},
},
], //table中显示的title
liveData: [], //table中显示的直播数据
};
},
watch: {
// 直播状态
"searchForm.status": {
handler() {
this.liveData = [];
this.getStoreLives();
},
deep: true,
},
},
mounted() {
this.getStoreLives();
},
methods: {
/**
* 是否推荐
*/
async star(val, index) {
let switched;
if (this.liveData[index].recommend) {
this.$set(this.liveData[index], "recommend", false);
switched = false;
} else {
this.$set(this.liveData[index], "recommend", true);
switched = true;
}
await whetherStar({ id: val.id, recommend: switched });
this.getStoreLives();
},
/**
* 页面数据大小分页回调
*/
changePageSize(val) {
this.searchForm.pageSize = val;
this.getStoreLives();
},
/**
* 分页回调
*/
changePageNumber(val) {
this.searchForm.pageNumber = val;
this.getStoreLives();
},
/**
* 获取店铺直播间列表
*/
async getStoreLives() {
let result = await getLiveList(this.searchForm);
if (result.success) {
this.liveData = result.result.records;
this.total = result.result.total;
}
},
/**
* 获取直播间详情
*/
getLiveDetail(val) {
this.$router.push({
path: "/live-detail",
query: { ...val, liveStatus: this.searchForm.status },
});
},
},
};
</script>
<style lang="scss" scoped>
.btns {
margin-bottom: 10px;
margin-top: 10px;
}
.page {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,191 @@
<template>
<div class="pintuan-goods">
<Card>
<h4>活动详情</h4>
<Table style="margin: 10px 0" border :columns="columns" :data="data"></Table>
<h4>商品信息</h4>
<Table
:loading="loading"
border
class="operation"
:columns="goodsColumns"
:data="goodsData"
ref="table"
sortable="custom"
>
<template slot-scope="{ row }" slot="goodsName">
<div>
<a class="mr_10" @click="linkTo(row.goodsId, row.skuId)">{{
row.goodsName
}}</a>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<vue-qr
:text="wapLinkTo(row.goodsId, row.skuId)"
:margin="0"
colorDark="#000"
colorLight="#fff"
:size="150"
></vue-qr>
</div>
<img
src="../../../assets/qrcode.svg"
style="vertical-align: middle"
class="hover-pointer"
width="20"
height="20"
alt=""
/>
</Poptip>
</div>
</template>
</Table>
<Row type="flex" justify="end" class="page operation">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getPintuanGoodsList, getPintuanDetail } from "@/api/promotion.js";
import vueQr from "vue-qr";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
components: {
"vue-qr": vueQr,
},
data() {
return {
loading: false, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
},
data: [], // 表单数据
total: 0, // 表单数据总数
columns: [
{
title: "活动名称",
key: "promotionName",
minWidth: 120,
},
{
title: "活动开始时间",
key: "startTime",
minWidth: 120,
},
{
title: "活动结束时间",
key: "endTime",
minWidth: 120,
},
{
title: "成团人数",
key: "requiredNum",
},
{
title: "限购数量",
key: "limitNum",
},
{
title: "状态",
key: "promotionStatus",
minWidth: 100,
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
],
goodsColumns: [
{
title: "商品名称",
slot: "goodsName",
minWidth: 120,
},
{
title: "库存",
key: "quantity",
minWidth: 40,
},
{
title: "拼团价格",
key: "price",
minWidth: 50,
render: (h, params) => {
return h("div", this.$options.filters.unitPrice(params.row.price, "¥"));
},
},
],
goodsData: [], // 商品数据
};
},
methods: {
// 初始化数据
init() {
this.getDataList();
this.getPintuanMsg();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
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) this.data.push(res.result);
});
},
},
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;
}
</style>

View File

@@ -0,0 +1,220 @@
<template>
<div class="search">
<Card>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="活动名称" prop="promotionName">
<Input
type="text"
v-model="searchForm.promotionName"
placeholder="请输入活动名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 200px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 200px"
></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
</Form>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
>
<template slot-scope="{ row }" slot="action">
<Button type="info" size="small" @click="view(row)" style="margin-right: 5px"
>查看</Button
>
<Button
type="error"
size="small"
:disabled="row.promotionStatus == 'END' || row.promotionStatus == 'CLOSE'"
@click="close(row)"
>关闭
</Button>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import { getPintuanList, updatePintuanStatus } from "@/api/promotion";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
name: "pintuan",
data() {
return {
selectDate: [], //选中的数据
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
},
columns: [
// 表头
{
title: "活动名称",
key: "promotionName",
minWidth: 150,
tooltip: true,
},
{
title: "状态",
key: "promotionStatus",
width: 110,
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
{
title: "所属店铺",
key: "storeName",
minWidth: 120,
tooltip: true,
},
{
title: "活动开始时间",
key: "startTime",
width: 180,
},
{
title: "活动结束时间",
key: "endTime",
width: 180,
},
{
fixed: "right",
title: "操作",
slot: "action",
align: "center",
width: 200,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
};
},
methods: {
// 初始化数据
init() {
this.getDataList();
},
// 分页 修改页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
// 分页 修改页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
// 获取拼团列表
getDataList() {
this.loading = true;
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
getPintuanList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
// 查看拼团商品
view(v) {
this.$router.push({ name: "pintuan-goods", query: { id: v.id } });
},
// 关闭当前活动
close(v) {
this.$Modal.confirm({
title: "确认关闭",
// 记得确认修改此处
content: "您确认要关闭此拼团活动?",
loading: true,
onOk: () => {
// 删除
updatePintuanStatus(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
}
});
},
});
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
.ivu-form-item {
margin-bottom: 0 !important;
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<div>
<Card>
<div class="operation mb_10">
<Button @click="addParent" type="primary" icon="md-add">添加积分商品分类</Button>
<Button icon="md-refresh" @click="init">刷新</Button>
</div>
<tree-table
ref="treeTable"
size="default"
:loading="loading"
:data="tableData"
:columns="columns"
:border="true"
:show-index="false"
:is-fold="true"
:expand-type="false"
primary-key="id"
>
<template slot="action" slot-scope="scope">
<Button @click.native="edit(scope.row)" style="margin-right:10px;" size="small">编辑</Button>
<Button @click.native="remove(scope.row)" type="primary" size="small">删除</Button>
</template>
</tree-table>
</Card>
<Modal
:title="modalTitle"
v-model="modalVisible"
:mask-closable="false"
:width="500"
>
<Form
ref="form"
:model="formAdd"
:label-width="100"
:rules="formValidate"
>
<FormItem label="分类名称" prop="name">
<Input v-model="formAdd.name" clearable style="width: 100%" />
</FormItem>
<FormItem label="排序值" prop="sortOrder">
<InputNumber v-model="formAdd.sortOrder" :min="0" clearable style="width: 100%" />
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="Submit"
>提交</Button
>
</div>
</Modal>
</div>
</template>
<script>
import {
getPointsGoodsCategoryList,
addPointsGoodsCategory,
updatePointsGoodsCategory,
deletePointsGoodsCategoryById,
} from "@/api/promotion";
import TreeTable from "@/views/my-components/tree-table/Table/Table";
export default {
name: "pointsGoodsCategory",
components: {
TreeTable
},
data() {
return {
submitLoading:false,
loading: false, // 加载状态
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalTitle: "", // 添加或编辑标题
showParent: false, // 是否展示上级菜单
parentTitle: "", // 父级菜单名称
formAdd: {
// 添加或编辑表单对象初始化数据
parentId: 0,
name: "",
deleteFlag: 0,
level: 0,
sortOrder:1
},
// 表单验证规则
formValidate: {
name: [{ required: true, message: "商品分类名称不能为空" }],
},
columns: [
{
title: "分类名称",
key: "name",
minWidth: "120px",
},
{
title: "操作",
key: "action",
align: "center",
headerAlign: "center",
width: "400px",
type: "template",
template: "action",
},
],
tableData: [], // 表格数据
};
},
methods: {
// 初始化数据
init() {
this.getAllList();
},
// 编辑分类
edit(v) {
this.modalType = 1;
this.modalTitle = "编辑";
this.formAdd.id = v.id;
this.formAdd.name = v.name;
this.formAdd.sortOrder = v.sortOrder;
this.showParent = false;
this.modalVisible = true;
},
// 添加顶级分类
addParent() {
this.modalType = 0;
this.modalTitle = "添加积分商品分类";
this.parentTitle = "顶级分类";
this.showParent = true;
this.$refs.form.resetFields();
delete this.formAdd.id;
this.formAdd.parentId = 0;
this.modalVisible = true;
},
// 提交
Submit() {
this.$refs.form.validate((valid) => {
console.log(valid);
if (valid) {
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete this.formAdd.id;
addPointsGoodsCategory(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("添加成功");
this.getAllList();
this.modalVisible = false;
this.$refs.form.resetFields();
}
});
} else {
// 编辑
updatePointsGoodsCategory(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getAllList();
this.modalVisible = false;
this.$refs.form.resetFields();
}
});
}
}
});
},
// 删除
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除 " + v.name + " ?",
loading: true,
onOk: () => {
// 删除
deletePointsGoodsCategoryById(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getAllList();
}
});
},
});
},
// 获取所有分类
getAllList() {
this.loading = true;
getPointsGoodsCategoryList().then((res) => {
this.loading = false;
if (res.success) {
this.tableData = res.result.records;
}
});
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,410 @@
<template>
<div class="wrapper">
<Card>
<Form ref="form" :model="form" :rules="formRule">
<div class="base-info-item">
<h4>添加积分商品</h4>
<div class="form-item-view">
<FormItem astyle="width: 100%">
<div style="display: flex; margin-bottom: 10px">
<Button type="primary" @click="openSkuList">选择商品</Button>
<Button
type="error"
ghost
style="margin-left: 10px"
@click="delSelectGoods"
>批量删除</Button
>
</div>
<Table
border
v-if="showTable"
:columns="columns"
:data="promotionGoodsList"
@on-selection-change="changeSelect"
>
<template slot-scope="{ row }" slot="skuId">
<div>{{ row.skuId }}</div>
</template>
<template slot-scope="{ index }" slot="settlementPrice">
<Input
type="number"
v-model="promotionGoodsList[index].settlementPrice"
/>
</template>
<template slot-scope="{ row, index }" slot="pointsGoodsCategory">
<Select
v-model="promotionGoodsList[index].pointsGoodsCategoryId"
:transfer="true"
:label-in-value="true"
@on-change="
(val) => {
changeCategory(val, index);
}
"
>
<Option
v-for="item in categoryList"
:value="item.id"
:key="item.id"
>{{ item.name }}</Option
>
</Select>
</template>
<template slot-scope="{ index }" slot="activeStock">
<Input type="number" v-model="promotionGoodsList[index].activeStock" />
</template>
<template slot-scope="{ index }" slot="points">
<Input type="number" v-model="promotionGoodsList[index].points" />
</template>
</Table>
</FormItem>
<FormItem label="兑换时间" prop="time">
<DatePicker
type="datetime"
v-model="form.startTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
:options="options"
clearable
style="width: 200px"
>
</DatePicker>
-
<DatePicker
type="datetime"
v-model="form.endTime"
format="yyyy-MM-dd HH:mm:ss"
:options="options"
placeholder="请选择"
clearable
style="width: 200px"
>
</DatePicker>
</FormItem>
<div>
<Button type="text" @click="closeCurrentPage">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
>提交</Button
>
</div>
</div>
</div>
</Form>
</Card>
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
</div>
</template>
<script>
import { addPointsGoods, getPointsGoodsCategoryList } from "@/api/promotion";
import { regular } from "@/utils";
import skuSelect from "@/views/lili-dialog";
export default {
name: "addPoinsGoods",
components: {
skuSelect,
},
data() {
const isLtEndDate = (rule, value, callback) => {
if (new Date(value).getTime() > new Date(this.form.endTime).getTime()) {
callback(new Error());
} else {
callback();
}
};
const isGtStartDate = (rule, value, callback) => {
if (new Date(value).getTime() < new Date(this.form.startTime).getTime()) {
callback(new Error());
} else {
callback();
}
};
return {
form: {
promotionGoodsList: [], // 活动商品列表
},
showTable: true,
promotionGoodsList: [], // 活动商品列表
categoryList: [], // 分类列表
submitLoading: false, // 添加或编辑提交状态
selectedGoods: [], // 已选商品列表,便于删除
formRule: {
startTime: [
{
required: true,
type: "date",
message: "请选择开始时间",
},
{
trigger: "change",
message: "开始时间要小于结束时间",
validator: isLtEndDate,
},
],
endTime: [
{
required: true,
type: "date",
message: "请选择结束时间",
},
{
trigger: "change",
message: "结束时间要大于开始时间",
validator: isGtStartDate,
},
],
discount: [
{ required: true, message: "请输入折扣" },
{
pattern: regular.discount,
message: "请输入0-10的数字,可有一位小数",
},
],
sellerCommission: [
{ required: true, message: "请输入店铺承担比例" },
{ pattern: regular.rate, message: "请输入0-100的正整数" },
],
publishNum: [
{ required: true, message: "请输入发放数量" },
{ pattern: regular.Integer, message: "请输入正整数" },
],
couponLimitNum: [
{ required: true, message: "请输入领取限制" },
{ pattern: regular.Integer, message: "请输入正整数" },
],
description: [{ required: true, message: "请输入范围描述" }],
},
columns: [
{
type: "selection",
width: 60,
align: "center",
},
{
title: "商品名称",
key: "goodsName",
minWidth: 120,
render: (h, params) => {
return h("div", params.row.goodsSku.goodsName);
},
},
{
title: "SKU编码",
slot: "skuId",
minWidth: 120,
},
{
title: "店铺名称",
key: "storeName",
minWidth: 60,
render: (h, params) => {
return h("div", params.row.goodsSku.storeName);
},
},
{
title: "商品价格",
key: "price",
minWidth: 40,
render: (h, params) => {
return h(
"div",
this.$options.filters.unitPrice(params.row.goodsSku.price, "")
);
},
},
{
title: "库存",
key: "quantity",
minWidth: 20,
render: (h, params) => {
return h("div", params.row.goodsSku.quantity);
},
},
{
title: "结算价格",
slot: "settlementPrice",
minWidth: 40,
},
{
title: "分类",
slot: "pointsGoodsCategory",
minWidth: 60,
},
{
title: "活动库存",
slot: "activeStock",
minWidth: 40,
},
{
title: "兑换积分",
slot: "points",
minWidth: 40,
},
{
title: "操作",
key: "action",
minWidth: 50,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
size: "small",
type: "error",
ghost: true,
},
on: {
click: () => {
this.delGoods(params.index);
},
},
},
"删除"
);
},
},
],
options: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
},
},
};
},
async mounted() {
await this.getCategory();
},
methods: {
// 获取商品分类
async getCategory() {
let res = await getPointsGoodsCategoryList();
this.categoryList = res.result.records;
},
/** 保存积分商品 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
let params = this.promotionGoodsList;
const start = this.$options.filters.unixToDate(this.form.startTime / 1000);
const end = this.$options.filters.unixToDate(this.form.endTime / 1000);
if (!params || params.length == 0) {
this.$Modal.warning({ title: "提示", content: "请选择指定商品" });
return;
}
this.submitLoading = true;
params = params.map((j) => {
j.startTime = start;
j.endTime = end;
return j;
});
addPointsGoods(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("积分商品创建成功");
this.closeCurrentPage();
}
});
}
});
},
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "add-points-goods");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
// 选择分类
changeCategory(val, index) {
this.promotionGoodsList[index].pointsGoodsCategoryName = val.label;
},
// 变更选中状态
changeSelect(e) {
// 已选商品批量选择
this.selectedGoods = e;
},
delSelectGoods() {
// 多选删除商品
if (this.selectedGoods.length <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选商品吗?",
onOk: () => {
let ids = [];
this.selectedGoods.forEach(function (e) {
ids.push(e.id);
});
this.promotionGoodsList = this.promotionGoodsList.filter((item) => {
return !ids.includes(item.id);
});
},
});
},
delGoods(index) {
// 删除商品
this.promotionGoodsList.splice(index, 1);
},
openSkuList() {
// 显示商品选择器
this.$refs.skuSelect.open("goods");
let data = JSON.parse(JSON.stringify(this.promotionGoodsList));
data.forEach((e) => {
e.id = e.skuId;
});
this.$refs.skuSelect.goodsData = data;
},
selectedGoodsData(item) {
// 回显已选商品
let list = [];
item.forEach((e) => {
const obj = {
settlementPrice: e.settlementPrice || 0,
pointsGoodsCategoryId: e.pointsGoodsCategoryId || 0,
pointsGoodsCategoryName: e.pointsGoodsCategoryName || "",
activeStock: e.activeStock || 0,
points: e.points || 0,
skuId: e.id,
goodsId: e.goodsId,
originalPrice: e.price || 0,
thumbnail: e.thumbnail || "",
goodsName: e.goodsName || "",
goodsSku: e,
};
list.push(obj);
});
this.promotionGoodsList = list;
},
},
};
</script>
<style lang="scss" scpoed>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.describe {
font-size: 12px;
margin-left: 10px;
color: #999;
}
.wrapper {
min-height: 800px;
}
</style>

View File

@@ -0,0 +1,365 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<h4>积分商品信息</h4>
<div class="form-item-view">
<FormItem label="商品名称">
<div>{{ form.goodsSku.goodsName }}</div>
</FormItem>
<FormItem label="SKU编码">
<div>{{ form.goodsSku.id }}</div>
</FormItem>
<FormItem label="店铺名称">
<div>{{ form.goodsSku.storeName }}</div>
</FormItem>
<FormItem label="商品价格">
<div>{{ form.goodsSku.price | unitPrice('¥') }}</div>
</FormItem>
<FormItem label="库存">
<div>{{ form.goodsSku.quantity }}</div>
</FormItem>
<FormItem label="结算价格" prop="settlementPrice">
<Input
type="num"
v-model="form.settlementPrice"
placeholder="请填写结算价格"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="分类" prop="pointsGoodsCategoryId">
<Select
v-model="form.pointsGoodsCategoryId"
label-in-value="true"
@on-change="
(val) => {
changeCategory(val, index);
}
"
>
<Option
v-for="item in categoryList"
:value="item.id"
:key="item.id"
>{{ item.name }}</Option
>
</Select>
</FormItem>
<FormItem label="活动库存" prop="activeStock">
<Input
type="number"
v-model="form.activeStock"
placeholder="请填写活动库存"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="兑换积分" prop="points">
<Input
type="number"
v-model="form.points"
placeholder="请填写兑换积分"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="活动开始时间" prop="startTime">
<DatePicker
type="datetime"
v-model="form.startTime"
format="yyyy-MM-dd HH:mm:ss"
:options="options"
placeholder="请选择"
clearable
style="width: 200px"
>
</DatePicker>
-
<DatePicker
type="datetime"
v-model="form.endTime"
format="yyyy-MM-dd HH:mm:ss"
:options="options"
placeholder="请选择"
clearable
style="width: 200px"
>
</DatePicker>
</FormItem>
</div>
<div class="footer">
<Button @click="closeCurrentPage" style="margin-right: 5px">返回</Button>
<Button
type="primary"
:loading="submitLoading"
@click="handleSubmit"
>保存</Button
>
</div>
</div>
</Form>
</Card>
</div>
</template>
<script>
import {
updatePointsGoods,
getPointsGoodsById,
getPointsGoodsCategoryList,
} from "@/api/promotion";
export default {
name: "editPointsGoods",
data() {
return {
form: {
/** 活动名称 */
promotionName: "",
/** 报名截止时间 */
applyEndTime: "",
/** 活动开始时间 */
startTime: "",
/** 抢购时间段 */
seckillPeriod: [],
/** 申请规则 */
seckillRule: "",
goodsSku: {},
promotionStatus: "NEW",
},
categoryList: [], // 分类列表
id: this.$route.query.id, // 活动id
submitLoading: false, // 添加或编辑提交状态
formRule: {
settlementPrice: [{ required: true, message: "请填写结算价格" }],
pointsGoodsCategoryId: [
{ required: true, message: "请选择积分商品分类" },
],
points: [{ required: true, message: "请填写兑换积分" }],
startTime: [{ required: true, message: "请填写活动开始时间" }],
},
};
},
async mounted() {
await this.getCategory();
// 如果id不为空则查询信息
if (this.id) {
this.getData();
}
},
methods: {
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "edit-points-goods");
localStorage.pageOpenedList = JSON.stringify(
this.$store.state.app.pageOpenedList
);
this.$router.go(-1);
},
// 获取商品数据
getData() {
getPointsGoodsById(this.id).then((res) => {
if (res.success) {
let data = res.result;
this.form = data;
}
});
},
// 获取分类
async getCategory() {
let res = await getPointsGoodsCategoryList();
this.categoryList = res.result.records;
},
/** 保存 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
const start = this.$options.filters.unixToDate(
this.form.startTime / 1000
);
const end = this.$options.filters.unixToDate(
this.form.endTime / 1000
);
this.form.startTime = start;
this.form.endTime = end;
this.submitLoading = true;
updatePointsGoods(this.form).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("积分商品修改成功");
this.closeCurrentPage();
}
});
}
});
},
},
};
</script>
<style lang="scss" scoped>
/*编辑基本信息*/
.el-form {
padding-bottom: 80px;
.el-form-item {
width: 100%;
color: gray;
text-align: left;
}
}
/*平铺*/
div.base-info-item > div {
margin-left: 5%;
}
div.base-info-item {
margin-bottom: 10px;
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.form-item-view {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
padding-left: 80px;
.shop-category-text {
font-size: 12px;
}
}
.item-goods-properts-row {
display: flex;
flex-direction: row;
word-break: break-all;
white-space: normal;
width: 300px;
height: 100px;
}
.item-goods-properts {
display: flex;
flex-direction: row;
margin-bottom: 10px;
}
.form-item {
display: flex;
align-items: center;
}
/** 审核信息-拒绝原因 */
.auth-info {
color: red;
}
.el-form-item {
width: 30%;
min-width: 300px;
}
.goods-name-width {
width: 50%;
min-width: 300px;
}
.el-form-item__content {
margin-left: 120px;
text-align: left;
}
p.goods-group-manager {
padding-left: 7.5%;
text-align: left;
color: #999;
font-size: 13px;
}
/*teatarea*/
/deep/ .el-textarea {
width: 150%;
}
.seo-text {
width: 150%;
}
}
/*商品描述*/
.goods-intro {
line-height: 40;
}
/** 底部步骤 */
.footer {
width: 100%;
padding: 10px;
background-color: #ffc;
position: fixed;
bottom: 0px;
right: 0;
text-align: center;
z-index: 9999;
}
/*图片上传组件第一张图设置封面*/
.goods-images {
/deep/ li.el-upload-list__item:first-child {
position: relative;
}
/deep/ li.el-upload-list__item:first-child:after {
content: "";
color: #fff;
font-weight: bold;
font-size: 12px;
position: absolute;
left: -15px;
top: -6px;
width: 40px;
height: 24px;
padding-top: 6px;
background: #13ce66;
text-align: center;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
}
}
.el-form-item__label {
word-break: break-all;
}
.step-view {
width: 33%;
height: 40px;
font-size: 19px;
text-align: center;
display: flex;
background-color: #fff;
justify-content: center;
align-items: center;
}
.page {
margin-top: 2vh;
margin-bottom: 5vh;
}
</style>

View File

@@ -0,0 +1,349 @@
<template>
<div class="search">
<Card>
<Row>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="商品名称">
<Input
type="text"
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="积分区间">
<Input
type="text"
v-model="searchForm.pointsS"
placeholder="请输入开始区间"
clearable
style="width: 200px"
/>
-
<Input
type="text"
v-model="searchForm.pointsE"
placeholder="请输入结束区间"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="状态">
<Select v-model="searchForm.promotionStatus" style="width: 200px">
<Option v-for="item in statusList" :value="item.value" :key="item.value">{{
item.label
}}</Option>
</Select>
</Form-item>
<Form-item label="SKU编码">
<Input
type="text"
v-model="searchForm.skuId"
placeholder="请输入SKU编码"
clearable
style="width: 200px"
/>
</Form-item>
<Button
@click="handleSearch"
type="primary"
icon="ios-search"
class="search-btn"
>搜索</Button
>
</Form>
</Row>
<Row class="operation padding-row">
<Button @click="addPointsGoods" type="primary">添加积分商品</Button>
</Row>
<Table :loading="loading" border :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="goodsName">
<div>
<a class="mr_10" @click="linkTo(row.goodsId, row.skuId)">{{
row.goodsName
}}</a>
<Poptip trigger="hover" title="扫码在手机中查看" transfer>
<div slot="content">
<vue-qr
:text="wapLinkTo(row.goodsId, row.skuId)"
:margin="0"
colorDark="#000"
colorLight="#fff"
:size="150"
></vue-qr>
</div>
<img
src="../../../assets/qrcode.svg"
style="vertical-align: middle"
class="hover-pointer"
width="20"
height="20"
alt=""
/>
</Poptip>
</div>
</template>
<template slot-scope="{ row }" slot="price">
<div>{{ row.originalPrice | unitPrice("¥") }}</div>
</template>
<template slot-scope="{ row }" slot="settlementPrice">
<div>{{ row.settlementPrice | unitPrice("¥") }}</div>
</template>
<template slot-scope="{ row }" slot="quantity">
<div>{{ row.activeStock }}</div>
</template>
<template slot-scope="{ row }" slot="startTime">
<div>{{ row.startTime }}</div>
<div>{{ row.endTime }}</div>
</template>
<template slot-scope="{ row }" slot="action">
<Button
v-if="row.promotionStatus == 'NEW'"
type="info"
size="small"
@click="edit(row.id)"
style="margin-right: 5px"
>编辑</Button
>
<Button
v-if="row.promotionStatus == 'START'"
type="warning"
size="small"
@click="statusChanged(row.id, 'CLOSE')"
style="margin-right: 5px"
>关闭</Button
>
<Button
v-if="row.promotionStatus == 'CLOSE'"
type="warning"
size="small"
@click="statusChanged(row.id, 'START')"
style="margin-right: 5px"
>开启</Button
>
<Button type="error" size="small" @click="close(row.id)">删除</Button>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import {
getPointsGoodsList,
editPointsGoodsStatus,
deletePointsGoodsStatus,
} from "@/api/promotion";
import vueQr from "vue-qr";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
name: "pointsGoods",
components: {
"vue-qr": vueQr,
},
data() {
return {
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
order: "desc", // 默认排序方式
},
statusList: [
// 活动状态
{ label: "未开始", value: "NEW" },
{ label: "已开始", value: "START" },
{ label: "已结束", value: "END" },
{ label: "已关闭", value: "CLOSE" },
],
columns: [
// 表头
{
title: "商品名称",
slot: "goodsName",
minWidth: 150,
fixed: "left",
tooltip: true,
},
{
title: "市场价",
slot: "price",
width: 100,
},
{
title: "结算价",
slot: "settlementPrice",
width: 100,
},
{
title: "库存数量",
slot: "quantity",
width: 100,
},
{
title: "活动剩余库存",
key: "activeStock",
width: 150,
},
{
title: "兑换积分",
key: "points",
width: 100,
},
{
title: "所属店铺",
key: "storeName",
width: 100,
},
{
title: "活动开始时间",
slot: "startTime",
minWidth: 150,
},
{
title: "状态",
key: "promotionStatus",
width: 100,
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
{
title: "分类",
key: "pointsGoodsCategoryName",
width: 100,
},
{
title: "操作",
slot: "action",
align: "center",
fixed: "right",
width: 150,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
};
},
methods: {
// 初始化数据
init() {
this.getDataList();
},
// 跳转添加商品页面
addPointsGoods() {
this.$router.push({ name: "add-points-goods" });
},
// 分页 修改页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 修改页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
if (this.searchForm.pointsS) {
this.searchForm.points =
this.searchForm.pointsS +
"_" +
(this.searchForm.pointsE ? this.searchForm.pointsE : "");
}
this.getDataList();
},
// 获取列表数据
getDataList() {
this.loading = true;
getPointsGoodsList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
// 编辑
edit(id) {
this.$router.push({ name: "edit-points-goods", query: { id: id } });
},
// 启用 停用积分商品
statusChanged(id, status, startTime, endTime) {
let text = "";
let params = {};
if (status == "START") {
text = "开启";
params = {
startTime: startTime,
endTime: endTime,
};
} else if (status == "CLOSE") {
text = "关闭";
}
this.$Modal.confirm({
title: "确认" + text,
content: "您确认要" + text + "此积分商品?",
loading: true,
onOk: () => {
editPointsGoodsStatus(id, params).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success(text + "成功");
this.getDataList();
}
});
},
});
},
// 删除积分商品
close(id) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除此积分商品?",
loading: true,
onOk: () => {
// 删除
deletePointsGoodsStatus(id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
}
});
},
});
},
},
mounted() {
this.init();
},
};
</script>

View File

@@ -0,0 +1,210 @@
<template>
<div>
<Card>
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
<div class="base-info-item">
<h4>基本信息</h4>
<div class="form-item-view">
<FormItem label="活动名称" prop="promotionName">
<Input
type="text"
v-model="form.promotionName"
placeholder="请填写活动名称"
clearable
style="width: 260px"
/>
</FormItem>
<FormItem label="报名截止时间" prop="applyEndTime">
<DatePicker
type="datetime"
v-model="form.applyEndTime"
format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择"
clearable
style="width: 200px"
>
</DatePicker>
</FormItem>
<FormItem label="活动开始时间" prop="startTime">
<DatePicker
type="datetime"
v-model="form.startTime"
format="yyyy-MM-dd"
placeholder="请选择"
clearable
style="width: 200px"
>
</DatePicker>
</FormItem>
<FormItem label="抢购时间段" prop="seckillPeriod">
<Tag
v-for="item in form.seckillPeriod"
:key="item"
:name="item"
closable
style="marrgin-left: 10px"
@on-close="removePeriodTime"
>{{ item >= 10 ? item : "0" + item }}:00</Tag
>
<InputNumber
:max="23"
:min="0"
v-model="periodTime"
v-show="showAddPeriod"
@on-blur="addPeriodTime"
></InputNumber>
<Button type="default" @click="addPeriod">添加时间段</Button>
</FormItem>
<FormItem label="申请规则" prop="seckillRule">
<Input
type="text"
v-model="form.seckillRule"
placeholder="申请规则"
clearable
style="width: 260px"
/>
</FormItem>
</div>
<div class="foot-btn">
<Button @click="closeCurrentPage" style="margin-right: 5px">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
>提交</Button
>
</div>
</div>
</Form>
</Card>
</div>
</template>
<script>
import { updateSeckill, seckillDetail } from "@/api/promotion";
export default {
name: "addSeckill",
data() {
return {
form: {
/** 活动名称 */
promotionName: "",
/** 报名截止时间 */
applyEndTime: "",
/** 活动开始时间 */
startTime: "",
/** 抢购时间段 */
seckillPeriod: [],
/** 申请规则 */
seckillRule: "",
promotionStatus: "NEW",
},
id: this.$route.query.id, // 活动id
periodTime: null, // 抢购时间段
showAddPeriod: false, // input显隐
submitLoading: false, // 添加或编辑提交状态
formRule: {
promotionName: [{ required: true, message: "请填写活动名称" }],
applyEndTime: [{ required: true, message: "请填写报名截止时间" }],
seckillPeriod: [{ required: true, message: "请填写抢购时间段" }],
startTime: [{ required: true, message: "请填写活动开始时间" }],
seckillRule: [{ required: true, message: "请输入申请规则" }],
},
};
},
mounted() {
// 如果id不为空则查询信息
if (this.id) {
this.getData();
}
},
methods: {
// 关闭当前页面
closeCurrentPage() {
this.$store.commit("removeTag", "manager-seckill-add");
localStorage.pageOpenedList = JSON.stringify(this.$store.state.app.pageOpenedList);
this.$router.go(-1);
},
// 获取详情数据
getData() {
seckillDetail(this.id).then((res) => {
if (res.success) {
let data = res.result;
data.seckillPeriod = res.result.hours.split(",");
this.form = data;
}
});
},
addPeriod() {
// 添加时间段显示input
this.addPeriodTime();
this.showAddPeriod = true;
},
addPeriodTime() {
// 添加秒杀时间段
this.showAddPeriod = false;
if (
this.periodTime !== null &&
!this.form.seckillPeriod.includes(this.periodTime)
) {
this.form.seckillPeriod.push(this.periodTime);
}
},
removePeriodTime(event, name) {
// 移除秒杀时间段
this.form.seckillPeriod = this.form.seckillPeriod.filter((i) => i !== name);
},
// // 申请截止时间格式化
// applyTimeChange (time) {
// console.log(time);
// this.form.applyEndTime = time
// },
// // 开始时间格式化
// startTimeChange (time) {
// this.form.startTime = time
// },
/** 添加秒杀活动 */
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.submitLoading = true;
this.form.hours = this.form.seckillPeriod.toString();
delete this.form.createTime;
delete this.form.updateTime;
delete this.form.endTime;
delete this.form.seckillApplyList;
let params = this.form;
params.startTime = this.$options.filters.unixToDate(this.form.startTime / 1000);
params.applyEndTime = this.$options.filters.unixToDate(
this.form.applyEndTime / 1000
);
// 编辑
updateSeckill(params).then((res) => {
this.submitLoading = false;
if (res && res.success) {
this.$Message.success("编辑成功");
this.closeCurrentPage();
}
});
}
});
},
},
};
</script>
<style lang="scss" scoped>
h4 {
margin-bottom: 10px;
padding: 0 10px;
border: 1px solid #ddd;
background-color: #f8f8f8;
font-weight: bold;
color: #333;
font-size: 14px;
line-height: 40px;
text-align: left;
}
.ivu-form-item {
margin-bottom: 30px;
}
</style>

View File

@@ -0,0 +1,311 @@
<template>
<div class="seckill-goods">
<Card>
<Table border :columns="columns" :data="data">
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
</template>
<template slot-scope="{ row }" slot="hours">
<Tag v-for="item in unixHours(row.hours)" :key="item">{{ item }}</Tag>
</template>
</Table>
<Table
:loading="loading"
border
class="operation"
:columns="goodsColumns"
:data="goodsList"
ref="table"
>
<template slot-scope="{ row }" slot="originalPrice">
<div>{{ row.originalPrice | unitPrice("¥") }}</div>
</template>
<template slot-scope="{ row }" slot="quantity">
<div>{{ row.quantity }}</div>
</template>
<template slot-scope="{ row }" slot="price">
<div>{{ row.price | unitPrice("¥") }}</div>
</template>
<template slot-scope="{ row }" slot="time">
<Tag>{{ row.timeLine + ":00" }}</Tag>
</template>
<template slot-scope="{ row }" slot="QRCode">
<img
v-if="row.QRCode"
:src="row.QRCode || '../../../assets/lili.png'"
width="50px"
height="50px"
alt=""
/>
</template>
<template slot-scope="{ row, index }" slot="action">
<Button
type="error"
size="small"
@click="delGoods(index,row)"
>删除
</Button>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber + 1"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</div>
</template>
<script>
import {
seckillGoodsList,
seckillDetail,
auditApplySeckill,
delSeckillGoods
} from "@/api/promotion.js";
export default {
data() {
return {
promotionStatus: "", // 活动状态
showModal: false, // modal显隐
openTip: true, // 显示提示
loading: false, // 表单加载状态
submitLoading: false, // 加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 0, // 当前页数
pageSize: 100, // 页面大小
},
total: 0, // 总数
selectList: [], // 多选数据
selectCount: 0, // 多选计数
data: [], // 表单数据
columns: [ // 表头
{
title: "活动名称",
key: "promotionName",
minWidth: 120,
},
{
title: "活动开始时间",
key: "startTime",
},
{
title: "报名截止时间",
slot: "applyEndTime",
},
{
title: "时间场次",
slot: "hours",
},
{
title: "活动状态",
key: "promotionStatus",
minWidth: 80,
sortable: false,
render: (h, params) => {
if (params.row.promotionStatus == "NEW") {
return h("div", [
h("Badge", {
props: {
status: "error",
text: "新建",
},
}),
]);
} else if (params.row.promotionStatus == "START") {
return h("div", [
h("Badge", {
props: {
status: "success",
text: "开始",
},
}),
]);
} else if (params.row.promotionStatus == "END") {
return h("div", [
h("Badge", {
props: {
status: "error",
text: "结束",
},
}),
]);
} else if (params.row.promotionStatus == "CLOSE") {
return h("div", [
h("Badge", {
props: {
status: "error",
text: "废弃",
},
}),
]);
}
},
},
],
goodsColumns: [ // 商品表单
{
title: "商品名称",
key: "goodsName",
minWidth: 120,
tooltip: true
},
{
title: "商品价格",
slot: "originalPrice",
width: 110,
},
{
title: "库存",
slot: "quantity",
minWidth: 30,
width: 90
},
{
title: "活动价格",
slot: "price",
width: 100,
},
{
title: "商家名称",
key: "storeName",
minWidth: 100,
tooltip: true
},
{
title: "活动场次",
width: 100,
slot: "time",
},
// {
// title: "状态",
// slot: "promotionApplyStatus",
// width: 90,
// },
{
title: "操作",
slot: "action",
width: 150,
align: "center",
},
],
goodsList: [], // 商品列表
params: { // 请求参数
seckillId: this.$route.query.id,
applyStatus: "PASS",
failReason: "",
ids: "",
},
rules: { // 验证规则
failReason: [{required: true, message: "请输入拒绝原因"}],
},
};
},
methods: {
// 初始化数据
init() {
this.getSeckillMsg();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 清除选中状态
clearSelectAll() {
this.$refs.table.selectAll(false);
},
getDataList() {
// 获取商品详情
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;
}
});
},
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();
}
});
},
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("删除成功!");
}
})
},
});
},
unixDate(time) {
// 处理报名截止时间
return this.$options.filters.unixToDate(new Date(time) / 1000);
},
unixHours(item) {
// 处理小时场次
let hourArr = item.split(",");
for (let i = 0; i < hourArr.length; i++) {
hourArr[i] += ":00";
}
return hourArr;
}
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
.operation {
margin: 10px 0;
}
.reason {
cursor: pointer;
color: #2d8cf0;
font-size: 12px;
}
</style>

View File

@@ -0,0 +1,150 @@
<template>
<div v-if="templateShow">
<Form :model="form" :label-width="120">
<FormItem label="每日场次设置">
<Row :gutter="16" class="row">
<Col class="time-item" @click.native="handleClickTime(item,index)" v-for="(item,index) in this.times" :key="index" span="3">
<div class="time" :class="{'active':item.check}">{{item.time}}:00</div>
</Col>
</Row>
</FormItem>
<FormItem label="秒杀规则">
<Input type="textarea" :autosize="{minRows: 4,}" v-model="form.seckillRule" placeholder="申请规则" clearable style="width: 360px; margin-left:10px" />
</FormItem>
<FormItem>
<div class="foot-btn">
<Button @click="closeCurrentPage" style="margin-right: 5px">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit">提交</Button>
</div>
</FormItem>
</Form>
</div>
</template>
<script>
import { getSetting, setSetting } from "@/api/index";
export default {
data() {
return {
templateShow:false, // 设置是否显示
submitLoading: false,
times: [], //时间集合 1-24点
form: {
seckillRule: "",
},
};
},
mounted() {
/**
* 初始化
*/
this.init();
},
methods: {
/**
* 关闭当前页面
*/
closeCurrentPage() {
this.$store.commit("removeTag", "manager-seckill-add");
localStorage.pageOpenedList = JSON.stringify(
this.$store.state.app.pageOpenedList
);
this.$router.go(-1);
},
/**
* 提交秒杀信息
*/
async handleSubmit() {
let hours = this.times
.filter((item) => {
return item.check;
})
.map((item) => {
return item.time;
})
.join(",");
let result = await setSetting("SECKILL_SETTING", {
seckillRule: this.form.seckillRule,
hours,
});
if (result.success) {
this.$Message.success("设置成功!");
this.init();
}
},
/**
* 初始化当前信息
*/
async init() {
let result = await getSetting("SECKILL_SETTING");
if (result.success) {
this.templateShow = true
this.form.seckillRule = result.result.seckillRule;
this.times=[]
for (let i = 0; i < 24; i++) {
// 将数据拆出
if (result.result.hours) {
let way = result.result.hours.split(",");
way.forEach((hours) => {
if (hours == i) {
this.times.push({
time: i,
check: true,
});
}
});
}
if (!this.times[i]) {
this.times.push({
time: i,
check: false,
});
}
}
}
},
/**
* 选中时间
*/
handleClickTime(val, index) {
val.check = !val.check;
},
},
};
</script>
<style scoped lang="scss">
.row {
width: 50%;
}
.foot-btn {
margin-left: 10px;
}
.time-list {
display: flex;
flex-wrap: wrap;
}
.active {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
color: #fff;
background: $theme_color !important;
}
.time {
width: 100%;
cursor: pointer;
transition: 0.35s;
border-radius: 0.8em;
justify-content: center;
align-items: center;
display: flex;
background: #f3f5f7;
height: 100%;
}
.time-item {
height: 50px;
margin: 8px 0;
font-size: 15px;
}
</style>

View File

@@ -0,0 +1,297 @@
<template>
<div class="seckill">
<Card>
<Row>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="活动名称" prop="promotionName">
<Input
type="text"
v-model="searchForm.promotionName"
placeholder="请输入活动名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 200px"
>
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动时间">
<DatePicker
v-model="selectDate"
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 200px"
>
</DatePicker>
</Form-item>
<Button
@click="handleSearch"
type="primary"
icon="ios-search"
class="search-btn"
>搜索</Button
>
</Form>
</Row>
<Tabs value="list" class="mt_10" @on-click="clickTabPane">
<TabPane label="秒杀活动列表" name="list">
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
>
<template slot-scope="{ row }" slot="action">
<Button
type="info"
size="small"
class="mr_5"
v-if="row.promotionStatus == 'NEW'"
@click="edit(row)"
>编辑</Button
>
<Button type="info" size="small" class="mr_5" v-else @click="manage(row)"
>查看</Button
>
<Button
type="success"
size="small"
class="mr_5"
v-if="row.promotionStatus == 'NEW'"
@click="manage(row)"
>管理</Button
>
<Button
type="error"
size="small"
v-if="row.promotionStatus == 'START' || row.promotionStatus == 'NEW'"
class="mr_5"
@click="off(row)"
>下架</Button
>
&nbsp;
<Button
type="error"
size="small"
v-if="row.promotionStatus == 'CLOSE'"
ghost
@click="expire(row)"
>删除</Button
>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
style="margin: 20px 0"
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</TabPane>
<TabPane label="秒杀活动设置" name="setup">
<setupSeckill v-if="setupFlag"></setupSeckill>
</TabPane>
</Tabs>
</Card>
</div>
</template>
<script>
import { getSeckillList, delSeckill, updateSeckillStatus } from "@/api/promotion";
import setupSeckill from "@/views/promotions/seckill/seckill-setup";
import { promotionsStatusRender } from "@/utils/promotions";
export default {
name: "seckill",
components: {
setupSeckill,
},
data() {
return {
selectDate: [],
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
},
setupFlag: false, //默认不请求设置
columns: [
// 表单
{
title: "活动名称",
key: "promotionName",
minWidth: 130,
tooltip: true,
},
{
title: "开始时间",
key: "startTime",
width: 180,
},
{
title: "申请截止时间",
key: "applyEndTime",
width: 180,
},
{
title: "活动状态",
key: "promotionStatus",
width: 100,
render: (h, params) => {
return promotionsStatusRender(h, params);
},
},
{
title: "申请规则",
key: "seckillRule",
minWidth: 120,
tooltip: true,
},
{
title: "操作",
slot: "action",
align: "center",
width: 250,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
};
},
methods: {
// tab栏点击切换列表和设置
clickTabPane(name) {
if (name == "setup") {
this.setupFlag = true;
} else {
this.setupFlag = false;
}
},
// 初始化信息
init() {
this.getDataList();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
edit(v) {
// 编辑
this.$router.push({ name: "manager-seckill-add", query: { id: v.id } });
},
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]) {
this.searchForm.startTime = this.selectDate[0].getTime();
this.searchForm.endTime = this.selectDate[1].getTime();
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
}
// 带多条件搜索参数获取表单数据
getSeckillList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss">
.mr_5 {
margin: 0 5px;
}
</style>