品牌列表,批量删除
parent
90476adffa
commit
61602c3adb
|
|
@ -250,8 +250,66 @@ export function importProductData(filePath, formData) {
|
|||
// 获取导入记录
|
||||
export function getImportRecord() {
|
||||
return request8081({
|
||||
baseUrl: 'http://192.168.0.7:8081',
|
||||
baseUrl: 'http://193.112.94.36:8081',
|
||||
url: '/mall/product/importRecord',
|
||||
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:'http://193.112.94.36:8080',
|
||||
// baseUrl = 'https://api.ruoyi.com'
|
||||
// prodApi: 'https://vue.ruoyi.vip/prod-api',
|
||||
// baseUrl: 'http://localhost:8080',
|
||||
// 应用信息
|
||||
|
|
|
|||
12
pages.json
12
pages.json
|
|
@ -155,6 +155,18 @@
|
|||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/batchDeleteProduct/batchDeleteProduct",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/addBrand/addBrand",
|
||||
"style": {
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"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="action-btn more-btn" @tap="showMoreActions(item)">
|
||||
<text>更多</text>
|
||||
<view class="action-btn more-btn" @tap="showMoreActions()">
|
||||
<text>更多</text>
|
||||
</view>
|
||||
<button class="action-button primary" @tap="addNewGoods">
|
||||
添加商品/库存
|
||||
|
|
@ -118,17 +118,29 @@
|
|||
<!-- 更多操作弹窗 -->
|
||||
<uni-popup ref="popup" type="bottom">
|
||||
<view class="popup-content">
|
||||
<view class="popup-item" @tap="editGoods(selectedGoods)">
|
||||
<uni-icons type="compose" size="20" color="#333"></uni-icons>
|
||||
<text>编辑商品</text>
|
||||
<view class="popup-item" @tap="goToInventoryCount">
|
||||
<uni-icons type="scan" size="20" color="#333"></uni-icons>
|
||||
<text>盘点库存</text>
|
||||
</view>
|
||||
<view class="popup-item" @tap="adjustStock(selectedGoods)">
|
||||
<uni-icons type="plus" size="20" color="#333"></uni-icons>
|
||||
<text>调整库存</text>
|
||||
<view class="popup-item" @tap="goToOutbound">
|
||||
<uni-icons type="arrowright" size="20" color="#333"></uni-icons>
|
||||
<text>出库</text>
|
||||
</view>
|
||||
<view class="popup-item" @tap="deleteGoods(selectedGoods)">
|
||||
<uni-icons type="trash" size="20" color="#ff4444"></uni-icons>
|
||||
<text style="color: #ff4444;">删除商品</text>
|
||||
<view class="popup-item" @tap="batchDeleteGoods">
|
||||
<uni-icons type="trash" size="20" color="#333"></uni-icons>
|
||||
<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 class="popup-item cancel" @tap="$refs.popup.close()">
|
||||
<text>取消</text>
|
||||
|
|
@ -262,8 +274,7 @@
|
|||
});
|
||||
},
|
||||
|
||||
showMoreActions(goods) {
|
||||
this.selectedGoods = goods;
|
||||
showMoreActions() {
|
||||
this.$refs.popup.open();
|
||||
},
|
||||
|
||||
|
|
@ -328,8 +339,8 @@
|
|||
|
||||
addNewGoods() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/enter/enter'
|
||||
// url: '/pages/addProduct/addProduct'
|
||||
// url: '/pages/enter/enter'
|
||||
url: '/pages/addProduct/addProduct'
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -339,7 +350,7 @@
|
|||
url: '/pages/expired/expired'
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
batchOperation() {
|
||||
uni.showActionSheet({
|
||||
itemList: ['批量修改价格', '批量修改库存', '批量下架'],
|
||||
|
|
@ -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) => {
|
||||
const requestUrl = config.baseUrl ? config.baseUrl + config.url : baseUrl + config.url
|
||||
|
||||
console.log('最终请求URL:', requestUrl)
|
||||
console.log('请求配置:', config)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue