feat:卖家管理开发
This commit is contained in:
parent
f1f3b01081
commit
930f48bfa3
@ -16,6 +16,7 @@
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.6.8",
|
||||
"element-china-area-data": "^6.1.0",
|
||||
"element-plus": "^2.11.5",
|
||||
"lz-utils-lib": "^1.0.51",
|
||||
"pinia": "^2.1.7",
|
||||
|
||||
@ -14,7 +14,14 @@ const order = {
|
||||
*/
|
||||
getUserReviews: ['/comment/list'], // 获取用户评论
|
||||
agreeComment: ['/comment/agree'], // 同意
|
||||
rejectComment: ['/comment/reject'] // 拒绝
|
||||
rejectComment: ['/comment/reject'], // 拒绝
|
||||
|
||||
/**
|
||||
* 卖家管理
|
||||
*/
|
||||
getSellerList: ['/seller/list'], // 卖家列表
|
||||
updateSeller: ['/seller/insertOrUpdate'], // 添加卖家
|
||||
updateAddress: ['/warehouse/insertOrUpdate'] // 添加仓库
|
||||
}
|
||||
|
||||
export default order
|
||||
|
||||
@ -452,13 +452,13 @@ export default [
|
||||
childList: []
|
||||
} */
|
||||
]
|
||||
}
|
||||
/* {
|
||||
},
|
||||
{
|
||||
id: 60,
|
||||
resourceName: '渠道管理',
|
||||
resourceName: '卖家管理',
|
||||
resourceType: 0,
|
||||
resourceCode: null,
|
||||
path: '/channel',
|
||||
path: '/seller-manage',
|
||||
pid: 0,
|
||||
resourceDesc: null,
|
||||
tenantId: 2,
|
||||
@ -472,10 +472,10 @@ export default [
|
||||
childList: [
|
||||
{
|
||||
id: 61,
|
||||
resourceName: '渠道配置',
|
||||
resourceName: '卖家列表',
|
||||
resourceType: 1,
|
||||
resourceCode: null,
|
||||
path: '/channel/config/index',
|
||||
path: '/seller-manage/list/index',
|
||||
pid: 60,
|
||||
resourceDesc: null,
|
||||
tenantId: 2,
|
||||
@ -489,7 +489,8 @@ export default [
|
||||
childList: []
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
/*
|
||||
{
|
||||
id: 110,
|
||||
resourceName: '产品管理',
|
||||
|
||||
@ -266,13 +266,13 @@ interface Order {
|
||||
|
||||
const tabs = reactive([
|
||||
{ name: 'all', label: '全部' },
|
||||
{ name: 'wait_shipping', label: '待发货', count: 3544 },
|
||||
{ name: 'wait_shipping', label: '待发货', count: '' },
|
||||
{ name: 'shipping', label: '已发货' },
|
||||
{ name: 'shipped', label: '已投递' },
|
||||
{ name: 'delivered', label: '已妥投' },
|
||||
{ name: 'delivered', label: '确认收货' },
|
||||
{ name: 'apply_cancel', label: '买家取消' },
|
||||
{ name: 'cancel', label: '卖家取消' },
|
||||
{ name: 'close', label: '已取消' },
|
||||
{ name: 'close', label: '已关闭' },
|
||||
{ name: 'delete', label: '已删除' },
|
||||
{ name: 'refund', label: '已退款' }
|
||||
])
|
||||
@ -285,7 +285,7 @@ const statusShortcuts = reactive([
|
||||
]) */
|
||||
|
||||
const summary = reactive({
|
||||
totalOrders: 3544
|
||||
totalOrders: 0
|
||||
})
|
||||
|
||||
const orders = ref<Order[]>([])
|
||||
@ -590,6 +590,10 @@ const handleGetOrderList = async (searchData: any = {}) => {
|
||||
}) */
|
||||
return item
|
||||
})
|
||||
summary.totalOrders = res.data.total
|
||||
if (activeTab.value === 'wait_shipping') {
|
||||
tabs.find((item) => item.name === 'wait_shipping')!.count = res.data.total
|
||||
}
|
||||
}
|
||||
|
||||
handleGetOrderList()
|
||||
|
||||
@ -55,12 +55,15 @@
|
||||
物流信息
|
||||
</h3>
|
||||
<el-form ref="formRef" :model="formData" inline :rules="formRules" label-width="100px">
|
||||
<el-form-item label="物流单号" prop="trackingNumber">
|
||||
<el-input v-model="formData.trackingNumber" placeholder="请输入物流单号" clearable />
|
||||
<el-form-item label="物流单号" prop="trackNumber">
|
||||
<el-input v-model="formData.trackNumber" placeholder="请输入物流单号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="物流公司" prop="logisticsCompany">
|
||||
<el-input v-model="formData.logisticsCompany" placeholder="请输入物流公司" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="卖家" prop="sellerId">
|
||||
<el-cascader v-model="formData.sellerId" :options="sellerList" />
|
||||
</el-form-item>
|
||||
<el-form-item label="运费" prop="shippingAmount">
|
||||
<el-input
|
||||
v-model="formData.shippingAmount"
|
||||
@ -128,10 +131,11 @@ interface TableItem {
|
||||
}
|
||||
|
||||
interface FormData {
|
||||
trackingNumber: string
|
||||
trackNumber: string
|
||||
logisticsCompany: string
|
||||
shippingAmount: string
|
||||
packageImageUrls: string[]
|
||||
sellerId: number[]
|
||||
}
|
||||
|
||||
interface OrderItem {
|
||||
@ -166,14 +170,15 @@ const selectedRows = ref<OrderItem[]>([])
|
||||
// 表单相关
|
||||
const formRef = ref<FormInstance>()
|
||||
const formData = ref<FormData>({
|
||||
trackingNumber: '',
|
||||
trackNumber: '',
|
||||
logisticsCompany: '',
|
||||
shippingAmount: '',
|
||||
packageImageUrls: []
|
||||
packageImageUrls: [],
|
||||
sellerId: []
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
trackingNumber: [{ required: true, message: '请输入物流单号', trigger: 'blur' }],
|
||||
trackNumber: [{ required: true, message: '请输入物流单号', trigger: 'blur' }],
|
||||
logisticsCompany: [{ required: true, message: '请输入物流公司', trigger: 'blur' }],
|
||||
shippingAmount: [{ required: true, message: '请输入运费', trigger: 'blur' }],
|
||||
packageImageUrls: [{ required: true, message: '请上传照片', trigger: 'blur' }]
|
||||
@ -217,7 +222,9 @@ const handleSubmit = async () => {
|
||||
try {
|
||||
const submitData = {
|
||||
tradeOrderLineIds: selectedRows.value.map((row) => row.orderLineId),
|
||||
...formData.value
|
||||
...formData.value,
|
||||
sellerId: formData.value.sellerId[0],
|
||||
sellerWarehouseId: formData.value.sellerId[1]
|
||||
}
|
||||
await api.order.packOrder.post!(submitData)
|
||||
ElMessage.success('打包成功')
|
||||
@ -247,7 +254,7 @@ const handleClose = (isClose = true) => {
|
||||
// 重置数据
|
||||
selectedRows.value = []
|
||||
formData.value = {
|
||||
trackingNumber: '',
|
||||
trackNumber: '',
|
||||
logisticsCompany: '',
|
||||
shippingAmount: '',
|
||||
packageImageUrls: []
|
||||
@ -257,11 +264,24 @@ const handleClose = (isClose = true) => {
|
||||
isClose && emit('close')
|
||||
}
|
||||
|
||||
const sellerList = ref<any[]>([])
|
||||
|
||||
// 监听弹窗打开和 id 变化
|
||||
watch(
|
||||
() => dialogVisible.value,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
api.order.getSellerList.post!<{ rows: any[] }>().then((res) => {
|
||||
sellerList.value = res.data.rows.map((item) => ({
|
||||
label: item.sellerName,
|
||||
value: item.id,
|
||||
children:
|
||||
item.sellerWarehouseList?.map((child) => ({
|
||||
label: `${child.province},${child.city},${child.district},${child.warehouseDetailAddress}:${child.warehousePhone}`,
|
||||
value: child.id
|
||||
})) || []
|
||||
}))
|
||||
})
|
||||
tableData.value = []
|
||||
;(props.orderLineData || []).forEach((item: OrderItem) => {
|
||||
tableData.value.push(
|
||||
|
||||
45
src/views/seller-manage/list/config.ts
Normal file
45
src/views/seller-manage/list/config.ts
Normal file
@ -0,0 +1,45 @@
|
||||
export const orderStatusOptions = [
|
||||
{ label: '待支付', value: 'wait_pay' },
|
||||
{ label: '待发货', value: 'wait_shipping' },
|
||||
{ label: '已经发货', value: 'shipping' },
|
||||
{ label: '已接收', value: 'delivered' },
|
||||
{ label: '全部退款', value: 'all_refund' },
|
||||
{ label: '部分退款', value: 'part_refund' }
|
||||
]
|
||||
|
||||
const configData = ref()
|
||||
export const initConfig = () => {
|
||||
configData.value = pageConfig({
|
||||
search: {
|
||||
id: { label: '卖家ID' },
|
||||
sellerName: { label: '卖家名称' }
|
||||
},
|
||||
table: {
|
||||
index: { label: '序号' },
|
||||
id: { label: '卖家ID' },
|
||||
sellerName: { label: '卖家名称' },
|
||||
sellerCount: { label: '卖出订单数量' },
|
||||
refundCount: { label: '退款数量' },
|
||||
sellerOriginGmv: { label: '卖家原始销售金额', width: 120 },
|
||||
sellerSaleGmv: { label: '已经销售金额' },
|
||||
refundOriginGmv: { label: '退款原始金额' },
|
||||
refundSaleGmv: { label: '退款销售金额' },
|
||||
createTimestamp: { label: '创建时间' },
|
||||
btn: {
|
||||
types: ['primary', 'success', 'danger'],
|
||||
names: ['编辑', '编辑仓库', '删除'],
|
||||
width: 170
|
||||
}
|
||||
},
|
||||
dialog: [
|
||||
{
|
||||
sellerName: { label: '卖家名称' }
|
||||
},
|
||||
{
|
||||
sellerName: { label: '卖家名称', disabled: true },
|
||||
addresses: { label: '仓库地址', slot: 'addresses', class: '!w-full' }
|
||||
}
|
||||
]
|
||||
})
|
||||
return configData
|
||||
}
|
||||
214
src/views/seller-manage/list/index.vue
Normal file
214
src/views/seller-manage/list/index.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="seller-list">
|
||||
<search-module :search="search" :table="table">
|
||||
<template #btn>
|
||||
<el-button type="primary" @click="onAddOrEditSeller('add', null)">新增卖家</el-button>
|
||||
</template>
|
||||
</search-module>
|
||||
<table-module :table="table">
|
||||
<template #status="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="'online'"
|
||||
:inactive-value="'down'"
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
</table-module>
|
||||
<dialog-module :dialog="$dialog" width="1000px">
|
||||
<template #addresses>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="$dialog.data.sellerWarehouseList[index]"
|
||||
:rules="rules"
|
||||
inline
|
||||
v-for="(item, index) in $dialog.data.sellerWarehouseList"
|
||||
:key="item.random"
|
||||
>
|
||||
<el-form-item label="仓库电话" prop="warehousePhone">
|
||||
<el-input
|
||||
v-model="$dialog.data.sellerWarehouseList[index].warehousePhone"
|
||||
placeholder="请输入仓库电话"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="省市区" prop="region">
|
||||
<el-cascader
|
||||
@change="addressChange"
|
||||
v-model="$dialog.data.sellerWarehouseList[index].region"
|
||||
:options="regionData"
|
||||
:props="{ value: 'label' }"
|
||||
clearable
|
||||
></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="详细地址"
|
||||
prop="warehouseDetailAddress"
|
||||
style="width: calc(100% - 150px)"
|
||||
>
|
||||
<el-input
|
||||
v-model="$dialog.data.sellerWarehouseList[index].warehouseDetailAddress"
|
||||
placeholder="请输入详细地址"
|
||||
clearable
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="w-20 inline-block">
|
||||
<el-icon size="30" @click="onAddAddress(index)">
|
||||
<CirclePlusFilled color="#409EFF"
|
||||
/></el-icon>
|
||||
<el-icon size="30" class="ml-2" @click="onDeleteAddress(item, index)"
|
||||
><RemoveFilled color="#F56C6C"
|
||||
/></el-icon>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
</dialog-module>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { initConfig } from './config'
|
||||
import { regionData } from 'element-china-area-data'
|
||||
import { CirclePlusFilled, RemoveFilled } from '@element-plus/icons-vue'
|
||||
|
||||
const onAddOrEditSeller = (row: any) => {
|
||||
const dialog = $dialog.value
|
||||
dialog.config = dialog1.value
|
||||
dialog.show = true
|
||||
dialog.title = row ? '编辑卖家' : '新增卖家'
|
||||
dialog.data = {
|
||||
id: row?.id,
|
||||
sellerName: row?.sellerName || ''
|
||||
}
|
||||
dialog.submit = async (value: any) => {
|
||||
await api.order.updateSeller.post!(value)
|
||||
ElMessage.success('操作成功')
|
||||
table.value.$onGetData(table.value, 1)
|
||||
dialog.show = false
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑添加仓库
|
||||
const formRef = ref<Array<any>>([])
|
||||
const onEditAddress = (row: any) => {
|
||||
const dialog = $dialog.value
|
||||
dialog.config = dialog2.value
|
||||
dialog.show = true
|
||||
dialog.title = '编辑仓库'
|
||||
// 重置表单引用数组
|
||||
formRef.value = []
|
||||
row.sellerWarehouseList = (row.sellerWarehouseList || []).map((item: any) => ({
|
||||
...item,
|
||||
region: [item.province, item.city, item.district],
|
||||
random: Math.random()
|
||||
}))
|
||||
const address = row.sellerWarehouseList?.[0]
|
||||
dialog.data = {
|
||||
sellerId: row.id,
|
||||
id: address?.id,
|
||||
sellerName: row?.sellerName || '',
|
||||
sellerWarehouseList: row.sellerWarehouseList
|
||||
}
|
||||
dialog.submit = async (value: any) => {
|
||||
// 等待 DOM 更新完成,确保所有表单都已渲染
|
||||
await nextTick()
|
||||
const validatePromises = formRef.value
|
||||
.filter((form: any) => form)
|
||||
.map((form: any) => form.validate())
|
||||
|
||||
Promise.all(validatePromises)
|
||||
.then(async () => {
|
||||
value.sellerWarehouseList.forEach(async (item) => {
|
||||
item.province = item.region[0]
|
||||
item.city = item.region[1]
|
||||
item.district = item.region[2]
|
||||
await api.order.updateAddress.post!(item)
|
||||
})
|
||||
deleteIds.forEach(async (id) => {
|
||||
await api.order.updateAddress.post!({ id, isDelete: 1 })
|
||||
})
|
||||
ElMessage.success('操作成功')
|
||||
table.value.$onGetData(table.value, 1)
|
||||
dialog.show = false
|
||||
deleteIds.length = 0
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.error('请填写完整')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
const onDeleteUser = (row: any) => {
|
||||
handleMessageBox({
|
||||
msg: `是否确认删除?`,
|
||||
success: api.order.updateSeller.post!,
|
||||
data: { id: row.id, isDelete: 1 }
|
||||
}).then(() => {
|
||||
ElMessage.success('操作成功')
|
||||
table.value.$onGetData(table.value, 1)
|
||||
})
|
||||
}
|
||||
|
||||
const addressChange = (arr: any) => {
|
||||
$dialog.value.data.province = arr[0]
|
||||
$dialog.value.data.city = arr[1]
|
||||
$dialog.value.data.district = arr[2]
|
||||
}
|
||||
|
||||
const validateRegion = (rule: any, value: any, callback: any) => {
|
||||
if (value.length !== 3) {
|
||||
callback(new Error('请选择省市区'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const rules = {
|
||||
warehousePhone: [{ required: true, message: '请输入仓库电话', trigger: 'blur' }],
|
||||
region: [{ required: true, validator: validateRegion, message: '请选择省市区', trigger: 'blur' }],
|
||||
warehouseDetailAddress: [{ required: true, message: '请输入详细地址', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const onAddAddress = (index: number) => {
|
||||
$dialog.value.data.sellerWarehouseList.splice(index + 1, 0, {
|
||||
random: Math.random(),
|
||||
warehousePhone: '',
|
||||
region: [],
|
||||
warehouseDetailAddress: '',
|
||||
sellerId: $dialog.value.data.sellerId
|
||||
})
|
||||
}
|
||||
|
||||
const deleteIds = []
|
||||
const onDeleteAddress = (item: any, index: number) => {
|
||||
if (item.id) {
|
||||
deleteIds.push(item.id)
|
||||
}
|
||||
$dialog.value.data.sellerWarehouseList.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 初始化页面 */
|
||||
const ConfigData = initConfig()
|
||||
const { search, table, dialog1, $dialog, dialog2 } = handleInit(
|
||||
ConfigData,
|
||||
api.order.getSellerList.post,
|
||||
[onAddOrEditSeller, onEditAddress, onDeleteUser]
|
||||
)
|
||||
table.value.$onGetData(table.value, 1)
|
||||
|
||||
/** 页面缓存 */
|
||||
defineOptions({ name: 'OrderList' })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#seller-list {
|
||||
.el-form-item .el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
12
yarn.lock
12
yarn.lock
@ -1560,6 +1560,11 @@ chalk@^4.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
china-division@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.npmmirror.com/china-division/-/china-division-2.7.0.tgz#4060a4d243be66c7833dea64a48a4038f3e53e74"
|
||||
integrity sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA==
|
||||
|
||||
chokidar@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||
@ -1964,6 +1969,13 @@ electron-to-chromium@^1.5.204:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.208.tgz#609c29502fd7257b4d721e3446f3ae391a0ca1b3"
|
||||
integrity sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==
|
||||
|
||||
element-china-area-data@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.npmmirror.com/element-china-area-data/-/element-china-area-data-6.1.0.tgz#f14b90c0762b21432e097ed5be8423514a0b57e3"
|
||||
integrity sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==
|
||||
dependencies:
|
||||
china-division "^2.7.0"
|
||||
|
||||
element-plus@^2.11.5:
|
||||
version "2.11.5"
|
||||
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.11.5.tgz#752c2c4f70e86d615e577686c2f08054860a0902"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user