staffDetail.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <script setup lang="ts">
  2. /**
  3. * @description 档案详情
  4. */
  5. defineOptions({ name: 'StaffDetail' })
  6. import { useQuery, useMutation } from '@tanstack/vue-query'
  7. import { getRecordsDetail, editRecordsDetail, generateStaffNum } from '@/api/oa/staffRecords'
  8. import { getConfigDict } from './index'
  9. import { ElRow, FormInstance } from 'element-plus'
  10. // import TechCertificate from './TechCertificate.vue'
  11. import avatarImg from '@/assets/imgs/avatar.jpg'
  12. import DeptSelect from '@/components/DeptSelect/index.vue'
  13. import { createImageViewer } from '@/components/ImageViewer'
  14. import WorkTable from './WorkTable.vue'
  15. import FamilyTable from './familyTable.vue'
  16. import SchoolTable from './SchoolTable.vue'
  17. import moment from 'moment'
  18. const formConfigList = getConfigDict()
  19. const { query } = useRoute()
  20. const { id, type } = query
  21. const formRef = ref<FormInstance>()
  22. const formData = ref({})
  23. let avatar = avatarImg
  24. /**获取员工档案详情 */
  25. useQuery(
  26. ['fetch-staff-detail', id],
  27. async () => {
  28. return await getRecordsDetail({ userId: id })
  29. },
  30. {
  31. onSuccess: (res) => {
  32. formData.value = handleTimeData(res)
  33. // formData.value = res
  34. // if (Array.isArray(formData.value['bysj'])) {
  35. // formData.value['bysj'] = res.bysj.join('-')
  36. // }
  37. avatar = res.avatar ? res.avatar : avatar
  38. }
  39. }
  40. )
  41. // 处理 [2001, 1, 1] 格式的时间数据
  42. const handleTimeData = (dataSource) => {
  43. const keyList = ['birthday', 'bysj', 'cjgzsj', 'yshtqssj', 'htdqs', 'htqdsj', 'rgssj', 'zzsj']
  44. Object.keys(dataSource).forEach((key) => {
  45. if (keyList.includes(key) && Array.isArray(dataSource[key])) {
  46. const dateString = dataSource[key].join('-')
  47. const dateValue = moment(dateString).valueOf()
  48. dataSource[key] = dateValue
  49. }
  50. })
  51. return dataSource
  52. }
  53. /**编辑员工档案详情 */
  54. const { mutate: addUserMutate } = useMutation({
  55. mutationFn: async (values: any) => {
  56. return await editRecordsDetail(values)
  57. },
  58. onSuccess() {
  59. ElMessage({
  60. message: '员工档案修改成功!',
  61. type: 'success'
  62. })
  63. },
  64. onError() {
  65. ElMessage({
  66. message: '员工档案修改失败,请稍后再试!',
  67. type: 'error'
  68. })
  69. }
  70. })
  71. /**生成工号 */
  72. const { mutate: generateStaffNumber } = useMutation({
  73. mutationFn: async () => {
  74. return await generateStaffNum()
  75. },
  76. onSuccess(res) {
  77. formData.value['loginName'] = res
  78. },
  79. onError() {
  80. ElMessage({
  81. message: '工号生成失败!',
  82. type: 'error'
  83. })
  84. }
  85. })
  86. /**表单保存 */
  87. const submitForm = (formEl: FormInstance | undefined) => {
  88. // console.log('formData.value', formData.value)
  89. // return
  90. if (!formEl) return
  91. formEl.validate((valid) => {
  92. if (valid) {
  93. addUserMutate(formData.value)
  94. } else {
  95. return false
  96. }
  97. })
  98. }
  99. /**部门切换时 */
  100. const deptOnChange = (id) => {
  101. formData.value['deptId'] = id
  102. }
  103. /**点击预览 */
  104. const imagePreview = (imgUrl: string) => {
  105. createImageViewer({
  106. zIndex: 99999999,
  107. urlList: [imgUrl]
  108. })
  109. }
  110. /**是否是编辑页面 */
  111. const isEdit = computed(() => {
  112. return type === 'edit'
  113. })
  114. // 修改并保存工作经历
  115. const saveWorkList = (data: any[]) => {
  116. // console.log('data', data)
  117. formData.value['workList'] = data
  118. }
  119. // 修改并保存家庭成员
  120. const saveFamilyList = (data: any[]) => {
  121. // console.log('data', data)
  122. formData.value['familyList'] = data
  123. }
  124. // 修改并保存学习经历
  125. const saveSchoolList = (data: any[]) => {
  126. // console.log('data', data)
  127. formData.value['schoolList'] = data
  128. }
  129. </script>
  130. <template>
  131. <div class="staff-files-wrap">
  132. <div class="staff-name">
  133. <el-image
  134. class="staff-avator"
  135. :src="avatar"
  136. :zoom-rate="1.2"
  137. :max-scale="7"
  138. :min-scale="0.2"
  139. @click="imagePreview(avatar)"
  140. :initial-index="0"
  141. />
  142. <span>{{ formData?.['nickname'] }}员工档案</span>
  143. </div>
  144. <div
  145. v-if="formData && Object.keys(formData)?.length > 0"
  146. :class="isEdit ? 'my-portrait' : 'my-portrait form-unable-edit'"
  147. >
  148. <el-form ref="formRef" :model="formData" label-width="150px" :disabled="!isEdit">
  149. <div class="my-portrait-item" v-for="(item, index) in formConfigList" :key="index">
  150. <div class="title">
  151. <i></i>
  152. <span>{{ item.title }}</span>
  153. </div>
  154. <div class="my-portrait-card">
  155. <ul>
  156. <li v-for="(child, c) in item.children" :key="c">
  157. <el-form-item :label="`${child.title}:`" :prop="child.name">
  158. <el-date-picker
  159. v-if="child.type === 'time'"
  160. v-model="formData[child?.name]"
  161. style="width: 100%"
  162. :placeholder="isEdit ? child.title : ''"
  163. type="date"
  164. format="YYYY-MM-DD"
  165. value-format="x"
  166. />
  167. <DeptSelect
  168. v-if="child.type === 'dept-select'"
  169. v-model="formData['deptId']"
  170. :defaultValue="formData['deptId'] ?? ''"
  171. />
  172. <el-select
  173. v-if="child.type === 'select'"
  174. v-model="formData[child?.name]"
  175. style="width: 100%"
  176. :placeholder="isEdit ? child.title : '-'"
  177. >
  178. <el-option
  179. v-for="opt in child.options"
  180. :key="opt.value"
  181. :label="opt.label"
  182. :value="opt.value"
  183. />
  184. </el-select>
  185. <el-input
  186. v-if="child?.type === undefined"
  187. v-model="formData[child?.name]"
  188. placeholder=""
  189. />
  190. <div v-if="child?.type === 'button'" class="generate-num">
  191. <el-input v-model="formData[child?.name]" placeholder="" :disabled="true" />
  192. <ElButton
  193. v-if="isEdit"
  194. type="primary"
  195. style="width: 70px; height: 30px; margin-left: 10px"
  196. @click="generateStaffNumber()"
  197. >生成工号</ElButton
  198. >
  199. </div>
  200. </el-form-item>
  201. </li>
  202. <li></li>
  203. </ul>
  204. </div>
  205. </div>
  206. <div class="my-portrait-item">
  207. <WorkTable :defaultData="formData['workList']" @onSave="saveWorkList" />
  208. </div>
  209. <div class="my-portrait-item">
  210. <FamilyTable :defaultData="formData['familyList']" @onSave="saveFamilyList" />
  211. </div>
  212. <div class="my-portrait-item">
  213. <SchoolTable :defaultData="formData['schoolList']" @onSave="saveSchoolList" />
  214. </div>
  215. <el-row justify="end">
  216. <el-form-item v-if="isEdit">
  217. <el-button color="#1B80EB" type="primary" @click="submitForm(formRef)">保存</el-button>
  218. </el-form-item>
  219. </el-row>
  220. </el-form>
  221. </div>
  222. </div>
  223. </template>
  224. <style lang="scss" scoped>
  225. .staff-files-wrap {
  226. height: calc(100% - 10px);
  227. padding: 26px 30px;
  228. margin: 40px 0 25px;
  229. overflow: hidden;
  230. background: #fff;
  231. border-radius: 20px;
  232. .staff-name {
  233. display: flex;
  234. justify-content: center;
  235. align-items: center;
  236. span {
  237. display: block;
  238. font-family: 'Microsoft YaHei';
  239. font-size: 32px;
  240. font-weight: bold;
  241. color: #000000;
  242. text-align: center;
  243. }
  244. .staff-avator {
  245. width: 36px;
  246. height: 36px;
  247. margin-right: 12px;
  248. cursor: pointer;
  249. border-radius: 50%;
  250. }
  251. }
  252. .my-portrait {
  253. width: 100%;
  254. height: calc(100% - 40px);
  255. padding: 0 0 10px;
  256. overflow: auto;
  257. .my-portrait-item {
  258. margin-bottom: 20px;
  259. width: 100%;
  260. .title {
  261. display: flex;
  262. align-items: center;
  263. margin-bottom: 8px;
  264. i {
  265. display: block;
  266. width: 16px;
  267. height: 16px;
  268. margin-right: 9px;
  269. background: url('../../../../assets/imgs/OA/mine/star.png') center no-repeat;
  270. background-size: 100%;
  271. }
  272. span {
  273. font-size: 18px;
  274. font-weight: bold;
  275. color: #000000;
  276. }
  277. }
  278. ul {
  279. display: flex;
  280. padding: 20px 40px 0;
  281. background: #f7f8fa;
  282. border-radius: 4px;
  283. flex-wrap: wrap;
  284. justify-content: space-between;
  285. li {
  286. width: calc(33.3% - 40px);
  287. }
  288. }
  289. }
  290. }
  291. .form-unable-edit {
  292. .my-portrait-item {
  293. ul {
  294. background: linear-gradient(90deg, #f2f7ff 0%, rgb(245 249 255 / 0%) 100%);
  295. border: 1px solid #e4e9f1;
  296. }
  297. }
  298. :deep(.el-form) {
  299. .el-input.is-disabled .el-input__wrapper {
  300. background-color: unset;
  301. box-shadow: none;
  302. }
  303. .el-input.is-disabled .el-input__inner {
  304. color: #000000;
  305. -webkit-text-fill-color: #000000;
  306. }
  307. .el-form-item__label {
  308. font-size: 16px;
  309. color: #455773;
  310. }
  311. .el-form-item--default {
  312. margin-bottom: 10px;
  313. }
  314. .el-input__inner {
  315. font-family: 'Microsoft YaHei';
  316. font-size: 16px;
  317. font-weight: 500;
  318. color: #000000;
  319. }
  320. .el-input__suffix {
  321. display: none;
  322. }
  323. }
  324. }
  325. }
  326. .generate-num {
  327. display: flex;
  328. width: 100%;
  329. }
  330. </style>