register.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <template>
  2. <div class="login-box py-5">
  3. <v-card class="pa-5" :class="isMobile? 'mobileBox' : 'default-width'" :elevation="isMobile? '0' : '3'">
  4. <!-- 标题 -->
  5. <div class="mt-3" v-if="!isMobile">
  6. <v-btn v-if="pageType !== 'noLoginToRegister'" color="primary" variant="text" @click="router.push('/recruitHome')">{{ `<< 回到首页` }}</v-btn>
  7. <div v-else style="height: 30px;"></div>
  8. </div>
  9. <!-- 表单 -->
  10. <div class="CtFormClass" :style="{width: isMobile ? '' : '600px'}">
  11. <div v-if="failureReason" class="mb-8" style="color: red;">
  12. <span class="mr-5">《审核不通过》</span>
  13. <span>原因:{{ failureReason }}</span>
  14. </div>
  15. <!-- 标题 -->
  16. <div class="mb-10" :class="isMobile ? 'mt-0': 'mt-n8'" style="font-size: 22px; font-weight: bold; text-align: center;">{{ $t('enterprise.registeringNewEnterprise') }}</div>
  17. <CtForm ref="CtFormRef" :items="formItems" style="width: 100%;">
  18. <template #businessLicense>
  19. <!-- 上传照片 -->
  20. <div class="d-flex flex-column mb-6">
  21. <div style="color: var(--color-999);">
  22. <span v-if="!prepareValue" class="mr-1" style="color: var(--v-error-base);">*</span>
  23. <span>上传营业执照</span>
  24. <span>支持jpg、jpeg、png格式,图片大小不得超过10M</span>
  25. </div>
  26. <div class="file-box">
  27. <Img
  28. class="mt-3"
  29. tips="上传图片"
  30. :value="licenseUrl"
  31. :showSnackbar="false"
  32. @imgClick="showPreview = !showPreview"
  33. :showCursor="true"
  34. @success="handleUploadImg"
  35. @delete="handleDeleteImg"
  36. ></Img>
  37. </div>
  38. </div>
  39. </template>
  40. </CtForm>
  41. <div class="note">
  42. <h4>注意事项:</h4>
  43. <span>企业名称为对外展示的企业名称,建议填写公司营业执照上的名称,请区分总公司和分公司</span>
  44. </div>
  45. </div>
  46. <div class="text-center">
  47. <!-- 提交 -->
  48. <v-btn
  49. :loading="loginLoading"
  50. color="primary" class="white--text my-8" min-width="350"
  51. @click="handleCommit"
  52. >
  53. {{ $t('common.complete') }}
  54. </v-btn>
  55. </div>
  56. </v-card>
  57. <PreviewImg v-if="showPreview" :current="current" :list="[licenseUrl]" @close="showPreview = !showPreview"></PreviewImg>
  58. <Loading :visible="loading"></Loading>
  59. </div>
  60. </template>
  61. <script setup>
  62. defineOptions({name: 'enterprise-enterpriseRegister-register'})
  63. import CtForm from '@/components/CtForm'
  64. import Snackbar from '@/plugins/snackbar'
  65. import { useI18n } from '@/hooks/web/useI18n'
  66. import { useRouter } from 'vue-router'; const router = useRouter()
  67. import { enterpriseRegisterApply } from '@/api/personal/user'
  68. import { onMounted, ref, computed } from 'vue';
  69. import { checkEmail } from '@/utils/validate'
  70. import { getBusinessLicenseOCR } from '@/api/common'
  71. const { t } = useI18n()
  72. const CtFormRef = ref()
  73. const loginLoading = ref(false)
  74. // 图片预览
  75. const loading = ref(false)
  76. const showPreview = ref(false)
  77. const current = ref(0)
  78. const email = localStorage.getItem('loginAccount') || ''
  79. // 组件挂载后添加事件监听器
  80. const isMobile = ref(false)
  81. onMounted(() => {
  82. const userAgent = navigator.userAgent
  83. isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
  84. })
  85. import { useRoute } from 'vue-router'; const route = useRoute()
  86. const pageType = route?.query?.type || '' // type: noLoginToRegister:->登录页注册企业
  87. // 是否筹建中
  88. const isPrepareChange = () => {
  89. const code = formItems.value.options.find(e => e.key === 'code')
  90. if (code) {
  91. code.label = prepareValue.value ? '企业统一社会信用代码' : '企业统一社会信用代码 *'
  92. code.rules = prepareValue.value ? [] : [v => !!v || '请输入企业统一社会信用代码']
  93. }
  94. }
  95. const handleSecondConfirm = () => {
  96. const obj = formItems.value.options.find(e => e.key === 'passwordConfirm')
  97. obj.type = obj.type === 'password' ? 'text' : 'password'
  98. obj.appendInnerIcon = obj.type === 'password' ? 'mdi-eye-off-outline' : 'mdi-eye-outline'
  99. }
  100. const handlePassword = () => {
  101. const obj = formItems.value.options.find(e => e.key === 'password')
  102. obj.type = obj.type === 'password' ? 'text' : 'password'
  103. obj.appendInnerIcon = obj.type === 'password' ? 'mdi-eye-off-outline' : 'mdi-eye-outline'
  104. }
  105. const formItems = ref({
  106. options: [
  107. {
  108. type: 'ifRadio',
  109. key: 'prepare',
  110. value: false,
  111. label: '是否筹建中 *',
  112. width: 100,
  113. items: [
  114. { label: '是', value: true },
  115. { label: '否', value: false }
  116. ],
  117. change: isPrepareChange
  118. },
  119. {
  120. slotName: 'businessLicense'
  121. },
  122. {
  123. type: 'text',
  124. key: 'name',
  125. value: '',
  126. label: '企业名称(需要与营业执照完全一致)*',
  127. counter: 50,
  128. rules: [v => !!v || '请输入企业名称']
  129. },
  130. {
  131. type: 'text',
  132. key: 'code',
  133. value: '',
  134. counter: 18,
  135. label: '企业统一社会信用代码 *',
  136. rules: [v => !!v || '请输入企业统一社会信用代码']
  137. },
  138. {
  139. type: 'text',
  140. key: 'contactName',
  141. value: '',
  142. label: '联系人姓名 *',
  143. rules: [v => !!v || '请输入联系人姓名']
  144. },
  145. {
  146. type: 'phoneNumber',
  147. key: 'phone',
  148. value: '',
  149. label: '联系电话 *',
  150. rules: [v => !!v || '请输入联系电话']
  151. },
  152. {
  153. type: 'text',
  154. key: 'email',
  155. value: email ? email : '',
  156. label: '企业邮箱 *',
  157. rules: [
  158. value => {
  159. if (value) return true
  160. return '请输入企业邮箱'
  161. },
  162. value => {
  163. if (checkEmail(value)) return true
  164. return '请输入正确的企业邮箱'
  165. }
  166. ]
  167. },
  168. {
  169. type: 'password',
  170. key: 'password',
  171. value: '',
  172. appendInnerIcon: 'mdi-eye-off-outline',
  173. label: '账户登录密码 *',
  174. placeholder: '请输入账户登录密码',
  175. appendInnerClick: handlePassword,
  176. rules: [
  177. value => {
  178. if (value) return true
  179. return '请输入账户登录密码'
  180. },
  181. value => {
  182. if (/^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16}$/.test(value)) return true
  183. return '请输入8-16位数由数字、大小写字母组成的密码'
  184. }
  185. ]
  186. },
  187. {
  188. type: 'password',
  189. key: 'passwordConfirm',
  190. value: '',
  191. appendInnerIcon: 'mdi-eye-off-outline',
  192. label: '请再次输入账户登录密码 *',
  193. placeholder: '请再次输入账户登录密码',
  194. appendInnerClick: handleSecondConfirm,
  195. rules: [
  196. value => {
  197. if (value) return true
  198. return '请再次输入密码'
  199. },
  200. value => {
  201. if (value === formItems.value.options.find(e => e.key === 'password').value) return true
  202. return '两次输入密码不一致'
  203. }
  204. ]
  205. },
  206. {
  207. type: 'textarea',
  208. key: 'description',
  209. value: '',
  210. clearable: true,
  211. resize: true,
  212. counter: 500,
  213. rows: 2,
  214. label: '备注/说明',
  215. },
  216. ]
  217. })
  218. // 是否筹建中
  219. const prepareValue = computed(() => {
  220. return formItems.value.options.find(e => e.key === 'prepare').value
  221. })
  222. // 识别营业执照图片
  223. const business = ref({})
  224. const getOcr = async () => {
  225. loading.value = true
  226. try {
  227. const data = await getBusinessLicenseOCR(licenseUrl.value)
  228. if (data && Object.keys(data).length) {
  229. formItems.value.options.find(e => e.key === 'code').value = data.code
  230. formItems.value.options.find(e => e.key === 'name').value = data.name
  231. business.value = data
  232. }
  233. } finally {
  234. loading.value = false
  235. }
  236. }
  237. // 上传
  238. let licenseUrl = ref('')
  239. const handleUploadImg = (url) => {
  240. licenseUrl.value = url
  241. if (licenseUrl.value) getOcr()
  242. }
  243. const handleDeleteImg = () => {
  244. licenseUrl.value = ''
  245. business.value = {}
  246. formItems.value.options.find(e => e.key === 'code').value = ''
  247. formItems.value.options.find(e => e.key === 'name').value = ''
  248. }
  249. // 提交 企业注册
  250. const handleCommit = async () => {
  251. const { valid } = await CtFormRef.value.formRef.validate()
  252. if (!valid) return
  253. const businessLicenseUrl = licenseUrl.value;
  254. if (!prepareValue.value && !businessLicenseUrl) return Snackbar.warning('请上传营业执照图片')
  255. const params = {
  256. businessLicenseUrl,
  257. prepare: prepareValue.value,
  258. }
  259. formItems.value.options.forEach(e => { params[e.key] = e.value })
  260. if (business.value && Object.keys(business.value).length) params.ocr = business.value
  261. await enterpriseRegisterApply(params)
  262. localStorage.removeItem('loginAccount')
  263. Snackbar.success(t('common.submittedSuccessfully'))
  264. router.push({ path: '/recruit/entRegister/inReview' })
  265. }
  266. // 不通过的企业注册申请 重新发起
  267. const failureReason = ref('')
  268. const info = JSON.parse(localStorage.getItem('userApplyInfo'))
  269. // 审核不通过的数据回显
  270. if (info && Object.keys(info).length && info.status === '2') {
  271. failureReason.value = info?.reason || ''
  272. licenseUrl.value = info?.businessLicenseUrl
  273. // prepareValue.value = info?.prepare || false
  274. formItems.value.options.forEach(e => {
  275. if (e.key === 'passwordConfirm') e.value = info.password
  276. else e.value = info[e.key]
  277. })
  278. isPrepareChange()
  279. }
  280. </script>
  281. <style lang="scss" scoped>
  282. .CtFormClass {
  283. margin: 0 auto;
  284. }
  285. .note {
  286. color: var(--color-666);
  287. font-size: 14px;
  288. line-height: 32px;
  289. }
  290. .login-box {
  291. position: relative;
  292. width: 100%;
  293. height: 100%;
  294. background-image: url('https://www.mendunerhr.com/images/userfiles/92d7e4a755e2428b94aab3636d5047f3/images/recruitment/adImages/2018/11/1920x940.jpg');
  295. background-size: cover;
  296. }
  297. .file-box {
  298. display: flex;
  299. flex-wrap: wrap; /* 允许换行 */
  300. width: 100%; /* 设置容器宽度 */
  301. .file-item {
  302. height: 80px;
  303. width: 100px;
  304. border-radius: 5px;
  305. margin-right: 8px;
  306. margin-top: 12px;
  307. // border: 1px solid rgb(188, 188, 188);
  308. border: 1px solid rgba(188, 188, 188, 0.5);
  309. }
  310. .file-input-box {
  311. position: relative;
  312. border: 1px solid rgb(188, 188, 188);
  313. cursor: pointer;
  314. .icon {
  315. position: absolute;
  316. top: 45%;
  317. left: 50%;
  318. transform: translate(-50%, -50%);
  319. color: var(--color-999);
  320. }
  321. }
  322. // 验证是否为空
  323. .verifyAct {
  324. color: var(--v-error-base);
  325. border: 1px solid var(--v-error-base);
  326. .icon { color: var(--v-error-base); }
  327. }
  328. }
  329. .PrepareBox {
  330. margin-top: 74px;
  331. margin-left: 32px;
  332. }
  333. .mobileBox {
  334. width: calc(100vw - 16px);
  335. margin: 0 auto;
  336. .resume-header {
  337. margin-bottom: 12px;
  338. }
  339. }
  340. </style>