mirror of
https://github.com/flipped-aurora/gin-vue-admin.git
synced 2026-10-13 04:39:36 +00:00
+ Updated translations.
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="profile-avatar relative w-[120px] h-[120px] rounded-full overflow-hidden cursor-pointer group">
|
||||
<img
|
||||
v-if="modelValue"
|
||||
class="w-full h-full object-cover"
|
||||
:src="getUrl(modelValue)"
|
||||
alt="头像"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="w-full h-full flex flex-col items-center justify-center bg-gray-100 dark:bg-slate-700"
|
||||
>
|
||||
<el-icon class="text-2xl text-gray-400">
|
||||
<avatar />
|
||||
</el-icon>
|
||||
<span class="mt-2 text-sm text-gray-400">点击上传</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute inset-0 bg-black/30 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-all duration-300"
|
||||
@click="chooseFile"
|
||||
>
|
||||
<div class="text-center text-white">
|
||||
<el-icon class="text-2xl"><camera-filled /></el-icon>
|
||||
<div class="text-xs mt-1">更换头像</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
class="hidden"
|
||||
accept="image/*"
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getUrl } from '@/utils/image'
|
||||
import service from '@/utils/request'
|
||||
|
||||
defineOptions({
|
||||
name: 'ProfileAvatar'
|
||||
})
|
||||
|
||||
const { modelValue } = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const fileInput = ref(null)
|
||||
|
||||
const chooseFile = () => {
|
||||
fileInput.value.click()
|
||||
}
|
||||
|
||||
const handleFileChange = async (e) => {
|
||||
const file = e.target.files[0]
|
||||
if (!file) return
|
||||
|
||||
// 验证文件类型
|
||||
if (!file.type.includes('image/')) {
|
||||
ElMessage.error('请选择图片文件')
|
||||
return
|
||||
}
|
||||
|
||||
// 验证文件大小(限制为2MB)
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
ElMessage.error('图片大小不能超过2MB')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
|
||||
const res = await service({
|
||||
url: '/fileUploadAndDownload/upload',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
|
||||
if (res.code === 0 && res.data?.file?.url) {
|
||||
emit('update:modelValue', res.data.file.url)
|
||||
ElMessage.success('头像上传成功')
|
||||
} else {
|
||||
ElMessage.error(res.msg || '上传失败')
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('头像上传失败,请重试')
|
||||
} finally {
|
||||
// 清空input,确保可以重复选择同一文件
|
||||
e.target.value = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.profile-avatar {
|
||||
img {
|
||||
@apply transition-transform duration-300;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
img {
|
||||
@apply scale-110;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -253,6 +253,7 @@
|
||||
},
|
||||
"user": {
|
||||
"loggingIn": "جارٍ تسجيل الدخول، يرجى الانتظار...",
|
||||
"loginFailed": "فشل تسجيل الدخول",
|
||||
"connectAdmin": "يرجى الاتصال بالمسؤول للحصول على إذن"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@
|
||||
},
|
||||
"user": {
|
||||
"loggingIn": "Logging in, please wait...",
|
||||
"loginFailed": "Login Failed",
|
||||
"connectAdmin": "Please contact the administrator for authorization"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,6 +1006,7 @@
|
||||
},
|
||||
"user": {
|
||||
"loggingIn": "登錄中,請稍候...",
|
||||
"loginFailed": "登入失敗",
|
||||
"connectAdmin": "請聯繫管理員進行授權"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +257,7 @@
|
||||
},
|
||||
"user": {
|
||||
"loggingIn": "登录中,请稍候...",
|
||||
"loginFailed": "登录失败",
|
||||
"connectAdmin": "请联系管理员进行授权"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
const res = await login(loginInfo)
|
||||
|
||||
if (res.code !== 0) {
|
||||
ElMessage.error(res.message || '登录失败')
|
||||
ElMessage.error(res.message || i18n.global.t('pinia.modules.user.loginFailed'))
|
||||
return false
|
||||
}
|
||||
// 登陆成功,设置用户信息和权限相关信息
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="left" fixed="right" :label="t('general.operations')" :min-width="appStore.operateMinWith">
|
||||
<el-table-column align="left" fixed="right" :label="t('general.operations')" :min-width="appStore.operateMinWith" width="180px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit"
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
/>
|
||||
<el-table-column
|
||||
align="left"
|
||||
:lable="t('general.operations')"
|
||||
width="460"
|
||||
:label="t('general.operations')"
|
||||
width="440"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
width="120"
|
||||
/>
|
||||
|
||||
<el-table-column align="left" :label="t('general.operations')" :min-width="appStore.operateMinWith">
|
||||
<el-table-column align="left" :label="t('general.operations')" :min-width="appStore.operateMinWith" width="200px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
min-width="360"
|
||||
prop="component"
|
||||
/>
|
||||
<el-table-column align="left" fixed="right" :label="t('general.operations')" :min-width="appStore.operateMinWith">
|
||||
<el-table-column align="left" fixed="right" :label="t('general.operations')" :min-width="appStore.operateMinWith" width="280px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
align="left"
|
||||
:label="t('general.request')"
|
||||
prop="path"
|
||||
width="100"
|
||||
width="200"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div>
|
||||
@@ -127,7 +127,7 @@
|
||||
align="left"
|
||||
:label="t('view.operation.sysOperationRecord.response')"
|
||||
prop="path"
|
||||
width="100"
|
||||
width="200"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div>
|
||||
@@ -160,7 +160,7 @@
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="left" :label="t('general.operations')">
|
||||
<el-table-column align="left" :label="t('general.operations')" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="delete"
|
||||
|
||||
@@ -113,10 +113,10 @@
|
||||
align="left"
|
||||
:label="t('view.superAdmin.params.paramName')"
|
||||
prop="name"
|
||||
width="160"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column align="left" :label="t('view.superAdmin.params.paramKey')" prop="key" width="160" />
|
||||
<el-table-column align="left" :label="t('view.superAdmin.params.paramValue')" prop="value" width="160" />
|
||||
<el-table-column align="left" :label="t('view.superAdmin.params.paramKey')" prop="key" width="200" />
|
||||
<el-table-column align="left" :label="t('view.superAdmin.params.paramValue')" prop="value" width="200" />
|
||||
<el-table-column
|
||||
align="left"
|
||||
:label="t('view.superAdmin.params.paramDesc')"
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('general.operations')" :min-width="appStore.operateMinWith" fixed="right">
|
||||
<el-table-column :label="t('general.operations')" :min-width="appStore.operateMinWith" align="left" fixed="right" width="300px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="left"
|
||||
:lable="t('general.operations')"
|
||||
:label="t('general.operations')"
|
||||
min-width="240"
|
||||
>
|
||||
<template #default="scope">
|
||||
|
||||
Reference in New Issue
Block a user