educationExp.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <!-- -->
  2. <template>
  3. <CtForm ref="CtFormRef" :items="items" style="width: 100%;"></CtForm>
  4. </template>
  5. <script setup>
  6. defineOptions({ name: 'resumeAnalysis-educationExp'})
  7. import { debounce } from 'lodash'
  8. import { getDict } from '@/hooks/web/useDictionaries'
  9. import { ref, reactive, watch } from 'vue'
  10. import { schoolSearchByName, schoolMajorByName } from '@/api/recruit/personal/resume'
  11. import { dealCanBeInputtedSave, dealCanBeInputtedValueAndLabel } from '@/utils/getText'
  12. const props = defineProps({
  13. id: {
  14. type: String,
  15. default: ''
  16. },
  17. data: {
  18. type: Object,
  19. default: () => {}
  20. }
  21. })
  22. const CtFormRef = ref()
  23. const dictItemsObj = reactive({})
  24. // 学校下拉列表
  25. const schoolNameInput = ref('')
  26. const getSchoolListData = async (name) => {
  27. const item = items.value.options.find(e => e.key === 'schoolId')
  28. if (!item) return
  29. if (item.items?.length && (schoolNameInput.value === name)) return // 防抖
  30. item[item.itemTextName] = schoolNameInput.value = name
  31. if (name === null || name === '') { item.items = [] }
  32. else {
  33. const data = await schoolSearchByName({ name })
  34. item.items = data
  35. }
  36. }
  37. const debouncedCallbackSchool = debounce(newValue => {
  38. if (!newValue) return
  39. getSchoolListData(newValue)
  40. }, 500)
  41. // 专业下拉列表
  42. const majorNameInput = ref('')
  43. const getMajorListData = async (name) => {
  44. const item = items.value.options.find(e => e.key === 'majorId')
  45. if (name === '') { // 此接口不支持传空值
  46. item.items = []
  47. return
  48. }
  49. if (item.items?.length && (majorNameInput.value === name)) return // 防抖
  50. item[item.itemTextName] = majorNameInput.value = name
  51. if (name === null || name === '') { item.items = [] }
  52. else {
  53. const data = await schoolMajorByName({ name })
  54. item.items = data
  55. }
  56. }
  57. const debouncedCallbackMajor = debounce(newValue => {
  58. getMajorListData(newValue)
  59. }, 500)
  60. const items = ref({
  61. options: [
  62. {
  63. type: 'combobox',
  64. key: 'schoolId',
  65. value: null,
  66. default: null,
  67. label: '学校名称 *',
  68. col: 6,
  69. outlined: true,
  70. clearable: true,
  71. canBeInputted: true, //
  72. itemTextName: 'schoolName',
  73. itemText: 'value',
  74. itemValue: 'key',
  75. rules: [v => !!v || '请选择学校名称'],
  76. search: debouncedCallbackSchool,
  77. items: []
  78. },
  79. {
  80. type: 'combobox',
  81. key: 'majorId',
  82. value: null,
  83. default: null,
  84. label: '所学专业 *',
  85. col: 6,
  86. outlined: true,
  87. clearable: true,
  88. canBeInputted: true, //
  89. itemTextName: 'major',
  90. itemText: 'nameCn',
  91. itemValue: 'id',
  92. rules: [v => !!v || '请选择所学专业'],
  93. search: debouncedCallbackMajor,
  94. items: []
  95. },
  96. {
  97. type: 'autocomplete',
  98. key: 'educationType',
  99. value: null,
  100. default: null,
  101. label: '学历 *',
  102. col: 6,
  103. outlined: true,
  104. itemText: 'label',
  105. itemValue: 'value',
  106. rules: [v => !!v || '请选择学历'],
  107. items: []
  108. },
  109. {
  110. type: 'autocomplete',
  111. key: 'educationSystemType',
  112. value: null,
  113. default: null,
  114. label: '学制类型 *',
  115. col: 6,
  116. outlined: true,
  117. itemText: 'label',
  118. itemValue: 'value',
  119. rules: [v => !!v || '请选择学制类型'],
  120. items: dictItemsObj.educationSystemType,
  121. },
  122. {
  123. type: 'datePicker',
  124. key: 'startTime',
  125. mode: 'month', // 时间类型 year month date time
  126. value: null,
  127. default: '2014-01',
  128. format: 'YYYY/MM',
  129. labelWidth: 80,
  130. label: '开始时间 *',
  131. defaultValue: new Date(2014, 1),
  132. disabledFutureDates: true,
  133. col: 6,
  134. rules: [v => !!v || '请选择起始时间']
  135. },
  136. {
  137. type: 'datePicker',
  138. key: 'endTime',
  139. mode: 'month', // 时间类型 year month date time
  140. value: null,
  141. default: '2018-01',
  142. format: 'YYYY/MM',
  143. defaultValue: new Date(2018, 1),
  144. disabledFutureDates: true,
  145. labelWidth: 80,
  146. label: '结束时间 *',
  147. col: 6,
  148. rules: [v => !!v || '请选择结束时间']
  149. },
  150. {
  151. type: 'textarea',
  152. key: 'content',
  153. value: null,
  154. default: null,
  155. rows: 5,
  156. flexStyle: 'mt-5',
  157. resize: true,
  158. counter: 1600,
  159. label: '在校经历',
  160. outlined: true
  161. },
  162. ]
  163. })
  164. watch(
  165. () => props.data,
  166. (newVal) => {
  167. if (newVal && Object.keys(newVal)) {
  168. schoolNameInput.value = newVal.schoolName || null
  169. majorNameInput.value = newVal.major || null
  170. //
  171. items.value.options.forEach(e => {
  172. if (newVal[e.key]) e.value = newVal[e.key]
  173. else e.value = e.default || null
  174. if (e.canBeInputted) { // 特殊处理可输入下拉框
  175. dealCanBeInputtedValueAndLabel(e, newVal)
  176. }
  177. })
  178. }
  179. },
  180. { immediate: true },
  181. )
  182. const submit = async () => {
  183. const { valid } = await CtFormRef.value.formRef.validate()
  184. if (!valid) return { id: props.id, data: null}
  185. const obj = {}
  186. items.value.options.forEach(e => {
  187. if (e.canBeInputted) { // 特殊处理可输入下拉框
  188. dealCanBeInputtedSave(e, obj)
  189. }
  190. else obj[e.key] = e.value
  191. })
  192. return { id: props.id, data: obj}
  193. }
  194. defineExpose({
  195. id: props.id,
  196. submit
  197. })
  198. // 左侧加mr
  199. items.value.options.forEach((e, index) => {
  200. if (((index + 2) % 2 === 0) && Boolean(e.col) && e.col !== 12) e.flexStyle = 'mr-3'
  201. })
  202. // 获取字典内容
  203. const dictList = [
  204. { type: 'menduner_education_type', key: 'educationType' },
  205. { type: 'menduner_education_system_type', key: 'educationSystemType' }
  206. ]
  207. const getDictData = async (obj) => {
  208. const item = items.value.options.find(e => e.key === obj.key)
  209. if (item) { // && !item.items?.length
  210. const { data } = await getDict(obj.type)
  211. item.items = data || []
  212. dictItemsObj[obj.key] = data || []
  213. }
  214. }
  215. const getOptions = () => {
  216. dictList.forEach(obj => getDictData(obj))
  217. }
  218. getOptions()
  219. </script>
  220. <style lang="scss" scoped>
  221. </style>