index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <div class="personal-info-container">
  3. <PageTitle title="个人信息" />
  4. <el-form ref="formRef" :model="formData" :rules="rules" label-position="top" class="info-form">
  5. <div class="form-row">
  6. <el-form-item label="用户ID" prop="userId">
  7. <el-input v-model="formData.userId" placeholder="请输入" />
  8. </el-form-item>
  9. <el-form-item label="手机号码" prop="phone">
  10. <el-input v-model="formData.phone" placeholder="请输入" />
  11. <div class="form-tip">手机号码用于登录账号、重置密码或其他安全认证 <el-button type="danger" link>更换手机号</el-button></div>
  12. </el-form-item>
  13. </div>
  14. <div class="form-row">
  15. <el-form-item label="真实姓名" prop="realName">
  16. <el-input v-model="formData.realName" placeholder="请输入" />
  17. </el-form-item>
  18. <el-form-item label="办公电话" prop="officePhone">
  19. <el-input v-model="formData.officePhone" placeholder="请输入" />
  20. </el-form-item>
  21. </div>
  22. <div class="form-row">
  23. <el-form-item label="性别" prop="gender">
  24. <el-select v-model="formData.gender" placeholder="请选择" style="width: 100%">
  25. <el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value" />
  26. </el-select>
  27. </el-form-item>
  28. <el-form-item label="角色" prop="role">
  29. <el-select v-model="formData.role" placeholder="请选择" style="width: 100%">
  30. <el-option v-for="role in roleList" :key="role.roleId" :label="role.roleName" :value="role.roleId.toString()" />
  31. </el-select>
  32. </el-form-item>
  33. </div>
  34. <div class="form-row">
  35. <el-form-item label="生日" prop="birthday">
  36. <el-date-picker v-model="formData.birthday" type="date" placeholder="请选择日期" style="width: 100%" />
  37. </el-form-item>
  38. <el-form-item label="微信号" prop="wechat">
  39. <el-input v-model="formData.wechat" placeholder="请输入" />
  40. </el-form-item>
  41. </div>
  42. <div class="form-row">
  43. <el-form-item label="邮箱" prop="email">
  44. <el-input v-model="formData.email" placeholder="请输入" />
  45. </el-form-item>
  46. <el-form-item label="所属部门" prop="department">
  47. <el-select v-model="formData.department" placeholder="请选择" style="width: 100%">
  48. <el-option v-for="dept in deptList" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId.toString()" />
  49. </el-select>
  50. </el-form-item>
  51. </div>
  52. <div class="form-row single">
  53. <el-form-item label="所在地区" prop="subDepartment">
  54. <el-input v-model="formData.subDepartment" placeholder="请输入省市区" />
  55. </el-form-item>
  56. </div>
  57. <div class="form-row single">
  58. <el-form-item label="详细地址" prop="address">
  59. <el-input v-model="formData.address" placeholder="请输入" maxlength="50" show-word-limit />
  60. </el-form-item>
  61. </div>
  62. <div class="form-row single">
  63. <el-form-item label="备注" prop="remark">
  64. <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入" maxlength="50" show-word-limit />
  65. </el-form-item>
  66. </div>
  67. <div class="form-actions">
  68. <el-button type="danger" @click="handleSave">保存</el-button>
  69. </div>
  70. </el-form>
  71. </div>
  72. </template>
  73. <script setup lang="ts">
  74. import { ref, reactive, onMounted } from 'vue';
  75. import { ElMessage } from 'element-plus';
  76. import { PageTitle } from '@/components';
  77. import { getCurrentUserInfo, updateContact, getDeptList, getDeptTree, getRoleList } from '@/api/pc/organization';
  78. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  79. const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
  80. const formRef = ref();
  81. const deptList = ref<any[]>([]);
  82. const roleList = ref<any[]>([]);
  83. const formData = reactive({
  84. id: 0,
  85. userId: '',
  86. phone: '',
  87. realName: '',
  88. officePhone: '',
  89. gender: '',
  90. role: '',
  91. birthday: '',
  92. wechat: '',
  93. email: '',
  94. department: '',
  95. subDepartment: '',
  96. address: '',
  97. remark: ''
  98. });
  99. const rules = {
  100. realName: [{ required: true, message: '请输入真实姓名', trigger: 'blur' }],
  101. phone: [{ required: true, message: '请输入手机号码', trigger: 'blur' }]
  102. };
  103. // 获取当前用户信息
  104. const loadUserInfo = async () => {
  105. try {
  106. const res = await getCurrentUserInfo();
  107. if (res.code === 200 && res.data) {
  108. // 映射后端字段到前端字段
  109. formData.id = res.data.id;
  110. formData.userId = res.data.id?.toString() || '';
  111. formData.phone = res.data.phone || '';
  112. formData.realName = res.data.contactName || '';
  113. formData.officePhone = res.data.officePhone || '';
  114. formData.gender = res.data.gender || '';
  115. formData.role = res.data.roleId?.toString() || '';
  116. formData.birthday = res.data.birthday || '';
  117. formData.wechat = res.data.customLoginName || ''; // 微信号映射到customLoginName
  118. formData.email = res.data.email || '';
  119. formData.department = res.data.deptId?.toString() || ''; // 部门ID
  120. formData.subDepartment = res.data.provincialCityCounty || ''; // 省市区
  121. formData.address = res.data.addressDetail || '';
  122. formData.remark = res.data.remark || '';
  123. }
  124. } catch (error) {
  125. console.error('获取用户信息失败:', error);
  126. ElMessage.error('获取用户信息失败');
  127. }
  128. };
  129. const handleSave = async () => {
  130. const valid = await formRef.value?.validate();
  131. if (!valid) return;
  132. try {
  133. // 映射前端字段到后端字段
  134. const data = {
  135. id: formData.id,
  136. contactName: formData.realName,
  137. phone: formData.phone,
  138. officePhone: formData.officePhone,
  139. gender: formData.gender,
  140. roleId: formData.role || undefined,
  141. deptId: formData.department || undefined,
  142. birthday: formData.birthday,
  143. customLoginName: formData.wechat,
  144. email: formData.email,
  145. provincialCityCounty: formData.subDepartment,
  146. addressDetail: formData.address,
  147. remark: formData.remark
  148. };
  149. await updateContact(data);
  150. ElMessage.success('保存成功');
  151. } catch (error) {
  152. console.error('保存失败:', error);
  153. ElMessage.error('保存失败');
  154. }
  155. };
  156. // 加载部门列表
  157. const loadDeptList = async () => {
  158. try {
  159. const res = await getDeptTree();
  160. console.log('部门列表响应:', res);
  161. if (res.code === 200 && res.data) {
  162. deptList.value = res.data;
  163. console.log('部门列表加载成功:', deptList.value);
  164. }
  165. } catch (error) {
  166. console.error('获取部门列表失败:', error);
  167. }
  168. };
  169. // 加载角色列表
  170. const loadRoleList = async () => {
  171. try {
  172. const res = await getRoleList();
  173. if (res.code === 200 && res.data) {
  174. roleList.value = res.data;
  175. }
  176. } catch (error) {
  177. console.error('获取角色列表失败:', error);
  178. }
  179. };
  180. // 页面加载时获取用户信息、部门列表和角色列表
  181. onMounted(async () => {
  182. // 先加载部门和角色列表,再加载用户信息
  183. await Promise.all([loadDeptList(), loadRoleList()]);
  184. await loadUserInfo();
  185. });
  186. </script>
  187. <style scoped lang="scss">
  188. .personal-info-container {
  189. padding: 20px;
  190. background: #fff;
  191. min-height: 100%;
  192. }
  193. .info-form {
  194. max-width: 900px;
  195. .form-row {
  196. display: grid;
  197. grid-template-columns: 1fr 1fr;
  198. gap: 20px 40px;
  199. &.single {
  200. grid-template-columns: 1fr;
  201. }
  202. }
  203. .form-tip {
  204. font-size: 12px;
  205. color: #999;
  206. margin-top: 5px;
  207. }
  208. :deep(.el-form-item__label) {
  209. font-size: 14px;
  210. color: #333;
  211. padding-bottom: 8px;
  212. }
  213. :deep(.el-input__wrapper),
  214. :deep(.el-select__wrapper),
  215. :deep(.el-textarea__inner) {
  216. background: #f5f5f5;
  217. box-shadow: none;
  218. border: none;
  219. }
  220. .form-actions {
  221. margin-top: 30px;
  222. text-align: center;
  223. }
  224. }
  225. </style>