项目创建

This commit is contained in:
浅念
2025-07-04 17:16:38 +08:00
parent ce47b39fa5
commit 719911918f
372 changed files with 105035 additions and 32 deletions
+344
View File
@@ -0,0 +1,344 @@
<template>
<div class="page-content">
<ElRow>
<ElCol :xs="24" :sm="12" :lg="6">
<ElInput placeholder="部门名称"></ElInput>
</ElCol>
<div style="width: 12px"></div>
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
<ElButton v-ripple>搜索</ElButton>
<ElButton @click="showDialog('add')" v-ripple>新增角色</ElButton>
</ElCol>
</ElRow>
<ArtTable :data="roleList" index>
<template #default>
<ElTableColumn label="角色名称" prop="roleName" />
<ElTableColumn label="角色编码" prop="roleCode" />
<ElTableColumn label="描述" prop="des" />
<ElTableColumn label="启用" prop="enable">
<template #default="scope">
<ElTag :type="scope.row.enable ? 'primary' : 'info'">
{{ scope.row.enable ? '启用' : '禁用' }}
</ElTag>
</template>
</ElTableColumn>
<ElTableColumn label="创建时间" prop="date">
<template #default="scope">
{{ formatDate(scope.row.date) }}
</template>
</ElTableColumn>
<ElTableColumn fixed="right" label="操作" width="200px">
<template #default="scope">
<ElRow>
<el-button link @click="showPermissionDialog()"> 菜单权限 </el-button>
<el-button link @click="showDialog('edit', scope.row)"> 编辑 </el-button>
<el-button link @click="deleteRole()"> 删除 </el-button>
<!-- <ArtButtonMore
:list="[
{ key: 'permission', label: '菜单权限' },
{ key: 'edit', label: '编辑角色' },
{ key: 'delete', label: '删除角色' }
]"
@click="buttonMoreClick($event, scope.row)"
/> -->
</ElRow>
</template>
</ElTableColumn>
</template>
</ArtTable>
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增角色' : '编辑角色'"
width="30%"
align-center
>
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElFormItem label="角色名称" prop="roleName">
<ElInput v-model="form.roleName" />
</ElFormItem>
<ElFormItem label="角色编码" prop="roleCode">
<ElInput v-model="form.roleCode" />
</ElFormItem>
<ElFormItem label="描述" prop="roleStatus">
<ElInput v-model="form.des" type="textarea" :rows="3" />
</ElFormItem>
<ElFormItem label="启用">
<ElSwitch v-model="form.enable" />
</ElFormItem>
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton @click="dialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleSubmit(formRef)">提交</ElButton>
</div>
</template>
</ElDialog>
<ElDialog
v-model="permissionDialog"
title="菜单权限"
width="520px"
align-center
class="el-dialog-border"
>
<ElScrollbar height="70vh">
<ElTree
ref="treeRef"
:data="processedMenuList"
show-checkbox
node-key="name"
:default-expand-all="isExpandAll"
:default-checked-keys="[1, 2, 3]"
:props="defaultProps"
@check="handleTreeCheck"
>
<template #default="{ data }">
<div style="display: flex; align-items: center">
<span v-if="data.isAuth">
{{ data.label }}
</span>
<span v-else>{{ defaultProps.label(data) }}</span>
</div>
</template>
</ElTree>
</ElScrollbar>
<template #footer>
<div class="dialog-footer">
<ElButton @click="toggleExpandAll">{{ isExpandAll ? '全部收起' : '全部展开' }}</ElButton>
<ElButton @click="toggleSelectAll" style="margin-left: 8px">{{
isSelectAll ? '取消全选' : '全部选择'
}}</ElButton>
<ElButton type="primary" @click="savePermission">保存</ElButton>
</div>
</template>
</ElDialog>
</div>
</template>
<script setup lang="ts">
import { useMenuStore } from '@/store/modules/menu'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { formatMenuTitle } from '@/router/utils/utils'
// import { ButtonMoreItem } from '@/components/core/forms/ArtButtonMore.vue'
import { Role, ROLE_LIST_DATA } from '@/mock/temp/formData'
defineOptions({ name: 'Role' })
const dialogVisible = ref(false)
const permissionDialog = ref(false)
const { menuList } = storeToRefs(useMenuStore())
const treeRef = ref()
const isExpandAll = ref(true)
const isSelectAll = ref(false)
// 处理菜单数据,将 authList 转换为子节点
const processedMenuList = computed(() => {
const processNode = (node: any) => {
const processed = { ...node }
// 如果有 authList,将其转换为子节点
if (node.meta && node.meta.authList && node.meta.authList.length) {
const authNodes = node.meta.authList.map((auth: any) => ({
id: `${node.id}_${auth.auth_mark}`,
name: `${node.name}_${auth.auth_mark}`,
label: auth.title,
auth_mark: auth.auth_mark,
isAuth: true,
checked: auth.checked || false
}))
processed.children = processed.children ? [...processed.children, ...authNodes] : authNodes
}
// 递归处理子节点
if (processed.children) {
processed.children = processed.children.map(processNode)
}
return processed
}
return menuList.value.map(processNode)
})
const formRef = ref<FormInstance>()
const rules = reactive<FormRules>({
name: [
{ required: true, message: '请输入角色名称', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
],
des: [{ required: true, message: '请输入角色描述', trigger: 'blur' }]
})
const form = reactive<Role>({
roleName: '',
roleCode: '',
des: '',
date: '',
enable: true
})
const roleList = ref<Role[]>([])
onMounted(() => {
getTableData()
})
const getTableData = () => {
roleList.value = ROLE_LIST_DATA
}
const dialogType = ref('add')
const showDialog = (type: string, row?: any) => {
dialogVisible.value = true
dialogType.value = type
if (type === 'edit' && row) {
form.roleName = row.roleName
form.roleCode = row.roleCode
form.des = row.des
form.date = row.date
form.enable = row.enable
} else {
form.roleName = ''
form.roleCode = ''
form.des = ''
form.date = ''
form.enable = true
}
}
// const buttonMoreClick = (item: ButtonMoreItem, row: any) => {
// if (item.key === 'permission') {
// showPermissionDialog()
// } else if (item.key === 'edit') {
// showDialog('edit', row)
// } else if (item.key === 'delete') {
// deleteRole()
// }
// }
const showPermissionDialog = () => {
permissionDialog.value = true
}
const defaultProps = {
children: 'children',
label: (data: any) => formatMenuTitle(data.meta?.title) || ''
}
const deleteRole = () => {
ElMessageBox.confirm('确定删除该角色吗?', '删除确认', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'error'
}).then(() => {
ElMessage.success('删除成功')
})
}
const handleSubmit = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
const message = dialogType.value === 'add' ? '新增成功' : '修改成功'
ElMessage.success(message)
dialogVisible.value = false
formEl.resetFields()
}
})
}
const savePermission = () => {
ElMessage.success('权限保存成功')
permissionDialog.value = false
}
const toggleExpandAll = () => {
const tree = treeRef.value
if (!tree) return
// 使用store.nodesMap直接控制所有节点的展开状态
const nodes = tree.store.nodesMap
for (const node in nodes) {
nodes[node].expanded = !isExpandAll.value
}
isExpandAll.value = !isExpandAll.value
}
const toggleSelectAll = () => {
const tree = treeRef.value
if (!tree) return
if (!isSelectAll.value) {
// 全选:获取所有节点的key并设置为选中
const allKeys = getAllNodeKeys(processedMenuList.value)
tree.setCheckedKeys(allKeys)
} else {
// 取消全选:清空所有选中
tree.setCheckedKeys([])
}
isSelectAll.value = !isSelectAll.value
}
const getAllNodeKeys = (nodes: any[]): string[] => {
const keys: string[] = []
const traverse = (nodeList: any[]) => {
nodeList.forEach((node) => {
if (node.name) {
keys.push(node.name)
}
if (node.children && node.children.length > 0) {
traverse(node.children)
}
})
}
traverse(nodes)
return keys
}
const handleTreeCheck = () => {
const tree = treeRef.value
if (!tree) return
// 使用树组件的getCheckedKeys方法获取选中的节点
const checkedKeys = tree.getCheckedKeys()
const allKeys = getAllNodeKeys(processedMenuList.value)
// 判断是否全选:选中的节点数量等于总节点数量
isSelectAll.value = checkedKeys.length === allKeys.length && allKeys.length > 0
}
const formatDate = (date: string) => {
return new Date(date)
.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
.replace(/\//g, '-')
}
</script>
<style lang="scss" scoped>
.page-content {
.svg-icon {
width: 1.8em;
height: 1.8em;
overflow: hidden;
vertical-align: -8px;
fill: currentcolor;
}
}
</style>
+685
View File
@@ -0,0 +1,685 @@
<template>
<ArtTableFullScreen>
<div class="account-page" id="table-full-screen">
<!-- 搜索栏 -->
<ArtSearchBar
v-model:filter="formFilters"
:items="formItems"
@reset="handleReset"
@search="handleSearch"
></ArtSearchBar>
<ElCard shadow="never" class="art-table-card">
<!-- 表格头部 -->
<ArtTableHeader v-model:columns="columnChecks" @refresh="handleRefresh">
<template #left>
<ElButton @click="showDialog('add')">新增</ElButton>
</template>
</ArtTableHeader>
<!-- 表格 -->
<ArtTable
ref="tableRef"
row-key="id"
:loading="loading"
:data="tableData"
:currentPage="pagination.currentPage"
:pageSize="pagination.pageSize"
:total="pagination.total"
:marginTop="10"
@selection-change="handleSelectionChange"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<template #default>
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
</template>
</ArtTable>
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '添加' : '编辑'"
width="60%"
align-center
class="custom-dialog-scroll"
style="max-height:80vh;overflow:auto;"
>
<ElForm ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="基本信息" name="first">
<el-row>
<el-col :sm="24" :md="12">
<ElFormItem label="产品名称" prop="name">
<ElInput v-model="formData.name" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="封面图" prop="phone">
<div style="display: flex; align-items: center;">
<el-upload
ref="upload"
v-model:file-list="fileList"
class="upload-demo"
action="https://usedcar.server.hnxinyouhe.com/console/upload/image"
name="image"
:on-success="handleCoverSuccess"
:show-file-list="false"
>
<el-button type="primary">点击上传</el-button>
</el-upload>
<img
v-if="coverImageUrl"
:src="coverImageUrl"
alt="封面图"
style="width: 40px; height: 40px; margin-left: 16px; border-radius: 4px; object-fit: cover;"
/>
</div>
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="车辆识别码" prop="vin">
<ElInput v-model="formData.vin" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="售价" prop="price">
<ElInput v-model="formData.price" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="品牌" prop="brand">
<ElSelect v-model="formData.brand" placeholder="请选择品牌" clearable>
<ElOption
v-for="brand in brandList"
:key="brand.id"
:value="brand.name"
:label="brand.name"
/>
</ElSelect>
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="型号" prop="model">
<ElInput v-model="formData.model" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="类型" prop="type">
<ElInput v-model="formData.type" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="能源" prop="energy">
<ElInput v-model="formData.energy" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="库存状态" prop="store_status">
<ElSelect v-model="formData.store_status">
<ElOption label="男" value="男" />
<ElOption label="女" value="女" />
</ElSelect>
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="里程" prop="mileage">
<ElInput v-model="formData.mileage" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="车龄(年)" prop="vehicle_age">
<ElInput v-model="formData.vehicle_age" />
</ElFormItem>
</el-col>
<el-col :sm="24" :md="12">
<ElFormItem label="位置" prop="location">
<ElSelect v-model="formData.location">
<ElOption
v-for="role in roleList"
:key="role.roleCode"
:value="role.roleCode"
:label="role.roleName"
/>
</ElSelect>
</ElFormItem>
</el-col>
<el-col :sm="24" :md="24">
<ElFormItem label="车况描述" prop="condition_desc">
<ElInput v-model="formData.condition_desc" :rows="4" type="textarea" />
</ElFormItem>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="车辆图册" name="second">
<el-row :gutter="20">
<el-col :span="8" v-for="(url, part) in carAlbum" :key="part">
<div style="margin-bottom: 16px; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<div style="margin-bottom: 8px; text-align: center;">{{ part }}</div>
<el-upload
:show-file-list="false"
:action="'https://usedcar.server.hnxinyouhe.com/console/upload/image'"
name="image"
:on-success="(res, file) => handleAlbumSuccess(res, file, part)"
>
<el-button type="primary" size="small">上传</el-button>
</el-upload>
<img
v-if="carAlbum[part]"
:src="carAlbum[part]"
style="display:block;width:60px;height:60px;margin-top:8px;object-fit:cover;border-radius:4px;"
/>
</div>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton @click="dialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleSubmit">提交</ElButton>
</div>
</template>
</ElDialog>
</ElCard>
</div>
</ArtTableFullScreen>
</template>
<script setup lang="ts">
import { h } from 'vue'
import { ROLE_LIST_DATA, ACCOUNT_TABLE_DATA } from '@/mock/temp/formData'
import { ElDialog, FormInstance, ElTag } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
import type { FormRules } from 'element-plus'
import { useCheckedColumns } from '@/composables/useCheckedColumns'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import { UserService } from '@/api/usersApi'
import { BrandService } from '@/api/carApi'
import { SearchChangeParams, SearchFormItem } from '@/types'
import type { TabsPaneContext } from 'element-plus'
import { ref } from 'vue'
const activeName = ref('first')
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
const { width } = useWindowSize()
defineOptions({ name: 'User' }) // 定义组件名称,用于 KeepAlive 缓存控制
const dialogType = ref('add')
const dialogVisible = ref(false)
const loading = ref(false)
// 定义表单搜索初始值
const initialSearchState = {
name: '',
phone: '',
address: '',
level: '',
email: '',
date: '',
daterange: '',
status: '1'
}
const roleList = ref<any[]>([])
const brandList = ref<any[]>([])
// 响应式表单数据
const formFilters = reactive({ ...initialSearchState })
const pagination = reactive({
currentPage: 1,
pageSize: 20,
total: 0
})
// 表格数据
const tableData = ref<any[]>([])
// 表格实例引用
const tableRef = ref()
// 选中的行数据
const selectedRows = ref<any[]>([])
// 重置表单
const handleReset = () => {
Object.assign(formFilters, { ...initialSearchState })
pagination.currentPage = 1 // 重置到第一页
getUserList()
}
// 搜索处理
const handleSearch = () => {
console.log('搜索参数:', formFilters)
pagination.currentPage = 1 // 搜索时重置到第一页
getUserList()
}
// 表单项变更处理
const handleFormChange = (params: SearchChangeParams): void => {
console.log('表单项变更:', params)
}
// 表单配置项
const formItems: SearchFormItem[] = [
{
label: '用户名',
prop: 'name',
type: 'input',
config: {
clearable: true
},
onChange: handleFormChange
},
{
label: '电话',
prop: 'phone',
type: 'input',
config: {
clearable: true
},
onChange: handleFormChange
},
{
label: '用户等级',
prop: 'level',
type: 'select',
config: {
clearable: true
},
options: () => [
{ label: '普通用户', value: 'normal' },
{ label: 'VIP用户', value: 'vip' },
{ label: '高级VIP', value: 'svip' },
{ label: '企业用户', value: 'enterprise', disabled: true }
],
onChange: handleFormChange
},
{
label: '地址',
prop: 'address',
type: 'input',
config: {
clearable: true
},
onChange: handleFormChange
},
{
label: '邮箱',
prop: 'email',
type: 'input',
config: {
clearable: true
},
onChange: handleFormChange
},
// 支持 9 种日期类型定义
// 具体可参考 src/components/core/forms/art-search-bar/widget/art-search-date/README.md
{
prop: 'date',
label: '日期',
type: 'date',
config: {
type: 'date',
placeholder: '请选择日期'
}
},
{
prop: 'daterange',
label: '日期范围',
type: 'daterange',
config: {
type: 'daterange',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间'
}
},
{
label: '状态',
prop: 'status',
type: 'radio',
options: [
{ label: '在线', value: '1' },
{ label: '离线', value: '2' }
],
onChange: handleFormChange
}
]
// 获取标签类型
// 1: 在线 2: 离线 3: 异常 4: 注销
const getTagType = (status: string) => {
switch (status) {
case '1':
return 'success'
case '2':
return 'info'
case '3':
return 'warning'
case '4':
return 'danger'
default:
return 'info'
}
}
// 构建标签文本
const buildTagText = (status: string) => {
let text = ''
if (status === '1') {
text = '在线'
} else if (status === '2') {
text = '离线'
} else if (status === '3') {
text = '异常'
} else if (status === '4') {
text = '注销'
}
return text
}
// 显示对话框
const showDialog = (type: string, row?: any) => {
dialogVisible.value = true
dialogType.value = type
// 重置表单验证状态
if (formRef.value) {
formRef.value.resetFields()
}
if (type === 'edit' && row) {
formData.name = row.username
} else {
formData.name=''
formData.cover=''
formData.vin=''
formData.price=''
formData.brand=''
formData.model=''
formData.type=''
formData.energy=''
formData.store_status=''
formData.mileage=''
formData.vehicle_age=''
formData.location=''
formData.condition_desc=''
}
}
// 删除用户
const deleteUser = () => {
ElMessageBox.confirm('确定要注销该用户吗?', '注销用户', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'error'
}).then(() => {
ElMessage.success('注销成功')
})
}
// 动态列配置
const { columnChecks, columns } = useCheckedColumns(() => [
{ type: 'selection' }, // 勾选列
// { type: 'expand', label: '展开', width: 80 }, // 展开列
// { type: 'index', label: '序号', width: 80 }, // 序号列
{
prop: 'avatar',
label: '用户名',
minWidth: width.value < 500 ? 220 : '',
formatter: (row: any) => {
return h('div', { class: 'user', style: 'display: flex; align-items: center' }, [
h('img', { class: 'avatar', src: row.avatar }),
h('div', {}, [
h('p', { class: 'user-name' }, row.userName),
h('p', { class: 'email' }, row.userEmail)
])
])
}
},
{
prop: 'userGender',
label: '性别',
sortable: true,
formatter: (row) => (row.userGender === 1 ? '男' : '女')
},
{ prop: 'userPhone', label: '手机号' },
{
prop: 'status',
label: '状态',
formatter: (row) => {
return h(ElTag, { type: getTagType(row.status) }, () => buildTagText(row.status))
}
},
{
prop: 'createTime',
label: '创建日期',
sortable: true
},
{
prop: 'operation',
label: '操作',
width: 150,
// fixed: 'right', // 固定在右侧
// disabled: true,
formatter: (row: any) => {
return h('div', [
h(ArtButtonTable, {
type: 'edit',
onClick: () => showDialog('edit', row)
}),
h(ArtButtonTable, {
type: 'delete',
onClick: () => deleteUser()
})
])
}
}
])
// 表单实例
const formRef = ref<FormInstance>()
// 表单数据
const formData = reactive({
name: '',
cover: '',
vin: '',
price: '',
brand: '',
model: '',
type: '',
energy: '',
store_status: '',
mileage: '',
vehicle_age: '',
location: '',
condition_desc: ''
})
const fileList = ref<any[]>([])
const coverImageUrl = ref('')
const handleCoverSuccess = (response: any, file: any) => {
coverImageUrl.value = response.data.image_url || ''
// 上传成功后清空 fileList,允许再次上传
fileList.value = []
}
defineExpose({ handleCoverSuccess })
onMounted(() => {
getUserList()
getRoleList()
getBrandList()
})
// 获取用户列表数据
const getUserList = async () => {
loading.value = true
try {
const { currentPage, pageSize } = pagination
const { records, current, size, total } = await UserService.getUserList({
current: currentPage,
size: pageSize
})
// 使用本地头像替换接口返回的头像
tableData.value = records.map((item: any, index: number) => ({
...item,
avatar: ACCOUNT_TABLE_DATA[index % ACCOUNT_TABLE_DATA.length].avatar
}))
// 更新分页信息
Object.assign(pagination, { currentPage: current, pageSize: size, total })
} catch (error) {
console.error('获取用户列表失败:', error)
} finally {
loading.value = false
}
}
const getRoleList = () => {
roleList.value = ROLE_LIST_DATA
}
// 获取品牌列表
const getBrandList = async () => {
try {
// 这里调用获取品牌列表的接口
const response = await BrandService.getBrandInfo()
brandList.value = response.data || []
// 临时使用模拟数据,实际使用时请替换为真实接口
// brandList.value = [
// { id: 1, name: '奔驰' },
// { id: 2, name: '宝马' },
// { id: 3, name: '奥迪' },
// { id: 4, name: '大众' },
// { id: 5, name: '丰田' },
// { id: 6, name: '本田' },
// { id: 7, name: '日产' },
// { id: 8, name: '现代' },
// { id: 9, name: '起亚' },
// { id: 10, name: '福特' }
// ]
} catch (error) {
console.error('获取品牌列表失败:', error)
ElMessage.error('获取品牌列表失败')
}
}
const handleRefresh = () => {
getUserList()
}
// 处理表格行选择变化
const handleSelectionChange = (selection: any[]) => {
selectedRows.value = selection
}
// 表单验证规则
const rules = reactive<FormRules>({
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur' }
],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
role: [{ required: true, message: '请选择角色', trigger: 'change' }]
})
// 提交表单
const handleSubmit = async () => {
if (!formRef.value) return
await formRef.value.validate((valid) => {
if (valid) {
ElMessage.success(dialogType.value === 'add' ? '添加成功' : '更新成功')
dialogVisible.value = false
}
})
}
// 处理表格分页变化
const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize
getUserList()
}
const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage
getUserList()
}
const carAlbum = reactive<Record<string, string>>({
'45度正脸': '',
'左前45度': '',
'左前大灯': '',
'正前': '',
'车头下部': ''
// 可继续添加更多部位
})
const handleAlbumSuccess = (response: any, file: any, part: string) => {
carAlbum[part] = response.data?.image_url || ''
}
</script>
<style lang="scss" scoped>
.account-page {
:deep(.user) {
.avatar {
width: 40px;
height: 40px;
border-radius: 6px;
}
> div {
margin-left: 10px;
.user-name {
font-weight: 500;
color: var(--art-text-gray-800);
}
}
}
}
.custom-dialog-scroll .el-dialog__body {
max-height: 60vh;
overflow-y: auto;
}
</style>
<style>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>