merchant-web/src/views/modules/operation-management/permission/merchant-account/index.vue

654 lines
20 KiB
Vue
Raw Normal View History

2025-09-10 17:55:35 +00:00
<template>
2025-09-11 02:36:47 +00:00
<div class="app-container">
<el-form
ref="ruleFormRef"
:model="form"
label-position="left"
label-width="auto"
:rules="rules"
style="max-width: 600px"
>
2025-09-11 16:49:14 +00:00
<el-form-item
v-if="!marketId && markets.length > 0"
label="选择市场"
prop="selectedMarketId"
>
<el-select
v-model="form.selectedMarketId"
placeholder="请选择市场"
style="width: 100%"
>
2025-09-11 02:36:47 +00:00
<el-option
v-for="market in markets"
:key="market.marketId"
:label="market.marketName"
:value="market.marketId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="操作类型" prop="operationType">
2025-09-11 16:49:14 +00:00
<el-select
v-model="form.operationType"
placeholder="请选择操作类型"
style="width: 100%"
>
2025-09-11 02:36:47 +00:00
<el-option label="创建新商户" value="create"></el-option>
<el-option label="维护商户信息" value="update"></el-option>
</el-select>
</el-form-item>
<template v-if="form.operationType === 'create'">
<el-form-item label="商户账号" prop="mobile">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.mobile"
placeholder="请输入商户账号"
></el-input>
2025-09-11 02:36:47 +00:00
</el-form-item>
<el-form-item label="密码" prop="password">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.password"
type="password"
placeholder="请输入密码"
></el-input>
2025-09-11 02:36:47 +00:00
</el-form-item>
2025-09-11 02:48:05 +00:00
<h3>店铺基础信息</h3>
<el-form-item label="摊位名称" prop="name">
<el-input v-model="form.name" placeholder="请输入摊位名称"></el-input>
</el-form-item>
<el-form-item label="主营类目" prop="categoryId">
2025-09-11 16:49:14 +00:00
<el-select
v-model="form.categoryId"
placeholder="请选择主营类目"
style="width: 100%"
>
2025-09-11 02:48:05 +00:00
<el-option
v-for="item in categoryList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="摊位背景图" prop="background">
<el-upload
2025-09-11 16:49:14 +00:00
accept="image/*"
2025-09-11 02:48:05 +00:00
:action="uploadUrl"
2025-09-11 16:49:14 +00:00
list-type="picture-card"
2025-09-11 02:48:05 +00:00
:headers="uploadHeaders"
:show-file-list="false"
:on-success="handleBackgroundSuccess"
:before-upload="beforeAvatarUpload"
>
2025-09-11 16:49:14 +00:00
<img v-if="form.background" :src="form.background" width="148px" height="148px" />
<i v-else class="el-icon-plus"></i>
2025-09-11 02:48:05 +00:00
</el-upload>
</el-form-item>
<el-form-item label="摊位联系电话" prop="contactPhone">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.contactPhone"
placeholder="请输入联系电话/手机号"
></el-input>
2025-09-11 02:48:05 +00:00
</el-form-item>
<el-form-item label="摊位照片" prop="fileList">
<el-upload
2025-09-11 16:49:14 +00:00
accept="image/*"
2025-09-11 02:48:05 +00:00
:action="uploadUrl"
:headers="uploadHeaders"
list-type="picture-card"
:file-list="form.fileList"
:on-success="handleFileListSuccess"
:before-upload="beforeAvatarUpload"
:on-remove="handleRemove"
>
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
<el-form-item label="摊位位置" prop="address">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.address"
placeholder="请输入摊位位置"
></el-input>
2025-09-11 02:48:05 +00:00
</el-form-item>
<el-form-item label="摊位详细地址" prop="detailAddress">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.detailAddress"
placeholder="请输入摊位详细地址"
></el-input>
2025-09-11 02:48:05 +00:00
</el-form-item>
<el-form-item label="许可证" prop="permits">
<el-upload
2025-09-11 16:49:14 +00:00
accept="image/*"
2025-09-11 02:48:05 +00:00
:action="uploadUrl"
:headers="uploadHeaders"
list-type="picture-card"
:file-list="form.permits"
:on-success="handlePermitsSuccess"
:before-upload="beforeAvatarUpload"
:on-remove="handlePermitsRemove"
>
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
<el-form-item label="是否自动营业" prop="isAutoBusiness">
<el-switch v-model="form.isAutoBusiness"></el-switch>
</el-form-item>
<el-form-item v-if="form.isAutoBusiness" label="营业时间">
<el-time-picker
is-range
v-model="businessHours"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
2025-09-11 16:49:14 +00:00
placeholder="选择时间范围"
>
2025-09-11 02:48:05 +00:00
</el-time-picker>
</el-form-item>
<el-form-item label="顾客自提点位置" prop="pickName">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.pickName"
placeholder="请输入顾客自提点位置"
></el-input>
2025-09-11 02:48:05 +00:00
</el-form-item>
<el-form-item label="自提点详细地址" prop="pickAddress">
2025-09-11 16:49:14 +00:00
<el-input
v-model="form.pickAddress"
placeholder="请输入自提点详细地址"
></el-input>
2025-09-11 02:48:05 +00:00
</el-form-item>
<el-form-item label="自提点位置示意图" prop="pickImg">
<el-upload
2025-09-11 16:49:14 +00:00
accept="image/*"
2025-09-11 02:48:05 +00:00
:action="uploadUrl"
2025-09-11 16:49:14 +00:00
list-type="picture-card"
2025-09-11 02:48:05 +00:00
:headers="uploadHeaders"
:show-file-list="false"
:on-success="handlePickImgSuccess"
:before-upload="beforeAvatarUpload"
>
2025-09-11 16:49:14 +00:00
<img v-if="form.pickImg" :src="form.pickImg" width="148px" height="148px" />
<i v-else class="el-icon-plus"></i>
2025-09-11 02:48:05 +00:00
</el-upload>
</el-form-item>
<el-form-item label="承诺送达自提点时间" prop="promisePickDeliveryTime">
2025-09-11 16:49:14 +00:00
<el-input
v-model.number="form.promisePickDeliveryTime"
placeholder="请输入小时数"
>
2025-09-11 02:48:05 +00:00
<template slot="append">小时以内</template>
</el-input>
</el-form-item>
2025-09-11 02:36:47 +00:00
</template>
<template v-if="form.operationType === 'update'">
2025-09-11 06:26:11 +00:00
<el-form-item label="选择商户账号" prop="merchantId">
2025-09-11 16:49:14 +00:00
<el-select
v-model="form.merchantId"
placeholder="请选择要更新的商户账号"
@change="handleAccountChange"
style="width: 100%"
>
2025-09-11 02:36:47 +00:00
<el-option
v-for="item in merchantAccountList"
2025-09-11 06:26:11 +00:00
:key="item.merchantId"
2025-09-11 02:36:47 +00:00
:label="item.name"
2025-09-11 06:26:11 +00:00
:value="item.merchantId"
2025-09-11 02:36:47 +00:00
></el-option>
</el-select>
</el-form-item>
<el-form-item>
2025-09-11 16:49:14 +00:00
<el-button type="warning" @click="openResetPasswordDialog"
>重置密码</el-button
>
2025-09-11 02:36:47 +00:00
</el-form-item>
<el-form-item label="状态">
2025-09-11 16:49:14 +00:00
<el-switch
v-model="form.enable"
active-text="启用"
inactive-text="禁用"
></el-switch>
2025-09-11 02:36:47 +00:00
</el-form-item>
</template>
<el-form-item label="权限分配" prop="permissionCodes">
<el-tree
ref="permissionTree"
:data="permissionList"
show-checkbox
node-key="id"
:props="defaultProps"
@check="handleTreeCheck"
>
</el-tree>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save">保存</el-button>
</el-form-item>
</el-form>
<el-dialog
title="重置密码"
:visible.sync="resetPasswordDialogVisible"
width="30%"
@close="newPassword = ''"
>
<el-form label-width="80px">
<el-form-item label="新密码">
2025-09-11 16:49:14 +00:00
<el-input
v-model="newPassword"
type="password"
placeholder="请输入新密码"
></el-input>
2025-09-11 02:36:47 +00:00
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetPasswordDialogVisible = false"> </el-button>
<el-button type="primary" @click="handleResetPassword"> </el-button>
</span>
</el-dialog>
</div>
2025-09-10 17:55:35 +00:00
</template>
<script>
2025-09-11 02:36:47 +00:00
import {
getAvailablePermissions,
2025-09-11 16:49:14 +00:00
checkUsername
2025-09-11 02:36:47 +00:00
} from '@/api/modules/subaccount' // Assuming some APIs can be reused
2025-09-11 16:49:14 +00:00
import {
inviteJoin,
setMerchantPermissions,
shopBaseConfig,
listPlatformCategory,
getMerchantList,
updatePassword
} from '@/api/modules/merchant' // New merchant API
2025-09-11 02:48:05 +00:00
import { mer_admin } from '@/api/modules/mer_admin'
2025-09-11 02:36:47 +00:00
import routerConfig from '@/router/full-routers'
import { mapState } from 'vuex'
2025-09-11 02:48:05 +00:00
import cookie from 'js-cookie'
2025-09-11 02:36:47 +00:00
// Function to filter the full menu tree based on available permissions
const filterTreeByPerms = (tree, availablePerms) => {
if (!Array.isArray(tree)) {
2025-09-11 16:49:14 +00:00
return []
2025-09-11 02:36:47 +00:00
}
return tree.reduce((acc, node) => {
2025-09-11 16:49:14 +00:00
const children =
node.list && node.list.length > 0
? filterTreeByPerms(node.list, availablePerms)
: []
2025-09-11 02:36:47 +00:00
if (availablePerms.includes(node.perms) || children.length > 0) {
acc.push({
...node,
2025-09-11 16:49:14 +00:00
list: children
})
2025-09-11 02:36:47 +00:00
}
2025-09-11 16:49:14 +00:00
return acc
}, [])
}
2025-09-11 02:36:47 +00:00
// Function to map the filtered tree to the format required by el-tree
2025-09-11 16:49:14 +00:00
const mapTreeForElTree = tree => {
return tree.map(item => ({
2025-09-11 02:36:47 +00:00
id: item.perms,
label: item.name,
2025-09-11 16:49:14 +00:00
children:
item.list && item.list.length > 0 ? mapTreeForElTree(item.list) : []
}))
}
2025-09-11 02:36:47 +00:00
2025-09-10 17:55:35 +00:00
export default {
2025-09-11 02:36:47 +00:00
name: 'MerchantAccount',
data() {
const validateMobile = (rule, value, callback) => {
if (this.form.operationType !== 'create') {
2025-09-11 16:49:14 +00:00
return callback()
2025-09-11 02:36:47 +00:00
}
if (!value) {
2025-09-11 16:49:14 +00:00
return callback(new Error('请输入商户账号'))
2025-09-11 02:36:47 +00:00
}
2025-09-11 16:49:14 +00:00
checkUsername(value, this.form.selectedMarketId || this.marketId)
.then(res => {
if (
res &&
res.data &&
res.data.data &&
res.data.data.available === true
) {
callback()
} else {
callback(new Error('商户账号已被占用'))
}
})
.catch(() => {
callback(new Error('商户账号校验失败'))
})
}
2025-09-11 02:36:47 +00:00
return {
resetPasswordDialogVisible: false,
newPassword: '',
form: {
operationType: 'create',
mobile: '',
password: '',
permissionCodes: [],
2025-09-11 06:26:11 +00:00
merchantId: null,
2025-09-11 02:36:47 +00:00
enable: true,
2025-09-11 02:48:05 +00:00
selectedMarketId: '',
name: '',
categoryId: '',
background: '',
isAutoBusiness: true,
businessDays: '1111111',
startBusinessTime: 0,
endBusinessTime: 1440,
contactPhone: '',
fileList: [],
address: '',
permits: [],
lng: '',
lat: '',
detailAddress: '',
pickName: '',
pickLng: '',
pickAddress: '',
pickLat: '',
pickImg: '',
2025-09-11 16:49:14 +00:00
promisePickDeliveryTime: ''
2025-09-11 02:36:47 +00:00
},
2025-09-11 16:49:14 +00:00
businessHours: [
new Date(2016, 9, 10, 0, 0),
new Date(2016, 9, 10, 23, 59)
],
2025-09-11 02:48:05 +00:00
categoryList: [],
2025-09-11 02:36:47 +00:00
merchantAccountList: [], // To be populated with merchant accounts
permissionList: [],
defaultProps: {
children: 'children',
label: 'label'
},
rules: {
operationType: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请选择操作类型', trigger: 'change' }
2025-09-11 02:36:47 +00:00
],
mobile: [
2025-09-11 16:49:14 +00:00
{ required: true, validator: validateMobile, trigger: 'blur' }
2025-09-11 02:48:05 +00:00
],
2025-09-11 16:49:14 +00:00
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
name: [{ required: true, message: '请输入摊位名称', trigger: 'blur' }],
2025-09-11 02:48:05 +00:00
categoryId: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请选择主营类目', trigger: 'change' }
2025-09-11 02:48:05 +00:00
],
background: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请上传摊位背景图', trigger: 'change' }
2025-09-11 02:48:05 +00:00
],
fileList: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请上传摊位照片', trigger: 'change' }
2025-09-11 02:48:05 +00:00
],
address: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请输入摊位位置', trigger: 'blur' }
2025-09-11 02:48:05 +00:00
],
detailAddress: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请输入摊位详细地址', trigger: 'blur' }
2025-09-11 02:48:05 +00:00
],
pickName: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请输入顾客自提点位置', trigger: 'blur' }
2025-09-11 02:48:05 +00:00
],
pickAddress: [
2025-09-11 16:49:14 +00:00
{ required: true, message: '请输入自提点详细地址', trigger: 'blur' }
2025-09-11 02:48:05 +00:00
],
promisePickDeliveryTime: [
2025-09-11 16:49:14 +00:00
{
required: true,
message: '请输入承诺送达自提点时间',
trigger: 'blur'
},
{ type: 'number', message: '必须为数字值' }
2025-09-11 02:48:05 +00:00
],
2025-09-11 02:36:47 +00:00
permissionCodes: [
2025-09-11 16:49:14 +00:00
{
required: true,
message: '请选择菜单权限',
trigger: 'change',
type: 'array'
}
2025-09-11 02:36:47 +00:00
],
2025-09-11 06:26:11 +00:00
merchantId: [
2025-09-11 16:49:14 +00:00
{
required: true,
message: '请选择要更新的商户账号',
trigger: 'change'
}
]
}
}
2025-09-11 02:36:47 +00:00
},
computed: {
2025-09-11 16:49:14 +00:00
...mapState('userData', [
'isMerchant',
'marketList',
'storeList',
'marketId',
'shopId',
'markets'
2025-09-11 02:48:05 +00:00
]),
uploadUrl() {
2025-09-11 16:49:14 +00:00
return mer_admin.uploadFile()
2025-09-11 02:48:05 +00:00
},
uploadHeaders() {
return {
token: cookie.get('token')
2025-09-11 16:49:14 +00:00
}
2025-09-11 02:48:05 +00:00
}
2025-09-11 02:36:47 +00:00
},
watch: {
'form.operationType'(newType) {
2025-09-11 16:49:14 +00:00
this.form.mobile = ''
this.form.password = ''
this.form.permissionCodes = []
this.form.merchantId = null
2025-09-11 02:36:47 +00:00
this.$nextTick(() => {
2025-09-11 16:49:14 +00:00
this.$refs.ruleFormRef.clearValidate()
})
2025-09-11 02:36:47 +00:00
if (this.$refs.permissionTree) {
2025-09-11 16:49:14 +00:00
this.$refs.permissionTree.setCheckedKeys([])
2025-09-11 02:36:47 +00:00
}
if (newType === 'update') {
2025-09-11 16:49:14 +00:00
this.loadMerchantAccountList()
2025-09-11 02:36:47 +00:00
}
}
},
created() {
2025-09-11 16:49:14 +00:00
this.getPermissions()
this.getPlatformCategory()
2025-09-11 02:36:47 +00:00
},
methods: {
2025-09-11 02:48:05 +00:00
getPlatformCategory() {
listPlatformCategory({ type: this.isCloudShop ? 1 : 0 }).then(res => {
2025-09-11 16:49:14 +00:00
this.categoryList = res.data.data
})
2025-09-11 02:48:05 +00:00
},
2025-09-11 02:36:47 +00:00
getPermissions() {
2025-09-11 16:49:14 +00:00
getAvailablePermissions().then(res => {
const availablePerms =
res && res.data && Array.isArray(res.data.data) ? res.data.data : []
const menuList =
routerConfig && Array.isArray(routerConfig.menuList)
? routerConfig.menuList
: []
const filteredTree = filterTreeByPerms(menuList, availablePerms)
this.permissionList = mapTreeForElTree(filteredTree)
})
2025-09-11 02:36:47 +00:00
},
openResetPasswordDialog() {
2025-09-11 06:26:11 +00:00
if (!this.form.merchantId) {
2025-09-11 16:49:14 +00:00
this.$message.error('请先选择要更新的商户账号')
return
2025-09-11 02:36:47 +00:00
}
2025-09-11 16:49:14 +00:00
this.resetPasswordDialogVisible = true
2025-09-11 02:36:47 +00:00
},
handleResetPassword() {
if (!this.newPassword) {
2025-09-11 16:49:14 +00:00
this.$message.error('请输入新密码')
return
2025-09-11 02:36:47 +00:00
}
2025-09-11 06:26:11 +00:00
updatePassword({ password: this.newPassword }).then(() => {
2025-09-11 16:49:14 +00:00
this.$message.success('密码重置成功')
this.resetPasswordDialogVisible = false
})
2025-09-11 02:36:47 +00:00
},
handleTreeCheck() {
2025-09-11 16:49:14 +00:00
this.form.permissionCodes = this.$refs.permissionTree.getCheckedKeys(true)
2025-09-11 02:36:47 +00:00
},
2025-09-11 02:48:05 +00:00
handleBackgroundSuccess(res) {
2025-09-11 16:49:14 +00:00
this.form.background = res.data
2025-09-11 02:48:05 +00:00
},
handleFileListSuccess(res, file, fileList) {
2025-09-11 16:49:14 +00:00
this.form.fileList = fileList
2025-09-11 02:48:05 +00:00
},
handlePermitsSuccess(res, file, fileList) {
2025-09-11 16:49:14 +00:00
this.form.permits = fileList
2025-09-11 02:48:05 +00:00
},
handlePickImgSuccess(res) {
2025-09-11 16:49:14 +00:00
this.form.pickImg = res.data
2025-09-11 02:48:05 +00:00
},
beforeAvatarUpload(file) {
2025-09-11 16:49:14 +00:00
const isImage = file.type.startsWith('image/')
const isLt2M = file.size / 1024 / 1024 < 2
2025-09-11 02:48:05 +00:00
2025-09-11 16:49:14 +00:00
if (!isImage) {
this.$message.error('上传文件只能是图片格式!')
2025-09-11 02:48:05 +00:00
}
if (!isLt2M) {
2025-09-11 16:49:14 +00:00
this.$message.error('上传图片大小不能超过 2MB!')
2025-09-11 02:48:05 +00:00
}
2025-09-11 16:49:14 +00:00
return isImage && isLt2M
2025-09-11 02:48:05 +00:00
},
handleRemove(file, fileList) {
2025-09-11 16:49:14 +00:00
this.form.fileList = fileList
2025-09-11 02:48:05 +00:00
},
handlePermitsRemove(file, fileList) {
2025-09-11 16:49:14 +00:00
this.form.permits = fileList
2025-09-11 02:48:05 +00:00
},
2025-09-11 06:26:11 +00:00
loadMerchantAccountList() {
2025-09-11 16:49:14 +00:00
getMerchantList({
marketId: this.form.selectedMarketId || this.marketId
}).then(res => {
this.merchantAccountList = res.data.data || []
})
2025-09-11 06:26:11 +00:00
},
handleAccountChange(merchantId) {
2025-09-11 16:49:14 +00:00
if (!merchantId) return
const accountDetails = this.merchantAccountList.find(
item => item.merchantId === merchantId
)
2025-09-11 06:26:11 +00:00
if (accountDetails) {
2025-09-11 16:49:14 +00:00
this.form.permissionCodes = accountDetails.permissionCodes || []
this.form.enable = accountDetails.enabled
2025-09-11 06:26:11 +00:00
this.$nextTick(() => {
2025-09-11 16:49:14 +00:00
this.$refs.permissionTree.setCheckedKeys(this.form.permissionCodes)
})
2025-09-11 06:26:11 +00:00
}
2025-09-11 02:36:47 +00:00
},
save() {
2025-09-11 16:49:14 +00:00
this.$refs.ruleFormRef.validate(valid => {
2025-09-11 02:36:47 +00:00
if (valid) {
2025-09-11 16:49:14 +00:00
const marketId = this.form.selectedMarketId || this.marketId
2025-09-11 02:36:47 +00:00
if (!marketId) {
2025-09-11 16:49:14 +00:00
this.$message.error('请选择市场')
return
2025-09-11 02:36:47 +00:00
}
if (this.form.operationType === 'create') {
const createData = {
marketId,
name: this.form.mobile,
mobile: this.form.mobile,
remark: '',
username: this.form.mobile,
password: this.form.password
2025-09-11 16:49:14 +00:00
}
inviteJoin(createData).then(res => {
const merchantAccountId = res.data.data.merchantAccountId // Assuming this is the merchant ID
const shopId = res.data.data.shopId // Assuming this is the shop ID
2025-09-11 02:36:47 +00:00
const permissionsData = {
merchantAccountId,
permissionCodes: this.form.permissionCodes,
marketId
2025-09-11 16:49:14 +00:00
}
2025-09-11 02:36:47 +00:00
setMerchantPermissions(permissionsData).then(() => {
2025-09-11 02:48:05 +00:00
const shopData = {
...this.form,
imgs: this.form.fileList.map(f => f.url).join(','),
permits: this.form.permits.map(f => f.url).join(','),
2025-09-11 16:49:14 +00:00
startBusinessTime:
this.businessHours[0].getHours() * 60 +
this.businessHours[0].getMinutes(),
endBusinessTime:
this.businessHours[1].getHours() * 60 +
this.businessHours[1].getMinutes()
}
2025-09-11 02:48:05 +00:00
shopBaseConfig({ shopId }, shopData).then(() => {
2025-09-11 16:49:14 +00:00
this.$message.success('商户创建成功,权限及店铺信息已设置')
this.$refs.ruleFormRef.resetFields()
})
})
})
2025-09-11 02:36:47 +00:00
} else if (this.form.operationType === 'update') {
2025-09-11 06:26:11 +00:00
if (!this.form.merchantId) {
2025-09-11 16:49:14 +00:00
this.$message.error('请先选择要更新的商户账号')
return
2025-09-11 02:36:47 +00:00
}
2025-09-11 06:26:11 +00:00
const permissionsData = {
merchantAccountId: this.form.merchantId,
2025-09-11 02:36:47 +00:00
permissionCodes: this.form.permissionCodes,
marketId
2025-09-11 16:49:14 +00:00
}
2025-09-11 06:26:11 +00:00
setMerchantPermissions(permissionsData).then(() => {
2025-09-11 16:49:14 +00:00
this.$message.success('商户信息更新成功')
this.$refs.ruleFormRef.resetFields()
})
2025-09-11 02:36:47 +00:00
}
}
2025-09-11 16:49:14 +00:00
})
2025-09-11 02:36:47 +00:00
}
2025-09-11 16:49:14 +00:00
}
2025-09-10 17:55:35 +00:00
}
</script>
<style scoped>
2025-09-11 02:36:47 +00:00
.app-container {
padding: 20px;
}
2025-09-11 02:48:05 +00:00
.avatar-uploader .el-upload {
2025-09-11 16:49:14 +00:00
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>