| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /**
- * 临时工招聘:条件展示 / 可用人员映射 / 提交载荷
- */
- import { formatWorkDurationUnit } from '@/utils/draft.js'
- function pick(raw, camel, snake) {
- if (!raw || typeof raw !== 'object') return null
- if (raw[camel] != null && raw[camel] !== '') return raw[camel]
- if (raw[snake] != null && raw[snake] !== '') return raw[snake]
- return null
- }
- /** 同步工种头统计与勾选样式 */
- export function syncRecruitGroupMeta(group) {
- if (!group) return
- const workers = group.workers || []
- let selectedCount = 0
- for (let i = 0; i < workers.length; i++) {
- const w = workers[i]
- if (w.selected) selectedCount += 1
- w.checkClass = w.selected ? 'recruit-check recruit-check--on' : 'recruit-check'
- }
- group.selectedCount = selectedCount
- group.countText = `${selectedCount}/${group.needCount || 0}`
- group.chevronText = group.expanded ? '▼' : '▶'
- }
- /**
- * 搜索条件
- * 需求人数:工种*人数(如 搬运*10人,分拣*5人)
- * 工作天数:工种*{x}天/月(月结用月,其余用天)
- */
- export function buildRecruitCriteria(workerGroups = []) {
- const groups = Array.isArray(workerGroups) ? workerGroups.filter((g) => g && g.workType) : []
- const criteriaTypes = groups.map((g) => g.workType).filter(Boolean)
- const needParts = []
- const dayParts = []
- const locations = []
- groups.forEach((g) => {
- const type = String(g.workType || '').trim()
- if (!type) return
- const count = Number(g.workerCount)
- if (g.workerCount != null && g.workerCount !== '' && !Number.isNaN(count) && count > 0) {
- needParts.push(`${type}*${count}人`)
- }
- const days = Number(g.workDays)
- if (g.workDays != null && g.workDays !== '' && !Number.isNaN(days)) {
- dayParts.push(`${type}*${days}${formatWorkDurationUnit(g.settlementMode)}`)
- }
- if (g.workLocation && locations.indexOf(g.workLocation) < 0) {
- locations.push(g.workLocation)
- }
- })
- return {
- jobTypeText: criteriaTypes.join(',') || '—',
- needCountText: needParts.length ? needParts.join(',') : '—',
- locationText: locations.join(',') || '—',
- daysText: dayParts.length ? dayParts.join(',') : '—'
- }
- }
- /** POST available 查询体 */
- export function buildAvailableQueries(workerGroups = []) {
- const groups = Array.isArray(workerGroups) ? workerGroups : []
- const queries = []
- const seen = {}
- for (let i = 0; i < groups.length; i++) {
- const g = groups[i]
- const jobType = String((g && g.workType) || '').trim()
- if (!jobType || seen[jobType]) continue
- seen[jobType] = true
- const workLocation = String((g && g.workLocation) || '').trim()
- const item = { jobType, job_type: jobType }
- if (workLocation) {
- item.workLocation = workLocation
- item.work_location = workLocation
- }
- queries.push(item)
- }
- return queries
- }
- /**
- * 可用列表仅脱敏时:按 worker_id 生成可过校验的明文(MVP Mock)
- * 接口若返回 mobile / id_card_no 则优先使用
- */
- export function resolveWorkerSubmitIdentity(worker = {}) {
- const mobilePlain = String(pick(worker, 'mobile', 'mobile') || pick(worker, 'phone', 'phone') || '').trim()
- const idCardPlain = String(
- pick(worker, 'idCardNo', 'id_card_no') || pick(worker, 'idCard', 'idCard') || ''
- ).trim().toUpperCase()
- if (/^1[3-9]\d{9}$/.test(mobilePlain) && idCardPlain.length === 18) {
- return { mobile: mobilePlain, idCardNo: idCardPlain }
- }
- const wid = Number(pick(worker, 'workerId', 'worker_id') || 0) || 0
- const mobile = /^1[3-9]\d{9}$/.test(mobilePlain)
- ? mobilePlain
- : `138${String(10000000 + (wid % 10000000)).slice(-8)}`
- const idCardNo = idCardPlain.length === 18 ? idCardPlain : buildMockIdCard(wid || 1)
- return { mobile, idCardNo }
- }
- /** 生成通过校验的 18 位身份证(仅 Mock 提交用) */
- function buildMockIdCard(seed) {
- const n = Math.abs(Number(seed) || 1) % 10000
- const base = `11010119900101${String(1000 + n).slice(-3)}`
- const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
- const codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
- let sum = 0
- for (let i = 0; i < 17; i++) sum += Number(base.charAt(i)) * weights[i]
- return base + codes[sum % 11]
- }
- /**
- * available 接口 → 弹层工种分组
- * @param {object} raw ThirdPartyWorkerGroupResponse
- * @param {Array} workerGroups 草稿工种(取需求人数)
- */
- export function mapAvailableToRecruitGroups(raw = {}, workerGroups = []) {
- const needMap = {}
- ;(Array.isArray(workerGroups) ? workerGroups : []).forEach((g) => {
- if (!g || !g.workType) return
- needMap[g.workType] = Number(g.workerCount) > 0 ? Number(g.workerCount) : 0
- })
- const apiGroups = (raw && (raw.groups || raw.Groups)) || []
- const list = Array.isArray(apiGroups) ? apiGroups : []
- const matchGroups = list.map((g, gi) => {
- const workType = pick(g, 'jobType', 'job_type') || `工种${gi + 1}`
- const needCount = needMap[workType] != null ? needMap[workType] : 0
- const workersRaw = g.workers || g.Workers || []
- const workers = (Array.isArray(workersRaw) ? workersRaw : []).map((w, wi) => {
- const name = pick(w, 'realName', 'real_name') || '临时工'
- const mobileMask = pick(w, 'mobileMask', 'mobile_mask') || ''
- const workerId = pick(w, 'workerId', 'worker_id')
- const identity = resolveWorkerSubmitIdentity(w)
- const selected = wi < (needCount > 0 ? needCount : workersRaw.length)
- return {
- msgKey: workerId != null ? `w_${workerId}` : `w_${gi}_${wi}`,
- workerId,
- name,
- avatarText: String(name).charAt(0) || '工',
- jobType: pick(w, 'confirmedWorkType', 'confirmed_work_type') || workType,
- mobileMask,
- mobile: identity.mobile,
- idCardNo: identity.idCardNo,
- metaText: mobileMask
- ? `${workType} · ${mobileMask}`
- : workType,
- selected,
- checkClass: selected ? 'recruit-check recruit-check--on' : 'recruit-check',
- raw: w
- }
- })
- const group = {
- msgKey: `g_${gi}_${workType}`,
- workType,
- needCount,
- selectedCount: 0,
- countText: `0/${needCount}`,
- expanded: true,
- chevronText: '▼',
- workers
- }
- syncRecruitGroupMeta(group)
- return group
- })
- const matchedTotal = Number(pick(raw, 'totalCount', 'total_count'))
- || matchGroups.reduce((n, g) => n + ((g.workers && g.workers.length) || 0), 0)
- return {
- matchGroups,
- matchedTotal,
- resultTitle: `匹配结果(${matchedTotal}人)`,
- message: (raw && raw.message) || ''
- }
- }
- /** 确认选择 → third-party/add body.workers */
- export function buildThirdPartyAddWorkers(matchGroups = []) {
- const workers = []
- const groups = Array.isArray(matchGroups) ? matchGroups : []
- for (let gi = 0; gi < groups.length; gi++) {
- const g = groups[gi]
- const list = g.workers || []
- for (let wi = 0; wi < list.length; wi++) {
- const w = list[wi]
- if (!w || !w.selected) continue
- const identity = resolveWorkerSubmitIdentity(w)
- const item = {
- real_name: w.name,
- realName: w.name,
- mobile: identity.mobile,
- id_card_no: identity.idCardNo,
- idCardNo: identity.idCardNo,
- confirmed_work_type: w.jobType || g.workType,
- confirmedWorkType: w.jobType || g.workType
- }
- if (w.workerId != null && w.workerId !== '') {
- item.worker_id = Number(w.workerId)
- item.workerId = Number(w.workerId)
- }
- workers.push(item)
- }
- }
- return workers
- }
|