index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. type: 'text',
  96. key: 'postName',
  97. value: '',
  98. label: '所属岗位'
  99. }
  100. ]
  101. })
  102. // 用户基本信息
  103. // let emailChange = false
  104. const baseInfo = ref(JSON.parse(localStorage.getItem('entBaseInfo')) || {})
  105. const query = ref({})
  106. // 获取字典数据以及字段回显
  107. formItems.value.options.forEach(item => {
  108. // if (item.dictTypeName) {
  109. // getDict(item.dictTypeName).then(({ data }) => {
  110. // data = data?.length && data || []
  111. // item.items = data
  112. // })
  113. // }
  114. if (Object.keys(baseInfo).length) {
  115. item.value = baseInfo.value[item.key]
  116. query.value.id = baseInfo.value.id
  117. }
  118. // if (item.key === 'email') {
  119. // item.disabled = checkEmail(item.value)
  120. // emailChange = !item.disabled
  121. // }
  122. })
  123. // 监听store变化
  124. userStore.$subscribe((mutation, state) => {
  125. baseInfo.value = state.baseInfo
  126. })
  127. // 选择文件
  128. const fileInput = ref()
  129. const clicked = ref(false)
  130. const openFileInput = () => {
  131. if (clicked.value) return
  132. clicked.value = true
  133. fileInput.value.click()
  134. clicked.value = false
  135. }
  136. // 上传头像
  137. const handleUploadFile = async (e) => {
  138. const file = e.target.files[0]
  139. if (!file) return
  140. const reader = new FileReader()
  141. reader.readAsDataURL(file)
  142. reader.onload = () => {
  143. selectPic.value = String(reader.result)
  144. isShowCopper.value = true
  145. }
  146. }
  147. const handleHideCopper = (data) => {
  148. isShowCopper.value = false
  149. if (data) {
  150. const { file } = data
  151. if (!file) return
  152. const formData = new FormData()
  153. formData.append('file', file)
  154. uploadFile(formData).then(async ({ data }) => {
  155. if (!data) return
  156. formItems.value.options.find(e => e.key === 'avatar').value = data
  157. })
  158. }
  159. }
  160. // 提交
  161. const handleSubmit = async () => {
  162. const { valid } = await CtFormRef.value.formRef.validate()
  163. if (!valid) return
  164. overlay.value = true
  165. formItems.value.options.forEach(item => {
  166. query.value[item.key] = item.value
  167. })
  168. await saveUserInfo(query.value)
  169. // if (query.value?.email && emailChange) await entUpdateEmail({ email: query.value.email })
  170. setTimeout(async () => {
  171. await userStore.getEnterpriseInfo()
  172. Snackbar.success(t('common.submittedSuccessfully'))
  173. overlay.value = false
  174. }, 1000)
  175. }
  176. </script>
  177. <style scoped lang="scss">
  178. .avatarsBox {
  179. height: 80px;
  180. width: 80px;
  181. position: relative;
  182. cursor: pointer;
  183. margin: 32px;
  184. margin-right: 40px;
  185. .img {
  186. width: 100%;
  187. height: 100%;
  188. }
  189. .mdi {
  190. font-size: 42px;
  191. color: #fff;
  192. }
  193. div {
  194. position: absolute;
  195. top: 50%;
  196. left: 50%;
  197. transform: translate(-50%, -50%);
  198. border-radius: 50%;
  199. }
  200. }
  201. </style>