fetch(add): 账户管理
This commit is contained in:
@@ -31,6 +31,9 @@
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
:default-expand-all="false"
|
||||
:pagination="false"
|
||||
@selection-change="handleSelectionChange"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
@@ -62,8 +65,24 @@
|
||||
|
||||
<ElRow :gutter="20" v-if="dialogType === 'add'">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="上级店铺ID" prop="parent_id">
|
||||
<ElInputNumber v-model="formData.parent_id" :min="1" placeholder="一级店铺可不填" style="width: 100%" clearable />
|
||||
<ElFormItem label="上级店铺" prop="parent_id">
|
||||
<ElSelect
|
||||
v-model="formData.parent_id"
|
||||
placeholder="一级店铺可不选"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="searchParentShops"
|
||||
:loading="parentShopLoading"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption
|
||||
v-for="shop in parentShopList"
|
||||
:key="shop.id"
|
||||
:label="shop.shop_name"
|
||||
:value="shop.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
@@ -102,7 +121,11 @@
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="联系电话" prop="contact_phone">
|
||||
<ElInput v-model="formData.contact_phone" placeholder="请输入联系电话" maxlength="11" />
|
||||
<ElInput
|
||||
v-model="formData.contact_phone"
|
||||
placeholder="请输入联系电话"
|
||||
maxlength="11"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
@@ -118,14 +141,23 @@
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="密码" prop="init_password">
|
||||
<ElInput v-model="formData.init_password" type="password" placeholder="请输入初始账号密码" show-password />
|
||||
<ElInput
|
||||
v-model="formData.init_password"
|
||||
type="password"
|
||||
placeholder="请输入初始账号密码"
|
||||
show-password
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="手机号" prop="init_phone">
|
||||
<ElInput v-model="formData.init_phone" placeholder="请输入初始账号手机号" maxlength="11" />
|
||||
<ElInput
|
||||
v-model="formData.init_phone"
|
||||
placeholder="请输入初始账号手机号"
|
||||
maxlength="11"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
@@ -142,7 +174,9 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="dialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit" :loading="submitLoading">提交</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit" :loading="submitLoading"
|
||||
>提交</ElButton
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
@@ -153,7 +187,15 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { FormInstance, ElMessage, ElMessageBox, ElTag, ElSwitch } from 'element-plus'
|
||||
import {
|
||||
FormInstance,
|
||||
ElMessage,
|
||||
ElMessageBox,
|
||||
ElTag,
|
||||
ElSwitch,
|
||||
ElSelect,
|
||||
ElOption
|
||||
} from 'element-plus'
|
||||
import type { FormRules } from 'element-plus'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
@@ -169,6 +211,9 @@
|
||||
const dialogVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const parentShopLoading = ref(false)
|
||||
const parentShopList = ref<ShopResponse[]>([])
|
||||
const searchParentShopList = ref<ShopResponse[]>([])
|
||||
|
||||
// 定义表单搜索初始值
|
||||
const initialSearchState = {
|
||||
@@ -211,7 +256,7 @@
|
||||
}
|
||||
|
||||
// 表单配置项
|
||||
const searchFormItems: SearchFormItem[] = [
|
||||
const searchFormItems = computed<SearchFormItem[]>(() => [
|
||||
{
|
||||
label: '店铺名称',
|
||||
prop: 'shop_name',
|
||||
@@ -231,12 +276,20 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '上级ID',
|
||||
label: '上级店铺',
|
||||
prop: 'parent_id',
|
||||
type: 'input',
|
||||
type: 'select',
|
||||
options: searchParentShopList.value.map((shop) => ({
|
||||
label: shop.shop_name,
|
||||
value: shop.id
|
||||
})),
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请输入上级店铺ID'
|
||||
filterable: true,
|
||||
remote: true,
|
||||
remoteMethod: handleSearchParentShop,
|
||||
loading: parentShopLoading.value,
|
||||
placeholder: '请选择或搜索上级店铺'
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -267,15 +320,13 @@
|
||||
placeholder: '请选择状态'
|
||||
}
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: 'ID', prop: 'id' },
|
||||
{ label: '店铺名称', prop: 'shop_name' },
|
||||
{ label: '店铺编号', prop: 'shop_code' },
|
||||
{ label: '层级', prop: 'level' },
|
||||
{ label: '上级ID', prop: 'parent_id' },
|
||||
{ label: '所在地区', prop: 'region' },
|
||||
{ label: '联系人', prop: 'contact_name' },
|
||||
{ label: '联系电话', prop: 'contact_phone' },
|
||||
@@ -286,19 +337,13 @@
|
||||
|
||||
// 显示对话框
|
||||
const showDialog = (type: string, row?: ShopResponse) => {
|
||||
dialogVisible.value = true
|
||||
dialogType.value = type
|
||||
|
||||
// 重置表单验证状态
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields()
|
||||
}
|
||||
|
||||
if (type === 'edit' && row) {
|
||||
formData.id = row.id
|
||||
formData.shop_name = row.shop_name
|
||||
formData.shop_code = ''
|
||||
formData.parent_id = null
|
||||
formData.parent_id = undefined
|
||||
formData.province = row.province || ''
|
||||
formData.city = row.city || ''
|
||||
formData.district = row.district || ''
|
||||
@@ -313,7 +358,7 @@
|
||||
formData.id = 0
|
||||
formData.shop_name = ''
|
||||
formData.shop_code = ''
|
||||
formData.parent_id = null
|
||||
formData.parent_id = undefined
|
||||
formData.province = ''
|
||||
formData.city = ''
|
||||
formData.district = ''
|
||||
@@ -325,6 +370,13 @@
|
||||
formData.init_password = ''
|
||||
formData.init_phone = ''
|
||||
}
|
||||
|
||||
// 重置表单验证状态
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate()
|
||||
})
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 删除店铺
|
||||
@@ -350,11 +402,6 @@
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
prop: 'id',
|
||||
label: 'ID',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'shop_name',
|
||||
label: '店铺名称',
|
||||
@@ -373,12 +420,6 @@
|
||||
return h(ElTag, { type: 'info', size: 'small' }, () => `${row.level}级`)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'parent_id',
|
||||
label: '上级ID',
|
||||
width: 100,
|
||||
formatter: (row: ShopResponse) => row.parent_id || '-'
|
||||
},
|
||||
{
|
||||
prop: 'region',
|
||||
label: '所在地区',
|
||||
@@ -388,6 +429,7 @@
|
||||
if (row.province) parts.push(row.province)
|
||||
if (row.city) parts.push(row.city)
|
||||
if (row.district) parts.push(row.district)
|
||||
if (row.address) parts.push(row.address)
|
||||
return parts.length > 0 ? parts.join(' / ') : '-'
|
||||
}
|
||||
},
|
||||
@@ -413,7 +455,7 @@
|
||||
activeText: getStatusText(CommonStatus.ENABLED),
|
||||
inactiveText: getStatusText(CommonStatus.DISABLED),
|
||||
inlinePrompt: true,
|
||||
'onUpdate:modelValue': (val: number) => handleStatusChange(row, val)
|
||||
'onUpdate:modelValue': (val: string | number | boolean) => handleStatusChange(row, val as number)
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -451,7 +493,7 @@
|
||||
id: 0,
|
||||
shop_name: '',
|
||||
shop_code: '',
|
||||
parent_id: null as number | null,
|
||||
parent_id: undefined as number | undefined,
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
@@ -466,15 +508,76 @@
|
||||
|
||||
onMounted(() => {
|
||||
getShopList()
|
||||
loadParentShopList()
|
||||
loadSearchParentShopList()
|
||||
})
|
||||
|
||||
// 加载上级店铺列表(用于新增对话框,默认加载20条)
|
||||
const loadParentShopList = async (shopName?: string) => {
|
||||
parentShopLoading.value = true
|
||||
try {
|
||||
const params: any = {
|
||||
page: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
if (shopName) {
|
||||
params.shop_name = shopName
|
||||
}
|
||||
const res = await ShopService.getShops(params)
|
||||
if (res.code === 0) {
|
||||
parentShopList.value = res.data.items || []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取上级店铺列表失败:', error)
|
||||
} finally {
|
||||
parentShopLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 加载搜索栏上级店铺列表(默认加载20条)
|
||||
const loadSearchParentShopList = async (shopName?: string) => {
|
||||
try {
|
||||
const params: any = {
|
||||
page: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
if (shopName) {
|
||||
params.shop_name = shopName
|
||||
}
|
||||
const res = await ShopService.getShops(params)
|
||||
if (res.code === 0) {
|
||||
searchParentShopList.value = res.data.items || []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取上级店铺列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索上级店铺(用于新增对话框)
|
||||
const searchParentShops = (query: string) => {
|
||||
if (query) {
|
||||
loadParentShopList(query)
|
||||
} else {
|
||||
loadParentShopList()
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索上级店铺(用于搜索栏)
|
||||
const handleSearchParentShop = (query: string) => {
|
||||
if (query) {
|
||||
loadSearchParentShopList(query)
|
||||
} else {
|
||||
loadSearchParentShopList()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取店铺列表
|
||||
const getShopList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.currentPage,
|
||||
page_size: pagination.pageSize,
|
||||
page: 1,
|
||||
page_size: 9999, // 获取所有数据用于构建树形结构
|
||||
shop_name: searchForm.shop_name || undefined,
|
||||
shop_code: searchForm.shop_code || undefined,
|
||||
parent_id: searchForm.parent_id,
|
||||
@@ -483,7 +586,8 @@
|
||||
}
|
||||
const res = await ShopService.getShops(params)
|
||||
if (res.code === 0) {
|
||||
tableData.value = res.data.items || []
|
||||
const items = res.data.items || []
|
||||
tableData.value = buildTreeData(items)
|
||||
pagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -493,6 +597,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 构建树形数据
|
||||
const buildTreeData = (items: ShopResponse[]) => {
|
||||
const map = new Map<number, ShopResponse & { children?: ShopResponse[] }>()
|
||||
const tree: ShopResponse[] = []
|
||||
|
||||
// 先将所有项放入 map
|
||||
items.forEach((item) => {
|
||||
map.set(item.id, { ...item, children: [] })
|
||||
})
|
||||
|
||||
// 构建树形结构
|
||||
items.forEach((item) => {
|
||||
const node = map.get(item.id)!
|
||||
if (item.parent_id && map.has(item.parent_id)) {
|
||||
// 有父节点,添加到父节点的 children 中
|
||||
const parent = map.get(item.parent_id)!
|
||||
if (!parent.children) parent.children = []
|
||||
parent.children.push(node)
|
||||
} else {
|
||||
// 没有父节点或父节点不存在,作为根节点
|
||||
tree.push(node)
|
||||
}
|
||||
})
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
const handleRefresh = () => {
|
||||
getShopList()
|
||||
}
|
||||
@@ -512,19 +643,15 @@
|
||||
{ required: true, message: '请输入店铺编号', trigger: 'blur' },
|
||||
{ min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
address: [
|
||||
{ max: 255, message: '地址不能超过255个字符', trigger: 'blur' }
|
||||
],
|
||||
contact_name: [
|
||||
{ max: 50, message: '联系人姓名不能超过50个字符', trigger: 'blur' }
|
||||
],
|
||||
address: [{ max: 255, message: '地址不能超过255个字符', trigger: 'blur' }],
|
||||
contact_name: [{ max: 50, message: '联系人姓名不能超过50个字符', trigger: 'blur' }],
|
||||
contact_phone: [
|
||||
{ len: 11, message: '联系电话必须为 11 位', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur' }
|
||||
],
|
||||
init_username: [
|
||||
{ required: true, message: '请输入初始账号用户名', trigger: 'blur' },
|
||||
{ min: 3, max: 50, message: '长度在 3 到 50 个字符', trigger: 'blur' }
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
init_password: [
|
||||
{ required: true, message: '请输入初始账号密码', trigger: 'blur' },
|
||||
@@ -611,7 +738,10 @@
|
||||
// 先更新UI
|
||||
row.status = newStatus
|
||||
try {
|
||||
await ShopService.updateShop(row.id, { status: newStatus })
|
||||
await ShopService.updateShop(row.id, {
|
||||
shop_name: row.shop_name,
|
||||
status: newStatus
|
||||
})
|
||||
ElMessage.success('状态切换成功')
|
||||
} catch (error) {
|
||||
// 切换失败,恢复原状态
|
||||
|
||||
Reference in New Issue
Block a user