index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <v-card class="pa-5 card-box d-flex flex-column align-center">
  3. <CtForm ref="CtFormRef" :items="formItems" style="width: 700px;">
  4. <template #avatar="{ item }">
  5. <div style="color: #7a7a7a;">头像</div>
  6. <div class="avatarsBox" @mouseover="showIcon = true" @mouseleave="showIcon = false">
  7. <v-avatar class="elevation-5" size=80 :image="getUserAvatar(item.value, baseInfo?.sex)"></v-avatar>
  8. <div v-show="showIcon" @click="openFileInput" v-bind="$attrs" class="mdi mdi-camera-outline">
  9. <input
  10. type="file"
  11. ref="fileInput"
  12. accept="image/png, image/jpg, image/jpeg"
  13. style="display: none;"
  14. @change="handleUploadFile"
  15. />
  16. </div>
  17. </div>
  18. <div style="font-size: 14px; color: var(--color-999);">只支持JPG、JPEG、PNG类型的图片,大小不超过10M</div>
  19. </template>
  20. </CtForm>
  21. <v-btn class="buttons mt-5" color="primary" @click.stop="handleSubmit">{{ $t('common.save') }}</v-btn>
  22. <v-btn class="mt-3" color="primary" variant="text" to="/recruit/enterprise/staffChangePassword">修改登录密码</v-btn>
  23. </v-card>
  24. <Loading :visible="overlay"></Loading>
  25. <ImgCropper :visible="isShowCopper" :image="selectPic" :cropBoxResizable="true" @submit="handleHideCopper" :aspectRatio="1 / 1" @close="isShowCopper = false"></ImgCropper>
  26. </template>
  27. <script setup>
  28. defineOptions({ name: 'information-setting'})
  29. import { ref } from 'vue'
  30. import { saveUserInfo } from '@/api/enterprise'
  31. import { uploadFile } from '@/api/common'
  32. import { useI18n } from '@/hooks/web/useI18n'
  33. import { getDict } from '@/hooks/web/useDictionaries'
  34. import { useUserStore } from '@/store/user'
  35. import Snackbar from '@/plugins/snackbar'
  36. import { getUserAvatar } from '@/utils/avatar'
  37. // import { checkEmail } from '@/utils/validate'
  38. const { t } = useI18n()
  39. const userStore = useUserStore()
  40. const showIcon = ref(false)
  41. // 图片裁剪
  42. const overlay = ref(false)
  43. const selectPic = ref('')
  44. const isShowCopper = ref(false)
  45. const CtFormRef = ref()
  46. const formItems = ref({
  47. options: [
  48. {
  49. slotName: 'avatar',
  50. key: 'avatar',
  51. value: '',
  52. flexStyle: 'align-center'
  53. },
  54. {
  55. type: 'ifRadio',
  56. key: 'sex',
  57. value: '2',
  58. label: '性别',
  59. width: 90,
  60. dictTypeName: 'menduner_sex',
  61. items: []
  62. },
  63. {
  64. type: 'text',
  65. key: 'name',
  66. value: '',
  67. label: '用户名 *',
  68. rules: [v => !!v || '请输入用户名']
  69. },
  70. {
  71. type: 'phoneNumber',
  72. key: 'phone',
  73. value: '',
  74. label: '手机号码 *',
  75. rules: [v => !!v || '请输入手机号码']
  76. },
  77. {
  78. type: 'text',
  79. key: 'email',
  80. value: '',
  81. label: '电子邮箱',
  82. disabled: true,
  83. // rules: [
  84. // value => {
  85. // if (value) return true
  86. // return '请输入联系邮箱'
  87. // },
  88. // value => {
  89. // if (checkEmail(value)) return true
  90. // return '请输入正确的电子邮箱'
  91. // }
  92. // ]
  93. }
  94. ]
  95. })
  96. // 用户基本信息
  97. // let emailChange = false
  98. const baseInfo = ref(JSON.parse(localStorage.getItem('entBaseInfo')) || {})
  99. const query = ref({})
  100. // 获取字典数据以及字段回显
  101. formItems.value.options.forEach(item => {
  102. if (item.dictTypeName) {
  103. getDict(item.dictTypeName).then(({ data }) => {
  104. data = data?.length && data || []
  105. item.items = data
  106. })
  107. }
  108. if (Object.keys(baseInfo).length) {
  109. item.value = baseInfo.value[item.key]
  110. query.value.id = baseInfo.value.id
  111. }
  112. // if (item.key === 'email') {
  113. // item.disabled = checkEmail(item.value)
  114. // emailChange = !item.disabled
  115. // }
  116. })
  117. // 监听store变化
  118. userStore.$subscribe((mutation, state) => {
  119. baseInfo.value = state.baseInfo
  120. })
  121. // 选择文件
  122. const fileInput = ref()
  123. const clicked = ref(false)
  124. const openFileInput = () => {
  125. if (clicked.value) return
  126. clicked.value = true
  127. fileInput.value.click()
  128. clicked.value = false
  129. }
  130. // 上传头像
  131. const handleUploadFile = async (e) => {
  132. const file = e.target.files[0]
  133. if (!file) return
  134. const reader = new FileReader()
  135. reader.readAsDataURL(file)
  136. reader.onload = () => {
  137. selectPic.value = String(reader.result)
  138. isShowCopper.value = true
  139. }
  140. }
  141. const handleHideCopper = (data) => {
  142. isShowCopper.value = false
  143. if (data) {
  144. const { file } = data
  145. if (!file) return
  146. const formData = new FormData()
  147. formData.append('file', file)
  148. uploadFile(formData).then(async ({ data }) => {
  149. if (!data) return
  150. formItems.value.options.find(e => e.key === 'avatar').value = data
  151. })
  152. }
  153. }
  154. // 提交
  155. const handleSubmit = async () => {
  156. const { valid } = await CtFormRef.value.formRef.validate()
  157. if (!valid) return
  158. overlay.value = true
  159. formItems.value.options.forEach(item => {
  160. query.value[item.key] = item.value
  161. })
  162. await saveUserInfo(query.value)
  163. // if (query.value?.email && emailChange) await entUpdateEmail({ email: query.value.email })
  164. setTimeout(async () => {
  165. await userStore.getEnterpriseInfo()
  166. Snackbar.success(t('common.submittedSuccessfully'))
  167. overlay.value = false
  168. }, 1000)
  169. }
  170. </script>
  171. <style scoped lang="scss">
  172. .avatarsBox {
  173. height: 80px;
  174. width: 80px;
  175. position: relative;
  176. cursor: pointer;
  177. margin: 32px;
  178. margin-right: 40px;
  179. .img {
  180. width: 100%;
  181. height: 100%;
  182. }
  183. .mdi {
  184. font-size: 42px;
  185. color: #fff;
  186. }
  187. div {
  188. position: absolute;
  189. top: 50%;
  190. left: 50%;
  191. transform: translate(-50%, -50%);
  192. border-radius: 50%;
  193. }
  194. }
  195. </style>