品牌列表,批量删除
parent
90476adffa
commit
61602c3adb
|
|
@ -250,8 +250,66 @@ export function importProductData(filePath, formData) {
|
||||||
// 获取导入记录
|
// 获取导入记录
|
||||||
export function getImportRecord() {
|
export function getImportRecord() {
|
||||||
return request8081({
|
return request8081({
|
||||||
baseUrl: 'http://192.168.0.7:8081',
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
url: '/mall/product/importRecord',
|
url: '/mall/product/importRecord',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量删除商品
|
||||||
|
export function batchDeleteProduct(ids) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: '/mall/product/batchDelete',
|
||||||
|
method: 'delete',
|
||||||
|
data: { ids: ids }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加品牌
|
||||||
|
export function addBrand(data) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: '/mall/brand/add',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取品牌列表
|
||||||
|
export function getBrandList(params) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: '/mall/brand/list',
|
||||||
|
method: 'get',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取品牌树状结构
|
||||||
|
export function getBrandTree(storeId) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: `/mall/brand/getTree/${storeId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除品牌
|
||||||
|
export function deleteBrand(brandId) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: `/mall/brand/delete/${brandId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改品牌名称
|
||||||
|
export function updateBrand(data) {
|
||||||
|
return request8081({
|
||||||
|
baseUrl: 'http://193.112.94.36:8081',
|
||||||
|
url: '/mall/brand/update',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ module.exports = {
|
||||||
// baseUrl: 'https://vue.ruoyi.vip/prod-api',
|
// baseUrl: 'https://vue.ruoyi.vip/prod-api',
|
||||||
|
|
||||||
baseUrl:'http://193.112.94.36:8080',
|
baseUrl:'http://193.112.94.36:8080',
|
||||||
|
// baseUrl = 'https://api.ruoyi.com'
|
||||||
// prodApi: 'https://vue.ruoyi.vip/prod-api',
|
// prodApi: 'https://vue.ruoyi.vip/prod-api',
|
||||||
// baseUrl: 'http://localhost:8080',
|
// baseUrl: 'http://localhost:8080',
|
||||||
// 应用信息
|
// 应用信息
|
||||||
|
|
|
||||||
12
pages.json
12
pages.json
|
|
@ -155,6 +155,18 @@
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": ""
|
"navigationBarTitleText": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/batchDeleteProduct/batchDeleteProduct",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/addBrand/addBrand",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,961 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<view class="navbar">
|
||||||
|
<view class="back-btn" @click="goBack">
|
||||||
|
<text class="back-icon">←</text>
|
||||||
|
</view>
|
||||||
|
<view class="title">品牌管理</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<view class="search-box">
|
||||||
|
<input type="text" placeholder="搜索品牌名称" class="search-input" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 品牌树状列表 -->
|
||||||
|
<view class="brand-tree">
|
||||||
|
<!-- 一级品牌项 -->
|
||||||
|
<view v-for="(brand, index) in brandList" :key="index" class="level1-item">
|
||||||
|
<view class="level1-header">
|
||||||
|
<text class="expand-icon" @click="toggleExpand(index)">{{ brand.expanded ? '▼' : '▶' }}</text>
|
||||||
|
<text class="level1-name" @click="toggleExpand(index)">{{ brand.name }}</text>
|
||||||
|
<view class="menu-container" style="position: relative;">
|
||||||
|
<view class="menu-btn" @click.stop="toggleMenuOptions(index)">
|
||||||
|
<text class="menu-icon">···</text>
|
||||||
|
</view>
|
||||||
|
<!-- 菜单选项列表 -->
|
||||||
|
<view v-if="showMenuOptions && selectedBrandIndex === index" class="menu-options">
|
||||||
|
<!-- 重命名选项 -->
|
||||||
|
<view class="menu-option" @click.stop="showRenameDialog(index)">
|
||||||
|
<text class="rename-icon">✏️</text>
|
||||||
|
<text>重命名</text>
|
||||||
|
</view>
|
||||||
|
<!-- 删除品牌选项 -->
|
||||||
|
<view class="menu-option delete-option" @click.stop="showDeleteBrandConfirm(index)">
|
||||||
|
<text class="trash-icon">🗑️</text>
|
||||||
|
<text>删除品牌</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 二级子品牌列表(展开时显示) -->
|
||||||
|
<view v-if="brand.expanded" class="level2-container">
|
||||||
|
<view
|
||||||
|
v-for="(subBrand, subIndex) in brand.children"
|
||||||
|
:key="subIndex"
|
||||||
|
class="level2-item"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="dragStart(index, subIndex)"
|
||||||
|
@dragover="dragOver"
|
||||||
|
@drop="drop(index, subIndex)"
|
||||||
|
>
|
||||||
|
<text class="level2-name">{{ subBrand.name }}</text>
|
||||||
|
<view class="edit-btn" @click.stop="openEditDialog(index, subIndex)">
|
||||||
|
<text class="edit-icon">✎</text>
|
||||||
|
<text class="edit-text">编辑</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 添加子品牌按钮 -->
|
||||||
|
<view class="add-sub-brand" @click="addSubBrand(index)">
|
||||||
|
<text class="add-icon">+</text>
|
||||||
|
<text class="add-text">添加子品牌</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部添加一级品牌按钮 -->
|
||||||
|
<view class="add-brand-btn" @click="addBrand">
|
||||||
|
<text class="add-btn-icon">+</text>
|
||||||
|
<text class="add-btn-text">添加品牌</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 修改品牌名称弹窗 -->
|
||||||
|
<view v-if="editDialogVisible" class="dialog-overlay">
|
||||||
|
<view class="dialog">
|
||||||
|
<view class="dialog-title">修改品牌名称</view>
|
||||||
|
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<view class="input-wrapper">
|
||||||
|
<input
|
||||||
|
v-model="editBrandName"
|
||||||
|
type="text"
|
||||||
|
class="dialog-input"
|
||||||
|
placeholder="请输入品牌名称"
|
||||||
|
:focus="inputFocus"
|
||||||
|
@blur="inputFocus = false"
|
||||||
|
@focus="onInputFocus"
|
||||||
|
/>
|
||||||
|
<text v-if="editBrandName" class="clear-icon" @click="clearInput">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 带垃圾桶图标的删除按钮 -->
|
||||||
|
<view class="delete-btn" @click="showDeleteConfirm">
|
||||||
|
<text class="trash-icon">🗑️</text>
|
||||||
|
<text>删除品牌</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="dialog-buttons">
|
||||||
|
<view class="cancel-btn" @click="closeEditDialog">取消</view>
|
||||||
|
<view class="confirm-btn" @click="confirmEdit">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 添加品牌弹窗 -->
|
||||||
|
<view v-if="addBrandDialogVisible" class="dialog-overlay">
|
||||||
|
<view class="dialog">
|
||||||
|
<view class="dialog-title">{{ isAddingSubBrand ? '添加子品牌' : '添加品牌' }}</view>
|
||||||
|
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<view class="input-wrapper">
|
||||||
|
<input
|
||||||
|
v-model="addBrandName"
|
||||||
|
type="text"
|
||||||
|
class="dialog-input"
|
||||||
|
placeholder="请输入品牌名称"
|
||||||
|
:focus="inputFocus"
|
||||||
|
@blur="inputFocus = false"
|
||||||
|
@focus="onInputFocus"
|
||||||
|
/>
|
||||||
|
<text v-if="addBrandName" class="clear-icon" @click="clearAddInput">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="dialog-buttons">
|
||||||
|
<view class="cancel-btn" @click="closeAddBrandDialog">取消</view>
|
||||||
|
<view class="confirm-btn" @click="confirmAddBrand">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 删除确认弹窗(在修改弹窗之上) -->
|
||||||
|
<view v-if="deleteConfirmVisible" class="delete-confirm-overlay">
|
||||||
|
<view class="delete-confirm-dialog">
|
||||||
|
<view class="delete-dialog-title">确认删除</view>
|
||||||
|
<view class="delete-dialog-content">确定要删除这个品牌吗?</view>
|
||||||
|
<view class="delete-dialog-buttons">
|
||||||
|
<view class="delete-cancel-btn" @click="hideDeleteConfirm">取消</view>
|
||||||
|
<view class="delete-confirm-btn" @click="deleteBrand">删除</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 导入品牌相关API
|
||||||
|
import { getBrandList, addBrand, getBrandTree, deleteBrand, updateBrand } from '@/api/product'
|
||||||
|
import { getStoreId } from '@/utils/auth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
brandList: [],
|
||||||
|
storeId: null,
|
||||||
|
editDialogVisible: false,
|
||||||
|
deleteConfirmVisible: false,
|
||||||
|
editParentIndex: null,
|
||||||
|
editSubIndex: null,
|
||||||
|
editBrandName: '',
|
||||||
|
inputFocus: false,
|
||||||
|
dragSource: {
|
||||||
|
parentIndex: null,
|
||||||
|
subIndex: null
|
||||||
|
},
|
||||||
|
// 添加品牌弹窗相关
|
||||||
|
addBrandDialogVisible: false,
|
||||||
|
addBrandName: '',
|
||||||
|
isAddingSubBrand: false,
|
||||||
|
currentParentIndex: null,
|
||||||
|
// 删除品牌相关
|
||||||
|
showMenuOptions: false,
|
||||||
|
selectedBrandIndex: null,
|
||||||
|
isDeletingLevel1Brand: false,
|
||||||
|
// 重命名弹窗相关
|
||||||
|
renameDialogVisible: false,
|
||||||
|
renameBrandName: '',
|
||||||
|
renameBrandIndex: null,
|
||||||
|
// 编辑二级品牌相关
|
||||||
|
editSubBrandId: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
// 获取storeId
|
||||||
|
this.storeId = getStoreId()
|
||||||
|
// 加载品牌列表
|
||||||
|
this.loadBrandList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goBack() {
|
||||||
|
uni.navigateBack()
|
||||||
|
},
|
||||||
|
// 加载品牌列表
|
||||||
|
async loadBrandList() {
|
||||||
|
try {
|
||||||
|
// 使用新的getBrandTree接口,传入storeId作为URL参数
|
||||||
|
const res = await getBrandTree(this.storeId)
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
// 新接口直接返回树状结构,可能不需要额外处理
|
||||||
|
// 但需要根据实际返回格式调整
|
||||||
|
this.brandList = this.formatBrandData(res.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载品牌列表失败:', error)
|
||||||
|
uni.showToast({ title: '加载品牌列表失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 格式化品牌数据为树状结构
|
||||||
|
formatBrandData(brandData) {
|
||||||
|
// 假设新接口返回的数据结构已经是树状的,包含id、brandName、children等字段
|
||||||
|
// 但需要根据实际返回格式进行调整
|
||||||
|
return brandData.map(brand => ({
|
||||||
|
name: brand.brandName,
|
||||||
|
id: brand.id,
|
||||||
|
expanded: true,
|
||||||
|
children: brand.children ? brand.children.map(subBrand => ({
|
||||||
|
name: subBrand.brandName,
|
||||||
|
id: subBrand.id
|
||||||
|
})) : []
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
// 展开/折叠一级品牌
|
||||||
|
toggleExpand(index) {
|
||||||
|
this.brandList[index].expanded = !this.brandList[index].expanded
|
||||||
|
},
|
||||||
|
// 添加一级品牌
|
||||||
|
addBrand() {
|
||||||
|
// 打开添加品牌弹窗
|
||||||
|
this.isAddingSubBrand = false
|
||||||
|
this.currentParentIndex = null
|
||||||
|
this.addBrandName = ''
|
||||||
|
this.addBrandDialogVisible = true
|
||||||
|
|
||||||
|
// 聚焦输入框
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.inputFocus = true
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 添加子品牌
|
||||||
|
addSubBrand(parentIndex) {
|
||||||
|
// 打开添加子品牌弹窗
|
||||||
|
this.isAddingSubBrand = true
|
||||||
|
this.currentParentIndex = parentIndex
|
||||||
|
this.addBrandName = ''
|
||||||
|
this.addBrandDialogVisible = true
|
||||||
|
|
||||||
|
// 聚焦输入框
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.inputFocus = true
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 确认添加或修改品牌
|
||||||
|
async confirmAddBrand() {
|
||||||
|
if (!this.addBrandName.trim()) {
|
||||||
|
uni.showToast({ title: '请输入品牌名称', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 构造请求参数
|
||||||
|
const params = {
|
||||||
|
brandName: this.addBrandName.trim(),
|
||||||
|
storeId: this.storeId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是添加子品牌,添加parentId参数
|
||||||
|
if (this.isAddingSubBrand) {
|
||||||
|
params.parentId = this.brandList[this.currentParentIndex].id || 0
|
||||||
|
} else {
|
||||||
|
// 添加一级品牌时,parentId为0
|
||||||
|
params.parentId = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用添加品牌接口
|
||||||
|
const res = await addBrand(params)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 关闭弹窗
|
||||||
|
this.closeAddBrandDialog()
|
||||||
|
// 重新加载品牌列表
|
||||||
|
await this.loadBrandList()
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '添加成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.msg || '操作失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('添加品牌失败:', error)
|
||||||
|
uni.showToast({ title: '添加失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 关闭添加品牌弹窗
|
||||||
|
closeAddBrandDialog() {
|
||||||
|
this.addBrandDialogVisible = false
|
||||||
|
this.addBrandName = ''
|
||||||
|
this.inputFocus = false
|
||||||
|
this.editSubBrandId = null
|
||||||
|
},
|
||||||
|
// 清除添加品牌输入框
|
||||||
|
clearAddInput() {
|
||||||
|
this.addBrandName = ''
|
||||||
|
// 聚焦输入框
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.inputFocus = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 打开编辑弹窗
|
||||||
|
openEditDialog(parentIndex, subIndex) {
|
||||||
|
this.editParentIndex = parentIndex
|
||||||
|
this.editSubIndex = subIndex
|
||||||
|
|
||||||
|
// 判断是一级品牌还是二级品牌
|
||||||
|
if (subIndex === undefined) {
|
||||||
|
// 一级品牌
|
||||||
|
this.isDeletingLevel1Brand = true
|
||||||
|
this.editBrandName = this.brandList[parentIndex].name
|
||||||
|
} else {
|
||||||
|
// 二级品牌
|
||||||
|
this.isDeletingLevel1Brand = false
|
||||||
|
this.editBrandName = this.brandList[parentIndex].children[subIndex].name
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editDialogVisible = true
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.inputFocus = true
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 输入框获取焦点
|
||||||
|
onInputFocus() {
|
||||||
|
this.inputFocus = true
|
||||||
|
},
|
||||||
|
// 关闭编辑弹窗
|
||||||
|
closeEditDialog() {
|
||||||
|
this.editDialogVisible = false
|
||||||
|
this.editParentIndex = null
|
||||||
|
this.editSubIndex = null
|
||||||
|
this.editBrandName = ''
|
||||||
|
this.inputFocus = false
|
||||||
|
},
|
||||||
|
// 清除输入框内容
|
||||||
|
clearInput() {
|
||||||
|
this.editBrandName = ''
|
||||||
|
setTimeout(() => {
|
||||||
|
this.inputFocus = true
|
||||||
|
}, 50)
|
||||||
|
},
|
||||||
|
// 确认修改
|
||||||
|
async confirmEdit() {
|
||||||
|
if (this.editBrandName.trim() === '') {
|
||||||
|
uni.showToast({ title: '请输入品牌名称', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 构造请求参数
|
||||||
|
let brandId;
|
||||||
|
|
||||||
|
// 判断是修改一级品牌还是二级品牌
|
||||||
|
if (this.isDeletingLevel1Brand) {
|
||||||
|
// 修改一级品牌,使用一级品牌的id
|
||||||
|
brandId = this.brandList[this.editParentIndex].id
|
||||||
|
} else {
|
||||||
|
// 修改二级品牌,使用二级品牌的id
|
||||||
|
brandId = this.brandList[this.editParentIndex].children[this.editSubIndex].id
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
brandName: this.editBrandName.trim(),
|
||||||
|
id: brandId,
|
||||||
|
storeId: this.storeId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用修改品牌名称API
|
||||||
|
const res = await updateBrand(params)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 更新本地数据
|
||||||
|
if (this.isDeletingLevel1Brand) {
|
||||||
|
// 修改一级品牌名称
|
||||||
|
this.brandList[this.editParentIndex].name = this.editBrandName.trim()
|
||||||
|
} else {
|
||||||
|
// 修改二级品牌名称
|
||||||
|
this.brandList[this.editParentIndex].children[this.editSubIndex].name = this.editBrandName.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
this.closeEditDialog()
|
||||||
|
|
||||||
|
uni.showToast({ title: '修改成功', icon: 'success' })
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.msg || '修改失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('修改品牌名称失败:', error)
|
||||||
|
uni.showToast({ title: '修改失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 显示删除确认弹窗
|
||||||
|
showDeleteConfirm() {
|
||||||
|
this.deleteConfirmVisible = true
|
||||||
|
},
|
||||||
|
// 隐藏删除确认弹窗
|
||||||
|
hideDeleteConfirm() {
|
||||||
|
this.deleteConfirmVisible = false
|
||||||
|
},
|
||||||
|
// 删除品牌
|
||||||
|
async deleteBrand() {
|
||||||
|
try {
|
||||||
|
let brandId;
|
||||||
|
|
||||||
|
// 判断是删除一级品牌还是二级品牌
|
||||||
|
if (this.isDeletingLevel1Brand) {
|
||||||
|
// 删除一级品牌,使用一级品牌的id
|
||||||
|
brandId = this.brandList[this.editParentIndex].id
|
||||||
|
} else {
|
||||||
|
// 删除二级品牌,使用二级品牌的id
|
||||||
|
brandId = this.brandList[this.editParentIndex].children[this.editSubIndex].id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用删除品牌API
|
||||||
|
const res = await deleteBrand(brandId)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 隐藏弹窗
|
||||||
|
this.hideDeleteConfirm()
|
||||||
|
this.closeEditDialog()
|
||||||
|
|
||||||
|
// 重新加载品牌列表
|
||||||
|
await this.loadBrandList()
|
||||||
|
|
||||||
|
uni.showToast({ title: '删除成功', icon: 'success' })
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.msg || '删除失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除品牌失败:', error)
|
||||||
|
uni.showToast({ title: '删除失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 切换菜单选项的显示/隐藏
|
||||||
|
toggleMenuOptions(index) {
|
||||||
|
if (this.showMenuOptions && this.selectedBrandIndex === index) {
|
||||||
|
// 如果点击的是当前显示选项的品牌,关闭选项
|
||||||
|
this.showMenuOptions = false
|
||||||
|
this.selectedBrandIndex = null
|
||||||
|
} else {
|
||||||
|
// 否则显示当前品牌的菜单选项
|
||||||
|
this.showMenuOptions = true
|
||||||
|
this.selectedBrandIndex = index
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 显示重命名弹窗(一级品牌)
|
||||||
|
showRenameDialog(index) {
|
||||||
|
// 关闭菜单选项
|
||||||
|
this.showMenuOptions = false
|
||||||
|
this.selectedBrandIndex = null
|
||||||
|
|
||||||
|
// 调用打开编辑弹窗方法,只传parentIndex,不传subIndex,表示修改一级品牌
|
||||||
|
this.openEditDialog(index)
|
||||||
|
},
|
||||||
|
// 显示删除品牌确认弹窗
|
||||||
|
showDeleteBrandConfirm(index) {
|
||||||
|
// 关闭菜单选项
|
||||||
|
this.showMenuOptions = false
|
||||||
|
this.selectedBrandIndex = null
|
||||||
|
|
||||||
|
// 设置要删除的品牌索引
|
||||||
|
this.editParentIndex = index
|
||||||
|
this.editSubIndex = 0
|
||||||
|
this.isDeletingLevel1Brand = true
|
||||||
|
|
||||||
|
// 显示删除确认弹窗
|
||||||
|
this.showDeleteConfirm()
|
||||||
|
},
|
||||||
|
// 拖拽开始
|
||||||
|
dragStart(parentIndex, subIndex) {
|
||||||
|
this.dragSource = { parentIndex, subIndex }
|
||||||
|
},
|
||||||
|
// 拖拽经过
|
||||||
|
dragOver(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
},
|
||||||
|
// 拖拽放下
|
||||||
|
drop(targetParentIndex, targetSubIndex) {
|
||||||
|
const { parentIndex, subIndex } = this.dragSource
|
||||||
|
if (parentIndex === targetParentIndex) {
|
||||||
|
const draggedItem = this.brandList[parentIndex].children.splice(subIndex, 1)[0]
|
||||||
|
this.brandList[targetParentIndex].children.splice(targetSubIndex, 0, draggedItem)
|
||||||
|
}
|
||||||
|
this.dragSource = { parentIndex: null, subIndex: null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 导航栏 */
|
||||||
|
.navbar {
|
||||||
|
background-color: #e62318;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
position: relative;
|
||||||
|
height: 88rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
font-size: 28rpx;
|
||||||
|
letter-spacing: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 菜单容器 */
|
||||||
|
.menu-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 菜单选项列表 */
|
||||||
|
.menu-options {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1rpx solid #f0f0f0;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
min-width: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 菜单项 */
|
||||||
|
.menu-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 菜单项 hover 效果 */
|
||||||
|
.menu-option:active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 重命名选项 */
|
||||||
|
.menu-option:not(.delete-option) {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 重命名图标 */
|
||||||
|
.rename-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 删除品牌选项 */
|
||||||
|
.menu-option.delete-option {
|
||||||
|
color: #e62318;
|
||||||
|
border-top: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 垃圾桶图标 */
|
||||||
|
.menu-option .trash-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索框 */
|
||||||
|
.search-box {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 16rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 18rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 品牌树 */
|
||||||
|
.brand-tree {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level1-item {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level1-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level1-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-btn {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
letter-spacing: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 二级子品牌容器 */
|
||||||
|
.level2-container {
|
||||||
|
display: flex;
|
||||||
|
padding: 24rpx 30rpx;
|
||||||
|
gap: 24rpx;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level2-item {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level2-name {
|
||||||
|
font-size: 36rpx;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-icon {
|
||||||
|
margin-right: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-sub-brand {
|
||||||
|
border: 2rpx dashed #1677ff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-icon {
|
||||||
|
font-size: 36rpx;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部添加按钮 */
|
||||||
|
.add-brand-btn {
|
||||||
|
background-color: #e62318;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin: 0 30rpx 30rpx 30rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn-icon {
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================ 弹窗样式 ================ */
|
||||||
|
.dialog-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
width: 85%;
|
||||||
|
max-width: 650rpx;
|
||||||
|
padding: 40rpx 50rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框样式 */
|
||||||
|
.input-wrapper {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-input {
|
||||||
|
border: 1rpx solid #e5e5e5;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 22rpx 60rpx 22rpx 22rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: none;
|
||||||
|
background-color: #fff;
|
||||||
|
pointer-events: auto;
|
||||||
|
user-select: text;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
caret-color: #e62318;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-input:focus {
|
||||||
|
border-color: #e62318;
|
||||||
|
box-shadow: 0 0 0 2rpx rgba(230, 35, 24, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
z-index: 1002;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-icon:active {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 删除按钮 */
|
||||||
|
.delete-btn {
|
||||||
|
color: #e62318;
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
/* background-color: #fff5f5; */
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn:active {
|
||||||
|
background-color: #ffeaea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trash-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 弹窗按钮 */
|
||||||
|
.dialog-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn:active {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #e62318;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn:active {
|
||||||
|
background-color: #d11f15;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================ 删除确认弹窗(在修改弹窗之上) ================ */
|
||||||
|
.delete-confirm-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 2000; /* 比修改弹窗更高的层级 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-confirm-dialog {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
width: 70%;
|
||||||
|
max-width: 560rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
animation: fadeIn 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-dialog-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-dialog-content {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-dialog-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-cancel-btn {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-cancel-btn:active {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-confirm-btn {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #e62318;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-confirm-btn:active {
|
||||||
|
background-color: #d11f15;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,380 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<view class="navbar">
|
||||||
|
<view class="nav-back" @tap="goBack">
|
||||||
|
<uni-icons type="back" size="18" color="#fff"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="nav-title">批量删除</view>
|
||||||
|
<view class="nav-more">
|
||||||
|
<uni-icons type="more-filled" size="18" color="#fff"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="search-bar">
|
||||||
|
<view class="search-input">
|
||||||
|
<uni-icons type="search" size="18" color="#999"></uni-icons>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="搜索商品名称、条码"
|
||||||
|
placeholder-class="placeholder"
|
||||||
|
v-model="searchText"
|
||||||
|
@confirm="onSearch"
|
||||||
|
/>
|
||||||
|
<uni-icons type="scan" size="18" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="filter-btn" @tap="showFilter = !showFilter">
|
||||||
|
<uni-icons type="filter" size="18" color="#999"></uni-icons>
|
||||||
|
<text>筛选</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品列表 -->
|
||||||
|
<scroll-view class="goods-list" scroll-y="true">
|
||||||
|
<!-- 空列表提示 -->
|
||||||
|
<view v-if="goodsList.length === 0" class="empty-tip">
|
||||||
|
<text>暂无商品数据</text>
|
||||||
|
</view>
|
||||||
|
<!-- 商品项 -->
|
||||||
|
<view
|
||||||
|
class="goods-item"
|
||||||
|
v-for="item in goodsList"
|
||||||
|
:key="item.id"
|
||||||
|
>
|
||||||
|
<view class="checkbox-wrap" @tap="toggleSelect(item.id)">
|
||||||
|
<view
|
||||||
|
class="custom-checkbox"
|
||||||
|
:class="{ checked: selectedIds.includes(String(item.id)) }"
|
||||||
|
>
|
||||||
|
<text v-if="selectedIds.includes(String(item.id))" class="check-icon">✓</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="goods-info">
|
||||||
|
<image
|
||||||
|
:src="item.mainImage ? 'http://193.112.94.36:8081' + item.mainImage : '/static/default-goods.png'"
|
||||||
|
class="goods-img"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<view class="goods-details">
|
||||||
|
<text class="goods-name">{{ item.productName || '未命名商品' }}</text>
|
||||||
|
<text class="goods-barcode">{{ item.productBarCode || '无条码' }}</text>
|
||||||
|
<text class="goods-price">¥{{ item.storePrice ? Number(item.storePrice).toFixed(2) : '0.00' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部操作栏 -->
|
||||||
|
<view class="bottom-bar" v-if="goodsList.length > 0">
|
||||||
|
<view class="select-all" @tap="toggleSelectAll">
|
||||||
|
<view class="custom-checkbox" :class="{ checked: isAllSelected }">
|
||||||
|
<text v-if="isAllSelected" class="check-icon">✓</text>
|
||||||
|
</view>
|
||||||
|
<text>全选 (已选{{ selectedIds.length }})</text>
|
||||||
|
</view>
|
||||||
|
<button
|
||||||
|
class="delete-btn"
|
||||||
|
:class="{ disabled: selectedIds.length === 0 }"
|
||||||
|
:disabled="selectedIds.length === 0"
|
||||||
|
@tap="onDeleteSelected"
|
||||||
|
>
|
||||||
|
删除商品
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getProductList as fetchProductList, batchDeleteProduct } from '@/api/product'
|
||||||
|
import { getToken, getStoreId } from '@/utils/auth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchText: '',
|
||||||
|
showFilter: false,
|
||||||
|
storeId: null,
|
||||||
|
goodsList: [],
|
||||||
|
selectedIds: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
allCheckboxValues() {
|
||||||
|
return this.goodsList.map(item => ({
|
||||||
|
text: '',
|
||||||
|
value: String(item.id)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
isAllSelected() {
|
||||||
|
return this.goodsList.length > 0 && this.selectedIds.length === this.goodsList.length;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
const storeId = getStoreId();
|
||||||
|
if (storeId) {
|
||||||
|
this.storeId = storeId;
|
||||||
|
this.getProductList();
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '请先选择门店', icon: 'none', duration: 1500 });
|
||||||
|
setTimeout(() => uni.navigateBack(), 1500);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goBack() {
|
||||||
|
uni.navigateBack();
|
||||||
|
},
|
||||||
|
// 加载商品列表
|
||||||
|
async getProductList(searchParams = {}) {
|
||||||
|
try {
|
||||||
|
if (this.storeId) {
|
||||||
|
searchParams.storeId = this.storeId;
|
||||||
|
}
|
||||||
|
const res = await fetchProductList(searchParams);
|
||||||
|
if (res && res.code === 200 && Array.isArray(res.data)) {
|
||||||
|
this.goodsList = res.data;
|
||||||
|
this.selectedIds = [];
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res?.msg || '获取商品失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取商品异常:', error);
|
||||||
|
uni.showToast({ title: '网络错误', icon: 'none' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 搜索
|
||||||
|
onSearch() {
|
||||||
|
const keyword = this.searchText.trim();
|
||||||
|
if (!keyword) {
|
||||||
|
this.getProductList();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const searchParams = /^\d+$/.test(keyword)
|
||||||
|
? { productBarCode: keyword }
|
||||||
|
: { productName: keyword };
|
||||||
|
this.getProductList(searchParams);
|
||||||
|
},
|
||||||
|
// 单个商品选中/取消
|
||||||
|
toggleSelect(id) {
|
||||||
|
const idStr = String(id);
|
||||||
|
const index = this.selectedIds.indexOf(idStr);
|
||||||
|
if (index > -1) {
|
||||||
|
this.selectedIds.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
this.selectedIds.push(idStr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 全选/取消全选
|
||||||
|
toggleSelectAll() {
|
||||||
|
if (this.isAllSelected) {
|
||||||
|
this.selectedIds = [];
|
||||||
|
} else {
|
||||||
|
this.selectedIds = this.goodsList.map(item => String(item.id));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 批量删除
|
||||||
|
async onDeleteSelected() {
|
||||||
|
if (this.selectedIds.length === 0) return;
|
||||||
|
|
||||||
|
uni.showModal({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定删除选中的${this.selectedIds.length}个商品?删除后不可恢复!`,
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
try {
|
||||||
|
const idsToDelete = this.selectedIds.map(id => Number(id));
|
||||||
|
const result = await batchDeleteProduct(idsToDelete);
|
||||||
|
if (result && result.code === 200) {
|
||||||
|
uni.showToast({ title: '删除成功', icon: 'success' });
|
||||||
|
this.getProductList();
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: result?.msg || '删除失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除异常:', error);
|
||||||
|
uni.showToast({ title: '网络错误', icon: 'none' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 全局容器 */
|
||||||
|
.container {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding-bottom: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 导航栏 */
|
||||||
|
.navbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: #e63946;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.nav-title { font-size: 18px; font-weight: 600; }
|
||||||
|
|
||||||
|
/* 搜索栏 */
|
||||||
|
.search-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
.search-input input {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.placeholder { color: #999; }
|
||||||
|
.filter-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.filter-btn text { margin-left: 4px; }
|
||||||
|
|
||||||
|
/* 商品列表 */
|
||||||
|
.goods-list {
|
||||||
|
height: calc(100vh - 200px);
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.empty-tip {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.goods-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 复选框容器 */
|
||||||
|
.checkbox-wrap {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义复选框样式 */
|
||||||
|
.custom-checkbox {
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
border: 2rpx solid #ddd;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-checkbox.checked {
|
||||||
|
background-color: #e63946;
|
||||||
|
border-color: #e63946;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-icon {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品信息 */
|
||||||
|
.goods-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.goods-img {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
.goods-details { flex: 1; }
|
||||||
|
.goods-name {
|
||||||
|
display: block;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.goods-barcode {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.goods-price {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #e63946;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部操作栏 */
|
||||||
|
.bottom-bar {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
.select-all {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.select-all text { margin-left: 6px; }
|
||||||
|
.delete-btn {
|
||||||
|
padding: 10px 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: #e63946;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.delete-btn.disabled {
|
||||||
|
background-color: #ccc;
|
||||||
|
color: #999;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -104,8 +104,8 @@
|
||||||
|
|
||||||
<!-- 底部操作按钮 -->
|
<!-- 底部操作按钮 -->
|
||||||
<view class="bottom-actions">
|
<view class="bottom-actions">
|
||||||
<view class="action-btn more-btn" @tap="showMoreActions(item)">
|
<view class="action-btn more-btn" @tap="showMoreActions()">
|
||||||
<text>更多</text>
|
<text>更多</text>
|
||||||
</view>
|
</view>
|
||||||
<button class="action-button primary" @tap="addNewGoods">
|
<button class="action-button primary" @tap="addNewGoods">
|
||||||
添加商品/库存
|
添加商品/库存
|
||||||
|
|
@ -118,17 +118,29 @@
|
||||||
<!-- 更多操作弹窗 -->
|
<!-- 更多操作弹窗 -->
|
||||||
<uni-popup ref="popup" type="bottom">
|
<uni-popup ref="popup" type="bottom">
|
||||||
<view class="popup-content">
|
<view class="popup-content">
|
||||||
<view class="popup-item" @tap="editGoods(selectedGoods)">
|
<view class="popup-item" @tap="goToInventoryCount">
|
||||||
<uni-icons type="compose" size="20" color="#333"></uni-icons>
|
<uni-icons type="scan" size="20" color="#333"></uni-icons>
|
||||||
<text>编辑商品</text>
|
<text>盘点库存</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="popup-item" @tap="adjustStock(selectedGoods)">
|
<view class="popup-item" @tap="goToOutbound">
|
||||||
<uni-icons type="plus" size="20" color="#333"></uni-icons>
|
<uni-icons type="arrowright" size="20" color="#333"></uni-icons>
|
||||||
<text>调整库存</text>
|
<text>出库</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="popup-item" @tap="deleteGoods(selectedGoods)">
|
<view class="popup-item" @tap="batchDeleteGoods">
|
||||||
<uni-icons type="trash" size="20" color="#ff4444"></uni-icons>
|
<uni-icons type="trash" size="20" color="#333"></uni-icons>
|
||||||
<text style="color: #ff4444;">删除商品</text>
|
<text>批量删除商品</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-item" @tap="goToCategoryManagement">
|
||||||
|
<uni-icons type="apps" size="20" color="#333"></uni-icons>
|
||||||
|
<text>分类管理</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-item" @tap="goToBrandManagement">
|
||||||
|
<uni-icons type="navigate" size="20" color="#333"></uni-icons>
|
||||||
|
<text>品牌管理</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-item" @tap="goToBarcodeSettings">
|
||||||
|
<uni-icons type="settings" size="20" color="#333"></uni-icons>
|
||||||
|
<text>条码规则设置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="popup-item cancel" @tap="$refs.popup.close()">
|
<view class="popup-item cancel" @tap="$refs.popup.close()">
|
||||||
<text>取消</text>
|
<text>取消</text>
|
||||||
|
|
@ -262,8 +274,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
showMoreActions(goods) {
|
showMoreActions() {
|
||||||
this.selectedGoods = goods;
|
|
||||||
this.$refs.popup.open();
|
this.$refs.popup.open();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -328,8 +339,8 @@
|
||||||
|
|
||||||
addNewGoods() {
|
addNewGoods() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/enter/enter'
|
// url: '/pages/enter/enter'
|
||||||
// url: '/pages/addProduct/addProduct'
|
url: '/pages/addProduct/addProduct'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -386,6 +397,48 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
// 盘点库存
|
||||||
|
goToInventoryCount() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/inventoryCount/inventoryCount'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 出库
|
||||||
|
goToOutbound() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/outbound/outbound'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 批量删除商品
|
||||||
|
batchDeleteGoods() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/batchDeleteProduct/batchDeleteProduct'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 分类管理
|
||||||
|
goToCategoryManagement() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/categoryManagement/categoryManagement'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 品牌管理
|
||||||
|
goToBrandManagement() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/addBrand/addBrand'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 条码规则设置
|
||||||
|
goToBarcodeSettings() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/barcodeSettings/barcodeSettings'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ const request = config => {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const requestUrl = config.baseUrl ? config.baseUrl + config.url : baseUrl + config.url
|
const requestUrl = config.baseUrl ? config.baseUrl + config.url : baseUrl + config.url
|
||||||
|
|
||||||
console.log('最终请求URL:', requestUrl)
|
console.log('最终请求URL:', requestUrl)
|
||||||
console.log('请求配置:', config)
|
console.log('请求配置:', config)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue