|
@@ -1,11 +1,154 @@
|
|
|
<template>
|
|
|
- <div>个人信息设置</div>
|
|
|
+ <v-card class="pa-5 card-box d-flex flex-column align-center">
|
|
|
+ <CtForm ref="CtFormRef" :items="formItems" style="width: 700px;">
|
|
|
+ <template #avatar="{ item }">
|
|
|
+ <div class="avatarsBox" @mouseover="showIcon = true" @mouseleave="showIcon = false">
|
|
|
+ <v-avatar class="elevation-5" size=80 :image="item.value || 'https://minio.citupro.com/dev/menduner/7.png'"></v-avatar>
|
|
|
+ <div v-show="showIcon" @click="openFileInput" v-bind="$attrs" class="mdi mdi-camera-outline">
|
|
|
+ <input
|
|
|
+ type="file"
|
|
|
+ ref="fileInput"
|
|
|
+ accept="image/png, image/jpg, image/jpeg"
|
|
|
+ style="display: none;"
|
|
|
+ @change="handleUploadFile"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </CtForm>
|
|
|
+ <v-btn class="buttons mt-5" color="primary" @click.stop="handleSubmit">提 交</v-btn>
|
|
|
+ </v-card>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
defineOptions({ name: 'information-setting'})
|
|
|
+import { ref } from 'vue'
|
|
|
+import { saveUserInfo } from '@/api/enterprise'
|
|
|
+import { uploadFile } from '@/api/common'
|
|
|
+import { useI18n } from '@/hooks/web/useI18n'
|
|
|
+import { getDict } from '@/hooks/web/useDictionaries'
|
|
|
+import { useUserStore } from '@/store/user'
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+const userStore = useUserStore()
|
|
|
+const showIcon = ref(false)
|
|
|
+const CtFormRef = ref()
|
|
|
+const formItems = ref({
|
|
|
+ options: [
|
|
|
+ {
|
|
|
+ slotName: 'avatar',
|
|
|
+ key: 'avatar',
|
|
|
+ value: ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'ifRadio',
|
|
|
+ key: 'sex',
|
|
|
+ value: '2',
|
|
|
+ label: '性别',
|
|
|
+ width: 90,
|
|
|
+ dictTypeName: 'system_user_sex',
|
|
|
+ items: []
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'name',
|
|
|
+ value: '',
|
|
|
+ label: '用户名 *',
|
|
|
+ rules: [v => !!v || '请输入用户名']
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'phone',
|
|
|
+ value: '',
|
|
|
+ label: '手机号码 *',
|
|
|
+ rules: [v => !!v || '请输入手机号码']
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'email',
|
|
|
+ value: '',
|
|
|
+ label: '电子邮箱'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 用户基本信息
|
|
|
+const baseInfo = ref(JSON.parse(localStorage.getItem('baseInfo')) || {})
|
|
|
+const query = ref({})
|
|
|
+// 获取字典数据以及字段回显
|
|
|
+formItems.value.options.forEach(item => {
|
|
|
+ if (item.dictTypeName) {
|
|
|
+ getDict(item.dictTypeName).then(({ data }) => {
|
|
|
+ data = data?.length && data || []
|
|
|
+ item.items = data
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (Object.keys(baseInfo).length) {
|
|
|
+ item.value = baseInfo.value[item.key]
|
|
|
+ query.value.id = baseInfo.value.id
|
|
|
+ }
|
|
|
+})
|
|
|
+// 监听store变化
|
|
|
+userStore.$subscribe((mutation, state) => {
|
|
|
+ baseInfo.value = state.baseInfo
|
|
|
+})
|
|
|
+
|
|
|
+// 选择文件
|
|
|
+const fileInput = ref()
|
|
|
+const clicked = ref(false)
|
|
|
+const openFileInput = () => {
|
|
|
+ if (clicked.value) return
|
|
|
+ clicked.value = true
|
|
|
+ fileInput.value.click()
|
|
|
+ clicked.value = false
|
|
|
+}
|
|
|
+
|
|
|
+// 上传头像
|
|
|
+const handleUploadFile = async (e) => {
|
|
|
+ const file = e.target.files[0]
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('file', file)
|
|
|
+ const { data } = await uploadFile(formData)
|
|
|
+ if (!data) return
|
|
|
+ formItems.value.options.find(e => e.key === 'avatar').value = data
|
|
|
+}
|
|
|
+
|
|
|
+// 提交
|
|
|
+const handleSubmit = async () => {
|
|
|
+ const { valid } = await CtFormRef.value.formRef.validate()
|
|
|
+ if (!valid) return
|
|
|
+ formItems.value.options.forEach(item => {
|
|
|
+ query.value[item.key] = item.value
|
|
|
+ })
|
|
|
+ await saveUserInfo(query.value)
|
|
|
+ Snackbar.success(t('common.submittedSuccessfully'))
|
|
|
+ await userStore.getEnterpriseInfo()
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
-
|
|
|
+.avatarsBox {
|
|
|
+ height: 80px;
|
|
|
+ width: 80px;
|
|
|
+ position: relative;
|
|
|
+ cursor: pointer;
|
|
|
+ margin: 32px;
|
|
|
+ margin-right: 40px;
|
|
|
+ .img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ .mdi {
|
|
|
+ font-size: 42px;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ div {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|