merchapp/java-mall-app-shop-admin/pages/warehouse/manage/classifyList.vue
2025-07-28 01:55:47 +08:00

1139 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="classifyList-container">
<view class="tips">
一级分类数量过多将严重影响买家进店转化 我们建议25个为宜
</view>
<view class="no-data" v-if="classifyList.length <= 0 && !loading">
<view class="no-data-bg"></view>
<view class="no-data-tips">暂无分类</view>
</view>
<view class="classifyList-content">
<favorite-loading
class="classifyList-loading"
v-show="loading"
:color="'#fe4119'"
text=""
animation="spinner15"
></favorite-loading>
<scroll-view
v-if="classifyList.length > 0 && !loading"
scroll-y
scroll-with-animation
:show-scrollbar="false"
class="classifyList-scroll"
>
<view class="myui_card">
<block v-for="(item, index) of classifyList" :key="index">
<tui-collapse
:index="index"
:current="current"
hdBgColor="#fff"
@click="handerCollApse($event, item)"
>
<template v-slot:title>
<view class="stair-item">
<view class="classify-info">
<view class="stair-name">{{ item.category_name }}</view>
<view class="stair-tips" v-if="item.sub.length > 0">
二级分类{{ item.category_order }}
</view>
<view class="stair-tips" v-else>
一级分类{{ item.category_order }} | 暂无子分类
</view>
</view>
<view
class="classify-btn-content"
@click.stop="handerSetting($event, item)"
>
<view class="classify-btn-item">
<u-icon name="edit-pen" size="16"> </u-icon>
设置
</view>
</view>
</view>
</template>
<template v-slot:content v-if="item.sub.length > 0">
<view
class="second-level-item"
v-for="(group, index2) of item.sub"
@click="handerCollApseChildren(group)"
>
<view
class="second-level-item-info"
:style="
item.sub.length >= 2 && index2 !== item.sub.length - 1
? 'padding-bottom: 40rpx'
: ''
"
>
<view class="second-level-item-info-name">
{{ group.category_name }}
</view>
<view class="second-level-item-info-sort">
排序{{ group.category_order }}
</view>
</view>
<view class="classify-btn-content">
<view class="classify-btn-item">
<u-icon name="edit-pen" size="16"> </u-icon>
设置
</view>
</view>
</view>
</template>
</tui-collapse>
</block>
</view>
</scroll-view>
</view>
<view class="classifyList-bottom">
<view class="bottom-list">
<u-button
class="bottom-btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="handerAddStairClassify()"
>
<u-icon
color="#fff"
size="20"
class="bottom-icon"
name="plus-circle"
></u-icon>
新建分类
</u-button>
</view>
</view>
<!--设置一级分类底部弹窗-->
<u-popup
class="stair-popup"
:show="showBottomStairPopup"
mode="bottom"
zIndex="10075"
@close="handerCloseBottomStairPopup"
>
<view class="stair-popup-content">
<view
class="stair-bottom-item"
@click="handerShowRightEditNamePopup(false)"
>
修改名称
</view>
<view class="stair-bottom-item" v-if="typeManageList.length > 0">
<view
:class="{
'stair-bottom-item-disabled': currStairItem.type_id != 0,
}"
@click="handerShowRightPopup(true)"
>
修改类型
</view>
<view
class="stair-bottom-item-tips"
v-if="currStairItem.type_id != 0"
>
已有商品类型无法修改
</view>
</view>
<view class="stair-bottom-item" @click="handerShowRightAddSecondLevel">
新增二级分类
</view>
<view
class="stair-bottom-item stair-bottom-item-delect"
@click="handerShowDelectPopup(false)"
>
删除
</view>
<view
class="stair-bottom-item stair-bottom-item-cancel"
@click="showBottomStairPopup = false"
>
取消
</view>
</view>
</u-popup>
<!--设置二级分类底部弹窗-->
<u-popup
class="stair-popup"
:show="showBottomSecondLevelPopup"
mode="bottom"
zIndex="10075"
@close="handerCloseBottomSecondLevelPopup"
>
<view class="stair-popup-content">
<view
class="stair-bottom-item"
@click="handerShowRightEditNamePopup(true)"
>
修改名称
</view>
<view class="stair-bottom-item" v-if="typeManageList.length > 0">
<view
:class="{
'stair-bottom-item-disabled': currSecondLevelItem.type_id != 0,
}"
@click="handerShowRightPopup(false)"
>
修改类型
</view>
<view
class="stair-bottom-item-tips"
v-if="currStairItem.type_id != 0"
>
已经添加有商品类型无法修改
</view>
</view>
<view
class="stair-bottom-item stair-bottom-item-delect"
@click="handerShowDelectPopup(true)"
>
删除
</view>
<view
class="stair-bottom-item stair-bottom-item-cancel"
@click="showBottomSecondLevelPopup = false"
>
取消
</view>
</view>
</u-popup>
<!--确认删除弹窗-->
<u-popup
class="affirm-popup"
zIndex="10077"
:show="showDelectPopup"
mode="center"
>
<view class="affirm-popup-content">
<view class="affirm-popup-title">
确认删除"{{ delectClassifyItem.category_name }}"?
</view>
<view class="popup-btn-list">
<u-button
class="btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="showDelectPopup = false"
>
取消
</u-button>
<u-button
class="btn-item btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerDelectClassify"
>
确认
</u-button>
</view>
</view>
</u-popup>
<!--商品类型弹窗-->
<u-popup
class="commodity-type-popup"
:show="showCommodityTypePopup"
mode="bottom"
zIndex="10080"
closeable
@close="handerCloseTypePopup"
>
<view class="commodity-type-popup-content">
<view class="commodity-type-popup-title">选择商品类型</view>
<view class="no-commodity-type" v-if="typeManageList.length <= 0">
<view class="no-commodity-type-bg"></view>
<view class="no-commodity-type-tips" @click="skipuBrandList">
暂无商品类型,点击马上添加
<u-icon
style="display: inline-block"
name="arrow-right"
color="red"
></u-icon>
</view>
</view>
<scroll-view
v-if="typeManageList.length > 0"
scroll-y
class="commodity-type-search-scroll"
:show-scrollbar="false"
@scrolltolower="handerScrolltolower"
refresher-enabled
:refresher-triggered="isRefreshing"
@refresherrefresh="handleRefresh"
:style="{
maxHeight: typeManageList.length >= 2 ? '500px' : 'none',
overflowY: typeManageList.length >= 2 ? 'auto' : 'visible',
}"
>
<u-radio-group
class="commodity-type-radio-group"
v-model="radioValue"
placement="column"
>
<u-radio
class="commodity-type-radio"
v-for="(item, index) in typeManageList"
:key="index"
:label="item.type_name"
:name="item.type_id"
></u-radio>
</u-radio-group>
<view
class="m-loading-box"
v-if="typeManageList.length > 0 && !isNotypeManageData"
>
<block v-if="loadingDownTypeManageData">
<view class="u-loadmore">
<view class="u-loading"></view>
<text class="u-loadmore-tips">正在加载...</text>
</view>
</block>
<!-- <block v-else>
<view class="u-loadmore u-loadmore-line">
<text class="u-loadmore-tips">没有更多商品类型了 ~</text>
</view>
</block> -->
</view>
</scroll-view>
<view class="popup-btn-list">
<u-button
class="btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="handerCancelCommodityTpye"
>
取消
</u-button>
<u-button
v-show="typeManageList.length > 0"
class="btn-item btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerAffirmCommodityType"
>
确认
</u-button>
</view>
</view>
</u-popup>
<!--新建一级分类弹窗-->
<u-popup
class="add-popup"
zIndex="10077"
:show="showAddStairClassifyPopup"
mode="center"
>
<view class="add-popup-content">
<view class="add-popup-title">新建分类</view>
<u-alert
:closable="true"
fontSize="12"
title="注意,确认商品类型后不可修改名称,商品类型,虚拟商品!"
type="warning" :show-icon="true"
></u-alert>
<u--form
labelPosition="left"
:model="form"
ref="uForm"
label-width="100"
:rules="rules"
>
<u-form-item
label="分类名称"
prop="category_name"
class="form-item"
required
>
<u--textarea
class="u-textarea"
v-model="form.category_name"
count
autoHeight
maxlength="8"
placeholder="请输入二级分类名称"
></u--textarea>
</u-form-item>
<u-form-item
label="商品类型"
prop="type_name"
class="form-item"
@click="hadnerShowCommodityTypePopup()"
>
<u--input
v-model="form.type_name"
disabled
disabledColor="#ffffff"
placeholder="请选择商品类型"
border="none"
@click="hideKeyboard()"
></u--input>
<u-icon slot="right" name="arrow-right"></u-icon>
</u-form-item>
<u-form-item label="分类排序" prop="category_order" class="form-item">
<u--input
v-model="form.category_order"
type="number"
placeholder="请输入商品排序"
border="none"
clearable
></u--input>
</u-form-item>
<u-form-item
label="允许虚拟商品"
prop="category_order"
class="form-item form-item-switch"
>
<u-switch
v-model="form.category_virtual_enable"
:activeValue="1"
:inactiveValue="0"
activeColor="#fe411b"
inactiveColor="#ccc"
></u-switch>
</u-form-item>
</u--form>
<view class="popup-btn-list">
<u-button
class="btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="showAddStairClassifyPopup = false"
>
取消
</u-button>
<u-button
class="btn-item btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerAffirmEditClassify"
>
添加
</u-button>
</view>
</view>
</u-popup>
<!--编辑弹窗-->
<u-popup
class="right-popup"
zIndex="10076"
:overlay="false"
:show="showRightPopup"
mode="right"
>
<editClassify
:classifyItem="currStairItem"
:currSecondLevelItem="currSecondLevelItem"
:isEditStairType="isEditStairType"
:isEditSecondLevelName="isEditSecondLevelName"
:isEditSecondLevelType="isEditSecondLevelType"
:isAddSecondLevelClassify="isAddSecondLevelClassify"
@pageBack="handerEditPage()"
@updateClassify="handerUpdateClassify"
@addClassify="handerUpdateAddClassify"
:isEdit="isEdit"
></editClassify>
</u-popup>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
import {
GetCommodityClassify,
UpdateCommodityClassify,
DelectCommodityClassify,
} from "@/api/warehouse/classifyList";
import { GetTypeManageList } from "@/api/warehouse/typeManage";
import tuiCollapse from "../manage/components/tui-collapse/classify-collapse.vue";
import editClassify from "../manage/editClassify.vue";
export default {
name: "classifyList",
components: {
tuiCollapse,
editClassify,
},
data() {
return {
classifyList: [],
current: -1,
loading: false,
showBottomStairPopup: false,
showBottomSecondLevelPopup: false,
showRightPopup: false,
currStairItem: {
sub: [],
},
currSecondLevelItem: {},
typeManageList: [],
pageNum: 1,
pageSize: 20,
isEdit: true,
isEditStairType: false,
isEditSecondLevelType: false,
showDelectPopup: false,
delectClassifyItem: {},
isDelectSubset: false,
isEditSecondLevelName: false,
isAddSecondLevelClassify: false,
showAddStairClassifyPopup: false,
showCommodityTypePopup: false,
isRefreshing: false,
isNotypeManageData: false,
isNoDownTypeManageData: false,
loadingDownTypeManageData: false,
radioValue: "",
time: null,
form: {
type_category_id: 0,
category_name: "",
category_virtual_enable: 0,
type_name: "",
},
rules: {
contact_name: [
{
required: true,
message: "请输入分类名称",
// 可以单个或者同时写两个触发验证方式
trigger: ["change", "blur"],
},
],
},
rules2: {
contact_name: [
{
required: true,
message: "请输入分类名称",
// 可以单个或者同时写两个触发验证方式
trigger: ["change", "blur"],
},
],
},
};
},
computed: {},
onLoad: function (options) {},
onReady() {
// this.$refs["uForm"].setRules(this.rule2);
},
onShow() {
this.getCommodityClassify();
this.getTypeManageList();
},
mounted() {},
methods: {
async getCommodityClassify(isAdd = false) {
if (!isAdd) {
this.loading = true;
}
let res = await GetCommodityClassify();
if (res && res.status == 200) {
this.classifyList = res.data;
}
this.loading = false;
},
async getTypeManageList() {
if (this.isRefreshing) {
this.pageNum = 1;
this.isNotypeManageData = false;
this.isNoDownTypeManageData = false;
}
let params = {
pageNum: this.pageNum,
pageSize: this.pageSize,
};
let res = await GetTypeManageList(params);
if (res && res.status == 200) {
if (this.loadingDownTypeManageData) {
if (res.data.items.length <= 0) {
this.loadingDownTypeManageData = false;
this.isNoDownTypeManageData = true;
return;
} else {
this.typeManageList = [...this.typeManageList, ...res.data.items];
}
} else {
this.typeManageList = res.data.items;
}
if (this.typeManageList.length <= 0) {
this.isNotypeManageData = true;
}
}
this.loadingDownTypeManageData = false;
this.isRefreshing = false;
},
handerScrolltolower() {
clearTimeout(this.time);
if (this.isNoDownTypeManageData) return;
this.loadingDownTypeManageData = true;
this.pageNum = this.pageNum + 1;
this.time = setTimeout(() => {
this.getTypeManageList();
}, 500);
},
handleRefresh() {
this.isRefreshing = true;
this.pageNum = 1;
this.getTypeManageList();
},
handerUpdateAddClassify(list) {
this.classifyList = list;
},
handerEditPage() {
this.showRightPopup = false;
},
handerUpdateClassify(item) {
// 找到匹配的索引
const index = this.classifyList.findIndex(
(group) => group.category_id === item.category_id
);
if (index !== -1) {
this.$set(this.classifyList, index, item);
}
console.log(this.classifyList);
},
handerCollApse(e, item, isStair) {
this.current = this.current == e.index ? -1 : e.index;
},
handerSetting(event, item) {
event.stopPropagation();
this.currStairItem = item;
this.showBottomStairPopup = true;
},
handerCloseTypePopup() {
this.showCommodityTypePopup = false;
},
handerCloseBottomStairPopup() {
this.showBottomStairPopup = false;
},
handersecondlevelSetting(item, group) {
this.showBottomSecondLevelPopup = true;
this.currStairItem = item;
this.currSecondLevelItem = group;
},
handerCloseBottomSecondLevelPopup() {
this.showBottomSecondLevelPopup = false;
},
handerShowRightAddSecondLevel() {
this.isAddSecondLevelClassify = true;
this.showBottomStairPopup = false;
this.showRightPopup = true;
},
hadnerShowCommodityTypePopup() {
this.showCommodityTypePopup = true;
},
handerCancelCommodityTpye() {
this.showCommodityTypePopup = false;
this.radioValue = "";
},
handerAffirmCommodityType() {
const matchedItem = this.typeManageList.find(
(item) => item.type_id === this.radioValue
);
if (matchedItem && Object.keys(matchedItem).length > 0) {
this.form.type_name = matchedItem.type_name;
}
this.showCommodityTypePopup = false;
},
handerAffirmEditClassify() {
console.log(this.radioValue);
this.$refs.uForm.validate().then(async (valid) => {
let params = {
category_image: "",
category_virtual_enable: this.form.category_virtual_enable,
category_id: "",
type_id: this.radioValue,
category_parent_id: 0,
category_name: this.form.category_name,
category_order: this.form.category_order,
};
let res = await UpdateCommodityClassify(params);
if (res && res.status == 200) {
this.$refs.uToast.show({
message: "添加成功",
type: "succeed",
duration: 1000,
});
await this.getCommodityClassify(true);
}
this.showAddStairClassifyPopup = false;
this.radioValue = "";
});
},
handerCollApseChildren(item) {},
handerShowRightEditNamePopup(isEditSecondLevelName) {
this.showRightPopup = true;
this.showBottomStairPopup = false;
this.isEditStairType = false;
this.isEditSecondLevelType = false;
this.isEditSecondLevelName = isEditSecondLevelName;
},
handerShowRightPopup(isStair) {
if (isStair && this.currStairItem.type_id == 0) {
this.isEditStairType = true;
this.showRightPopup = true;
this.showBottomStairPopup = false;
}
if (!isStair && this.currSecondLevelItem.type_id == 0) {
this.isEditSecondLevelType = true;
this.showRightPopup = true;
this.showBottomSecondLevelPopup = false;
}
},
handerAddStairClassify() {
this.showAddStairClassifyPopup = true;
// setTimeout(() => {
// this.$refs["uForm"].setRules(this.rules);
// }, 0);
},
handerShowDelectPopup(isDelectSubset) {
if (!isDelectSubset) {
this.delectClassifyItem = this.currStairItem;
} else {
this.delectClassifyItem = this.currSecondLevelItem;
}
this.isDelectSubset = isDelectSubset;
this.showDelectPopup = true;
},
async handerDelectClassify() {
const categoryId = this.delectClassifyItem.category_id;
let params = {
category_id: categoryId,
};
let res = await DelectCommodityClassify(params);
if (res && res.status == 200) {
if (!this.isDelectSubset) {
this.classifyList = this.classifyList.filter(
(item) => item.category_id !== categoryId
);
} else {
this.classifyList = this.classifyList.map((parent) => {
if (
parent.sub &&
parent.sub.some((child) => child.category_id === categoryId)
) {
return {
...parent,
sub: parent.sub.filter(
(child) => child.category_id !== categoryId
),
};
}
return parent;
});
}
this.$refs.uToast.show({
message: "删除成功",
type: "succeed",
duration: 1000,
});
}
this.showDelectPopup = false;
if (!this.isDelectSubset) {
this.showBottomStairPopup = false;
} else {
this.showBottomSecondLevelPopup = false;
}
},
skipuBrandList() {
uni.navigateTo({
url: "/pages/warehouse/manage/typeManagement",
});
},
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/variables.scss";
.classifyList-container {
height: calc(100vh - 148rpx);
background: #f5f6fa;
overflow: hidden;
.tips {
padding: 24rpx;
font-size: 24rpx;
background: #fdf6f2;
border: 1px solid #efe8e2;
border-radius: 16rpx;
color: #3a3230;
margin: 24rpx;
}
.classifyList-content {
.myui_card {
margin: 0 24rpx;
padding: 24rpx;
}
::v-deep .tui-collapse {
margin-bottom: 40rpx;
&:last-child {
margin-bottom: 0;
}
}
.stair-item {
display: flex;
align-items: center;
justify-content: space-between;
&:last-child {
margin-bottom: 0;
}
.classify-info {
padding-left: 32rpx;
.stair-name {
font-size: 28rpx;
}
.stair-tips {
padding-top: 16rpx;
font-size: 24rpx;
color: #666;
}
}
}
}
::v-deep.tui-collapse-body {
margin: 20rpx 0;
}
.classifyList-scroll {
-ms-overflow-style: none; /* IE和Edge */
scrollbar-width: none; /* Firefox */
height: calc(100vh - 400rpx);
}
.classifyList-scroll::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}
.second-level-item {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
margin-left: 40rpx;
&::before {
content: "";
position: absolute;
height: 100%;
border: 1px solid #eeeeee;
}
.second-level-item-info {
display: flex;
flex-flow: column;
justify-content: space-between;
padding-left: 20rpx;
height: 100rpx;
.second-level-item-info-name {
font-size: 17px;
font-weight: 400;
}
.second-level-item-info-sort {
font-size: 14px;
color: #606060;
}
}
}
.no-data {
.no-data-bg {
margin: 50% auto;
margin-bottom: 0;
width: 300rpx;
height: 200rpx;
background-image: url("../../../static/warehouse/no-classify.png");
background-size: 100%;
}
.no-data-tips {
margin: 80rpx auto;
color: #aaaaaa;
text-align: center;
}
}
.no-commodity-type {
.no-commodity-type-bg {
margin: 6% auto;
margin-bottom: 0;
width: 300rpx;
height: 200rpx;
background-image: url("../../../static/warehouse/no-commodity-type.png");
background-size: 100%;
}
.no-commodity-type-tips {
margin: 80rpx auto;
color: $base-color;
text-align: center;
}
}
.classify-btn-content {
.classify-btn-item {
font-size: 24rpx;
display: flex;
color: #333;
border: 1rpx solid #999;
border-radius: 50rpx;
padding: 10rpx 16rpx;
}
}
.m-loading-box {
text-align: center;
padding: 40rpx;
color: #aaaa;
font-size: 28rpx;
}
.classifyList-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx;
background: #fff;
border-top: 2rpx solid $uni-border-color;
z-index: 2;
.bottom-list {
display: flex;
align-items: center;
.bottom-btn-item {
font-size: 28rpx;
border-color: $base-color;
color: #fff;
background: $base-color;
.bottom-icon {
margin-right: 8rpx;
}
&::after {
border: none;
}
}
}
}
.commodity-type-popup {
::v-deep.u-fade-enter-to {
z-index: 10079 !important;
}
.commodity-type-popup-content {
.commodity-type-popup-title {
padding: 40rpx;
text-align: center;
font-weight: 500;
}
.commodity-type-radio-group {
margin: 40rpx;
.commodity-type-radio {
margin-bottom: 40rpx;
}
}
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 64rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
.add-popup {
::v-deep.u-popup__content {
border-radius: 16rpx;
}
::v-deep.u-fade-enter-to {
z-index: 10076 !important;
}
.add-popup-content {
width: 700rpx;
.add-popup-title {
padding: 40rpx;
text-align: center;
font-weight: bold;
font-size: 36rpx;
}
.add-tips {
padding: 0 24rpx;
text-align: center;
color: red;
}
.u-form {
margin: 0 40rpx;
.form-item {
margin: 28rpx 0;
}
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 64rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
}
.affirm-popup {
::v-deep.u-popup__content {
border-radius: 16rpx;
}
::v-deep.u-fade-enter-to {
z-index: 10076 !important;
}
.affirm-popup-content {
width: 600rpx;
.affirm-popup-title {
padding: 40rpx;
text-align: center;
font-weight: bold;
}
.affirm-popup-tips {
padding: 0 60rpx;
font-size: 28rpx;
text-align: center;
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 64rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
}
.stair-popup {
::v-deep.u-popup__content {
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
}
.stair-popup-content {
.stair-bottom-item {
padding: 24rpx;
border-bottom: 1px solid #eeeeee;
font-size: 28rpx;
text-align: center;
.stair-bottom-item-tips {
color: #999;
font-size: 24rpx;
}
}
.stair-bottom-item-disabled {
color: #999;
}
.stair-bottom-item-delect {
color: $base-color;
}
.stair-bottom-item-cancel {
border: none;
}
}
}
.classifyList-loading {
margin: 70% auto;
display: flex;
}
}
</style>