baseInfo.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <div>
  3. <CtForm ref="formPageRef" :items="items" style="width: 650px;">
  4. <template #positionId="{ item }">
  5. <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
  6. <template v-slot:activator="{ props }">
  7. <textUI
  8. :modelValue="item.value"
  9. :item="item"
  10. v-bind="props"
  11. style="position: relative;"
  12. ></textUI>
  13. </template>
  14. <jobTypeCard class="jobTypeCardBox" :select="[query.positionId].filter(Boolean)" :isSingle="true" @handleJobClick="handleJobClickItem"></jobTypeCard>
  15. </v-menu>
  16. <v-btn v-if="showTemplateBtn" class="ml-3 half-button" color="primary" style="margin-top: 2px;" @click="useJobTemplate(item)">岗位模版</v-btn>
  17. </template>
  18. </CtForm>
  19. </div>
  20. </template>
  21. <script setup>
  22. defineOptions({ name: 'position-add-baseInfo'})
  23. import CtForm from '@/components/CtForm'
  24. import { reactive, ref, watch } from 'vue'
  25. import textUI from '@/components/FormUI/TextInput'
  26. import jobTypeCard from '@/components/jobTypeCard'
  27. import { getRecruitPositionDetails } from '@/api/recruit/enterprise/position'
  28. import Confirm from '@/plugins/confirm'
  29. import Snackbar from '@/plugins/snackbar'
  30. import { useI18n } from '@/hooks/web/useI18n';
  31. const { t } = useI18n()
  32. const props = defineProps({
  33. itemData: Object
  34. })
  35. const getValue = (key) => {
  36. return items.value.options.find(e => e.key === key)
  37. }
  38. const showTemplateBtn = ref(true)
  39. const formPageRef = ref()
  40. let query = reactive({})
  41. const items = ref({
  42. options: [
  43. {
  44. type: 'text',
  45. key: 'name',
  46. value: '',
  47. label: '职位名称 *',
  48. rules: [v => !!v || '请填写职位名称']
  49. },
  50. {
  51. type: 'datePicker',
  52. key: 'expireTime',
  53. value: null,
  54. format: 'YYYY-MM-DD',
  55. label: '到期时间 *',
  56. labelWidth: 120
  57. },
  58. {
  59. slotName: 'positionId',
  60. key: 'positionId',
  61. value: '',
  62. flexStyle: 'mt-5',
  63. labelKey: 'positionName',
  64. label: '职位类型 *',
  65. noParam: true,
  66. readonly: true,
  67. rules: [v => !!v || '请选择职位类型']
  68. },
  69. {
  70. type: 'wangEditor',
  71. key: 'content',
  72. value: '',
  73. label: '岗位职责 *',
  74. maxLength: 5000,
  75. rules: '请填写岗位职责'
  76. },
  77. {
  78. type: 'wangEditor',
  79. key: 'requirement',
  80. value: '',
  81. label: '岗位要求 *',
  82. maxLength: 5000,
  83. rules: '请填写岗位要求'
  84. }
  85. ]
  86. })
  87. // 编辑回显
  88. watch(
  89. () => props.itemData,
  90. (val) => {
  91. if (!Object.keys(val).length) return
  92. items.value.options.forEach(e => {
  93. if (e.labelKey) {
  94. query[e.key] = val[e.key]
  95. e.value = val[e.labelKey]
  96. return
  97. }
  98. if (e.noParam) return
  99. e.value = val[e.key]
  100. })
  101. },
  102. { immediate: true },
  103. { deep: true }
  104. )
  105. // 职位类型
  106. const handleJobClickItem = (list, name) => {
  107. const positionId = getValue('positionId')
  108. if (!list.length) {
  109. delete query.positionId
  110. positionId.value = ''
  111. return
  112. }
  113. showTemplateBtn.value = true
  114. query.positionId = list[0]
  115. positionId.value = name
  116. }
  117. const useJobTemplate = async () => {
  118. if (!query.positionId) return Snackbar.warning('请先选择职位类型')
  119. // 获取职位模板内容-赋值
  120. const res = await getRecruitPositionDetails(query.positionId)
  121. if (!res || !res.content || !res.requirement) {
  122. Snackbar.warning('此职位类型没有可使用的模板!')
  123. showTemplateBtn.value = false
  124. return
  125. }
  126. const content = items.value.options.find(e => e.key === 'content')
  127. const requirement = items.value.options.find(e => e.key === 'requirement')
  128. if ((content && content.value) || (requirement && requirement.value)) {
  129. // 弹窗提示
  130. Confirm(t('common.confirmTitle'), '您确定要放弃目前岗位描述的内容吗?').then(() => {
  131. content.value = res.content
  132. requirement.value = res.requirement
  133. Snackbar.success('模板填充完成!')
  134. })
  135. } else {
  136. // 无内容点击默认填充
  137. if (content) content.value = res.content
  138. if (requirement) requirement.value = res.requirement
  139. Snackbar.success('模板填充完成!')
  140. }
  141. }
  142. const getQuery = async () => {
  143. const { valid } = await formPageRef.value.formRef.validate()
  144. if (!valid) return
  145. const obj = {
  146. hirePrice: 0,
  147. hire: false
  148. }
  149. items.value.options.forEach(e => {
  150. if (e.noParam) return
  151. else obj[e.key] = e.value
  152. })
  153. if (!obj.content) {
  154. Snackbar.warning('请填写岗位职责')
  155. return 'failed'
  156. }
  157. if (!obj.requirement) {
  158. Snackbar.warning('请填写岗位要求')
  159. return 'failed'
  160. }
  161. query = Object.assign(query, obj)
  162. return query
  163. }
  164. defineExpose({
  165. formPageRef,
  166. getQuery
  167. })
  168. </script>
  169. <style scoped lang="scss">
  170. .jobTypeCardBox {
  171. position: absolute;
  172. top: -22px;
  173. left: 0;
  174. }
  175. .calculation {
  176. display: block;
  177. width: 120px;
  178. }
  179. </style>