add.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <template>
  2. <div>
  3. <v-card class="pa-5">
  4. <v-timeline align="start" side="end">
  5. <v-timeline-item
  6. v-for="(val, i) in list"
  7. :key="i"
  8. :dot-color="val.color"
  9. :icon="val.icon"
  10. >
  11. <div>
  12. <h2 class="mt-n1 headline font-weight-regular">{{ val.title }}</h2>
  13. <div class="mb-4 desc">{{ val.desc }}</div>
  14. <component :is="val.path" :ref="val.ref" :itemData="itemData"></component>
  15. </div>
  16. </v-timeline-item>
  17. <slot name="timeline"></slot>
  18. </v-timeline>
  19. <div class="text-center mb">
  20. <v-btn class="half-button mr-3" color="primary" variant="outlined" @click="handleCancel()">{{ $t('common.cancel') }}</v-btn>
  21. <v-btn class="half-button" color="primary" :loading="loading" @click="handleSave">{{ $t('common.release') }}</v-btn>
  22. </div>
  23. </v-card>
  24. <!-- 弹窗支付 -->
  25. <confirmPaymentDialog
  26. v-if="showConfirmPaymentDialog"
  27. :cost="payInfo.cost"
  28. :spuId="payInfo.spuId"
  29. :spuName="payInfo.spuName"
  30. :showEnterpriseJump="true"
  31. :showOriginalPrice="true"
  32. :orderType="1"
  33. @paySuccess="paySuccess"
  34. @close="handlePayClose"
  35. ></confirmPaymentDialog>
  36. </div>
  37. </template>
  38. <script setup>
  39. defineOptions({ name: 'enterprise-position-add'})
  40. import { ref } from 'vue'
  41. import { useRouter, useRoute } from 'vue-router'
  42. import { dealDictObjData } from '@/utils/position'
  43. import { saveJobAdvertised, getJobDetails } from '@/api/position'
  44. import baseInfo from './baseInfo.vue'
  45. import jobRequirements from './jobRequirements.vue'
  46. import Snackbar from '@/plugins/snackbar'
  47. import { useI18n } from '@/hooks/web/useI18n'
  48. import { useUserStore } from '@/store/user'
  49. import { createTradeOrder } from '@/api/position'
  50. // 添加只为之后是否需要额外操作
  51. const props = defineProps({
  52. afterAdd: Function,
  53. valid: Function,
  54. isFair: Boolean
  55. })
  56. const { t } = useI18n()
  57. const route = useRoute()
  58. const router = useRouter()
  59. const userStore = useUserStore()
  60. const baseInfoRef = ref()
  61. const jobRequirementsRef = ref()
  62. const loading = ref(false)
  63. const itemData = ref({})
  64. const showConfirmPaymentDialog = ref(false)
  65. const payInfo = ref({})
  66. const list = [
  67. {
  68. color: '#00897B',
  69. icon: 'mdi-numeric-1',
  70. title: t('position.positionInformation'),
  71. desc: '',
  72. path: baseInfo,
  73. ref: baseInfoRef
  74. },
  75. {
  76. color: 'indigo-lighten-2',
  77. icon: 'mdi-numeric-2',
  78. title: t('position.jobRequirements'),
  79. desc: t('position.requirementDesc'),
  80. path: jobRequirements,
  81. ref: jobRequirementsRef
  82. }
  83. ]
  84. let submitParams = {}
  85. // 发布
  86. const handleSave = async () => {
  87. const baseInfo = await baseInfoRef.value[0].getQuery()
  88. if (baseInfo === 'failed') return
  89. const requirement = await jobRequirementsRef.value[0].getQuery()
  90. if (!requirement) return Snackbar.warning('请按要求填写信息')
  91. if (!baseInfo.expireTime && !baseInfo.soFar) {
  92. Snackbar.warning('请选择职位过期时间')
  93. window.scrollTo({ top: 0, behavior: 'smooth' })
  94. return
  95. }
  96. // if (!requirement?.areaId) return Snackbar.warning('请选择工作城市')
  97. if (!baseInfo || !requirement) return Snackbar.warning('请将信息填写完整')
  98. submitParams = Object.assign(baseInfo, requirement, { currency_type: 0, source: props.isFair ? '2' : '0', bizId: props.isFair ? route.params.id : null }) // currency_type: 写死0(人民币) source: 0职位管理|1招聘会
  99. console.log('submitParams', submitParams)
  100. if (route.query && route.query.id) submitParams.id = route.query.id // 有id则为编辑
  101. if (props.valid) {
  102. const { valid } = await props.valid()
  103. if (!valid) {
  104. return
  105. }
  106. }
  107. saveEmit()
  108. }
  109. const saveEmit = async () => {
  110. loading.value = true
  111. try {
  112. const res = await saveJobAdvertised({ ...submitParams, fair: props.isFair ? true : false }) // fair:是否为招聘会职位编辑-必填
  113. // status:99为待支付职位,弹窗支付
  114. if (submitParams?.status && submitParams?.status === '99') {
  115. loading.value = true
  116. // 金额*100,页面展示/100
  117. await createTradeOrder({ spuId: res, spuName: submitParams.name, price: 39900, type: 1 }) // 普通职位type 1
  118. loading.value = false
  119. payInfo.value = { cost: 39900, spuId: res, spuName: submitParams.name }
  120. showConfirmPaymentDialog.value = true
  121. Snackbar.warning('当前可发布职位额度不足,请扫码支付')
  122. return
  123. }
  124. if (props.afterAdd) {
  125. await props.afterAdd(res)
  126. return
  127. }
  128. Snackbar.success(submitParams.id ? t('common.editSuccessMsg') : '发布成功')
  129. handleCancel()
  130. } catch (error) {
  131. console.log('error', error)
  132. // 可发布职位额度不足时,将status设为99重新提交
  133. if (error === '企业额度已超过') {
  134. submitParams.status = '99'
  135. saveEmit()
  136. }
  137. } finally {
  138. loading.value = false
  139. }
  140. }
  141. const paySuccess = async () => {
  142. showConfirmPaymentDialog.value = false
  143. if (props.afterAdd) {
  144. await props.afterAdd(payInfo.value.spuId)
  145. payInfo.value = {}
  146. return
  147. }
  148. payInfo.value = {}
  149. Snackbar.success(submitParams.id ? t('common.editSuccessMsg') : '发布成功')
  150. handleCancel()
  151. }
  152. const handlePayClose = () => {
  153. Snackbar.warning('您已取消支付')
  154. itemData.value = {}
  155. showConfirmPaymentDialog.value = false
  156. router.push({ path: '/recruit/enterprise/position', query: { key: 0 }})
  157. }
  158. // 获取编辑的职位详情
  159. const getPositionDetail = async (id) => {
  160. const data = await getJobDetails({ id })
  161. if (!data && !Object.keys(data).length) return
  162. itemData.value = {...data, ...dealDictObjData({}, data)}
  163. }
  164. // 有id为编辑
  165. if (route.query && route.query.id) {
  166. if (route.query.id) getPositionDetail(route.query.id)
  167. }
  168. // 取消
  169. const handleCancel = () => {
  170. itemData.value = {}
  171. const currentPage = router.currentRoute.value.path
  172. router.push({ path: currentPage.indexOf('jobFair') !== -1 ? '/recruit/enterprise/jobFair' : '/recruit/enterprise/position' })
  173. // 新增职位发布需更新账户信息
  174. if (route.query && !route.query?.id) {
  175. setTimeout(async () => {
  176. await userStore.getEnterpriseUserAccountInfo()
  177. }, 2000)
  178. }
  179. }
  180. </script>
  181. <style scoped lang="scss">
  182. .desc {
  183. font-size: 13px;
  184. color: var(--color-666);
  185. }
  186. </style>
  187. <style lang="scss" scoped>
  188. .mb {
  189. margin-bottom: 100px;
  190. }
  191. </style>