manager 升级到vue3

This commit is contained in:
pikachu1995@126.com
2026-05-25 10:49:09 +08:00
parent e7350899bf
commit 615ee91511
239 changed files with 22907 additions and 30841 deletions

View File

@@ -1,253 +1,289 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
label-width="70px"
class="search-form"
@keydown.enter.native="handleSearch"
@keyup.enter="handleSearch"
>
<Form-item label="商品名称" prop="goodsName">
<Input
type="text"
<el-form-item label="商品名称" prop="goodsName">
<el-input
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="商品编号" prop="id">
<Input
type="text"
</el-form-item>
<el-form-item label="商品编号" prop="id">
<el-input
v-model="searchForm.id"
placeholder="请输入商品编号"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="店铺名称" prop="id">
<Input
type="text"
</el-form-item>
<el-form-item label="店铺名称" prop="storeName">
<el-input
v-model="searchForm.storeName"
placeholder="请输入店铺名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="销售模式" prop="status">
<Select
</el-form-item>
<el-form-item label="销售模式" prop="salesModel">
<el-select
v-model="searchForm.salesModel"
placeholder="请选择"
clearable
style="width: 240px"
>
<Option value="RETAIL">零售</Option>
<Option value="WHOLESALE">批发</Option>
</Select>
</Form-item>
<Form-item label="商品类型" prop="status">
<Select
<el-option label="零售" value="RETAIL" />
<el-option label="批发" value="WHOLESALE" />
</el-select>
</el-form-item>
<el-form-item label="商品类型" prop="goodsType">
<el-select
v-model="searchForm.goodsType"
placeholder="请选择"
clearable
style="width: 240px"
>
<Option value="PHYSICAL_GOODS">实物商品</Option>
<Option value="VIRTUAL_GOODS">虚拟商品</Option>
</Select>
</Form-item>
<Form-item label="商品分组" prop="groupId">
<Select
<el-option label="实物商品" value="PHYSICAL_GOODS" />
<el-option label="虚拟商品" value="VIRTUAL_GOODS" />
</el-select>
</el-form-item>
<el-form-item label="商品分组" prop="groupId">
<el-select
v-model="searchForm.groupId"
placeholder="请选择商品分组"
clearable
filterable
style="width: 240px"
>
<Option v-for="item in goodsGroupList" :value="item.id" :key="item.id">{{ item.groupName }}</Option>
</Select>
</Form-item>
<Button
@click="handleSearch"
class="search-btn"
type="primary"
icon="ios-search"
>搜索</Button
>
</Form>
</Card>
<Card>
<el-option
v-for="item in goodsGroupList"
:key="item.id"
:label="item.groupName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="goods-tab">
<Tabs v-model="currentStatus" @on-click="goodsStatusClick">
<TabPane v-for="(item,index) in goodsStatusWithCount" :key="index" :label="item.title" :name="item.value">
</TabPane>
</Tabs>
<el-card>
<div class="goods-tab">
<el-tabs v-model="currentStatus" @tab-click="onStatusTabClick">
<el-tab-pane
v-for="(item, index) in goodsStatusWithCount"
:key="index"
:label="item.title"
:name="item.value"
/>
</el-tabs>
</div>
<!-- 批量操作按钮 -->
<div class="batch-operations" style="margin: 10px 0;">
<Button
<div class="batch-operations" style="margin: 10px 0">
<el-button
type="primary"
:disabled="selectedRows.length === 0"
style="margin-right: 10px"
@click="openSetGoodsGroup"
style="margin-right: 10px;"
>
批量设置分组
</Button>
<Button
</el-button>
<el-button
type="success"
:disabled="selectedRows.length === 0"
style="margin-right: 10px"
@click="batchUpper"
style="margin-right: 10px;"
>
批量上架
</Button>
<Button
</el-button>
<el-button
type="warning"
:disabled="selectedRows.length === 0"
style="margin-right: 10px"
@click="batchLower"
style="margin-right: 10px;"
>
批量下架
</Button>
<Button
</el-button>
<el-button
v-if="currentStatus === 'TOBEAUDITED'"
type="primary"
:disabled="selectedRows.length === 0"
@click="batchAudit"
>
批量审核
</Button>
</el-button>
</div>
<Table
:loading="loading"
:columns="columns"
:data="data"
<el-table
ref="table"
v-loading="loading"
:data="data"
class="mt_10"
@on-select="onSelect"
@on-select-all="onSelectAll"
@on-selection-change="onSelectionChange"
row-key="id"
@selection-change="onSelectionChange"
>
<!-- 商品图片格式化 -->
<template slot="imageSlot" slot-scope="{ row }">
<div style="margin-top: 5px;">
<el-table-column type="selection" width="100" align="center" />
<el-table-column prop="id" label="商品ID" width="200" show-overflow-tooltip />
<el-table-column label="商品图片" width="100" align="center">
<template #default="{ row }">
<img
v-if="row && row.original"
:src="row.original"
style="height: 50px; width: 50px; object-fit: cover;"
style="height: 50px; width: 50px; object-fit: cover"
/>
</div>
</template>
</template>
</el-table-column>
<el-table-column label="商品名称" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<a class="link-text" @click="linkTo(row.id, row.skuId)">{{ row.goodsName }}</a>
</template>
</el-table-column>
<el-table-column label="价格" width="200">
<template #default="{ row }">
<span :style="{ color: $mainColor }">{{ $filters.unitPrice(row.price, '¥') }}</span>
</template>
</el-table-column>
<el-table-column prop="buyCount" label="销量" width="150" />
<el-table-column prop="quantity" label="库存" width="150" />
<el-table-column label="销售模式" width="150">
<template #default="{ row }">
<span v-if="row">{{ salesModelText(row.salesModel) }}</span>
</template>
</el-table-column>
<el-table-column label="商品类型" width="150">
<template #default="{ row }">
<span v-if="row">{{ goodsTypeText(row.goodsType) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="150">
<template #default="{ row }">
<span v-if="row">{{ marketEnableText(row.marketEnable) }}</span>
</template>
</el-table-column>
<el-table-column label="审核状态" width="150">
<template #default="{ row }">
<span v-if="row">{{ authFlagText(row.authFlag) }}</span>
</template>
</el-table-column>
<el-table-column prop="storeName" label="店铺名称" width="200" show-overflow-tooltip />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<template v-if="row.authFlag === 'TOBEAUDITED'">
<a class="link-text" @click="openAuditModal(row)">审核</a>
<span class="op-split">|</span>
<a class="link-text" @click="showDetail(row)">查看</a>
</template>
<template v-else-if="row.marketEnable === 'DOWN'">
<a class="link-text" @click="upper(row)">上架</a>
<span class="op-split">|</span>
<a class="link-text" @click="showDetail(row)">查看</a>
</template>
<template v-else>
<a class="link-text" @click="edit(row)">下架</a>
<span class="op-split">|</span>
<a class="link-text" @click="showDetail(row)">查看</a>
</template>
</template>
</el-table-column>
</el-table>
<!-- 商品栏目格式化 -->
<template slot="goodsSlot" slot-scope="{ row }">
<div style="margin: 5px 0px; padding: 10px 0px;">
<div class="div-zoom">
<a @click="linkTo(row.id, row.skuId)">{{ row.goodsName }}</a>
</div>
</div>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
<Modal
title="下架操作"
v-model="modalVisible"
:mask-closable="false"
:width="500"
>
<Form ref="underForm" :model="underForm" :label-width="100">
<FormItem label="下架原因" prop="reason">
<Input v-model="underForm.reason" clearable style="width: 100%" />
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="lower"
>提交</Button
>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</Modal>
<Modal
title="商品审核"
v-model="auditModalVisible"
:mask-closable="false"
:width="500"
>
<Form ref="auditForm" :model="goodsAuditForm" :label-width="100">
<FormItem label="审核结果" prop="auth_flag">
<RadioGroup v-model="goodsAuditForm.auth_flag">
<Radio :label="1">审核通过</Radio>
<Radio :label="2">审核拒绝</Radio>
</RadioGroup>
</FormItem>
<!-- <FormItem label="审核备注" prop="reason" v-if="goodsAuditForm.auth_flag === 2">
<Input v-model="goodsAuditForm.reason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />
</FormItem> -->
</Form>
<div slot="footer">
<Button type="text" @click="auditModalVisible = false">取消</Button>
<Button type="primary" @click="confirmAudit">提交审核</Button>
</div>
</Modal>
<!-- 批量审核弹框 -->
<Modal
title="批量商品审核"
</el-card>
<el-dialog v-model="modalVisible" title="下架操作" width="500px" :close-on-click-modal="false">
<el-form ref="underForm" :model="underForm" label-width="100px">
<el-form-item label="下架原因" prop="reason">
<el-input v-model="underForm.reason" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="lower">提交</el-button>
</template>
</el-dialog>
<el-dialog v-model="auditModalVisible" title="商品审核" width="500px" :close-on-click-modal="false">
<el-form ref="auditForm" :model="goodsAuditForm" label-width="100px">
<el-form-item label="审核结果" prop="auth_flag">
<el-radio-group v-model="goodsAuditForm.auth_flag">
<el-radio :value="1">审核通过</el-radio>
<el-radio :value="2">审核拒绝</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="auditModalVisible = false">取消</el-button>
<el-button type="primary" @click="confirmAudit">提交审核</el-button>
</template>
</el-dialog>
<el-dialog
v-model="batchAuditModalVisible"
:mask-closable="false"
:width="500"
title="批量商品审核"
width="500px"
:close-on-click-modal="false"
>
<Form ref="batchAuditForm" :model="batchAuditForm" :label-width="100">
<FormItem label="审核结果" prop="auth_flag">
<RadioGroup v-model="batchAuditForm.auth_flag">
<Radio :label="1">审核通过</Radio>
<Radio :label="2">审核拒绝</Radio>
</RadioGroup>
</FormItem>
<FormItem label="审核备注" prop="reason" v-if="batchAuditForm.auth_flag === 2">
<Input v-model="batchAuditForm.reason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />
</FormItem>
<FormItem label="选中商品">
<div style="max-height: 200px; overflow-y: auto;">
<Tag v-for="item in selectedRows" :key="item.id" style="margin: 2px;">{{item.goodsName}}</Tag>
<el-form ref="batchAuditForm" :model="batchAuditForm" label-width="100px">
<el-form-item label="审核结果" prop="auth_flag">
<el-radio-group v-model="batchAuditForm.auth_flag">
<el-radio :value="1">审核通过</el-radio>
<el-radio :value="2">审核拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="batchAuditForm.auth_flag === 2" label="审核备注" prop="reason">
<el-input v-model="batchAuditForm.reason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />
</el-form-item>
<el-form-item label="选中商品">
<div style="max-height: 200px; overflow-y: auto">
<el-tag v-for="item in selectedRows" :key="item.id" style="margin: 2px">{{ item.goodsName }}</el-tag>
</div>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="batchAuditModalVisible = false">取消</Button>
<Button type="primary" @click="submitBatchAudit">提交审核</Button>
</div>
</Modal>
<Modal v-model="goodsGroupFlag" title="批量设置商品分组" width="420">
<Form ref="goodsGroupForm" :model="goodsGroupForm" :rules="goodsGroupRule" :label-width="90">
<FormItem label="商品分组" prop="groupId">
<Select v-model="goodsGroupForm.groupId" clearable filterable style="width: 240px">
<Option v-for="item in goodsGroupList" :value="item.id" :key="item.id">{{ item.groupName }}</Option>
</Select>
</FormItem>
</Form>
<div slot="footer">
<Button @click="goodsGroupFlag = false">取消</Button>
<Button type="primary" :loading="goodsGroupLoading" @click="submitSetGoodsGroup">确定</Button>
</div>
</Modal>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="batchAuditModalVisible = false">取消</el-button>
<el-button type="primary" @click="submitBatchAudit">提交审核</el-button>
</template>
</el-dialog>
<el-dialog v-model="goodsGroupFlag" title="批量设置商品分组" width="420px">
<el-form ref="goodsGroupForm" :model="goodsGroupForm" :rules="goodsGroupRule" label-width="90px">
<el-form-item label="商品分组" prop="groupId">
<el-select v-model="goodsGroupForm.groupId" clearable filterable style="width: 240px">
<el-option
v-for="item in goodsGroupList"
:key="item.id"
:label="item.groupName"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="goodsGroupFlag = false">取消</el-button>
<el-button type="primary" :loading="goodsGroupLoading" @click="submitSetGoodsGroup">确定</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -261,11 +297,7 @@ import {
getGoodsGroupByPage,
addGoodsGroupItems
} from "@/api/goods";
import vueQr from "vue-qr";
export default {
components: {
"vue-qr": vueQr,
},
name: "goods",
data() {
return {
@@ -291,259 +323,10 @@ export default {
auditModalVisible: false, // 审核弹框显示状态
currentAuditGoods: null, // 当前审核的商品
submitLoading: false, // 添加或编辑提交状态
columns: [
{
type: 'selection',
width: 60,
align: 'center'
},
{
title: "商品ID",
key: "id",
width: 180,
tooltip: true,
},
{
title: "商品图片",
key: "original",
width: 180,
slot: "imageSlot",
},
{
title: "商品名称",
key: "goodsName",
minWidth: 180,
slot: "goodsSlot",
},
{
title: "价格",
key: "price",
width: 100,
render: (h, params) => {
return h("priceColorScheme", {props:{value:params.row.price,color:this.$mainColor}} );
},
},
{
title: "销量",
key: "buyCount",
width: 100,
render: (h, params) => {
return h("span", params.row.buyCount || 0);
},
},
{
title: "库存",
key: "quantity",
width: 100,
render: (h, params) => {
return h("span", params.row.quantity || 0);
},
},
{
title: "销售模式",
key: "salesModel",
width: 100,
render: (h, params) => {
if (params.row.salesModel === "RETAIL") {
return h("Tag", { props: { color: "orange" } }, "零售");
} else if (params.row.salesModel === "WHOLESALE") {
return h("Tag", { props: { color: "magenta" } }, "批发");
} else {
return h("Tag", { props: { color: "volcano" } }, "其他类型");
}
},
},
{
title: "商品类型",
key: "goodsType",
width: 120,
render: (h, params) => {
if (params.row.goodsType === "PHYSICAL_GOODS") {
return h("Tag", { props: { color: "green" } }, "实物商品");
} else if (params.row.goodsType === "VIRTUAL_GOODS") {
return h("Tag", { props: { color: "volcano" } }, "虚拟商品");
} else {
return h("Tag", { props: { color: "geekblue" } }, "电子卡券");
}
},
},
{
title: "状态",
key: "marketEnable",
width: 120,
render: (h, params) => {
if (params.row.marketEnable == "DOWN") {
return h("Tag", { props: { color: "volcano" } }, "下架");
} else if (params.row.marketEnable == "UPPER") {
return h("Tag", { props: { color: "green" } }, "上架");
}
},
},
{
title: "审核状态",
key: "authFlag",
width: 180,
render: (h, params) => {
if (params.row.authFlag == "TOBEAUDITED") {
return h("Tag", { props: { color: "volcano" } }, "待审核");
} else if (params.row.authFlag == "PASS") {
return h("Tag", { props: { color: "green" } }, "通过");
} else if (params.row.authFlag == "REFUSE") {
return h("Tag", { props: { color: "red" } }, "拒绝");
}
},
},
{
title: "店铺名称",
key: "storeName",
width: 180, // 使用minWidth替代width
tooltip: true,
},
{
title: "操作",
key: "action",
align: "center",
fixed: "right",
width: 200,
render: (h, params) => {
// 如果是待审核状态,显示审核按钮
if (params.row.authFlag === "TOBEAUDITED") {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.openAuditModal(params.row);
},
},
},
"审核"
),
h("span", {
style: {
margin: "0 8px",
color: "#dcdee2"
}
}, "|"),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.showDetail(params.row);
},
},
},
"查看"
),
]);
}
// 原有的上架/下架逻辑
else if (params.row.marketEnable == "DOWN") {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.upper(params.row);
},
},
},
"上架"
),
h("span", {
style: {
margin: "0 8px",
color: "#dcdee2"
}
}, "|"),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.showDetail(params.row);
},
},
},
"查看"
),
]);
} else {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.edit(params.row);
},
},
},
"下架"
),
h("span", {
style: {
margin: "0 8px",
color: "#dcdee2"
}
}, "|"),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.showDetail(params.row);
},
},
},
"查看"
),
]);
}
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
currentStatus: '',
currentStatus: "ALL",
goodsNumerData: {},
goodsAuditForm: {
// 商品编辑表单
auth_flag: 1,
},
selectedRows: [], // 选中的行数据
selectAll: false, // 全选状态
batchAuditModalVisible: false, // 批量审核弹框显示状态
@@ -565,7 +348,7 @@ export default {
computed: {
goodsStatusWithCount() {
return [
{title: '全部', value: ''},
{title: '全部', value: 'ALL'},
{title: `出售中${this.goodsNumerData.upperGoodsNum ? '(' + this.goodsNumerData.upperGoodsNum + ')' : ''}`, value: 'UPPER'},
{title: `仓库中${this.goodsNumerData.downGoodsNum ? '(' + this.goodsNumerData.downGoodsNum + ')' : ''}`, value: 'DOWN'},
{title: `待审核${this.goodsNumerData.auditGoodsNum ? '(' + this.goodsNumerData.auditGoodsNum + ')' : ''}`, value: 'TOBEAUDITED'},
@@ -574,6 +357,33 @@ export default {
}
},
methods: {
clearTableSelection() {
this.$refs.table?.clearSelection?.();
},
onStatusTabClick(tab) {
this.goodsStatusClick(tab.paneName);
},
salesModelText(v) {
if (v === "RETAIL") return "零售";
if (v === "WHOLESALE") return "批发";
return "其他类型";
},
goodsTypeText(v) {
if (v === "PHYSICAL_GOODS") return "实物商品";
if (v === "VIRTUAL_GOODS") return "虚拟商品";
return "电子卡券";
},
marketEnableText(v) {
if (v === "DOWN") return "下架";
if (v === "UPPER") return "上架";
return "";
},
authFlagText(v) {
if (v === "TOBEAUDITED") return "待审核";
if (v === "PASS") return "通过";
if (v === "REFUSE") return "拒绝";
return "";
},
// 初始化数据
init() {
this.getDataList();
@@ -667,31 +477,23 @@ export default {
//查看商品详情
showDetail(v) {
let id = v.id;
this.$options.filters.customRouterPush({
this.$filters.customRouterPush({
name: "goods-detail",
query: { id: id },
})
query: { id: v.id },
});
},
// 商品状态筛选
goodsStatusClick(item) {
// 根据选择的状态设置搜索条件
if (item === 0) {
// 全部:清除状态筛选
goodsStatusClick(name) {
if (name === "ALL" || name === "" || name === undefined || name === null) {
delete this.searchForm.goodsStatus;
this.currentStatus = "ALL";
} else {
// 其他状态正常赋值
this.searchForm.goodsStatus = item;
this.searchForm.goodsStatus = name;
this.currentStatus = name;
}
this.currentStatus = item;
// tab切换时清除选中内容
this.selectedRows = [];
if (this.$refs.table) {
this.$refs.table.selectAll(false);
}
this.clearTableSelection();
this.getDataList();
},
examine(v, authFlag) {
@@ -762,15 +564,6 @@ export default {
});
},
// 选择框事件处理
onSelect(selection, row) {
// 单行选择时触发
},
onSelectAll(selection) {
// 全选时触发
},
onSelectionChange(selection) {
this.selectedRows = selection;
},
@@ -939,9 +732,7 @@ export default {
this.goodsGroupFlag = false;
this.selectedRows = [];
this.selectAll = false;
if (this.$refs.table && this.$refs.table.selectAll) {
this.$refs.table.selectAll(false);
}
this.clearTableSelection();
this.getDataList();
} else if (res && res.message) {
this.$Message.error(res.message);
@@ -961,7 +752,7 @@ export default {
<style lang="scss" scoped>
// Tab组件样式
.goods-tab {
::v-deep .ivu-tabs-tab {
:deep(.el-tabs__item) {
font-size: 14px;
}
}

View File

@@ -1,79 +1,93 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
@keydown.enter.native="handleSearch"
:model="searchForm"
inline
:label-width="70"
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<Form-item label="商品名称" prop="goodsName">
<Input
type="text"
<el-form-item label="商品名称" prop="goodsName">
<el-input
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="商品编号" prop="id">
<Input
type="text"
</el-form-item>
<el-form-item label="商品编号" prop="id">
<el-input
v-model="searchForm.id"
placeholder="请输入商品编号"
clearable
style="width: 240px"
/>
</Form-item>
<Button @click="handleSearch" class="search-btn" type="primary" icon="ios-search"
>搜索</Button
>
</Form>
</Card>
<Card>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
>
<!-- 商品栏目格式化 -->
<template slot="goodsSlot" slot-scope="scope">
<div style="margin-top: 5px; height: 80px; display: flex">
<div style="">
<img
:src="scope.row.original"
style="height: 60px; margin-top: 3px; width: 60px"
/>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<div style="margin-left: 13px">
<div class="div-zoom">
<a>{{ scope.row.goodsName }}</a>
<el-card>
<el-table v-loading="loading" :data="data" ref="table" class="mt_10" style="width: 100%">
<el-table-column label="商品名称" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<div v-if="row" style="margin-top: 5px; height: 80px; display: flex; align-items: flex-start">
<img
v-if="row.original"
:src="row.original"
style="height: 60px; width: 60px; object-fit: cover; margin-top: 3px"
alt=""
/>
<div style="margin-left: 13px">
<div class="div-zoom">
<a class="link-text">{{ row.goodsName }}</a>
</div>
</div>
</div>
</div>
</template>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
</template>
</el-table-column>
<el-table-column prop="id" label="商品编号" min-width="120" show-overflow-tooltip />
<el-table-column label="价格" min-width="120">
<template #default="{ row }">
<span v-if="row" :style="{ color: $mainColor }">{{ $filters.unitPrice(row.price, "") }}</span>
</template>
</el-table-column>
<el-table-column label="审核状态" min-width="120">
<template #default="{ row }">
<el-tag v-if="row" :type="authFlagTagType(row.authFlag)">{{ authFlagText(row.authFlag) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="storeName" label="店铺名称" min-width="120" show-overflow-tooltip />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<template v-if="row">
<a class="link-text" @click="examine(row, 1)">通过</a>
<span class="op-split">|</span>
<a class="link-text" @click="examine(row, 2)">拒绝</a>
<span class="op-split">|</span>
<a class="link-text" @click="showDetail(row)">查看</a>
</template>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
</div>
</template>
@@ -81,214 +95,82 @@
import { authGoods, getAuthGoodsListData } from "@/api/goods";
export default {
name: "goods",
components: {},
name: "goodsApply",
data() {
return {
id: "", //要操作的id
loading: true, // 表单加载状态
loading: true,
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
pageNumber: 1,
pageSize: 20,
sort: "create_time",
order: "desc",
},
goodsAuditForm: {
// 商品编辑表单
auth_flag: 1,
},
columns: [
{
title: "商品名称",
key: "goodsName",
minWidth: 180,
slot: "goodsSlot",
tooltip: true,
},
{
title: "商品编号",
key: "id",
minWidth: 100,
tooltip: true,
},
{
title: "价格",
key: "price",
minWidth: 130,
render: (h, params) => {
return h("priceColorScheme", {props:{value:params.row.price,color:this.$mainColor}} );
},
},
{
title: "审核状态",
key: "authFlag",
minWidth: 130,
render: (h, params) => {
if (params.row.authFlag == "TOBEAUDITED") {
return h("div", [
h("Badge", {
props: {
status: "error",
text: "待审核",
},
}),
]);
} else if (params.row.authFlag == "PASS") {
return h("div", [
h("Badge", {
props: {
status: "success",
text: "审核通过",
},
}),
]);
} else if (params.row.authFlag == "REFUSE") {
return h("div", [
h("Badge", {
props: {
status: "error",
text: "审核拒绝",
},
}),
]);
}
},
},
{
title: "店铺名称",
key: "storeName",
minWidth: 100,
tooltip: true,
},
{
title: "操作",
key: "action",
align: "center",
fixed: "right",
width: 200,
render: (h, params) => {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
marginRight: "5px",
},
on: {
click: () => {
this.examine(params.row, 1);
},
},
},
"通过"
),
h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
marginRight: "5px",
},
on: {
click: () => {
this.examine(params.row, 2);
},
},
},
"拒绝"
),
h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.showDetail(params.row);
},
},
},
"查看"
),
]);
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
data: [],
total: 0,
};
},
methods: {
authFlagText(v) {
const map = {
TOBEAUDITED: "待审核",
PASS: "审核通过",
REFUSE: "审核拒绝",
};
return map[v] || v || "-";
},
authFlagTagType(v) {
const map = {
TOBEAUDITED: "warning",
PASS: "success",
REFUSE: "danger",
};
return map[v] || "info";
},
init() {
// 初始化数据
this.getDataList();
},
changePage(v) {
// 改变页码
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
// 改变每页数量
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
// 搜索
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getDataList();
},
getDataList() {
// 获取列表数据
this.loading = true;
// 带多条件搜索参数获取表单数据
this.searchForm.authFlag = 0;
getAuthGoodsListData(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
getAuthGoodsListData(this.searchForm)
.then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
})
.catch(() => {
this.loading = false;
});
},
examine(v, authFlag) {
// 审核商品
let examine = "通过";
this.goodsAuditForm.authFlag = "PASS";
if (authFlag != 1) {
examine = "拒绝";
this.goodsAuditForm.authFlag = "REFUSE";
}
const examine = authFlag === 1 ? "通过" : "拒绝";
this.goodsAuditForm.authFlag = authFlag === 1 ? "PASS" : "REFUSE";
this.$Modal.confirm({
title: "确认审核",
content: "您确认要审核" + examine + " " + v.goodsName + " ?",
content: `您确认要审核${examine} ${v.goodsName} ?`,
loading: true,
onOk: () => {
let formData = new FormData();
formData.append('goodsIds', v.id);
formData.append('authFlag', this.goodsAuditForm.authFlag);
const formData = new FormData();
formData.append("goodsIds", v.id);
formData.append("authFlag", this.goodsAuditForm.authFlag);
authGoods(formData).then((res) => {
this.$Modal.remove();
if (res.success) {
@@ -299,13 +181,11 @@ export default {
},
});
},
//查看商品详情
showDetail(v) {
let id = v.id;
this.$options.filters.customRouterPush({
this.$filters.customRouterPush({
name: "goods-detail",
query: { id: id },
})
query: { id: v.id },
});
},
},
mounted() {
@@ -313,3 +193,20 @@ export default {
},
};
</script>
<style scoped>
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
.op-split {
margin: 0 8px;
color: #dcdee2;
}
.div-zoom {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

View File

@@ -1,247 +1,159 @@
<template>
<div>
<Form :label-width="120">
<Card>
<el-form label-width="120px">
<el-card>
<div class="base-info-item">
<h4>基本信息</h4>
<div class="form-item-view">
<FormItem label="商品分类">
<el-form-item label="商品分类">
<span v-for="(item, index) in goods.categoryName" :key="index">
{{ item }}
<i v-if="index !== goods.categoryName.length - 1">&gt;</i>
</span>
</FormItem>
<FormItem label="商品名称">
{{ goods.goodsName }}
</FormItem>
<FormItem label="商品卖点">
{{ goods.sellingPoint }}
</FormItem>
<FormItem label="商品参数">
<div v-if="goods.goodsParamsDTOList && goods.goodsParamsDTOList.length" v-for="(item,index) in goods.goodsParamsDTOList" :key="index">
<div style="margin-bottom: 10px; display: flex; align-items: center;" >
{{ item.groupName }} : <tag v-for="(child,i) in item.goodsParamsItemDTOList" :key="i">
</el-form-item>
<el-form-item label="商品名称">{{ goods.goodsName }}</el-form-item>
<el-form-item label="商品卖点">{{ goods.sellingPoint }}</el-form-item>
<el-form-item label="商品参数">
<div
v-if="goods.goodsParamsDTOList && goods.goodsParamsDTOList.length"
v-for="(item, index) in goods.goodsParamsDTOList"
:key="index"
style="margin-bottom: 10px; display: flex; align-items: center"
>
{{ item.groupName }} :
<el-tag v-for="(child, i) in item.goodsParamsItemDTOList" :key="i" style="margin-left: 4px">
{{ child.paramName }} - {{ child.paramValue }}
</tag>
</div>
</div>
</FormItem>
</el-tag>
</div>
</el-form-item>
</div>
<h4>商品交易信息</h4>
<div class="form-item-view">
<FormItem label="计量单位"> {{ goods.goodsUnit }}</FormItem>
<FormItem label="销售模式">
<el-form-item label="计量单位">{{ goods.goodsUnit }}</el-form-item>
<el-form-item label="销售模式">
{{ goods.salesModel === "RETAIL" ? "零售型" : "批发型" }}
</FormItem>
<FormItem label="销售规则" v-if="goods.salesModel !== 'RETAIL'">
<Table
border
:columns="wholesalePreviewColumns"
:data="wholesaleData"
>
</Table>
</FormItem>
</el-form-item>
<el-form-item v-if="goods.salesModel !== 'RETAIL'" label="销售规则">
<el-table border :data="wholesaleData" style="width: 100%">
<el-table-column label="销售规则" width="300">
<template #default="{ row }">
<span v-if="row">
当商品购买数量 {{ row.num }} 售价为 {{ row.price }} /{{ goods.goodsUnit }}</span>
</template>
</el-table-column>
</el-table>
</el-form-item>
</div>
<h4>商品规格及图片</h4>
<div class="form-item-view">
<FormItem label="商品编号"> {{ goods.id }}</FormItem>
<FormItem label="商品价格">
<priceColorScheme :value="goods.price" :color="$mainColor"></priceColorScheme>
</FormItem>
<FormItem label="商品图片">
<el-form-item label="商品编号">{{ goods.id }}</el-form-item>
<el-form-item label="商品价格">
<priceColorScheme :value="goods.price" :color="$mainColor" />
</el-form-item>
<el-form-item label="商品图片">
<div
class="demo-upload-list"
v-for="(item, __index) in goods.goodsGalleryList"
:key="__index"
class="demo-upload-list"
>
<img :src="item" />
<div class="demo-upload-list-cover">
<Icon
type="ios-eye-outline"
@click.native="handleViewGoodsPicture(item)"
></Icon>
<el-icon class="preview-icon" @click="handleViewGoodsPicture(item)"><View /></el-icon>
</div>
<Modal title="View Image" v-model="goodsPictureVisible">
<img
:src="previewGoodsPicture"
v-if="goodsPictureVisible"
style="width: 100%"
/>
</Modal>
</div>
</FormItem>
<FormItem label="商品视频">
<video
v-if="goods.goodsVideo"
controls
class="player"
:src="goods.goodsVideo"
/>
</FormItem>
<FormItem label="商品规格">
<Table :columns="skuColumn" :data="skuData">
<template slot="showImage" slot-scope="scope">
<div style="margin-top: 5px; display: flex">
<div>
<el-dialog v-model="goodsPictureVisible" title="View Image" width="600px">
<img v-if="goodsPictureVisible" :src="previewGoodsPicture" style="width: 100%" />
</el-dialog>
</el-form-item>
<el-form-item label="商品视频">
<video v-if="goods.goodsVideo" controls class="player" :src="goods.goodsVideo" />
</el-form-item>
<el-form-item label="商品规格">
<el-table :data="skuData" style="width: 100%">
<el-table-column prop="specs" label="规格" />
<el-table-column prop="sn" label="编号" />
<el-table-column prop="weight" label="重量(kg)" />
<el-table-column
v-for="(item, index) in wholesaleData"
:key="'wp' + index"
:label="'购买量 ≥ ' + item.num"
>
<template #default>
<el-input v-if="wholesaleData[index]" v-model="wholesaleData[index].price" disabled>
<template #append></template>
</el-input>
</template>
</el-table-column>
<el-table-column v-if="goods.salesModel !== 'WHOLESALE'" label="价格">
<template #default="{ row }">
<priceColorScheme v-if="row" :value="row.price" :color="$mainColor" />
</template>
</el-table-column>
<el-table-column v-if="goods.salesModel !== 'WHOLESALE'" prop="quantity" label="库存" />
<el-table-column label="图片">
<template #default="{ row }">
<div v-if="row" style="margin-top: 5px; display: flex">
<img
v-for="(item,index) in scope.row.image"
v-for="(item, index) in row.image"
:key="index"
:src="item"
style="height: 60px; margin:10px; width: 60px"
style="height: 60px; margin: 10px; width: 60px"
/>
</div>
</div>
</template>
<template slot-scope="{ row }" slot="wholePrice0">
<Input
v-if="wholesaleData[0]"
clearable
disabled
v-model="wholesaleData[0].price"
>
<span slot="append"></span>
</Input>
</template>
<template slot-scope="{ row }" slot="wholePrice1">
<Input
v-if="wholesaleData[1]"
clearable
disabled
v-model="wholesaleData[1].price"
>
<span slot="append"></span>
</Input>
</template>
<template slot-scope="{ row }" slot="wholePrice2">
<Input
v-if="wholesaleData[2]"
clearable
disabled
v-model="wholesaleData[2].price"
>
<span slot="append"></span>
</Input>
</template>
</Table>
</FormItem>
</template>
</el-table-column>
</el-table>
</el-form-item>
</div>
<h4>商品详情描述</h4>
<div class="form-item-view">
<FormItem label="商品描述">
<el-form-item label="商品描述">
<div v-html="goods.intro"></div>
</FormItem>
<FormItem label="移动端描述">
</el-form-item>
<el-form-item label="移动端描述">
<div v-html="goods.mobileIntro"></div>
</FormItem>
</el-form-item>
</div>
</div>
</Card>
</Form>
</el-card>
</el-form>
</div>
</template>
<script>
import { View } from "@element-plus/icons-vue";
import { getGoodsDetail } from "@/api/goods";
export default {
name: "goodsDetail",
components: { View },
data() {
return {
goods: {}, // 商品信息
previewGoodsPicture: "", // 预览图片
goodsPictureVisible: false, // 预览图片模态框
wholesalePreviewColumns: [
{
title: "销售规则",
width: 300,
render: (h, params) => {
let guide =
"当商品购买数量 ≥" +
params.row.num +
" 时,售价为 ¥" +
params.row.price +
" /" +
this.goods.goodsUnit;
return h("div", guide);
},
},
],
goods: {},
previewGoodsPicture: "",
goodsPictureVisible: false,
wholesaleData: [],
skuColumn: [
// 规格表头
{
title: "规格",
key: "specs",
},
{
title: "编号",
key: "sn",
},
{
title: "重量(kg)",
key: "weight",
},
],
skuData: [], // sku数据
skuData: [],
};
},
mounted() {
this.initGoods(this.$route.query.id);
},
methods: {
// 初始化数据,获取商品详情
initGoods(id) {
getGoodsDetail(id).then((res) => {
this.goods = res.result;
let that = this;
res.result.skuList.forEach(function (sku, index, array) {
that.skuData.push({
specs: sku.goodsName,
sn: sku.sn,
weight: sku.weight,
cost: sku.cost,
price:sku.price,
image: sku.goodsGalleryList,
quantity:sku.quantity
});
});
if (res.result.salesModel === "WHOLESALE" && res.result.wholesaleList) {
res.result.wholesaleList.forEach((item, index) => {
this.skuColumn.push({
title: "购买量 ≥ " + item.num,
slot: "wholePrice" + index,
});
});
} else {
this.skuColumn.push(
// {
// title: "成本",
// key: "cost",
// render: (h, params) => {
// console.log(params)
// return h("priceColorScheme", {props:{value:params.row.cost,color:this.$mainColor}} );
// },
// },
{
title: "价格",
key: "price",
render: (h, params) => {
return h("priceColorScheme", {props:{value:params.row.price,color:this.$mainColor}} );
},
},{
title: "库存",
key: "quantity",
}
);
}
this.skuColumn.push({
title: "图片",
slot: "showImage",
});
this.wholesaleData = res.result.wholesaleList;
this.skuData = res.result.skuList.map((sku) => ({
specs: sku.goodsName,
sn: sku.sn,
weight: sku.weight,
cost: sku.cost,
price: sku.price,
image: sku.goodsGalleryList,
quantity: sku.quantity,
}));
this.wholesaleData = res.result.wholesaleList || [];
});
},
// 预览商品图片
handleViewGoodsPicture(url) {
this.previewGoodsPicture = url;
this.goodsPictureVisible = true;
@@ -251,7 +163,6 @@ export default {
</script>
<style lang="scss" soped>
/*平铺*/
div.base-info-item {
h4 {
margin-bottom: 10px;
@@ -300,13 +211,10 @@ div.base-info-item {
.demo-upload-list:hover .demo-upload-list-cover {
display: block;
}
.demo-upload-list-cover i {
.preview-icon {
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.ivu-table table {
width: 100% !important;
margin-top: 20px;
}
</style>

View File

@@ -1,74 +1,148 @@
<template>
<div class="search">
<Card>
<Form ref="searchForm" @submit.native.prevent @keydown.enter.native="handleSearch" :model="searchForm" inline :label-width="70"
class="search-form">
<Form-item label="品牌名称">
<Input type="text" v-model="searchForm.name" placeholder="请输入品牌名称" clearable style="width: 240px"/>
</Form-item>
<Button @click="handleSearch" type="primary">搜索</Button>
</Form>
</Card>
<Card>
<Row class="operation padding-row">
<Button @click="add" type="primary">添加</Button>
</Row>
<Table :loading="loading" border :columns="columns" :data="data" ref="table"></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="[20, 50, 100]" size="small"
show-total show-elevator show-sizer></Page>
</Row>
</Card>
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="500">
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
<FormItem label="品牌名称" prop="name">
<Input v-model="form.name" clearable style="width: 100%"/>
</FormItem>
<FormItem label="品牌图标" prop="logo">
<div style="display: flex; align-items: center; gap: 12px;">
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<el-form-item label="品牌名称">
<el-input
v-model="searchForm.name"
placeholder="请输入品牌名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="add">添加</el-button>
</div>
<el-table ref="table" v-loading="loading" border :data="data" style="width: 100%">
<el-table-column prop="name" label="品牌名称" width="200" />
<el-table-column label="品牌图标" align="left" >
<template #default="{ row }">
<img
v-if="row"
:src="row.logo || ''"
alt="加载图片失败"
style="cursor: pointer; width: 80px; height: 60px; margin: 10px 0; object-fit: contain"
/>
</template>
</el-table-column>
<el-table-column label="状态" align="left" width="150">
<template #default="{ row }">
<el-switch
v-if="row"
:model-value="row.deleteFlag == 0"
inline-prompt
active-text="启用"
inactive-text="禁用"
@change="(val) => handleStatusSwitchChange(row, val)"
/>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="170" show-overflow-tooltip />
<el-table-column label="操作" width="230" align="center" fixed="right">
<template #default="{ row }">
<template v-if="row">
<a class="link-text" @click="edit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="openCategoryModal(row)">关联分类</a>
<span class="op-split">|</span>
<a class="link-text" @click="delBrand(row.id)">删除</a>
</template>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
:close-on-click-modal="false"
destroy-on-close
>
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="品牌名称" prop="name">
<el-input v-model="form.name" clearable style="width: 100%" />
</el-form-item>
<el-form-item label="品牌图标" prop="logo">
<div style="display: flex; align-items: center; gap: 12px">
<img
:src="form.logo || defaultPic"
alt="品牌图标"
style="width: 80px; height: 60px; object-fit: contain; border: 1px solid #dcdee2; border-radius: 4px; background: #fff;"
style="width: 80px; height: 60px; object-fit: contain; border: 1px solid #dcdee2; border-radius: 4px; background: #fff"
/>
<Button type="text" @click="openLogoPicker">修改</Button>
<el-button type="primary" link @click="openLogoPicker">修改</el-button>
</div>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit">提交</Button>
</div>
</Modal>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">提交</el-button>
</template>
</el-dialog>
<Modal width="1200px" v-model="picModelFlag" footer-hide>
<ossManage @callback="callbackSelected" :isComponent="true" :initialize="picModelFlag" ref="ossManage" />
</Modal>
<el-dialog v-model="picModelFlag" width="1200px" :show-close="true">
<ossManage
ref="ossManage"
:is-component="true"
:initialize="picModelFlag"
@callback="callbackSelected"
/>
</el-dialog>
<Modal
:title="categoryModalTitle"
<el-dialog
v-model="categoryModalVisible"
:mask-closable="false"
:width="700"
:title="categoryModalTitle"
width="700px"
:close-on-click-modal="false"
>
<div style="position: relative; max-height: 520px; overflow: auto;">
<Spin size="large" fix v-if="categoryTreeLoading"></Spin>
<Tree
<div v-loading="categoryTreeLoading" style="position: relative; max-height: 520px; overflow: auto">
<el-tree
ref="categoryTree"
:key="categoryTreeKey"
:data="categoryTreeData"
:props="{ label: 'title', children: 'children' }"
node-key="id"
show-checkbox
@on-check-change="onCategoryTreeCheckChange"
></Tree>
default-expand-all
:default-checked-keys="selectedCategoryIds"
@check="onCategoryTreeCheckChange"
/>
</div>
<div slot="footer">
<Button type="text" @click="categoryModalVisible = false">取消</Button>
<Button type="primary" :loading="categorySubmitLoading" @click="submitBrandCategory"
>提交</Button
>
</div>
</Modal>
<template #footer>
<el-button @click="categoryModalVisible = false">取消</el-button>
<el-button type="primary" :loading="categorySubmitLoading" @click="submitBrandCategory">
提交
</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -84,22 +158,21 @@ import {
saveBrandCategory,
} from "@/api/goods";
import ossManage from "@/views/sys/oss-manage/ossManage";
import {regular} from "@/utils";
import { regular } from "@/utils";
export default {
name: "brand",
components: {
ossManage
ossManage,
},
data() {
return {
defaultPic: require("@/assets/default.png"),
loading: true, // 表单加载状态
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalTitle: "", // 添加或编辑标题
picModelFlag: false, // 图片选择器
loading: true,
modalType: 0,
modalVisible: false,
modalTitle: "",
picModelFlag: false,
categoryModalVisible: false,
categoryModalTitle: "关联分类",
categoryTreeLoading: false,
@@ -109,173 +182,23 @@ export default {
currentBrandId: "",
selectedCategoryIds: [],
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
pageNumber: 1,
pageSize: 20,
sort: "create_time",
order: "desc",
},
form: {
// 添加或编辑表单对象初始化数据
name: "",
logo: "",
deleteFlag: "",
},
// 表单验证规则
formValidate: {
name: [
regular.REQUIRED,
regular.VARCHAR20
],
logo: [
regular.REQUIRED,
regular.URL200
],
name: [regular.REQUIRED, regular.VARCHAR20],
logo: [regular.REQUIRED, regular.URL200],
},
submitLoading: false, // 添加或编辑提交状态
columns: [
{
title: "品牌名称",
key: "name",
width: 200,
resizable: true,
sortable: false,
},
{
title: "品牌图标",
key: "logo",
align: "left",
render: (h, params) => {
return h("img", {
attrs: {
src: params.row.logo || '',
alt: "加载图片失败",
},
style: {
cursor: "pointer",
width: "80px",
height: "60px",
margin: "10px 0",
"object-fit": "contain",
},
});
},
},
{
title: "状态",
key: "deleteFlag",
align: "left",
render: (h, params) => {
return h(
"i-switch",
{
props: {
value: params.row.deleteFlag == 0,
size: "large",
},
on: {
"on-change": (checked) => {
this.handleStatusSwitchChange(params.row, checked);
},
},
},
[
h("span", { slot: "open" }, "启用"),
h("span", { slot: "close" }, "禁用"),
]
);
},
filters: [
{
label: "启用",
value: 0,
},
{
label: "禁用",
value: 1,
},
],
filterMultiple: false,
filterMethod(value, row) {
if (value == 0) {
return row.deleteFlag == 0;
} else if (value == 1) {
return row.deleteFlag == 1;
}
},
},
{
title: "操作",
key: "action",
width: 210,
align: "center",
fixed: "right",
render: (h, params) => {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.edit(params.row);
},
},
},
"编辑"
),
h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.openCategoryModal(params.row);
},
},
},
"关联分类"
),
h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.delBrand(params.row.id);
},
},
},
"删除"
),
]);
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
submitLoading: false,
data: [],
total: 0,
};
},
methods: {
@@ -287,18 +210,13 @@ export default {
this.picModelFlag = false;
this.form.logo = val.url;
},
buildCategoryTreeNodes(list, selectedSet) {
buildCategoryTreeNodes(list) {
if (!Array.isArray(list) || list.length === 0) return [];
return list.map((item) => {
const children = this.buildCategoryTreeNodes(item.children || [], selectedSet);
return {
id: item.id,
title: item.name,
expand: true,
checked: selectedSet.has(item.id),
children,
};
});
return list.map((item) => ({
id: item.id,
title: item.name,
children: this.buildCategoryTreeNodes(item.children || []),
}));
},
async openCategoryModal(row) {
this.currentBrandId = row.id;
@@ -319,22 +237,16 @@ export default {
.filter(Boolean)
: [];
this.selectedCategoryIds = selectedIds;
const selectedSet = new Set(selectedIds);
this.categoryTreeData = treeRes && treeRes.success
? this.buildCategoryTreeNodes(treeRes.result || [], selectedSet)
: [];
this.categoryTreeData =
treeRes && treeRes.success
? this.buildCategoryTreeNodes(treeRes.result || [])
: [];
} finally {
this.categoryTreeLoading = false;
}
},
onCategoryTreeCheckChange(checkedNodes) {
if (!Array.isArray(checkedNodes)) {
this.selectedCategoryIds = [];
return;
}
this.selectedCategoryIds = checkedNodes
.map((node) => node && node.id)
.filter(Boolean);
onCategoryTreeCheckChange(_data, checkedInfo) {
this.selectedCategoryIds = checkedInfo?.checkedKeys || [];
},
submitBrandCategory() {
if (!this.currentBrandId) return;
@@ -342,16 +254,17 @@ export default {
saveBrandCategory(
this.currentBrandId,
(this.selectedCategoryIds || []).map((id) => String(id))
).then((res) => {
this.categorySubmitLoading = false;
if (res && res.success) {
this.$Message.success("操作成功");
this.categoryModalVisible = false;
return;
}
}).catch(() => {
this.categorySubmitLoading = false;
});
)
.then((res) => {
this.categorySubmitLoading = false;
if (res && res.success) {
this.$Message.success("操作成功");
this.categoryModalVisible = false;
}
})
.catch(() => {
this.categorySubmitLoading = false;
});
},
handleStatusSwitchChange(row, checked) {
const disable = !checked;
@@ -373,36 +286,29 @@ export default {
},
});
},
// 删除品牌
async delBrand(id) {
let res = await delBrand(id);
const res = await delBrand(id);
if (res.success) {
this.$Message.success("品牌删除成功!");
this.getDataList();
}
},
// 初始化数据
init() {
this.getDataList();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 获取数据
getDataList() {
this.loading = true;
getManagerBrandPage(this.searchForm).then((res) => {
@@ -413,13 +319,11 @@ export default {
}
});
},
// 提交表单
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete this.form.id;
addBrand(this.form).then((res) => {
this.submitLoading = false;
@@ -430,7 +334,6 @@ export default {
}
});
} else {
// 编辑
updateBrand(this.form).then((res) => {
this.submitLoading = false;
if (res.success) {
@@ -443,28 +346,24 @@ export default {
}
});
},
// 添加
add() {
this.modalType = 0;
this.modalTitle = "添加";
this.$refs.form.resetFields();
this.$refs.form?.resetFields();
delete this.form.id;
this.modalVisible = true;
},
// 编辑
edit(v) {
this.modalType = 1;
this.modalTitle = "编辑";
this.$refs.form.resetFields();
// 转换null为""
for (let attr in v) {
this.$refs.form?.resetFields();
for (const attr in v) {
if (v[attr] === null) {
v[attr] = "";
}
}
let str = JSON.stringify(v);
let data = JSON.parse(str);
const str = JSON.stringify(v);
const data = JSON.parse(str);
this.form = data;
this.modalVisible = true;
},
@@ -474,3 +373,6 @@ export default {
},
};
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,165 +1,163 @@
<template>
<div>
<Card>
<el-card>
<div class="mb_10">
<Button @click="addParent" icon="md-add">添加一级分类</Button>
<el-button type="primary" @click="addParent">添加一级分类</el-button>
</div>
<Table
update-show-children
<el-table
v-loading="loading"
class="table"
:load-data="handleLoadData"
row-key="id"
:loading="loading"
:data="tableData"
:columns="columns"
row-key="id"
border
:tree-props="{ children: 'children' }"
style="width: 100%"
>
<template slot="action" slot-scope="scope">
<div class="ops">
<a class="ops-link" @click="edit(scope.row)">编辑</a>
<a class="ops-link" @click="remove(scope.row)">删除</a>
<a v-show="scope.row.level != 2" class="ops-link" @click="addChildren(scope.row)">添加子分类</a>
</div>
</template>
<template slot="commissionRate" slot-scope="scope">
<priceColorScheme v-if="scope.row.commissionRate > 0" unit="" :color="$mainColor" :value="scope.row.commissionRate">%</priceColorScheme>
<priceColorScheme v-else :value="scope.row.commissionRate" unit="" >%</priceColorScheme>
<!-- {{ scope.row.commissionRate }}% -->
</template>
<template slot="deleteFlag" slot-scope="{ row }">
<i-switch
size="large"
v-model="row.deleteFlag"
:true-value="false"
:false-value="true"
:loading="row._statusLoading"
@on-change="onStatusSwitchChange(row, $event)"
>
<span slot="open">开启</span>
<span slot="close">关闭</span>
</i-switch>
</template>
</Table>
<Modal
:title="modalTitle"
v-model="modalVisible"
:mask-closable="false"
:width="500"
>
<Form ref="form" :model="formAdd" :label-width="100" :rules="formValidate">
<div v-if="showParent">
<FormItem label="上级分类" prop="parentId">
{{ parentTitle }}
<Input
v-model="formAdd.parentId"
clearable
style="width: 100%; display: none"
/>
</FormItem>
</div>
<FormItem label="层级" prop="level" style="display: none">
<Input v-model="formAdd.level" clearable style="width: 100%" />
</FormItem>
<FormItem label="分类名称" prop="name">
<Input v-model="formAdd.name" clearable style="width: 100%" />
</FormItem>
<FormItem label="分类图标" prop="image" v-if="formAdd.level !== 1">
<upload-pic-input
v-model="formAdd.image"
style="width: 100%"
></upload-pic-input>
</FormItem>
<FormItem label="排序值" prop="sortOrder" style="width: 345px">
<InputNumber v-model="formAdd.sortOrder"></InputNumber>
</FormItem>
<FormItem label="佣金比例(%)" prop="commissionRate" style="width: 345px">
<InputNumber :max="100" :min="0" v-model="formAdd.commissionRate"></InputNumber>
</FormItem>
<FormItem label="是否启用" prop="deleteFlag">
<i-switch
size="large"
v-model="formAdd.deleteFlag"
:true-value="false"
:false-value="true"
<el-table-column prop="name" label="分类名称" min-width="200" />
<el-table-column label="状态" width="120">
<template #default="{ row }">
<el-switch
v-if="row"
v-model="row.deleteFlag"
:active-value="false"
:inactive-value="true"
inline-prompt
active-text="开启"
inactive-text="关闭"
:loading="!!row._statusLoading"
@change="(val) => onStatusSwitchChange(row, val)"
/>
</template>
</el-table-column>
<el-table-column label="佣金" width="120">
<template #default="{ row }">
<span
v-if="row"
:style="row.commissionRate > 0 ? { color: $mainColor } : {}"
>
<span slot="open">启用</span>
<span slot="close">禁用</span>
</i-switch>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="Submit">提交</Button>
</div>
</Modal>
{{ row.commissionRate }}%
</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="220" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops">
<a class="link-text" @click="edit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
<template v-if="row.level != 2">
<span class="op-split">|</span>
<a class="link-text" @click="addChildren(row)">添加子分类</a>
</template>
</div>
</template>
</el-table-column>
</el-table>
<Modal
:title="modalBrandTitle"
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
:close-on-click-modal="false"
destroy-on-close
>
<el-form ref="form" :model="formAdd" label-width="100px" :rules="formValidate">
<el-form-item v-if="showParent" label="上级分类" prop="parentId">
{{ parentTitle }}
<el-input v-model="formAdd.parentId" style="display: none" />
</el-form-item>
<el-form-item label="层级" prop="level" style="display: none">
<el-input v-model="formAdd.level" />
</el-form-item>
<el-form-item label="分类名称" prop="name">
<el-input v-model="formAdd.name" clearable />
</el-form-item>
<el-form-item v-if="formAdd.level !== 1" label="分类图标" prop="image">
<upload-pic-input v-model="formAdd.image" style="width: 100%" />
</el-form-item>
<el-form-item label="排序值" prop="sortOrder">
<el-input-number v-model="formAdd.sortOrder" style="width: 200px" />
</el-form-item>
<el-form-item label="佣金比例(%)" prop="commissionRate">
<el-input-number v-model="formAdd.commissionRate" :min="0" :max="100" style="width: 200px" />
</el-form-item>
<el-form-item label="是否启用" prop="deleteFlag">
<el-switch
v-model="formAdd.deleteFlag"
:active-value="false"
:inactive-value="true"
inline-prompt
active-text="启用"
inactive-text="禁用"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="Submit">提交</el-button>
</template>
</el-dialog>
<el-dialog
v-model="modalBrandVisible"
:mask-closable="false"
:width="500"
:title="modalBrandTitle"
width="500px"
:close-on-click-modal="false"
>
<Form ref="brandForm" :model="brandForm" :label-width="100">
<Select v-model="brandForm.categoryBrands" filterable multiple>
<Option v-for="item in brandWay" :value="item.id" :key="item.id">{{
item.name
}}</Option>
</Select>
</Form>
<div slot="footer">
<Button type="text" @click="modalBrandVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="saveCategoryBrand"
>提交</Button
>
</div>
</Modal>
<el-form ref="brandForm" :model="brandForm" label-width="100px">
<el-select v-model="brandForm.categoryBrands" filterable multiple style="width: 100%">
<el-option v-for="item in brandWay" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form>
<template #footer>
<el-button @click="modalBrandVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="saveCategoryBrand">提交</el-button>
</template>
</el-dialog>
<Modal
:title="modalSpecTitle"
<el-dialog
v-model="modalSpecVisible"
:mask-closable="false"
:width="500"
:title="modalSpecTitle"
width="500px"
:close-on-click-modal="false"
>
<Form ref="specForm" :model="specForm" :label-width="100">
<Select v-model="specForm.categorySpecs" multiple>
<Option
<el-form ref="specForm" :model="specForm" label-width="100px">
<el-select v-model="specForm.categorySpecs" multiple style="width: 100%">
<el-option
v-for="item in specifications"
:value="item.id"
:key="item.id"
:label="item.specName"
>
</Option>
</Select>
</Form>
<div slot="footer">
<Button type="text" @click="modalSpecVisible = false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="saveCategorySpec"
>提交</Button
>
</div>
</Modal>
</Card>
:value="item.id"
/>
</el-select>
</el-form>
<template #footer>
<el-button @click="modalSpecVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="saveCategorySpec">提交</el-button>
</template>
</el-dialog>
</el-card>
</div>
</template>
<script>
import {
delCategory,
disableCategory,
getBrandListData,
getCategoryBrandListData,
getCategorySpecListData,
getCategoryTree,
getSpecificationList,
insertCategory,
saveCategoryBrand,
saveCategorySpec,
updateCategory,
delCategory,
disableCategory,
getBrandListData,
getCategoryBrandListData,
getCategorySpecListData,
getCategoryTree,
getSpecificationList,
insertCategory,
saveCategoryBrand,
saveCategorySpec,
updateCategory,
} from "@/api/goods";
import uploadPicInput from "@/components/lili/upload-pic-input";
import { regular } from "@/utils";
export default {
name: "goods-category",
components: {
@@ -167,69 +165,44 @@ export default {
},
data() {
return {
recordLevel:[], // 记录当前层级
submitLoading: false, //加载状态
categoryList: [], // 分类列表
loading: false, // 加载状态
brands: [], //品牌集合
specifications: [], //规格集合
categoryId: "", // 分类id
categorySpecs: [], //已经选择的规格
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalBrandVisible: false, //品牌关联编辑显示
modalSpecVisible: false, //品牌关联编辑显示
modalTitle: "", // 添加或编辑标题
showParent: false, // 是否展示上级菜单
parentTitle: "", // 父级菜单名称
modalBrandTitle: "", // 品牌弹窗标题
modalSpecTitle: "", // 规格弹窗标题
submitLoading: false,
categoryList: [],
loading: false,
brands: [],
specifications: [],
categoryId: "",
categorySpecs: [],
modalType: 0,
modalVisible: false,
modalBrandVisible: false,
modalSpecVisible: false,
modalTitle: "",
showParent: false,
parentTitle: "",
modalBrandTitle: "",
modalSpecTitle: "",
formAdd: {
// 添加或编辑表单对象初始化数据
parentId: "",
name: "",
image: "",
sortOrder: 0,
deleteFlag: 0,
deleteFlag: false,
commissionRate: 0,
level: 0,
},
brandForm: {
categoryBrands: [],
},
brandWay: "", //请求绑定品牌的信息
specForm: {}, // 规格数据
// 表单验证规则
brandWay: [],
specForm: {
categorySpecs: [],
},
formValidate: {
commissionRate: [regular.REQUIRED, regular.INTEGER],
name: [regular.REQUIRED, regular.VARCHAR20],
sortOrder: [regular.REQUIRED, regular.INTEGER],
},
columns: [
{
title: "分类名称",
key: "name",
tree: true,
},
{
title: "状态",
slot: "deleteFlag",
},
{
title: "佣金",
key: "commissionRate",
slot: "commissionRate",
},
{
title: "操作",
key: "action",
slot: "action",
},
],
tableData: [], // 表格数据
checkedCategoryChildren: "", //选中的分类子级
tableData: [],
};
},
methods: {
@@ -250,48 +223,38 @@ export default {
const isClosing = nextDeleteFlag === true;
this.$Modal.confirm({
title: isClosing ? "确认关闭" : "确认开启",
content:
"您是否要" +
(isClosing ? "关闭" : "开启") +
"当前分类 " +
row.name +
" 及其子分类?",
content: `您是否要${isClosing ? "关闭" : "开启"}当前分类 ${row.name} 及其子分类?`,
loading: true,
okText: "是",
cancelText: "否",
onOk: () => {
this.$set(row, "_statusLoading", true);
disableCategory(row.id, { enableOperations: isClosing ? true : 0 }).then(
(res) => {
this.$Modal.remove();
this.$set(row, "_statusLoading", false);
if (res && res.success) {
this.$Message.success("操作成功");
this.getAllList(0);
return;
}
row.deleteFlag = previousDeleteFlag;
row._statusLoading = true;
disableCategory(row.id, { enableOperations: isClosing ? true : 0 }).then((res) => {
this.$Modal.remove();
row._statusLoading = false;
if (res && res.success) {
this.$Message.success("操作成功");
this.getAllList();
return;
}
);
row.deleteFlag = previousDeleteFlag;
});
},
onCancel: () => {
row.deleteFlag = previousDeleteFlag;
},
});
},
// 初始化数据
init() {
this.getAllList(0);
this.getAllList();
this.getBrandList();
this.getSpecList();
},
//获取所有品牌
getBrandList() {
getBrandListData().then((res) => {
this.brandWay = res;
});
},
//获取所有规格
getSpecList() {
getSpecificationList().then((res) => {
if (res.length != 0) {
@@ -299,7 +262,6 @@ export default {
}
});
},
//弹出品牌关联框
brandOperation(v) {
getCategoryBrandListData(v.id).then((res) => {
this.categoryId = v.id;
@@ -308,7 +270,6 @@ export default {
this.modalBrandVisible = true;
});
},
//弹出规格关联框
specOperation(v) {
getCategorySpecListData(v.id).then((res) => {
this.categoryId = v.id;
@@ -317,7 +278,6 @@ export default {
this.modalSpecVisible = true;
});
},
//保存分类规格绑定
saveCategorySpec() {
saveCategorySpec(this.categoryId, this.specForm).then((res) => {
this.submitLoading = false;
@@ -327,7 +287,6 @@ export default {
}
});
},
//保存分类品牌绑定
saveCategoryBrand() {
saveCategoryBrand(this.categoryId, this.brandForm).then((res) => {
this.submitLoading = false;
@@ -337,19 +296,17 @@ export default {
}
});
},
// 添加子分类
addChildren(v) {
this.modalType = 0;
this.modalTitle = "添加子分类";
this.parentTitle = v.name;
this.formAdd.level = eval(v.level + "+1");
this.formAdd.level = Number(v.level) + 1;
this.formAdd.commissionRate = v.commissionRate;
this.showParent = true;
delete this.formAdd.id;
this.formAdd.parentId = v.id;
this.modalVisible = true;
},
// 编辑分类
edit(v) {
this.modalType = 1;
this.modalTitle = "编辑";
@@ -364,57 +321,51 @@ export default {
this.showParent = false;
this.modalVisible = true;
},
// 添加一级分类
addParent() {
this.modalType = 0;
this.modalTitle = "添加一级分类";
this.parentTitle = "顶级分类";
this.showParent = true;
this.$refs.form.resetFields();
this.$refs.form?.resetFields();
delete this.formAdd.id;
this.formAdd.parentId = 0;
this.formAdd.level = 0;
this.modalVisible = true;
},
// 提交
Submit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete this.formAdd.id;
insertCategory(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("添加成功");
this.getAllList();
this.modalVisible = false;
this.$refs.form.resetFields();
}
});
} else {
// 编辑
updateCategory(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getAllList();
this.modalVisible = false;
this.$refs.form.resetFields();
}
});
}
if (!valid) return;
this.submitLoading = true;
if (this.modalType === 0) {
delete this.formAdd.id;
insertCategory(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("添加成功");
this.getAllList();
this.modalVisible = false;
this.$refs.form.resetFields();
}
});
} else {
updateCategory(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: () => {
// 删除
delCategory(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
@@ -425,80 +376,22 @@ export default {
},
});
},
// 异步手动加载分类名称
handleLoadData(item, callback) {
this.recordLevel[item.level] = item.id;
if (item.level == 0) {
let categoryList = JSON.parse(JSON.stringify(this.categoryList));
categoryList.forEach((val) => {
if (val.id == item.id) {
val.children.map((child) => {
child._loading = false;
child.children = [];
});
this.normalizeCategoryTree(val.children);
// 模拟加载
setTimeout(() => {
callback(val.children);
}, 100);
}
});
} else {
this.deepCategoryChildren(item.id, this.categoryList);
this.normalizeCategoryTree(this.checkedCategoryChildren);
setTimeout(() => {
callback(this.checkedCategoryChildren);
}, 100);
}
},
// 通过递归children来实现手动加载数据
deepCategoryChildren(id, list) {
if (id != "0" && list.length != 0) {
for (let i = 0; i < list.length; i++) {
let item = list[i];
if (item.id == id) {
this.checkedCategoryChildren = item.children;
return;
} else {
this.deepCategoryChildren(id, item.children);
}
}
}
},
// 获取分类数据
getAllList() {
this.loading = true;
getCategoryTree().then((res) => {
this.loading = false;
if (res.success) {
localStorage.setItem("category", JSON.stringify(res.result));
this.normalizeCategoryTree(res.result);
this.categoryList = JSON.parse(JSON.stringify(res.result));
this.tableData = res.result.map((item) => {
if(this.recordLevel[0] && item.id === this.recordLevel[0]) {
item._showChildren = true
// 继续判断第二层
if(this.recordLevel[1] && item.children){
item.children.map((child)=>{
if(this.recordLevel[1] && child.id === this.recordLevel[1]){
child._showChildren = true
}
})
}
}else{
if (item.children.length !== 0) {
item.children = [];
item._loading = false;
}
}
return item;
});
}
});
getCategoryTree()
.then((res) => {
this.loading = false;
if (res.success) {
localStorage.setItem("category", JSON.stringify(res.result));
this.normalizeCategoryTree(res.result);
this.categoryList = JSON.parse(JSON.stringify(res.result));
this.tableData = JSON.parse(JSON.stringify(res.result));
}
})
.catch(() => {
this.loading = false;
});
},
// 启用分类
enable(v) {
this.$Modal.confirm({
title: "确认启用",
@@ -511,16 +404,15 @@ export default {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getAllList(0);
this.getAllList();
}
});
},
onCancel: () => {
this.getAllList(0);
this.getAllList();
},
});
},
// 禁用分类
disable(v) {
this.$Modal.confirm({
title: "确认禁用",
@@ -533,12 +425,12 @@ export default {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getAllList(0);
this.getAllList();
}
});
},
onCancel: () => {
this.getAllList(0);
this.getAllList();
},
});
},
@@ -548,31 +440,15 @@ export default {
},
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-table-wrapper {
:deep(.el-table__body-wrapper) {
overflow: auto;
}
.table {
min-height: 100vh;
height: auto;
min-height: 60vh;
}
.ops-link {
color: #2d8cf0;
cursor: pointer;
text-decoration: none;
}
.ops {
display: flex;
flex-wrap: wrap;
}
.ops-link + .ops-link {
margin-left: 16px;
position: relative;
}
.ops-link + .ops-link::before {
content: "|";
position: absolute;
left: -10px;
color: #dcdee2;
.mb_10 {
margin-bottom: 10px;
}
</style>

View File

@@ -1,73 +1,92 @@
<template>
<div class="search">
<Card>
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
<FormItem label="参数名称" prop="paramName">
<Input v-model="form.paramName" clearable style="width: 520px" />
</FormItem>
<FormItem label="是否必填" prop="required">
<RadioGroup v-model="form.required">
<Radio :label="0"></Radio>
<Radio :label="1"></Radio>
</RadioGroup>
<span style="margin-left: 10px; color: #999; font-size: 12px"
>商品发布时参数是否必填</span
>
</FormItem>
<FormItem label="是否索引" prop="isIndex">
<RadioGroup v-model="form.isIndex">
<Radio :label="0"></Radio>
<Radio :label="1"></Radio>
</RadioGroup>
<span style="margin-left: 10px; color: #999; font-size: 12px"
>开启索引后用户将可以通过该参数筛选商品索引开关不影响商详页的参数展示</span
>
</FormItem>
<FormItem label="排序" prop="sort">
<InputNumber :min="0" type="number" v-model="form.sort" style="width: 520px" />
</FormItem>
<FormItem label="参数值" prop="options">
<Table :columns="optionColumns" :data="form.options" border size="small" style="width: 520px" />
<el-card>
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="参数名称" prop="paramName">
<el-input v-model="form.paramName" clearable style="width: 520px" />
</el-form-item>
<el-form-item label="是否必填" prop="required">
<el-radio-group v-model="form.required">
<el-radio :value="0"></el-radio>
<el-radio :value="1"></el-radio>
</el-radio-group>
<span style="margin-left: 10px; color: #999; font-size: 12px">商品发布时参数是否必填</span>
</el-form-item>
<el-form-item label="是否索引" prop="isIndex">
<el-radio-group v-model="form.isIndex">
<el-radio :value="0"></el-radio>
<el-radio :value="1"></el-radio>
</el-radio-group>
<span style="margin-left: 10px; color: #999; font-size: 12px">
开启索引后用户将可以通过该参数筛选商品索引开关不影响商详页的参数展示
</span>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number :min="0" v-model="form.sort" style="width: 520px" />
</el-form-item>
<el-form-item label="参数值" prop="options">
<el-table :data="form.options" border size="small" style="width: 520px">
<el-table-column label="参数值" min-width="420">
<template #default="{ row, $index }">
<el-input
v-if="row"
v-model="form.options[$index].value"
clearable
@blur="touchOptionsValidate"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="90" align="center">
<template #default="{ row, $index }">
<a v-if="row" class="link-text" @click="removeOptionRow($index)">
删除
</a>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 10px">
<Button type="primary" @click="addOptionRow">新增</Button>
<el-button type="primary" @click="addOptionRow">新增</el-button>
</div>
</FormItem>
<FormItem label="关联分类">
<Button type="default" @click="openCategoryModal">选择分类</Button>
<span v-if="selectedCategoryNamesText" style="margin-left: 10px; color: #999; font-size: 12px"
>{{ selectedCategoryNamesText }}</span
>
<span v-else style="margin-left: 10px; color: #999; font-size: 12px"
>已选择{{ selectedCategoryIds.length }}个分类</span
>
</FormItem>
<FormItem>
<Button type="default" @click="back">返回</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit">保存</Button>
</FormItem>
</Form>
</Card>
</el-form-item>
<el-form-item label="关联分类">
<el-button @click="openCategoryModal">选择分类</el-button>
<span v-if="selectedCategoryNamesText" style="margin-left: 10px; color: #999; font-size: 12px">
{{ selectedCategoryNamesText }}</span>
<span v-else style="margin-left: 10px; color: #999; font-size: 12px">
已选择{{ selectedCategoryIds.length }}个分类
</span>
</el-form-item>
<el-form-item>
<el-button @click="back">返回</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</el-card>
<Modal
:title="categoryModalTitle"
<el-dialog
v-model="categoryModalVisible"
:mask-closable="false"
:width="700"
:title="categoryModalTitle"
width="700px"
:close-on-click-modal="false"
>
<div style="position: relative; max-height: 520px; overflow: auto;">
<Spin size="large" fix v-if="categoryTreeLoading"></Spin>
<Tree
<div v-loading="categoryTreeLoading" style="position: relative; max-height: 520px; overflow: auto">
<el-tree
ref="categoryTree"
:key="categoryTreeKey"
:data="categoryTreeData"
:props="{ label: 'title', children: 'children' }"
node-key="id"
show-checkbox
@on-check-change="onCategoryTreeCheckChange"
></Tree>
default-expand-all
:default-checked-keys="selectedCategoryIds"
@check="onCategoryTreeCheckChange"
/>
</div>
<div slot="footer">
<Button type="text" @click="categoryModalVisible = false">取消</Button>
<Button type="primary" style="margin-left: 8px" @click="categoryModalVisible = false">确定</Button>
</div>
</Modal>
<template #footer>
<el-button @click="categoryModalVisible = false">取消</el-button>
<el-button type="primary" style="margin-left: 8px" @click="categoryModalVisible = false">确定</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -190,51 +209,6 @@ export default {
isIndex: 0,
sort: 0,
},
optionColumns: [
{
title: "参数值",
key: "value",
minWidth: 420,
render: (h, params) => {
return h("Input", {
props: {
value: params.row.value,
clearable: true,
},
on: {
input: (val) => {
if (!Array.isArray(this.form.options)) this.form.options = [];
if (!this.form.options[params.index]) return;
this.form.options[params.index].value = val;
},
"on-blur": () => {
this.touchOptionsValidate();
},
},
});
},
},
{
title: "操作",
width: 90,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
type: "error",
size: "small",
},
on: {
click: () => this.removeOptionRow(params.index),
},
},
"删除",
);
},
},
],
formValidate: {
paramName: [regular.REQUIRED, regular.VARCHAR5],
options: [{ required: true, validator: validateOptions, trigger: "change" }],
@@ -253,8 +227,8 @@ export default {
const selectedSet = new Set(toStringArray(this.selectedCategoryIds));
const isSelected = (node) => {
if (!node) return false;
const id = node.id !== undefined && node.id !== null ? String(node.id) : "";
if (id && selectedSet.has(id)) return true;
const nodeId = node.id !== undefined && node.id !== null ? String(node.id) : "";
if (nodeId && selectedSet.has(nodeId)) return true;
const children = Array.isArray(node.children) ? node.children : [];
if (children.length === 0) return false;
return children.every(isSelected);
@@ -276,11 +250,11 @@ export default {
watch: {
"form.required"(val) {
const n = normalize01(val, 0);
if (val !== n) this.$set(this.form, "required", n);
if (val !== n) this.form.required = n;
},
"form.isIndex"(val) {
const n = normalize01(val, 0);
if (val !== n) this.$set(this.form, "isIndex", n);
if (val !== n) this.form.isIndex = n;
},
},
methods: {
@@ -302,18 +276,13 @@ export default {
this.form.options.splice(index, 1);
this.touchOptionsValidate();
},
buildCategoryTreeNodes(list, selectedSet) {
buildCategoryTreeNodes(list) {
if (!Array.isArray(list) || list.length === 0) return [];
return list.map((item) => {
const children = this.buildCategoryTreeNodes(item.children || [], selectedSet);
return {
id: item.id,
title: item.name,
expand: true,
checked: selectedSet.has(String(item.id)),
children,
};
});
return list.map((item) => ({
id: item.id,
title: item.name,
children: this.buildCategoryTreeNodes(item.children || []),
}));
},
async loadDetail(parameterId) {
if (!parameterId) return;
@@ -337,7 +306,6 @@ export default {
this.categoryTreeLoading = true;
this.categoryTreeKey += 1;
try {
const selectedSet = new Set(toStringArray(this.selectedCategoryIds));
if (!Array.isArray(this.categoryTreeSource) || this.categoryTreeSource.length === 0) {
const treeRes = await getCategoryTree();
this.categoryTreeSource = treeRes && treeRes.success ? treeRes.result || [] : [];
@@ -345,17 +313,13 @@ export default {
buildCategoryIdNameMap(this.categoryTreeSource, map);
this.categoryIdNameMap = map;
}
this.categoryTreeData = this.buildCategoryTreeNodes(this.categoryTreeSource || [], selectedSet);
this.categoryTreeData = this.buildCategoryTreeNodes(this.categoryTreeSource || []);
} finally {
this.categoryTreeLoading = false;
}
},
onCategoryTreeCheckChange(checkedNodes) {
if (!Array.isArray(checkedNodes)) {
this.selectedCategoryIds = [];
return;
}
this.selectedCategoryIds = toStringArray(checkedNodes.map((node) => node && node.id).filter(Boolean));
onCategoryTreeCheckChange(_data, checkedInfo) {
this.selectedCategoryIds = toStringArray(checkedInfo?.checkedKeys || []);
},
initForm() {
if (this.id) {

View File

@@ -1,55 +1,72 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
@submit.native.prevent
@keydown.enter.native="handleSearch"
:model="searchForm"
inline
:label-width="70"
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<Form-item label="参数名称">
<Input
type="text"
<el-form-item label="参数名称">
<el-input
v-model="searchForm.paramName"
placeholder="请输入参数名称"
clearable
style="width: 240px"
/>
</Form-item>
<Button @click="handleSearch" type="primary">搜索</Button>
</Form>
</Card>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<Card>
<Row class="operation padding-row">
<Button @click="goAdd" type="primary">添加</Button>
</Row>
<Table :loading="loading" border :columns="columns" :data="data" ref="table"></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="goAdd">添加</el-button>
</div>
<el-table v-loading="loading" border :data="data" ref="table" style="width: 100%">
<el-table-column prop="paramName" label="参数名称" width="300" />
<el-table-column prop="options" label="参数值" min-width="260" show-overflow-tooltip />
<el-table-column label="必填" width="300" align="center">
<template #default="{ row }">
<span v-if="row">{{ isTruthyFlag(row.required) ? "是" : "否" }}</span>
</template>
</el-table-column>
<el-table-column label="可索引" width="300" align="center">
<template #default="{ row }">
<span v-if="row">{{ isTruthyFlag(row.isIndex) ? "是" : "否" }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row">
<a class="link-text" @click="goEdit(row)">编辑</a>
<span class="op-split">|</span>|<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
</div>
</template>
<script>
import {
deleteParams,
getGoodsParamsPage,
} from "@/api/goods";
import { deleteParams, getGoodsParamsPage } from "@/api/goods";
export default {
name: "categoryParams",
@@ -66,90 +83,12 @@ export default {
paramName: "",
},
data: [],
columns: [
{
title: "参数名称",
key: "paramName",
width: 300,
resizable: true,
sortable: false,
},
{
title: "参数值",
key: "options",
minWidth: 260,
tooltip: true,
},
{
title: "必填",
key: "required",
width: 300,
align: "center",
render: (h, params) => {
const val = params.row.required;
const on = val === 1 || val === "1" || val === true;
return h("span", on ? "是" : "否");
},
},
{
title: "可索引",
key: "isIndex",
width: 300,
align: "center",
render: (h, params) => {
const val = params.row.isIndex;
const on = val === 1 || val === "1" || val === true;
return h("span", on ? "是" : "否");
},
},
{
title: "操作",
key: "action",
width: 300,
align: "center",
fixed: "right",
render: (h, params) => {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.goEdit(params.row);
},
},
},
"编辑"
),
h("span", { style: { margin: "0 8px", color: "#dcdee2" } }, "|"),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.remove(params.row);
},
},
},
"删除"
),
]);
},
},
],
};
},
methods: {
isTruthyFlag(val) {
return val === 1 || val === "1" || val === true;
},
init() {
this.getDataList();
},
@@ -209,4 +148,10 @@ export default {
},
};
</script>
<style lang="scss"></style>
<style lang="scss">
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
</style>

View File

@@ -1,103 +1,171 @@
<template>
<div>
<Card>
<Row>
<Form ref="searchForm" :model="searchForm" @keydown.enter.native="handleSearch" @submit.native.prevent inline :label-width="70" class="search-form">
<Form-item label="会员名称" prop="memberName">
<Input type="text" v-model="searchForm.memberName" placeholder="请输入会员名称" clearable style="width: 240px"/>
</Form-item>
<Form-item label="商品名称" prop="goodsName">
<Input type="text" v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable style="width: 240px"/>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn" icon="ios-search">搜索</Button>
</Form>
</Row>
</Card>
<Card>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" class="mt_10">
<!-- 页面展示 -->
<template slot="shopDisableSlot" slot-scope="scope">
<i-switch size="large" true-value="OPEN" false-value="CLOSE" v-model="scope.row.status"
@on-change="changeSwitch(scope.row)">
<span slot="open">展示</span>
<span slot="close">隐藏</span>
</i-switch>
</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="[20, 50, 100]"
size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
<!-- 评价详情 -->
<Modal v-model="infoFlag" width="800" :title="infoTitle">
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<el-form-item label="会员名称" prop="memberName">
<el-input
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item label="商品名称" prop="goodsName">
<el-input
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-table ref="table" v-loading="loading" border :data="data" class="mt_10" style="width: 100%">
<el-table-column prop="goodsName" label="商品名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="memberName" label="会员名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="content" label="评论内容" min-width="220" show-overflow-tooltip />
<el-table-column label="是否置顶" width="100" align="center">
<template #default="{ row }">
<el-tag v-if="row" :type="row.top ? 'danger' : 'info'">
{{ row.top ? "已置顶" : "未置顶" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="评价" width="90">
<template #default="{ row }">
<el-tag v-if="row" :type="gradeTagType(row.grade)">{{ gradeText(row.grade) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="评价时间" width="170" />
<el-table-column label="页面展示" width="100">
<template #default="{ row }">
<el-switch
v-if="row"
v-model="row.status"
active-value="OPEN"
inactive-value="CLOSE"
inline-prompt
active-text="展示"
inactive-text="隐藏"
@change="changeSwitch(row)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="220" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops">
<a class="link-text" @click="info(row)">查看</a>
<span class="op-split">|</span>
<a class="link-text" @click="updateTop(row)">{{ row.top ? "取消置顶" : "置顶评论" }}</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
<el-dialog v-model="infoFlag" :title="infoTitle" width="800px">
<div class="info-list" style="overflow: hidden">
<div class="left-container">
<div class="product">
<img class="img" :src=infoData.goodsImage>
<img class="img" :src="infoData.goodsImage" />
</div>
<div class="show">
<label>页面展示</label>
<i-switch size="large" true-value="OPEN" false-value="CLOSE" v-model="infoData.status"
@on-change="changeSwitchView" style="margin-top: 3px">
<span slot="open">展示</span>
<span slot="close">隐藏</span>
</i-switch>
<el-switch
v-model="infoData.status"
active-value="OPEN"
inactive-value="CLOSE"
inline-prompt
active-text="展示"
inactive-text="隐藏"
style="margin-top: 3px"
@change="changeSwitchView"
/>
</div>
</div>
<div class="right-container">
<div class="border-b">{{ infoData.goodsName }}</div>
<div class="border-b">
<div class="div-height"> 店铺名称{{ infoData.storeName }}</div>
<div class="div-height"> 订单号{{ infoData.orderNo }}</div>
<div class="div-height">店铺名称{{ infoData.storeName }}</div>
<div class="div-height">订单号{{ infoData.orderNo }}</div>
</div>
<div class="border-b">
<List>
<ListItem>
<ListItemMeta :avatar="infoData.memberProfile" :title="infoData.memberName"
:description="infoData.content"/>
</ListItem>
<div class="score-content">
<span>物流评分{{infoData.deliveryScore}}</span>
<span>服务评分{{infoData.serviceScore}}</span>
<span>描述评分{{infoData.descriptionScore}}</span>
<div class="review-item">
<el-avatar v-if="infoData.memberProfile" :src="infoData.memberProfile" :size="40" />
<div class="review-meta">
<div class="review-name">{{ infoData.memberName }}</div>
<div class="review-content">{{ infoData.content }}</div>
</div>
<div class="" v-if="infoData.haveImage">
评价图
<div style="margin-left: 40px">
<template v-if="infoData.images && infoData.images.length">
<img style="width: 100px;height: 110px;margin-left: 2px"
v-for="(img,index) in infoData.images.split(',')" :src="img"
alt="" :key="index"/>
</template>
</div>
</div>
<div class="score-content">
<span>物流评分{{ infoData.deliveryScore }}</span>
<span>服务评分{{ infoData.serviceScore }}</span>
<span>描述评分{{ infoData.descriptionScore }}</span>
</div>
<div v-if="infoData.haveImage">
评价图
<div style="margin-left: 40px">
<template v-if="infoData.images && infoData.images.length">
<img
v-for="(img, index) in infoData.images.split(',')"
:key="index"
style="width: 100px; height: 110px; margin-left: 2px"
:src="img"
alt=""
/>
</template>
</div>
</List>
</div>
</div>
<div class="border-b" v-if="infoData.reply">
<div v-if="infoData.reply" class="border-b">
<div>
<div>
<div style="float: left"> 商家回复</div>
<div style="margin-left: 60px">{{ infoData.reply }}</div>
</div>
<div v-if="infoData.haveReplyImage">
<div style="margin-left: 60px">
<template v-if="infoData.replyImage && infoData.replyImage.length">
<img style="width: 100px;height: 110px" v-for="(img,index) in infoData.replyImage.split(',')" :key="index"
:src="img" alt=""/>
</template>
</div>
<div style="float: left">商家回复</div>
<div style="margin-left: 60px">{{ infoData.reply }}</div>
</div>
<div v-if="infoData.haveReplyImage">
<div style="margin-left: 60px">
<template v-if="infoData.replyImage && infoData.replyImage.length">
<img
v-for="(img, index) in infoData.replyImage.split(',')"
:key="index"
style="width: 100px; height: 110px"
:src="img"
alt=""
/>
</template>
</div>
</div>
</div>
</div>
</div>
</Modal>
</el-dialog>
</div>
</template>
@@ -105,223 +173,66 @@
import * as API_Member from "@/api/member";
export default {
name: "goods-review", // 会员评价
name: "goods-review",
data() {
return {
infoData: {}, // 商品信息
infoFlag: false, // 评价展示
infoTitle: "", // modal名称
loading: true, // 表单加载状态
infoData: {},
infoFlag: false,
infoTitle: "",
loading: true,
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
pageNumber: 1,
pageSize: 20,
goodsName: "",
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
},
columns: [
// 表头
{
title: "商品名称",
key: "goodsName",
minWidth: 120,
align: "left",
tooltip: true,
},
{
title: "会员名称",
key: "memberName",
minWidth: 120,
align: "left",
tooltip: true,
},
{
title: "评论内容",
key: "content",
minWidth: 220,
align: "left",
tooltip: true,
},
{
title: "是否置顶",
key: "top",
align: "center",
width: 100,
render: (h, params) => {
return h(
"Tag",
{
props: {
color: params.row.top ? "red" : "default",
},
},
params.row.top ? "已置顶" : "未置顶"
);
},
},
{
title: "评价",
key: "grade",
align: "left",
width: 90,
render: (h, params) => {
if (params.row.grade == "GOOD") {
return h("Tag", {props: {color: "green",},}, "好评");
} else if (params.row.grade == "MODERATE") {
return h("Tag", {props: {color: "orange",},}, "中评");
} else {
return h("Tag", {props: {color: "red",},}, "差评");
}
}
},
{
title: "评价时间",
key: "createTime",
align: "left",
width: 170
},
{
title: "页面展示",
key: "shopDisable",
align: "left",
width: 100,
slot: "shopDisableSlot",
},
{
title: "操作",
key: "action",
width: 220,
align: "center",
fixed: "right",
render: (h, params) => {
return h("div", { class: "ops" }, [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.info(params.row);
},
},
},
"查看"
),
h(
"span",
{
style: {
margin: "0 8px",
color: "#dcdee2",
},
},
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.updateTop(params.row);
},
},
},
params.row.top ? "取消置顶" : "置顶评论"
),
h(
"span",
{
style: {
margin: "0 8px",
color: "#dcdee2",
},
},
"|"
),
h(
"Poptip",
{
props: { confirm: true, title: "确认删除" },
on: {
"on-ok": () => {
this.remove(params.row);
},
},
},
[
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
},
"删除"
),
]
),
]);
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
data: [],
total: 0,
};
},
methods: {
// 切换查看switch
changeSwitchView(val) {
let status = val;
API_Member.updateMemberReview(this.infoData.id, {status}).then(
(res) => {
this.$Message.success("修改成功!");
this.init();
}
);
gradeTagType(grade) {
if (grade === "GOOD") return "success";
if (grade === "MODERATE") return "warning";
return "danger";
},
gradeText(grade) {
if (grade === "GOOD") return "好评";
if (grade === "MODERATE") return "中评";
return "差评";
},
changeSwitchView(val) {
const status = val;
API_Member.updateMemberReview(this.infoData.id, { status }).then(() => {
this.$Message.success("修改成功!");
this.init();
});
},
// 初始化数据
init() {
this.getDataList();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getDataList();
},
//列表直接选择页面是否展示
changeSwitch(v) {
let status = v.status;
API_Member.updateMemberReview(v.id, {status: status}).then((res) => {
const status = v.status;
API_Member.updateMemberReview(v.id, { status }).then(() => {
this.init();
});
},
// 置顶评论
updateTop(v) {
const top = !v.top;
API_Member.updateMemberReviewTop(v.id, { top }).then((res) => {
@@ -340,7 +251,6 @@ export default {
}
});
},
// 获取列表
getDataList() {
this.loading = true;
API_Member.getMemberReview(this.searchForm).then((res) => {
@@ -353,7 +263,6 @@ export default {
this.total = this.data.length;
this.loading = false;
},
//评价详情
info(v) {
this.infoFlag = true;
this.infoTitle = `用户${v.memberName}的评价详情`;
@@ -363,14 +272,13 @@ export default {
}
});
},
// 删除评论
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除会员" + v.memberName + "的评论?",
loading: true,
onOk: () => {
API_Member.delMemberReview(v.id).then((res) => {
API_Member.delMemberReview(v.id).then(() => {
this.$Modal.remove();
this.$Message.success("修改成功");
this.init();
@@ -384,6 +292,7 @@ export default {
},
};
</script>
<style lang="scss" scoped>
.left-container {
float: left;
@@ -408,8 +317,8 @@ img {
border: 1px solid #d9d9d9;
border-radius: 3px;
}
.show{
label{
.show {
label {
font-size: 14px;
}
margin-top: 15px;
@@ -430,12 +339,26 @@ label {
position: relative;
margin-top: 12px;
}
.div-height{
.div-height {
line-height: 25px;
}
.score-content {
margin: 5px 0;
span{margin-right: 20px;}
span {
margin-right: 20px;
}
}
.review-item {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.review-name {
font-weight: 500;
}
.review-content {
color: #666;
margin-top: 4px;
}
.ops a {
color: #2d8cf0;

View File

@@ -1,61 +1,70 @@
<template>
<div class="search">
<Card>
<Row class="operation padding-row">
<Button type="primary" @click="openAdd">添加分组</Button>
</Row>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="openAdd">添加分组</el-button>
</div>
<el-table ref="table" v-loading="loading" :data="data" border class="mt_10" style="width: 100%">
<el-table-column prop="groupName" label="分组名称" min-width="160" show-overflow-tooltip />
<el-table-column prop="description" label="分组描述" min-width="240" show-overflow-tooltip />
<el-table-column prop="createTime" label="创建时间" width="180" />
<el-table-column prop="updateTime" label="更新时间" width="180" />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops" style="display: flex; justify-content: center">
<a class="link-text" @click="openEdit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
<Modal v-model="addFlag" title="添加商品分组">
<Form ref="addForm" :model="formAdd" :rules="rulesAdd" :label-width="90">
<FormItem label="分组名称" prop="groupName" style="width: 90%;">
<Input v-model="formAdd.groupName" maxlength="30" placeholder="请输入分组名称" />
</FormItem>
<FormItem label="分组描述" prop="description" style="width: 90%;">
<Input v-model="formAdd.description" maxlength="200" placeholder="请输入分组描述" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="addFlag = false">取消</Button>
<Button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</Button>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</Modal>
<Modal v-model="editFlag" title="编辑商品分组">
<Form ref="editForm" :model="formEdit" :rules="rulesEdit" :label-width="90">
<Input v-model="formEdit.id" v-show="false" />
<FormItem label="分组名称" prop="groupName" style="width: 90%;">
<Input v-model="formEdit.groupName" maxlength="30" placeholder="请输入分组名称" />
</FormItem>
<FormItem label="分组描述" prop="description" style="width: 90%;">
<Input v-model="formEdit.description" maxlength="200" placeholder="请输入分组描述" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="editFlag = false">取消</Button>
<Button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</Button>
</div>
</Modal>
</el-card>
<el-dialog v-model="addFlag" title="添加商品分组" width="500px" :close-on-click-modal="false" destroy-on-close>
<el-form ref="addForm" :model="formAdd" :rules="rulesAdd" label-width="90px">
<el-form-item label="分组名称" prop="groupName" style="width: 90%">
<el-input v-model="formAdd.groupName" maxlength="30" placeholder="请输入分组名称" />
</el-form-item>
<el-form-item label="分组描述" prop="description" style="width: 90%">
<el-input v-model="formAdd.description" maxlength="200" placeholder="请输入分组描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="addFlag = false">取消</el-button>
<el-button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="editFlag" title="编辑商品分组" width="500px" :close-on-click-modal="false" destroy-on-close>
<el-form ref="editForm" :model="formEdit" :rules="rulesEdit" label-width="90px">
<el-input v-model="formEdit.id" style="display: none" />
<el-form-item label="分组名称" prop="groupName" style="width: 90%">
<el-input v-model="formEdit.groupName" maxlength="30" placeholder="请输入分组名称" />
</el-form-item>
<el-form-item label="分组描述" prop="description" style="width: 90%">
<el-input v-model="formEdit.description" maxlength="200" placeholder="请输入分组描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editFlag = false">取消</el-button>
<el-button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -71,54 +80,6 @@ export default {
pageNumber: 1,
pageSize: 20,
},
columns: [
{
title: "分组名称",
key: "groupName",
minWidth: 160,
tooltip: true,
},
{
title: "分组描述",
key: "description",
minWidth: 240,
tooltip: true,
},
{
title: "创建时间",
key: "createTime",
width: 180,
},
{
title: "更新时间",
key: "updateTime",
width: 180,
},
{
title: "操作",
key: "action",
align: "center",
width: 200,
fixed: "right",
render: (h, params) => {
const linkStyle = {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
};
const sep = h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
);
return h("div", { class: "ops", style: { display: "flex", justifyContent: "center" } }, [
h("a", { style: linkStyle, on: { click: () => this.openEdit(params.row) } }, "编辑"),
sep,
h("a", { style: linkStyle, on: { click: () => this.remove(params.row) } }, "删除"),
]);
},
},
],
data: [],
total: 0,
addFlag: false,
@@ -135,10 +96,10 @@ export default {
description: "",
},
rulesAdd: {
groupName: [{ required: true, message: "请输入分组名称" }],
groupName: [{ required: true, message: "请输入分组名称", trigger: "blur" }],
},
rulesEdit: {
groupName: [{ required: true, message: "请输入分组名称" }],
groupName: [{ required: true, message: "请输入分组名称", trigger: "blur" }],
},
};
},
@@ -248,7 +209,7 @@ export default {
remove(row) {
this.$Modal.confirm({
title: "提示",
content: "<p>确定删除该分组?</p>",
content: "确定删除该分组?",
onOk: () => {
API_Goods.deleteGoodsGroup(row.id)
.then((res) => {
@@ -271,3 +232,16 @@ export default {
},
};
</script>
<style scoped>
.ops a {
color: #2d8cf0;
cursor: pointer;
text-decoration: none;
}
.ops span {
display: inline-block;
margin: 0 8px;
color: #dcdee2;
}
</style>

View File

@@ -1,120 +1,160 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
label-width="70px"
class="search-form"
@keydown.enter.native="handleSearch"
@keyup.enter="handleSearch"
>
<Form-item label="商品名称" prop="goodsName">
<Input
<el-form-item label="商品名称" prop="goodsName">
<el-input
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="商品ID" prop="goodsId">
<Input
</el-form-item>
<el-form-item label="商品ID" prop="goodsId">
<el-input
v-model="searchForm.goodsId"
placeholder="请输入商品ID"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="SKU货号" prop="sn">
<Input
</el-form-item>
<el-form-item label="SKU货号" prop="sn">
<el-input
v-model="searchForm.sn"
placeholder="请输入SKU货号"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="店铺名称" prop="storeName">
<Input
</el-form-item>
<el-form-item label="店铺名称" prop="storeName">
<el-input
v-model="searchForm.storeName"
placeholder="请输入店铺名称"
clearable
style="width: 240px"
/>
</Form-item>
<Button
@click="handleSearch"
class="search-btn"
type="primary"
icon="ios-search"
>
搜索
</Button>
<Button @click="handleReset" style="margin-left: 8px">重置</Button>
</Form>
</Card>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
<el-button style="margin-left: 8px" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<Card class="mt_10">
<Alert show-icon>
支持按规格逐条设置虚拟销量列表总销量 = 真实销量 + 虚拟销量
</Alert>
<el-card class="mt_10">
<el-alert
type="info"
show-icon
:closable="false"
title="支持按规格逐条设置虚拟销量,列表总销量 = 真实销量 + 虚拟销量。"
style="margin-bottom: 10px"
/>
<div class="batch-operations">
<Button
<el-button
type="primary"
:disabled="selectedRows.length === 0"
@click="openBatchVirtualSalesModal"
>
批量设置虚拟销量
</Button>
</el-button>
</div>
<Table
:loading="loading"
:columns="columns"
:data="data"
<el-table
ref="table"
v-loading="loading"
:data="data"
class="mt_10"
sortable="custom"
@on-sort-change="changeSort"
@on-selection-change="handleSelectionChange"
style="width: 100%"
@sort-change="changeSort"
@selection-change="handleSelectionChange"
>
<template slot="goodsSlot" slot-scope="{ row }">
<div class="goods-info">
<img
:src="row.thumbnail"
class="goods-thumbnail"
/>
<div class="goods-text">
<div class="div-zoom">{{ row.goodsName }}</div>
<div class="sub-title" v-if="row.simpleSpecs">
规格{{ row.simpleSpecs.trim() || "-" }}
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="id" label="SKU ID" width="180" show-overflow-tooltip />
<el-table-column prop="goodsId" label="商品ID" width="180" show-overflow-tooltip />
<el-table-column label="商品信息" min-width="360">
<template #default="{ row }">
<div v-if="row" class="goods-info">
<img
v-if="row.thumbnail"
:src="row.thumbnail"
class="goods-thumbnail"
alt=""
/>
<div class="goods-text">
<div class="div-zoom">{{ row.goodsName }}</div>
<div v-if="row.simpleSpecs" class="sub-title">
规格{{ row.simpleSpecs.trim() || "-" }}
</div>
</div>
</div>
</div>
</template>
</Table>
</template>
</el-table-column>
<el-table-column label="真实销量" width="110">
<template #default="{ row }">
<span v-if="row">{{ row.buyCount || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="虚拟销量" width="110">
<template #default="{ row }">
<span v-if="row">{{ row.virtualSalesInput || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="总销量" width="110">
<template #default="{ row }">
<span v-if="row">{{ getTotalSales(row) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="100">
<template #default="{ row }">
<el-tag v-if="row" :type="row.marketEnable === 'UPPER' ? 'success' : 'warning'">
{{ row.marketEnable === "UPPER" ? "上架" : "下架" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="{ row, $index }">
<a
v-if="row"
class="link-text"
:class="{ disabled: row.saving }"
@click="!row.saving && openVirtualSalesModal(row, $index)"
>
设置
</a>
</template>
</el-table-column>
</el-table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
@on-change="changePage"
@on-page-size-change="changePageSize"
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
<Modal
<el-dialog
v-model="editModalVisible"
:title="modalMode === 'batch' ? '批量设置虚拟销量' : '设置虚拟销量'"
:mask-closable="false"
:closable="!modalSubmitting"
width="480px"
:close-on-click-modal="false"
:close-on-press-escape="!modalSubmitting"
:show-close="!modalSubmitting"
destroy-on-close
>
<div v-if="modalMode === 'single' && currentSku" class="virtual-sales-modal">
<div class="sku-info-item">
@@ -129,50 +169,42 @@
<span class="sku-info-label">SKU ID</span>
<span>{{ currentSku.id || "-" }}</span>
</div>
<Form :label-width="90" class="mt_10">
<Form-item label="虚拟销量">
<InputNumber
<el-form label-width="90px" class="mt_10">
<el-form-item label="虚拟销量">
<el-input-number
v-model="editForm.virtualSales"
:min="0"
:max="99999999"
:precision="0"
style="width: 200px"
/>
</Form-item>
</Form>
</el-form-item>
</el-form>
</div>
<div v-else-if="modalMode === 'batch'" class="virtual-sales-modal">
<div class="sku-info-item">
<span class="sku-info-label">已选规格</span>
<span>{{ selectedRows.length }} </span>
</div>
<Form :label-width="90" class="mt_10">
<Form-item label="虚拟销量">
<InputNumber
<el-form label-width="90px" class="mt_10">
<el-form-item label="虚拟销量">
<el-input-number
v-model="editForm.virtualSales"
:min="0"
:max="99999999"
:precision="0"
style="width: 200px"
/>
</Form-item>
</Form>
</el-form-item>
</el-form>
</div>
<div slot="footer">
<Button @click="handleCancelVirtualSales" :disabled="modalSubmitting">
取消
</Button>
<Button
type="primary"
:loading="modalSubmitting"
@click="handleSubmitVirtualSales"
>
<template #footer>
<el-button :disabled="modalSubmitting" @click="handleCancelVirtualSales">取消</el-button>
<el-button type="primary" :loading="modalSubmitting" @click="handleSubmitVirtualSales">
提交
</Button>
</div>
</Modal>
</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -216,84 +248,6 @@ export default {
sn: "",
storeName: "",
},
columns: [
{
type: "selection",
width: 60,
align: "center",
},
{
title: "SKU ID",
key: "id",
width: 180,
tooltip: true,
},
{
title: "商品ID",
key: "goodsId",
width: 180,
tooltip: true,
},
{
title: "商品信息",
key: "goodsName",
minWidth: 360,
slot: "goodsSlot",
},
{
title: "真实销量",
key: "buyCount",
width: 110,
render: (h, params) => h("span", params.row.buyCount || 0),
},
{
title: "虚拟销量",
key: "virtualSalesInput",
width: 110,
render: (h, params) => h("span", params.row.virtualSalesInput || 0),
},
{
title: "总销量",
key: "totalSalesDisplay",
width: 110,
render: (h, params) => h("span", this.getTotalSales(params.row)),
},
{
title: "状态",
key: "marketEnable",
width: 100,
render: (h, params) => {
const isUpper = params.row.marketEnable === "UPPER";
return h(
"Tag",
{ props: { color: isUpper ? "green" : "volcano" } },
isUpper ? "上架" : "下架"
);
},
},
{
title: "操作",
key: "action",
width: 100,
align: "center",
render: (h, params) => {
return h(
"Button",
{
props: {
type: "primary",
size: "small",
loading: !!params.row.saving,
},
on: {
click: () => this.openVirtualSalesModal(params.row, params.index),
},
},
"设置"
);
},
},
],
data: [],
total: 0,
};
@@ -328,12 +282,13 @@ export default {
};
this.getDataList();
},
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order === "normal") {
changeSort({ prop, order }) {
if (!order) {
this.searchForm.sort = "create_time";
this.searchForm.order = "desc";
} else {
this.searchForm.sort = prop;
this.searchForm.order = order === "ascending" ? "asc" : "desc";
}
this.getDataList();
},
@@ -394,9 +349,7 @@ export default {
this.editModalVisible = true;
},
handleCancelVirtualSales() {
if (this.modalSubmitting) {
return;
}
if (this.modalSubmitting) return;
this.resetVirtualSalesModal();
},
resetVirtualSalesModal() {
@@ -416,18 +369,21 @@ export default {
this.handleBatchSubmitVirtualSales(virtualSales);
return;
}
if (!this.currentSku || this.currentIndex < 0) {
return;
}
if (!this.currentSku || this.currentIndex < 0) return;
const currentIndex = this.currentIndex;
const currentSkuId = this.currentSku.id;
this.modalSubmitting = true;
this.$set(this.data[currentIndex], "saving", true);
if (this.data[currentIndex]) {
this.data[currentIndex].saving = true;
}
updateGoodsSkuVirtualSales(currentSkuId, { virtualSales })
.then((res) => {
if (res && res.success) {
this.$set(this.data[currentIndex], "virtualSales", virtualSales);
this.$set(this.data[currentIndex], "virtualSalesInput", virtualSales);
if (this.data[currentIndex]) {
this.data[currentIndex].virtualSales = virtualSales;
this.data[currentIndex].virtualSalesInput = virtualSales;
}
this.$Message.success("虚拟销量设置成功");
this.resetVirtualSalesModal();
} else {
@@ -439,7 +395,7 @@ export default {
})
.finally(() => {
if (this.data[currentIndex]) {
this.$set(this.data[currentIndex], "saving", false);
this.data[currentIndex].saving = false;
}
this.modalSubmitting = false;
});
@@ -455,9 +411,7 @@ export default {
.then((res) => {
if (res && res.success) {
this.data = this.data.map((item) => {
if (!skuIds.includes(item.id)) {
return item;
}
if (!skuIds.includes(item.id)) return item;
return {
...item,
virtualSales,
@@ -465,9 +419,7 @@ export default {
};
});
this.selectedRows = [];
if (this.$refs.table) {
this.$refs.table.selectAll(false);
}
this.$refs.table?.clearSelection();
this.$Message.success("虚拟销量设置成功");
this.resetVirtualSalesModal();
} else {
@@ -517,6 +469,12 @@ export default {
min-width: 0;
}
.div-zoom {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.batch-operations {
margin-top: 10px;
}
@@ -537,4 +495,8 @@ export default {
color: #808695;
flex-shrink: 0;
}
.mt_10 {
margin-top: 10px;
}
</style>