refactor(ui): 替换iView为TDesign组件库并优化相关代码

feat(coupon): 新增优惠券详情页面
feat(api): 添加会员评价状态更新和删除接口
perf(pagination): 统一分页大小选项为[20, 50, 100]
style(theme): 移除旧主题文件并更新样式类名
fix(menu): 修复菜单组件兼容性问题
chore(deps): 更新package.json依赖项
docs(modal): 添加全局Modal组件兼容层
This commit is contained in:
pikachu1995@126.com
2025-12-07 19:08:03 +08:00
parent d701c72928
commit 43f214b40a
89 changed files with 2253 additions and 1556 deletions

View File

@@ -0,0 +1,84 @@
<template>
<div class="info">
<t-card>
<t-descriptions title="优惠券详情" column="2" bordered>
<t-descriptions-item label="活动名称">{{ info.promotionName }}</t-descriptions-item>
<t-descriptions-item label="优惠券名称">{{ info.couponName }}</t-descriptions-item>
<t-descriptions-item label="类型">{{ couponTypeText }}</t-descriptions-item>
<t-descriptions-item label="金额/折扣">
<div v-if="info.couponType === 'PRICE'"><priceColorScheme :value="info.price" :color="$mainColor" /></div>
<div v-else>{{ (info.couponDiscount || 0) + '' }}</div>
</t-descriptions-item>
<t-descriptions-item label="活动方式">{{ getTypeText }}</t-descriptions-item>
<t-descriptions-item label="发放数量">{{ info.publishNum === 0 ? '不限制' : info.publishNum }}</t-descriptions-item>
<t-descriptions-item label="领取限制">{{ info.couponLimitNum === 0 ? '不限制' : info.couponLimitNum }}</t-descriptions-item>
<t-descriptions-item label="消费门槛">{{ info.consumeThreshold }}</t-descriptions-item>
<t-descriptions-item label="有效期">
<span v-if="info.getType === 'ACTIVITY' && info.rangeDayType === 'DYNAMICTIME'">长期有效</span>
<span v-else-if="info.startTime && info.endTime"><div v-html="info.startTime + '<br/>' + info.endTime"></div></span>
</t-descriptions-item>
<t-descriptions-item label="使用范围">{{ scopeTypeText }}</t-descriptions-item>
<t-descriptions-item label="范围描述">{{ info.description }}</t-descriptions-item>
</t-descriptions>
<div v-if="info.scopeType === 'PORTION_GOODS' && info.promotionGoodsList && info.promotionGoodsList.length" class="mt_10">
<t-table :columns="goodsColumns" :data="info.promotionGoodsList" rowKey="skuId"></t-table>
</div>
<div class="mt_10">
<t-button theme="primary" @click="back">返回</t-button>
</div>
</t-card>
</div>
</template>
<script>
import { getShopCoupon } from "@/api/promotion";
export default {
name: "coupon-info",
data() {
return {
info: {},
goodsColumns: [
{ title: "商品名称", colKey: "goodsName", minWidth: 120 },
{ title: "商品价格", colKey: "price", minWidth: 80, cell: (h, { row }) => h('priceColorScheme', { props: { value: row.price, color: this.$mainColor } }) },
{ title: "库存", colKey: "quantity", minWidth: 80 }
]
};
},
computed: {
couponTypeText() {
const t = this.info.couponType;
return t === "DISCOUNT" ? "打折" : t === "PRICE" ? "减免现金" : "";
},
getTypeText() {
const t = this.info.getType;
return t === "FREE" ? "免费领取" : t === "ACTIVITY" ? "活动赠送" : "";
},
scopeTypeText() {
const t = this.info.scopeType;
return t === "ALL" ? "全品类" : t === "PORTION_GOODS" ? "指定商品" : t === "PORTION_GOODS_CATEGORY" ? "部分商品分类" : "";
}
},
methods: {
init() {
const id = this.$route.query.id;
getShopCoupon(id).then((res) => {
if (res && res.success) {
const data = res.result || {};
if (!Array.isArray(data.promotionGoodsList)) data.promotionGoodsList = data.promotionGoodsList || [];
this.info = data;
}
});
},
back() {
this.$router.push({ name: "coupon" });
}
},
mounted() {
this.init();
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";
</style>

View File

@@ -117,7 +117,7 @@
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<div style="display: flex; margin-bottom: 10px">
<div class="flex mb_10">
<Button :disabled="disabled" type="primary" @click="openSkuList"
>选择商品</Button
>
@@ -609,7 +609,7 @@ h4 {
margin-left: 10px;
color: #999;
}
.ivu-form-item {
.t-form__item {
margin-bottom: 24px !important;
}
.wrapper {

View File

@@ -1,12 +1,12 @@
<template>
<div class="search">
<Card>
<Button style="margin-bottom: 10px" @click="back()">返回</Button>
<Button class="mb_10" @click="back()">返回</Button>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="75"
:label-width="100"
class="search-form mb_10"
>
<Form-item label="优惠券名称" prop="couponName">
@@ -46,7 +46,7 @@
type="daterange"
clearable
placeholder="选择起始时间"
style="width: 240px"
style="width: 360px"
></DatePicker>
</Form-item>
<Button
@@ -77,7 +77,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -102,7 +102,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
getType: "", // 默认排序方式
@@ -244,7 +244,7 @@ export default {
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
/**
@@ -282,3 +282,10 @@ export default {
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";
.search-form {
width: 100% !important;
}
</style>

View File

@@ -1,72 +1,63 @@
<template>
<div class="search">
<Card>
<Row>
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="100"
class="search-form"
>
<Form-item label="优惠券名称">
<Input
type="text"
v-model="searchForm.couponName"
placeholder="请输入优惠券名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 240px"
>
<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: 240px"
></DatePicker>
</Form-item>
<Button
<t-card>
<t-form
ref="searchForm"
:data="searchForm"
layout="inline"
:labelWidth="100"
class="search-form"
>
<t-form-item label="优惠券名称" name="couponName">
<t-input
v-model="searchForm.couponName"
placeholder="请输入优惠券名称"
clearable
style="width: 240px"
/>
</t-form-item>
<t-form-item label="活动时间">
<t-date-range-picker
v-model="selectDate"
clearable
placeholder="选择起始时间"
style="width: 300px"
valueType="time-stamp"
/>
</t-form-item>
<t-form-item>
<t-button
@click="handleSearch"
type="primary"
theme="primary"
class="search-btn"
icon="ios-search"
>搜索</Button
>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Row>
</Card>
<Card>
<Row class="operator padding-row">
<Button @click="add" type="primary">添加</Button>
<Button @click="delAll" class="ml_10">批量关闭</Button>
<Button @click="receivePage()" class="ml_10" type="info">优惠券领取记录</Button>
</Row>
<Table
>搜索</t-button>
<t-button @click="handleReset" class="search-btn" style="margin-left: 8px">重置</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<div class="operator padding-row">
<t-button @click="add" theme="primary">添加</t-button>
<t-button @click="delAll" class="ml_10">批量关闭</t-button>
<t-button @click="receivePage()" class="ml_10" variant="outline">优惠券领取记录</t-button>
</div>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<t-table
class="mt_10"
:loading="loading"
border
:columns="columns"
:columns="tColumns"
:data="data"
ref="table"
@on-selection-change="changeSelect"
rowKey="id"
:rowSelection="{ type: 'multiple', selectedRowKeys }"
@select-change="onSelectChange"
>
<template slot-scope="{ row }" slot="action">
<template #action="{ row }">
<a
v-if="row.promotionStatus === 'NEW' || row.promotionStatus === 'CLOSE'"
style="color:#2d8cf0;cursor:pointer;text-decoration:none"
@@ -92,31 +83,27 @@
@click="receivePage(row.id)"
>领取记录</a>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
</t-table>
<div class="mt_10" style="display:flex;justify-content:flex-end">
<t-pagination
:current="searchForm.pageNumber"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:total="Number(total)"
:pageSize="searchForm.pageSize"
:pageSizeOptions="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
showJumper
showPageSize
@change="({ current }) => changePage(current)"
@page-size-change="(size) => changePageSize(size)"
/>
</div>
</t-card>
</div>
</template>
<script>
import { getShopCouponList, updateCouponStatus } from "@/api/promotion";
import {
promotionsStatusRender,
promotionsScopeTypeRender,
} from "@/utils/promotions";
export default {
name: "coupon",
@@ -127,12 +114,14 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
},
selectList: [], // 多选数据
selectCount: 0, // 多选计数
selectedRowKeys: [],
columns: [
// 表头
{
@@ -175,7 +164,7 @@ export default {
},
{
title: "已被使用的数量/已领取数量",
key: "publishNum",
key: "usedCount",
render: (h, params) => {
return h("div", params.row.usedNum + "/" + params.row.receivedNum);
},
@@ -193,14 +182,7 @@ export default {
return h("div", [text]);
},
},
{
title: "品类描述",
key: "scopeType",
width: 120,
render: (h, params) => {
return promotionsScopeTypeRender(h, params);
},
},
{
title: "活动时间",
width: 150,
@@ -226,7 +208,9 @@ export default {
key: "promotionStatus",
fixed: "right",
render: (h, params) => {
return promotionsStatusRender(h, params);
const s = params?.row?.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -241,6 +225,30 @@ export default {
total: 0, // 表单数据总数
};
},
computed: {
tColumns() {
return (this.columns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
if (nc.render && !nc.cell && typeof nc.render === 'function') {
const origRender = nc.render
nc.cell = (h, { row, col, rowIndex }) => origRender(h, { row, column: col, index: rowIndex })
delete nc.render
}
return nc
})
}
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
init() {
this.getDataList();
@@ -279,7 +287,7 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
};
@@ -287,18 +295,22 @@ export default {
this.getDataList();
},
clearSelectAll() {
this.$refs.table.selectAll(false);
this.selectedRowKeys = [];
this.selectList = [];
this.selectCount = 0;
},
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
onSelectChange(selectedRowKeys, { selectedRowData } = {}) {
this.selectedRowKeys = selectedRowKeys || [];
const rows = selectedRowData || [];
this.selectList = rows;
this.selectCount = rows.length;
},
// 获取列表数据
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();
this.searchForm.startTime = this.selectDate[0];
this.searchForm.endTime = this.selectDate[1];
} else {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
@@ -315,9 +327,11 @@ export default {
},
// 跳转编辑优惠券页面
see(v, only) {
let data;
only ? (data = { onlyView: true, id: v.id }) : (data = { id: v.id });
this.$router.push({ name: "add-coupon", query: data });
if (only) {
this.$router.push({ name: "coupon-info", query: { id: v.id } });
} else {
this.$router.push({ name: "add-coupon", query: { id: v.id } });
}
},
// 下架优惠券
remove(v) {

View File

@@ -11,13 +11,9 @@
</FormItem>
<FormItem label="活动时间" prop="rangeTime">
<DatePicker type="datetimerange" v-model="form.rangeTime" :disabled="form.promotionStatus != 'NEW'"
format="yyyy-MM-dd HH:mm:ss" placeholder="请选择" :options="options" style="width: 280px">
format="yyyy-MM-dd HH:mm:ss" placeholder="请选择" :options="options" style="width: 420px">
</DatePicker>
</FormItem>
<FormItem label="活动描述" prop="description">
<Input v-model="form.description" :disabled="form.promotionStatus != 'NEW'" type="textarea" :rows="4"
clearable style="width: 280px" />
</FormItem>
</div>
<h4>优惠设置</h4>
@@ -82,7 +78,7 @@
</FormItem>
<FormItem style="width: 100%" v-if="form.scopeType == 'PORTION_GOODS'">
<div style="display: flex; margin-bottom: 10px" v-if="form.promotionStatus == 'NEW'">
<div class="flex mb_10" v-if="form.promotionStatus == 'NEW'">
<Button type="primary" @click="openSkuList">选择商品</Button>
<Button type="error" ghost style="margin-left: 10px" @click="delSelectGoods">批量删除</Button>
</div>
@@ -156,6 +152,7 @@ export default {
Cookies,
form: {
// 活动表单
promotionName: "",
discountType: "fullMinusFlag",
scopeType: "ALL",
promotionGoodsList: [],
@@ -164,15 +161,14 @@ export default {
id: this.$route.query.id, // 活动id
submitLoading: false, // 添加或编辑提交状态
selectedGoods: [], // 已选商品列表,便于删除
formRule: {
// 验证规则
promotionName: [{ required: true, message: "活动名称不能为空" }],
rangeTime: [{ required: true, message: "请选择活动时间" }],
description: [{ required: true, message: "请填写活动描述" }],
price: [
{ required: true, message: "请输入面额" },
{ validator: checkPrice },
],
formRule: {
// 验证规则
promotionName: [{ required: true, message: "活动名称不能为空" }],
rangeTime: [{ required: true, message: "请选择活动时间" }],
price: [
{ required: true, message: "请输入面额" },
{ validator: checkPrice },
],
consumptionLimit: [{ required: true, validator: checkWeight }],
fullMoney: [{ required: true, validator: checkWeight }],
fullMinus: [
@@ -236,6 +232,9 @@ export default {
this.getDetail();
this.columns.shift()
this.columns.pop()
} else {
const today = this.$options.filters.unixToDate(Date.now() / 1000, "yyyy-MM-dd");
this.$set(this.form, 'promotionName', `满额活动${today}`);
}
await this.getCouponList();
await this.getGiftList();
@@ -397,7 +396,7 @@ export default {
getCouponList (query) {
// 优惠券列表
let params = {
pageSize: 10,
pageSize: 20,
pageNumber: 0,
getType: "ACTIVITY",
couponName: query,
@@ -414,7 +413,7 @@ export default {
getGiftList (query) {
// 赠品列表
let params = {
pageSize: 10,
pageSize: 20,
pageNumber: 1,
id: query === this.form.giftId ? this.form.giftId : null,
goodsName: query === this.form.giftId ? null : query,
@@ -452,7 +451,7 @@ h4 {
color: #999;
}
.ivu-form-item {
.t-form__item {
margin-bottom: 24px !important;
}
</style>

View File

@@ -2,17 +2,9 @@
<div class="search">
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="活动名称">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select v-model="searchForm.promotionStatus" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动名称">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动时间">
<DatePicker v-model="selectDate" type="daterange" clearable placeholder="选择起始时间" style="width: 240px">
</DatePicker>
@@ -27,6 +19,13 @@
<Row class="operation">
<Button type="primary" @click="newAct">新增</Button>
</Row>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
@@ -74,6 +73,7 @@ export default {
pageSize: 20,
sort: "startTime",
order: "desc",
promotionStatus: "",
},
columns: [
{
@@ -101,32 +101,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "default";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "blue";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [
h(
"Tag",
{
props: {
color: color,
},
},
text
),
]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -139,6 +116,15 @@ export default {
data: [], // 表格数据
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
// 改变页码
newAct () {
@@ -161,7 +147,7 @@ export default {
// 搜索
handleSearch () {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -173,6 +159,7 @@ export default {
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.getDataList();
},

View File

@@ -526,7 +526,7 @@ export default {
<style lang="scss" scoped>
.action {
display: flex;
::v-deep .ivu-btn {
::v-deep .t-button {
margin: 0 5px !important;
}
}

View File

@@ -1,38 +1,23 @@
<template>
<div>
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="100" class="search-form">
<Form-item label="直播状态" prop="promotionStatus">
<Select v-model="searchForm.status" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">直播中</Option>
<Option value="END">已结束</Option>
</Select>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card>
<t-card>
<div class="btns">
<Button @click="createLive()" type="primary">创建直播</Button>
<t-button theme="primary" @click="createLive()">创建直播</t-button>
</div>
<Tabs v-model="searchForm.status">
<t-tabs v-model="searchForm.status">
<!-- 标签栏 -->
<TabPane v-for="(item,index) in tabs" :key="index" :name="item.status" :label="item.title">
<t-tab-panel v-for="(item,index) in tabs" :key="index" :value="item.status" :label="item.title">
</TabPane>
</t-tab-panel>
</Tabs>
<Table :columns="liveColumns" :data="liveData"></Table>
<Row type="flex" 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="[20, 50, 100]"
size="small" show-total show-elevator show-sizer></Page>
</Row>
</t-tabs>
<t-table :columns="liveColumns" :data="liveData"></t-table>
<t-row justify="end" class="mt_10">
<t-pagination :current="searchForm.pageNumber" :total="Number(total)" :pageSize="searchForm.pageSize" @change="(info) => { if (info && typeof info.pageSize !== 'undefined' && info.pageSize !== searchForm.pageSize) { changePageSize(info.pageSize) } if (info && typeof info.current !== 'undefined') { changePageNumber(info.current) } }" :pageSizeOptions="[20, 50, 100]" size="small" :showJumper="true" />
</t-row>
</Card>
</t-card>
</div>
</template>
@@ -47,10 +32,14 @@ export default {
searchForm: {
pageSize: 20,
pageNumber: 1,
status: "NEW",
status: "",
},
// 直播tab选项栏
tabs: [
{
title: "全部",
status: "",
},
{
title: "直播中",
status: "START",
@@ -67,81 +56,26 @@ export default {
liveColumns: [
{
title: "直播标题",
key: "name",
colKey: "name",
},
{
title: "主播昵称",
key: "anchorName",
colKey: "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: "直播状态",
render: (h, params) => {
return h(
"span",
params.row.status == "NEW"
? "未开始"
: params.row.status == "START"
? "直播中"
: "已结束"
);
},
title: "开始时间",
colKey: "startTime",
cell: (h, { row }) => h('span', this.$options.filters.unixToDate(row.startTime))
},
{
title: "操作",
key: "action",
render: (h, params) => {
return h(
"div",
{
style: {
display: "flex",
},
},
[
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.getLiveDetail(params.row);
},
},
},
"查看/添加商品"
),
]
);
},
},
], //table中显示的title
colKey: "action",
cell: (h, { row }) => h('a', {
style: { color: '#2d8cf0', cursor: 'pointer', textDecoration: 'none' },
on: { click: () => this.getLiveDetail(row) }
}, '查看/添加商品')
}
],
liveData: [], //table中显示的直播数据
};
},
@@ -149,6 +83,7 @@ export default {
"searchForm.status": {
handler() {
this.liveData = [];
this.searchForm.pageNumber = 1;
this.getStoreLives();
},
deep: true,

View File

@@ -1,59 +1,59 @@
<template>
<div class="wrapper">
<Card>
<Form ref="searchForm" :model="params" inline :label-width="100" class="search-form">
<Form-item label="商品名称">
<Input type="text" v-model="params.name" placeholder="请输入商品名称" clearable style="width: 240px" />
</Form-item>
<t-card>
<t-form ref="searchForm" :data="params" layout="inline" :labelWidth="100" class="search-form">
<t-form-item label="商品名称" name="name">
<t-input v-model="params.name" placeholder="请输入商品名称" clearable style="width: 240px" />
</t-form-item>
<Button @click="getLiveGoodsMethods('clear')" type="primary" class="search-btn" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card>
<t-form-item>
<t-button @click="getLiveGoodsMethods('clear')" theme="primary" class="search-btn">搜索</t-button>
</t-form-item>
</t-form>
</t-card>
<t-card>
<h4 v-if="!reviewed">
由于直播商品需经过小程序直播平台的审核你需要在此先提审商品为了不影响直播间选取商品请提前1天提审商品
</h4>
<div>
<Tabs v-model="params.auditStatus">
<TabPane v-for="(item,index) in liveTabWay" :key="index" :label="item.label" :name="item.type+''">
</TabPane>
</Tabs>
<t-tabs :value="params.auditStatus" @change="val => params.auditStatus = Number(val)">
<t-tab-panel v-for="(item,index) in liveTabWay" :key="index" :label="item.label" :value="item.type">
</t-tab-panel>
</t-tabs>
</div>
<Button v-if="!reviewed" type="primary" style="margin-bottom:10px;" @click="addNewLiveGoods" icon="md-add">选择商品</Button>
<Button type="primary" v-if="params.auditStatus == 0" ghost style="margin:0 0 10px 10px" @click="getLiveGoodsMethods('clear')">更新状态</Button>
<t-button v-if="!reviewed" theme="primary" class="mb_10" @click="addNewLiveGoods">选择商品</t-button>
<t-button theme="primary" v-if="params.auditStatus == 0" variant="outline" style="margin:0 0 10px 10px" @click="getLiveGoodsMethods('clear')">更新状态</t-button>
<div style="position:relative">
<Spin size="large" fix v-if="tableLoading">
</Spin>
<Table class="mt_10" disabled-hover :columns="liveGoodsColumns" :data="liveGoodsData">
<t-table class="mt_10" :columns="tColumns" :data="liveGoodsData" rowKey="id">
<template slot-scope="{ row }" slot="goodsName">
<template #goodsName="{ row }">
<div class="flex-goods">
<img class="thumbnail" :src="row.thumbnail || row.goodsImage">
{{ row.goodsName || row.name }}
</div>
</template>
<template slot-scope="{ row ,index }" class="price" slot="price">
<template #price="{ row ,index }">
<!-- 如果为新增商品显示 -->
<RadioGroup v-if="params.auditStatus == 99" @on-change="changeRadio(row,'priceType')" v-model="row.priceType">
<t-radio-group v-if="params.auditStatus == 99" @change="val => changeRadio(row,'priceType', val)" v-model="row.priceType">
<div class="price-item">
<Radio :label="1">一口价:</Radio>
<InputNumber :min="0.1" v-if="liveGoodsData[index].priceType == 1" style="width:100px" v-model="liveGoodsData[index].price"></InputNumber>
<t-radio :value="1">一口价:</t-radio>
<t-input-number :min="0.1" v-if="liveGoodsData[index].priceType == 1" style="width:100px" v-model="liveGoodsData[index].price"></t-input-number>
</div>
<div class="price-item">
<Radio :label="2">区间价:</Radio> <span v-if="liveGoodsData[index].priceType == 2">
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price" />
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
<t-radio :value="2">区间价:</t-radio> <span v-if="liveGoodsData[index].priceType == 2">
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price" />
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
</span>
</div>
<div class="price-item">
<Radio :label="3">折扣价:</Radio> <span v-if="liveGoodsData[index].priceType == 3">原价<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price"></InputNumber>现价
<InputNumber :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
<t-radio :value="3">折扣价:</t-radio> <span v-if="liveGoodsData[index].priceType == 3">原价<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price"></t-input-number>现价
<t-input-number :min="0.1" style="width:100px" v-model="liveGoodsData[index].price2" />
</span>
</div>
</RadioGroup>
</t-radio-group>
<div v-else>
<div v-if="row.priceType == 1"><priceColorScheme :value="row.price" :color="$mainColor" /></div>
<div class="flex" v-if="row.priceType == 2"><priceColorScheme :value="row.price" :color="$mainColor" />至<priceColorScheme :value="row.price2" :color="$mainColor" /></div>
@@ -62,25 +62,23 @@
</template>
<template slot-scope="{ row ,index }" slot="action">
<template #action="{ row ,index }">
<a v-if="params.auditStatus == 99" @click="liveGoodsData.splice(index,1)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">删除</a>
<span v-if="params.auditStatus == 99 || (params.auditStatus != 99 && !reviewed) || reviewed" style="margin:0 8px;color:#dcdee2">|</span>
<a v-if="params.auditStatus != 99 && !reviewed" @click="$router.push({path:'/goods-operation-edit',query:{id:row.goodsId}})" style="color:#2d8cf0;cursor:pointer;text-decoration:none">查看</a>
<span v-if="reviewed" style="margin:0 8px;color:#dcdee2">|</span>
<a v-if="reviewed" @click="selectedLiveGoods(row,index)" style="color:#2d8cf0;cursor:pointer;text-decoration:none">{{row.___selected ? '':''}}选择</a>
</template>
</Table>
</t-table>
<div class="flex">
<Page size="small" :total="goodsTotal" @on-change="changePageNumber" class="pageration" @on-page-size-change="changePageSize" :page-size="params.pageSize" show-total show-elevator
show-sizer>
</Page>
<t-pagination size="small" :total="Number(goodsTotal)" @change="({ current }) => changePageNumber(current)" class="pageration" @page-size-change="(size) => changePageSize(size)" :pageSize="params.pageSize" :pageSizeOptions="[20, 50, 100]" showJumper showPageSize />
</div>
</div>
</Card>
</t-card>
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
<div v-if="params.auditStatus == 99" class="submit">
<Button type="primary" :loading="saveGoodsLoading" @click="saveLiveGoods">保存商品</Button>
<t-button theme="primary" :loading="saveGoodsLoading" @click="saveLiveGoods">保存商品</t-button>
</div>
</div>
</template>
@@ -99,7 +97,7 @@ export default {
tableLoading: false, //表格是否加载
params: {
pageNumber: 1,
pageSize: 10,
pageSize: 20,
auditStatus: 2, //商品状态
},
// 商品审核状态
@@ -152,6 +150,16 @@ export default {
selectedGoods: [],
};
},
computed: {
tColumns() {
return (this.liveGoodsColumns || []).map(c => {
const nc = Object.assign({}, c)
if (nc.key && !nc.colKey) { nc.colKey = nc.key; delete nc.key }
if (nc.slot && !nc.colKey) { nc.colKey = nc.slot; delete nc.slot }
return nc
})
}
},
props: {
// 是否是已审核,此处为组件模式时使用。去除添加等功能 只保留查询以及新增选择回调数据
reviewed: {

View File

@@ -181,7 +181,7 @@ export default {
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-form-item {
::v-deep .t-form__item {
padding: 18px 10px !important;
}
</style>

View File

@@ -49,7 +49,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -89,7 +89,7 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
},
submitLoading: false, // 添加或编辑提交状态
@@ -230,7 +230,7 @@ export default {
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},

View File

@@ -18,19 +18,6 @@
style="width: 240px"
/>
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select
v-model="searchForm.promotionStatus"
placeholder="请选择"
clearable
style="width: 240px"
>
<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"
@@ -55,6 +42,13 @@
<Row class="operation padding-row">
<Button @click="newAct" type="primary">添加</Button>
</Row>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table">
<template slot-scope="{ row }" slot="action">
<div class="row">
@@ -77,7 +71,7 @@
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
@@ -98,9 +92,10 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 0, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime", // 默认排序字段
order: "desc", // 默认排序方式
promotionStatus: "",
},
selectDate: null, // 选择的时间
columns: [
@@ -122,22 +117,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "default";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "blue";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [h("Tag", { props: { color: color } }, text)]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -151,6 +133,15 @@ export default {
total: 0, // 表单数据总数
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 0
this.getDataList()
},
deep: true
}
},
methods: {
// 初始化数据
init() {
@@ -169,7 +160,7 @@ export default {
// 搜索
handleSearch() {
this.searchForm.pageNumber = 0;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -177,9 +168,10 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 0, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.selectDate = "";

View File

@@ -2,17 +2,9 @@
<div class="seckill">
<Card>
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="活动名称" prop="goodsName">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动状态" prop="promotionStatus">
<Select v-model="searchForm.promotionStatus" placeholder="请选择" clearable style="width: 240px">
<Option value="NEW">未开始</Option>
<Option value="START">已开始/上架</Option>
<Option value="END">已结束/下架</Option>
<Option value="CLOSE">紧急关闭/作废</Option>
</Select>
</Form-item>
<Form-item label="活动名称" prop="goodsName">
<Input type="text" v-model="searchForm.promotionName" placeholder="请输入活动名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="活动时间">
<DatePicker v-model="selectDate" type="daterange" clearable placeholder="选择起始时间" style="width: 240px">
</DatePicker>
@@ -22,6 +14,13 @@
</Form>
</Card>
<Card>
<t-tabs v-model="searchForm.promotionStatus" class="mt_10">
<t-tab-panel value="" label="全部" />
<t-tab-panel value="NEW" label="未开始" />
<t-tab-panel value="START" label="已开始/上架" />
<t-tab-panel value="END" label="已结束/下架" />
<t-tab-panel value="CLOSE" label="紧急关闭/作废" />
</t-tabs>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" class="mt_10">
<template slot-scope="{ row }" slot="applyEndTime">
{{ unixDate(row.applyEndTime) }}
@@ -38,7 +37,7 @@
</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
@on-page-size-change="changePageSize" :page-size-opts="[20, 50, 100]" size="small" show-total show-elevator
show-sizer></Page>
</Row>
</Card>
@@ -57,9 +56,10 @@ export default {
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
},
columns: [
{
@@ -84,32 +84,9 @@ export default {
key: "promotionStatus",
width: 100,
render: (h, params) => {
let text = "未知",
color = "default";
if (params.row.promotionStatus == "NEW") {
text = "未开始";
color = "geekblue";
} else if (params.row.promotionStatus == "START") {
text = "已开始";
color = "green";
} else if (params.row.promotionStatus == "END") {
text = "已结束";
color = "volcano";
} else if (params.row.promotionStatus == "CLOSE") {
text = "已关闭";
color = "red";
}
return h("div", [
h(
"Tag",
{
props: {
color: color,
},
},
text
),
]);
const s = params && params.row && params.row.promotionStatus
const map = { NEW: "未开始", START: "已开始", END: "已结束", CLOSE: "紧急关闭" }
return h('div', map[s] || s || '-')
},
},
{
@@ -123,6 +100,15 @@ export default {
total: 0, // 表单数据总数
};
},
watch: {
'searchForm.promotionStatus': {
handler() {
this.searchForm.pageNumber = 1
this.getDataList()
},
deep: true
}
},
methods: {
// 初始化数据
init () {
@@ -141,7 +127,7 @@ export default {
// 搜索
handleSearch () {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 重置
@@ -149,9 +135,10 @@ export default {
this.searchForm = {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
pageSize: 20, // 页面大小
sort: "startTime",
order: "desc", // 默认排序方式
promotionStatus: "",
};
this.selectDate = "";
this.getDataList();