|
|
@@ -0,0 +1,1029 @@
|
|
|
+import { getApiBaseUrl, getServerConfig, request } from '@/utils/auth'
|
|
|
+import {
|
|
|
+ probationEmployees,
|
|
|
+ regularizationStatus,
|
|
|
+ regularizationStages,
|
|
|
+ regularizationTemplates,
|
|
|
+ regularizations,
|
|
|
+} from '@/data/mock'
|
|
|
+import {
|
|
|
+ addCreatedRegularization,
|
|
|
+ formatNow,
|
|
|
+ getCreatedRegularizations,
|
|
|
+ getCurrentUser,
|
|
|
+ getLoginUser,
|
|
|
+ getRegularizationIds,
|
|
|
+ getRegularizationStates,
|
|
|
+ loadRegularizationBillMap,
|
|
|
+ rememberRegularizationId,
|
|
|
+ removeRegularizationBillId,
|
|
|
+ saveRegularizationBillId,
|
|
|
+ setRegularizationLocalState,
|
|
|
+ updateCreatedRegularization,
|
|
|
+} from '@/utils/storage'
|
|
|
+
|
|
|
+// ============ 模式判断 ============
|
|
|
+function isServerMode() {
|
|
|
+ return getServerConfig().mode === 'server'
|
|
|
+}
|
|
|
+
|
|
|
+function serverPath() {
|
|
|
+ const base = getApiBaseUrl()
|
|
|
+ if (!base) throw new Error('缺少服务器地址,请先在登录页右上角配置')
|
|
|
+ return base
|
|
|
+}
|
|
|
+
|
|
|
+function delay(ms = 200) {
|
|
|
+ return new Promise((resolve) => setTimeout(resolve, ms))
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 工具 ============
|
|
|
+function compact(object = {}) {
|
|
|
+ return Object.keys(object).reduce((result, key) => {
|
|
|
+ const value = object[key]
|
|
|
+ if (value !== '' && value !== null && value !== undefined) result[key] = value
|
|
|
+ return result
|
|
|
+ }, {})
|
|
|
+}
|
|
|
+
|
|
|
+function dateOnly(value) {
|
|
|
+ if (!value) return ''
|
|
|
+ return String(value).slice(0, 10)
|
|
|
+}
|
|
|
+
|
|
|
+function labelOf(map, raw, fallback = '') {
|
|
|
+ const text = String(raw || '').trim()
|
|
|
+ if (!text) return fallback
|
|
|
+ return map[text] || map[text.toUpperCase()] || text
|
|
|
+}
|
|
|
+
|
|
|
+function asList(data) {
|
|
|
+ if (Array.isArray(data)) return data
|
|
|
+ if (Array.isArray(data?.list)) return data.list
|
|
|
+ if (Array.isArray(data?.records)) return data.records
|
|
|
+ if (data && typeof data === 'object' && data.id != null) return [data]
|
|
|
+ return []
|
|
|
+}
|
|
|
+
|
|
|
+function keepBigIntId(value) {
|
|
|
+ if (value === undefined || value === null || value === '') return undefined
|
|
|
+ const text = String(value).trim()
|
|
|
+ if (!/^-?\d+$/.test(text)) return value
|
|
|
+ if (!Number.isSafeInteger(Number(text))) return text
|
|
|
+ return Number(text)
|
|
|
+}
|
|
|
+
|
|
|
+function extractId(result) {
|
|
|
+ if (result == null) return null
|
|
|
+ if (typeof result === 'object') {
|
|
|
+ return result.id ?? result.regularizationId ?? null
|
|
|
+ }
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+function firstBigIntId(value) {
|
|
|
+ if (Array.isArray(value)) {
|
|
|
+ const hit = value.find((item) => item !== undefined && item !== null && item !== '')
|
|
|
+ return keepBigIntId(hit)
|
|
|
+ }
|
|
|
+ if (value && typeof value === 'object') {
|
|
|
+ return keepBigIntId(value.id ?? value.fileId ?? value.value)
|
|
|
+ }
|
|
|
+ return keepBigIntId(value)
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 枚举(与 PC 端 src/api/hr/regularization.js 对齐)============
|
|
|
+
|
|
|
+/** 转正类型 */
|
|
|
+export const REGULARIZATION_TYPE_LABELS = {
|
|
|
+ NORMAL: '按期转正',
|
|
|
+ EARLY: '提前转正',
|
|
|
+ EXTENDED: '延期转正',
|
|
|
+ FAILED: '不予转正',
|
|
|
+}
|
|
|
+
|
|
|
+export const REGULARIZATION_TYPE_OPTIONS = Object.keys(
|
|
|
+ REGULARIZATION_TYPE_LABELS,
|
|
|
+).map((value) => ({ value, label: REGULARIZATION_TYPE_LABELS[value] }))
|
|
|
+
|
|
|
+/** 审批状态 */
|
|
|
+export const APPROVAL_STATUS_LABELS = {
|
|
|
+ DRAFT: '草稿',
|
|
|
+ PENDING: '审批中',
|
|
|
+ APPROVING: '审批中',
|
|
|
+ APPROVED: '已通过',
|
|
|
+ REJECTED: '已驳回',
|
|
|
+ WITHDRAWN: '已撤回',
|
|
|
+ CANCELLED: '已取消',
|
|
|
+}
|
|
|
+
|
|
|
+/** 生效状态 */
|
|
|
+export const EFFECTIVE_STATUS_LABELS = {
|
|
|
+ PENDING: '待生效',
|
|
|
+ SCHEDULED: '已排期',
|
|
|
+ EFFECTIVE: '已生效',
|
|
|
+ CANCELLED: '已取消',
|
|
|
+}
|
|
|
+
|
|
|
+/** 转正结果 */
|
|
|
+export const RESULT_LABELS = {
|
|
|
+ NORMAL: '按期转正',
|
|
|
+ EARLY: '提前转正',
|
|
|
+ EXTENDED: '延期',
|
|
|
+ FAILED: '不通过',
|
|
|
+}
|
|
|
+
|
|
|
+/** 页面展示态文案(标签 + 样式定义在 data/mock.js) */
|
|
|
+export const DISPLAY_STATUS_LABELS = {
|
|
|
+ pending_apply: '待申请',
|
|
|
+ draft: '草稿',
|
|
|
+ reviewing: '审批中',
|
|
|
+ done: '已转正',
|
|
|
+ rejected: '已驳回',
|
|
|
+ withdrawn: '已撤回',
|
|
|
+ cancelled: '已取消',
|
|
|
+}
|
|
|
+
|
|
|
+export const REGULARIZATION_DISPLAY_STATUS = regularizationStatus
|
|
|
+
|
|
|
+export const REGULARIZATION_STAGES = regularizationStages
|
|
|
+
|
|
|
+export const REGULARIZATION_STATUS_FILTERS = [
|
|
|
+ { value: 'all', label: '全部' },
|
|
|
+ { value: 'pending_apply', label: '待申请' },
|
|
|
+ { value: 'draft', label: '草稿' },
|
|
|
+ { value: 'reviewing', label: '审批中' },
|
|
|
+ { value: 'done', label: '已转正' },
|
|
|
+ { value: 'rejected', label: '已驳回' },
|
|
|
+ { value: 'withdrawn', label: '已撤回' },
|
|
|
+]
|
|
|
+
|
|
|
+// ============ 状态机 ============
|
|
|
+
|
|
|
+/**
|
|
|
+ * 列表 / 详情统一展示态
|
|
|
+ * pending_apply | draft | reviewing | done | rejected | withdrawn | cancelled
|
|
|
+ * 与 PC 端 deriveRegularizationDisplayStatus 完全一致
|
|
|
+ */
|
|
|
+export function deriveRegularizationDisplayStatus(raw = {}) {
|
|
|
+ if (!raw || (!raw.id && !raw.regularizationId && !raw.approvalStatus)) {
|
|
|
+ return 'pending_apply'
|
|
|
+ }
|
|
|
+ const approval = String(raw.approvalStatus || '').toUpperCase()
|
|
|
+ const effective = String(raw.effectiveStatus || '').toUpperCase()
|
|
|
+ const result = String(raw.result || '').toUpperCase()
|
|
|
+
|
|
|
+ if (approval === 'CANCELLED' || effective === 'CANCELLED') return 'cancelled'
|
|
|
+ if (approval === 'WITHDRAWN') return 'withdrawn'
|
|
|
+ if (approval === 'REJECTED') return 'rejected'
|
|
|
+ if (
|
|
|
+ effective === 'EFFECTIVE' ||
|
|
|
+ (approval === 'APPROVED' && (result === 'NORMAL' || result === 'EARLY' || !result))
|
|
|
+ ) {
|
|
|
+ return 'done'
|
|
|
+ }
|
|
|
+ if (approval === 'PENDING' || approval === 'APPROVING' || approval === 'APPROVED') {
|
|
|
+ return 'reviewing'
|
|
|
+ }
|
|
|
+ if (approval === 'DRAFT' || !approval) return 'draft'
|
|
|
+ return 'pending_apply'
|
|
|
+}
|
|
|
+
|
|
|
+export function canApplyRegularization(row = {}) {
|
|
|
+ return ['pending_apply', 'draft', 'rejected', 'withdrawn'].includes(row.status)
|
|
|
+}
|
|
|
+
|
|
|
+export function canEditRegularization(row = {}) {
|
|
|
+ return ['draft', 'rejected', 'withdrawn'].includes(row.status)
|
|
|
+}
|
|
|
+
|
|
|
+export function canSubmitRegularization(row = {}) {
|
|
|
+ if (!row?.regularizationId) return false
|
|
|
+ return ['draft', 'rejected', 'withdrawn'].includes(row.status)
|
|
|
+}
|
|
|
+
|
|
|
+export function canWithdrawRegularization(row = {}) {
|
|
|
+ return row?.status === 'reviewing' && Boolean(row.regularizationId)
|
|
|
+}
|
|
|
+
|
|
|
+export function canCancelRegularization(row = {}) {
|
|
|
+ if (!row?.regularizationId) return false
|
|
|
+ return ['draft', 'pending_apply', 'withdrawn', 'rejected'].includes(row.status)
|
|
|
+}
|
|
|
+
|
|
|
+export function matchDisplayStatus(row = {}, filter = '') {
|
|
|
+ if (!filter || filter === 'all') return true
|
|
|
+ return row.status === filter
|
|
|
+}
|
|
|
+
|
|
|
+function stageKeyOf(displayStatus) {
|
|
|
+ if (displayStatus === 'done') return 'effective'
|
|
|
+ if (displayStatus === 'reviewing') return 'approval'
|
|
|
+ return 'submit'
|
|
|
+}
|
|
|
+
|
|
|
+function progressOf(displayStatus) {
|
|
|
+ switch (displayStatus) {
|
|
|
+ case 'done':
|
|
|
+ return 100
|
|
|
+ case 'reviewing':
|
|
|
+ return 60
|
|
|
+ case 'rejected':
|
|
|
+ return 40
|
|
|
+ case 'withdrawn':
|
|
|
+ case 'cancelled':
|
|
|
+ return 30
|
|
|
+ case 'draft':
|
|
|
+ return 20
|
|
|
+ default:
|
|
|
+ return 10
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function progressTipOf(displayStatus) {
|
|
|
+ switch (displayStatus) {
|
|
|
+ case 'pending_apply':
|
|
|
+ return '试用期员工尚未建立转正单,请发起转正申请。'
|
|
|
+ case 'draft':
|
|
|
+ return '转正申请为草稿,提交后进入审批流程。'
|
|
|
+ case 'reviewing':
|
|
|
+ return '转正审批中,请等待主管与 HR 的审批结果。'
|
|
|
+ case 'done':
|
|
|
+ return '转正审批已通过,员工状态按生效日期更新。'
|
|
|
+ case 'rejected':
|
|
|
+ return '审批已驳回,可修改后重新提交。'
|
|
|
+ case 'withdrawn':
|
|
|
+ return '本次转正申请已撤回。'
|
|
|
+ case 'cancelled':
|
|
|
+ return '本次转正申请已取消。'
|
|
|
+ default:
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ============ VO / 演示记录 → 页面形状 ============
|
|
|
+
|
|
|
+export function adaptRegularization(raw = {}, extras = {}) {
|
|
|
+ if (!raw || typeof raw !== 'object') return null
|
|
|
+ const displayStatus = deriveRegularizationDisplayStatus(raw)
|
|
|
+ const statusMeta =
|
|
|
+ REGULARIZATION_DISPLAY_STATUS[displayStatus] || REGULARIZATION_DISPLAY_STATUS.draft
|
|
|
+ const plannedRegularDate =
|
|
|
+ dateOnly(raw.plannedRegularDate) ||
|
|
|
+ dateOnly(extras.plannedRegularDate) ||
|
|
|
+ dateOnly(extras.plannedDate) ||
|
|
|
+ ''
|
|
|
+ const effectiveDate =
|
|
|
+ dateOnly(raw.effectiveDate) || dateOnly(extras.effectiveDate) || ''
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...raw,
|
|
|
+ /** 业务单主键;列表行请用 userId,勿把 id 当员工主键 */
|
|
|
+ id: raw.id,
|
|
|
+ billId: raw.id,
|
|
|
+ regularizationId: raw.id ?? extras.regularizationId,
|
|
|
+ userId: raw.userId ?? extras.userId,
|
|
|
+ employeeNo: extras.employeeNo || raw.employeeNo || '',
|
|
|
+ name: extras.name || raw.name || raw.employeeName || extras.employeeName || '',
|
|
|
+ avatar: extras.avatar || raw.avatar || '',
|
|
|
+ phone: extras.phone || raw.phone || '',
|
|
|
+ company: extras.company || raw.groupName || raw.company || '',
|
|
|
+ department: extras.department || raw.deptName || raw.department || '',
|
|
|
+ position: extras.position || raw.positionName || raw.position || '',
|
|
|
+ level: extras.level || raw.level || '',
|
|
|
+ manager: extras.manager || raw.manager || '',
|
|
|
+ hireDate: dateOnly(extras.hireDate || raw.hireDate) || '',
|
|
|
+ plannedDate: plannedRegularDate,
|
|
|
+ plannedRegularDate,
|
|
|
+ regularDate: effectiveDate || plannedRegularDate,
|
|
|
+ effectiveDate,
|
|
|
+ regularizationType: raw.regularizationType || 'NORMAL',
|
|
|
+ regularizationTypeLabel: labelOf(
|
|
|
+ REGULARIZATION_TYPE_LABELS,
|
|
|
+ raw.regularizationType || 'NORMAL',
|
|
|
+ ),
|
|
|
+ extensionDays: raw.extensionDays,
|
|
|
+ extensionReason: raw.extensionReason || '',
|
|
|
+ newProbationEndDate: dateOnly(raw.newProbationEndDate) || '',
|
|
|
+ userSummary: raw.userSummary || '',
|
|
|
+ managerEvaluation: raw.managerEvaluation || '',
|
|
|
+ hrComment: raw.hrComment || '',
|
|
|
+ remark: raw.userSummary || extras.remark || '',
|
|
|
+ approvalStatus: raw.approvalStatus || '',
|
|
|
+ approvalStatusLabel: labelOf(APPROVAL_STATUS_LABELS, raw.approvalStatus, '未提交'),
|
|
|
+ approvalNode: raw.approvalNode || '',
|
|
|
+ approvalComment: raw.hrComment || raw.managerEvaluation || extras.approvalComment || '',
|
|
|
+ approvalInstanceId: raw.approvalInstanceId || '',
|
|
|
+ effectiveStatus: raw.effectiveStatus || '',
|
|
|
+ effectiveStatusLabel: labelOf(EFFECTIVE_STATUS_LABELS, raw.effectiveStatus, '-'),
|
|
|
+ result: raw.result || '',
|
|
|
+ resultLabel: labelOf(RESULT_LABELS, raw.result),
|
|
|
+ employmentPeriodId: raw.employmentPeriodId,
|
|
|
+ onlineDocumentId: raw.onlineDocumentId,
|
|
|
+ onlineDocumentTemplateId:
|
|
|
+ raw.onlineDocumentTemplateId || extras.onlineDocumentTemplateId,
|
|
|
+ approvalDocumentFileId: firstBigIntId(raw.approvalDocumentFileId),
|
|
|
+ online: Boolean(
|
|
|
+ raw.onlineDocumentId ||
|
|
|
+ raw.onlineDocumentTemplateId ||
|
|
|
+ extras.onlineDocumentTemplateId,
|
|
|
+ ),
|
|
|
+ status: displayStatus,
|
|
|
+ statusLabel: statusMeta.label,
|
|
|
+ statusClass: statusMeta.class,
|
|
|
+ stageKey: stageKeyOf(displayStatus),
|
|
|
+ progress: progressOf(displayStatus),
|
|
|
+ progressTip: progressTipOf(displayStatus),
|
|
|
+ applyDate: dateOnly(raw.applyDate || raw.createTime || raw.submitDate) || '',
|
|
|
+ createTime: raw.createTime || '',
|
|
|
+ source: extras.source || raw.source || '',
|
|
|
+ raw,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const EMPLOYEE_FIELDS = [
|
|
|
+ 'id',
|
|
|
+ 'employeeNo',
|
|
|
+ 'name',
|
|
|
+ 'avatar',
|
|
|
+ 'phone',
|
|
|
+ 'company',
|
|
|
+ 'department',
|
|
|
+ 'position',
|
|
|
+ 'level',
|
|
|
+ 'manager',
|
|
|
+ 'hireDate',
|
|
|
+ 'regularDate',
|
|
|
+ 'groupId',
|
|
|
+ 'deptId',
|
|
|
+]
|
|
|
+
|
|
|
+function pickEmployeeFields(employee = {}) {
|
|
|
+ return EMPLOYEE_FIELDS.reduce((result, key) => {
|
|
|
+ if (employee[key] !== undefined) result[key] = employee[key]
|
|
|
+ return result
|
|
|
+ }, {})
|
|
|
+}
|
|
|
+
|
|
|
+/** 试用期员工 + 可选转正单 → 列表行(与 PC 端 mergeEmployeeRegularization 对齐) */
|
|
|
+export function mergeEmployeeRegularization(employee = {}, bill = null) {
|
|
|
+ const base = {
|
|
|
+ ...pickEmployeeFields(employee),
|
|
|
+ userId: employee.id,
|
|
|
+ id: employee.id,
|
|
|
+ avatar: employee.avatar || String(employee.name || '').charAt(0),
|
|
|
+ company: employee.company || employee.legalEntity || '',
|
|
|
+ department: employee.department || employee.deptName || '',
|
|
|
+ position: employee.position || employee.postName || '',
|
|
|
+ hireDate: dateOnly(employee.hireDate),
|
|
|
+ plannedDate: dateOnly(employee.regularDate),
|
|
|
+ plannedRegularDate: dateOnly(employee.regularDate),
|
|
|
+ regularDate: dateOnly(employee.regularDate),
|
|
|
+ }
|
|
|
+ if (!bill) {
|
|
|
+ const statusMeta = REGULARIZATION_DISPLAY_STATUS.pending_apply
|
|
|
+ return {
|
|
|
+ ...base,
|
|
|
+ regularizationId: null,
|
|
|
+ status: 'pending_apply',
|
|
|
+ statusLabel: statusMeta.label,
|
|
|
+ statusClass: statusMeta.class,
|
|
|
+ approvalStatus: '',
|
|
|
+ approvalStatusLabel: '未提交',
|
|
|
+ approvalComment: '',
|
|
|
+ regularizationType: 'NORMAL',
|
|
|
+ regularizationTypeLabel: REGULARIZATION_TYPE_LABELS.NORMAL,
|
|
|
+ effectiveDate: '',
|
|
|
+ effectiveStatus: '',
|
|
|
+ effectiveStatusLabel: '-',
|
|
|
+ stageKey: 'submit',
|
|
|
+ progress: progressOf('pending_apply'),
|
|
|
+ progressTip: progressTipOf('pending_apply'),
|
|
|
+ online: true,
|
|
|
+ onlineDocumentTemplateId: null,
|
|
|
+ approvalDocumentFileId: null,
|
|
|
+ remark: '',
|
|
|
+ userSummary: '',
|
|
|
+ managerEvaluation: '',
|
|
|
+ hrComment: '',
|
|
|
+ extensionDays: undefined,
|
|
|
+ extensionReason: '',
|
|
|
+ newProbationEndDate: '',
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ ...base,
|
|
|
+ ...adaptRegularization(bill, base),
|
|
|
+ id: employee.id,
|
|
|
+ userId: employee.id,
|
|
|
+ regularizationId: bill.id,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 表单字段 → /main/regularizations 请求参数(与 PC 端 buildRegularizationPayload 对齐) */
|
|
|
+export function buildRegularizationPayload(form = {}) {
|
|
|
+ const type = form.regularizationType || 'NORMAL'
|
|
|
+ return compact({
|
|
|
+ id: keepBigIntId(form.regularizationId || form.billId || form.id),
|
|
|
+ userId: keepBigIntId(form.userId),
|
|
|
+ employmentPeriodId: keepBigIntId(form.employmentPeriodId),
|
|
|
+ plannedRegularDate: dateOnly(
|
|
|
+ form.plannedRegularDate || form.plannedDate || form.regularDate,
|
|
|
+ ),
|
|
|
+ effectiveDate: dateOnly(form.effectiveDate || form.regularDate),
|
|
|
+ regularizationType: type,
|
|
|
+ extensionDays:
|
|
|
+ type === 'EXTENDED' ? Number(form.extensionDays || 0) || undefined : undefined,
|
|
|
+ extensionReason: type === 'EXTENDED' ? form.extensionReason : undefined,
|
|
|
+ newProbationEndDate:
|
|
|
+ type === 'EXTENDED' ? dateOnly(form.newProbationEndDate) : undefined,
|
|
|
+ userSummary: form.userSummary || form.remark,
|
|
|
+ managerEvaluation: form.managerEvaluation,
|
|
|
+ hrComment: form.hrComment,
|
|
|
+ approvalDocumentFileId: firstBigIntId(form.approvalDocumentFileId),
|
|
|
+ onlineDocumentTemplateId: form.online
|
|
|
+ ? keepBigIntId(form.onlineDocumentTemplateId || form.templateId)
|
|
|
+ : undefined,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 服务端接口(M02-员工转正)============
|
|
|
+
|
|
|
+/** 员工 VO → 页面员工形状(字段口径与 PC 端 adaptEmployee 一致) */
|
|
|
+export function adaptEmployeeBrief(raw = {}) {
|
|
|
+ const name = raw.name || raw.userName || ''
|
|
|
+ return {
|
|
|
+ id: raw.id,
|
|
|
+ employeeNo: raw.jobNumber || raw.employeeNo || '',
|
|
|
+ name,
|
|
|
+ avatar: raw.avatar || String(name).charAt(0),
|
|
|
+ phone: raw.phone || '',
|
|
|
+ company: raw.groupName || raw.company || '',
|
|
|
+ department: raw.deptName || raw.deptNames || '',
|
|
|
+ position: raw.postName || raw.position || '',
|
|
|
+ level: raw.positionLevelName || raw.level || '',
|
|
|
+ manager: raw.managerName || raw.manager || '',
|
|
|
+ hireDate: dateOnly(raw.joinDate || raw.hireDate || raw.entryDate),
|
|
|
+ regularDate: dateOnly(raw.positiveDate || raw.regularDate),
|
|
|
+ groupId: raw.groupId,
|
|
|
+ deptId: raw.deptId,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 试用期员工分页 GET /main/user/getUserPage */
|
|
|
+export async function getProbationUserPage(params = {}) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/user/getUserPage`,
|
|
|
+ method: 'GET',
|
|
|
+ data: compact({
|
|
|
+ status: 5,
|
|
|
+ isQueryLZ: 0,
|
|
|
+ pageNum: params.pageNum,
|
|
|
+ size: params.size,
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ const data = res.data || {}
|
|
|
+ return {
|
|
|
+ list: asList(data),
|
|
|
+ count: Number(data?.count ?? data?.total ?? 0),
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 分页拉全量试用期员工(有上限,避免一次性打爆接口) */
|
|
|
+export async function fetchProbationEmployees(options = {}) {
|
|
|
+ const pageSize = options.pageSize || 200
|
|
|
+ const maxPages = options.maxPages || 10
|
|
|
+ const list = []
|
|
|
+ let pageNum = 1
|
|
|
+ let total = Infinity
|
|
|
+ while (pageNum <= maxPages && list.length < total) {
|
|
|
+ const data = await getProbationUserPage({ pageNum, size: pageSize })
|
|
|
+ const chunk = Array.isArray(data?.list) ? data.list : []
|
|
|
+ total = Number(data?.count ?? list.length + chunk.length)
|
|
|
+ list.push(...chunk)
|
|
|
+ if (!chunk.length || chunk.length < pageSize) break
|
|
|
+ pageNum += 1
|
|
|
+ }
|
|
|
+ return { list: list.map(adaptEmployeeBrief), count: total === Infinity ? list.length : total }
|
|
|
+}
|
|
|
+
|
|
|
+const employeeCache = new Map()
|
|
|
+
|
|
|
+/** 员工简要信息 GET /main/user/getById/{userId}(详情页缺少员工字段时补齐) */
|
|
|
+async function fetchEmployeeBrief(userId) {
|
|
|
+ if (userId === undefined || userId === null || userId === '') return null
|
|
|
+ const key = String(userId)
|
|
|
+ if (employeeCache.has(key)) return employeeCache.get(key)
|
|
|
+ try {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/user/getById/${key}`,
|
|
|
+ method: 'GET',
|
|
|
+ })
|
|
|
+ const brief = adaptEmployeeBrief(res.data || {})
|
|
|
+ employeeCache.set(key, brief)
|
|
|
+ return brief
|
|
|
+ } catch (error) {
|
|
|
+ employeeCache.set(key, null)
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 新建转正草稿,返回转正单 id POST /main/regularizations */
|
|
|
+export async function createRegularization(payload) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/regularizations`,
|
|
|
+ method: 'POST',
|
|
|
+ data: payload,
|
|
|
+ })
|
|
|
+ const id = extractId(res.data)
|
|
|
+ if (id != null) {
|
|
|
+ rememberRegularizationId(id)
|
|
|
+ if (payload?.userId != null) saveRegularizationBillId(payload.userId, id)
|
|
|
+ }
|
|
|
+ return id
|
|
|
+}
|
|
|
+
|
|
|
+/** 修改转正草稿 PUT /main/regularizations */
|
|
|
+export async function updateRegularization(payload) {
|
|
|
+ await request({
|
|
|
+ url: `${serverPath()}/main/regularizations`,
|
|
|
+ method: 'PUT',
|
|
|
+ data: payload,
|
|
|
+ })
|
|
|
+ if (payload?.id != null) {
|
|
|
+ rememberRegularizationId(payload.id)
|
|
|
+ if (payload?.userId != null) saveRegularizationBillId(payload.userId, payload.id)
|
|
|
+ }
|
|
|
+ return payload?.id
|
|
|
+}
|
|
|
+
|
|
|
+/** 查询转正单 GET /main/regularizations/{id} */
|
|
|
+export async function getRegularizationById(id, extras = {}) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/regularizations/${id}`,
|
|
|
+ method: 'GET',
|
|
|
+ })
|
|
|
+ const adapted = adaptRegularization(res.data, extras)
|
|
|
+ if (adapted?.userId != null && adapted.id != null) {
|
|
|
+ saveRegularizationBillId(adapted.userId, adapted.id)
|
|
|
+ }
|
|
|
+ return adapted
|
|
|
+}
|
|
|
+
|
|
|
+/** 提交转正审批 POST /main/regularizations/{id}/submit */
|
|
|
+export async function submitRegularization(id) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/regularizations/${id}/submit`,
|
|
|
+ method: 'POST',
|
|
|
+ })
|
|
|
+ return res.data
|
|
|
+}
|
|
|
+
|
|
|
+/** 撤回转正审批 POST /main/regularizations/{id}/withdraw */
|
|
|
+export async function withdrawRegularization(id, reason = '') {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/regularizations/${id}/withdraw`,
|
|
|
+ method: 'POST',
|
|
|
+ data: compact({ reason }),
|
|
|
+ })
|
|
|
+ return res.data
|
|
|
+}
|
|
|
+
|
|
|
+/** 取消转正单 POST /main/regularizations/{id}/cancel */
|
|
|
+export async function cancelRegularization(id, reason = '') {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/regularizations/${id}/cancel`,
|
|
|
+ method: 'POST',
|
|
|
+ data: compact({ reason }),
|
|
|
+ })
|
|
|
+ return res.data
|
|
|
+}
|
|
|
+
|
|
|
+/** 任职周期(计划转正日 / employmentPeriodId)GET /main/users/{userId}/employment-periods */
|
|
|
+export async function getEmploymentPeriods(userId) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/users/${userId}/employment-periods`,
|
|
|
+ method: 'GET',
|
|
|
+ })
|
|
|
+ return asList(res.data)
|
|
|
+}
|
|
|
+
|
|
|
+/** 从人事时间轴尝试找回转正单 id(与 PC 端策略一致) */
|
|
|
+export async function resolveRegularizationIdFromHistory(userId) {
|
|
|
+ const mapped = loadRegularizationBillMap()[String(userId)]
|
|
|
+ if (mapped) return mapped
|
|
|
+ try {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/main/users/${userId}/history`,
|
|
|
+ method: 'GET',
|
|
|
+ })
|
|
|
+ const list = asList(res.data)
|
|
|
+ const hit = [...list].reverse().find((item) => {
|
|
|
+ const text = `${item.eventType || ''} ${item.sourceBusinessType || ''}`.toUpperCase()
|
|
|
+ return text.includes('REGULAR')
|
|
|
+ })
|
|
|
+ if (hit?.sourceBusinessId != null) {
|
|
|
+ saveRegularizationBillId(userId, hit.sourceBusinessId)
|
|
|
+ return hit.sourceBusinessId
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 时间轴不可用时不阻塞列表
|
|
|
+ }
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
+/** 启用态线上 Word 模板分页 GET /hr/online-documents/templates */
|
|
|
+export async function getRegularizationTemplatePage(params = {}) {
|
|
|
+ const res = await request({
|
|
|
+ url: `${serverPath()}/hr/online-documents/templates`,
|
|
|
+ method: 'GET',
|
|
|
+ data: compact({
|
|
|
+ pageNum: 1,
|
|
|
+ size: 200,
|
|
|
+ templateStatus: 'ENABLED',
|
|
|
+ ...params,
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ const data = res.data || {}
|
|
|
+ return { list: asList(data), count: Number(data?.count ?? data?.total ?? 0) }
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 演示模式本地实现 ============
|
|
|
+
|
|
|
+function currentUserId() {
|
|
|
+ const login = getLoginUser() || {}
|
|
|
+ const raw = getCurrentUser()?.raw || {}
|
|
|
+ const candidates = [login.userId, login.id, raw.userId, raw.id]
|
|
|
+ return candidates.find((value) => value !== undefined && value !== null && value !== '')
|
|
|
+}
|
|
|
+
|
|
|
+function currentUserKeys() {
|
|
|
+ const user = getCurrentUser() || {}
|
|
|
+ const login = getLoginUser() || {}
|
|
|
+ return [user.id, user.name, login.userId, login.loginName, login.userName]
|
|
|
+ .filter((value) => value !== undefined && value !== null && value !== '')
|
|
|
+ .map(String)
|
|
|
+}
|
|
|
+
|
|
|
+function isMine(row = {}) {
|
|
|
+ const mine = currentUserKeys()
|
|
|
+ if (!mine.length) return true
|
|
|
+ return [row.userId, row.employeeNo, row.name]
|
|
|
+ .filter((value) => value !== undefined && value !== null && value !== '')
|
|
|
+ .map(String)
|
|
|
+ .some((value) => mine.includes(value))
|
|
|
+}
|
|
|
+
|
|
|
+function regularizationText(row = {}) {
|
|
|
+ return `${row.name}${row.employeeNo}${row.department}${row.position}${row.regularizationTypeLabel}`
|
|
|
+}
|
|
|
+
|
|
|
+function mergeDemoBills() {
|
|
|
+ const overrides = getRegularizationStates()
|
|
|
+ const created = getCreatedRegularizations()
|
|
|
+ const seen = new Set(created.map((item) => String(item.id)))
|
|
|
+ const base = [...created, ...regularizations.filter((item) => !seen.has(String(item.id)))]
|
|
|
+ return base.map((record) =>
|
|
|
+ adaptRegularization(
|
|
|
+ { ...record, ...(overrides[String(record.id)] || {}) },
|
|
|
+ { source: 'demo' },
|
|
|
+ ),
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function mergeBillIntoRow(rows, bill) {
|
|
|
+ const index = rows.findIndex((row) => String(row.userId) === String(bill.userId))
|
|
|
+ if (index >= 0) {
|
|
|
+ rows[index] = mergeEmployeeRegularization(rows[index], bill)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ rows.push({
|
|
|
+ ...bill,
|
|
|
+ id: bill.userId,
|
|
|
+ userId: bill.userId,
|
|
|
+ regularizationId: bill.regularizationId || bill.id,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/** 演示模式列表行:试用期员工 + 转正单合并(与 PC 端 loadList 口径一致) */
|
|
|
+export function buildDemoRegularizationRows() {
|
|
|
+ const bills = mergeDemoBills()
|
|
|
+ const billMap = new Map(bills.map((bill) => [String(bill.userId), bill]))
|
|
|
+ const rows = probationEmployees.map((employee) => {
|
|
|
+ const bill = billMap.get(String(employee.id)) || null
|
|
|
+ return mergeEmployeeRegularization(employee, bill)
|
|
|
+ })
|
|
|
+ bills.forEach((bill) => {
|
|
|
+ if (
|
|
|
+ !probationEmployees.some((employee) => String(employee.id) === String(bill.userId))
|
|
|
+ ) {
|
|
|
+ mergeBillIntoRow(rows, bill)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return rows
|
|
|
+}
|
|
|
+
|
|
|
+function persistDemoRegularization(id, form, submit) {
|
|
|
+ const type = form.regularizationType || 'NORMAL'
|
|
|
+ const record = {
|
|
|
+ id: String(id),
|
|
|
+ userId: form.userId,
|
|
|
+ name: form.name || '',
|
|
|
+ avatar: form.avatar || String(form.name || '').charAt(0),
|
|
|
+ employeeNo: form.employeeNo || '',
|
|
|
+ phone: form.phone || '',
|
|
|
+ company: form.company || '',
|
|
|
+ department: form.department || '',
|
|
|
+ position: form.position || '',
|
|
|
+ level: form.level || '',
|
|
|
+ manager: form.manager || '',
|
|
|
+ hireDate: dateOnly(form.hireDate),
|
|
|
+ regularizationType: type,
|
|
|
+ plannedRegularDate: dateOnly(
|
|
|
+ form.plannedRegularDate || form.plannedDate || form.regularDate,
|
|
|
+ ),
|
|
|
+ effectiveDate: dateOnly(form.effectiveDate),
|
|
|
+ extensionDays: type === 'EXTENDED' ? Number(form.extensionDays || 0) || undefined : undefined,
|
|
|
+ extensionReason: type === 'EXTENDED' ? form.extensionReason || '' : '',
|
|
|
+ newProbationEndDate:
|
|
|
+ type === 'EXTENDED' ? dateOnly(form.newProbationEndDate) : '',
|
|
|
+ userSummary: form.userSummary || '',
|
|
|
+ managerEvaluation: form.managerEvaluation || '',
|
|
|
+ hrComment: form.hrComment || '',
|
|
|
+ onlineDocumentTemplateId: form.onlineDocumentTemplateId || null,
|
|
|
+ approvalDocumentFileId: form.approvalDocumentFileId || null,
|
|
|
+ approvalStatus: submit ? 'PENDING' : 'DRAFT',
|
|
|
+ effectiveStatus: 'PENDING',
|
|
|
+ approvalNode: submit ? '主管审批' : '',
|
|
|
+ applyDate: dateOnly(formatNow()),
|
|
|
+ source: 'demo',
|
|
|
+ createdByApp: true,
|
|
|
+ }
|
|
|
+ addCreatedRegularization(record)
|
|
|
+ return record
|
|
|
+}
|
|
|
+
|
|
|
+function updateDemoRegularization(id, patch) {
|
|
|
+ setRegularizationLocalState(id, patch)
|
|
|
+ updateCreatedRegularization(id, patch)
|
|
|
+ return mergeDemoBills().find((item) => String(item.id) === String(id)) || null
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 对外统一入口(页面只调用这些)============
|
|
|
+
|
|
|
+/**
|
|
|
+ * 转正办理列表。
|
|
|
+ * @param {object} params
|
|
|
+ * - scope: 'all' 全部员工(HR 视图,默认);'mine' 只看本人
|
|
|
+ * - status: REGULARIZATION_STATUS_FILTERS 的 value
|
|
|
+ * - keyword: 姓名 / 工号 / 部门 / 岗位 模糊匹配
|
|
|
+ */
|
|
|
+export async function loadRegularizationList(params = {}) {
|
|
|
+ const { scope = 'all', status = 'all', keyword = '' } = params
|
|
|
+ const match = (rows) =>
|
|
|
+ rows
|
|
|
+ .filter((row) => (scope === 'mine' ? isMine(row) : true))
|
|
|
+ .filter((row) => matchDisplayStatus(row, status))
|
|
|
+ .filter((row) => (keyword ? regularizationText(row).includes(keyword) : true))
|
|
|
+
|
|
|
+ if (!isServerMode()) {
|
|
|
+ await delay(150)
|
|
|
+ const list = match(buildDemoRegularizationRows()).sort((a, b) =>
|
|
|
+ String(b.plannedRegularDate || b.applyDate).localeCompare(
|
|
|
+ String(a.plannedRegularDate || a.applyDate),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ return { list, count: list.length, source: 'demo' }
|
|
|
+ }
|
|
|
+
|
|
|
+ let rows = []
|
|
|
+ try {
|
|
|
+ const { list } = await fetchProbationEmployees()
|
|
|
+ const billMap = loadRegularizationBillMap()
|
|
|
+ rows = await Promise.all(
|
|
|
+ list.map(async (employee) => {
|
|
|
+ const billId = billMap[String(employee.id)]
|
|
|
+ if (!billId) return mergeEmployeeRegularization(employee, null)
|
|
|
+ try {
|
|
|
+ const bill = await getRegularizationById(billId, employee)
|
|
|
+ return mergeEmployeeRegularization(employee, bill)
|
|
|
+ } catch (error) {
|
|
|
+ removeRegularizationBillId(employee.id)
|
|
|
+ return mergeEmployeeRegularization(employee, null)
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ } catch (error) {
|
|
|
+ rows = []
|
|
|
+ }
|
|
|
+
|
|
|
+ // 集合接口不可用时,按本机记住的转正单主键补拉(与 PC 端兜底策略一致)
|
|
|
+ const ids = getRegularizationIds()
|
|
|
+ const attached = new Set(
|
|
|
+ rows.filter((row) => row.regularizationId).map((row) => String(row.regularizationId)),
|
|
|
+ )
|
|
|
+ const missing = ids.filter((id) => !attached.has(String(id)))
|
|
|
+ if (missing.length) {
|
|
|
+ const bills = (
|
|
|
+ await Promise.all(
|
|
|
+ missing.map((id) => getRegularizationById(id).catch(() => null)),
|
|
|
+ )
|
|
|
+ ).filter(Boolean)
|
|
|
+ bills.forEach((bill) => mergeBillIntoRow(rows, bill))
|
|
|
+ }
|
|
|
+
|
|
|
+ return { list: match(rows), count: rows.length, source: 'api' }
|
|
|
+}
|
|
|
+
|
|
|
+/** 转正单详情;传列表行时优先用行内数据兜底 */
|
|
|
+export async function loadRegularizationDetail(id, fallbackRow = null) {
|
|
|
+ if (!id) return fallbackRow || null
|
|
|
+
|
|
|
+ if (!isServerMode()) {
|
|
|
+ const rows = buildDemoRegularizationRows()
|
|
|
+ return (
|
|
|
+ rows.find((row) => String(row.regularizationId) === String(id)) ||
|
|
|
+ rows.find((row) => String(row.userId) === String(id)) ||
|
|
|
+ null
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ const extras = fallbackRow
|
|
|
+ ? {
|
|
|
+ userId: fallbackRow.userId,
|
|
|
+ employeeNo: fallbackRow.employeeNo,
|
|
|
+ name: fallbackRow.name,
|
|
|
+ avatar: fallbackRow.avatar,
|
|
|
+ phone: fallbackRow.phone,
|
|
|
+ company: fallbackRow.company,
|
|
|
+ department: fallbackRow.department,
|
|
|
+ position: fallbackRow.position,
|
|
|
+ level: fallbackRow.level,
|
|
|
+ manager: fallbackRow.manager,
|
|
|
+ hireDate: fallbackRow.hireDate,
|
|
|
+ }
|
|
|
+ : {}
|
|
|
+ const bill = await getRegularizationById(id, extras)
|
|
|
+ if (!bill) return null
|
|
|
+ // 服务端单据只带 userId 时,回查员工档案补齐姓名 / 组织信息
|
|
|
+ if (!bill.name || !bill.department) {
|
|
|
+ const brief = await fetchEmployeeBrief(bill.userId)
|
|
|
+ if (brief) {
|
|
|
+ Object.assign(bill, {
|
|
|
+ name: bill.name || brief.name,
|
|
|
+ avatar: bill.avatar || brief.avatar,
|
|
|
+ employeeNo: bill.employeeNo || brief.employeeNo,
|
|
|
+ phone: bill.phone || brief.phone,
|
|
|
+ company: bill.company || brief.company,
|
|
|
+ department: bill.department || brief.department,
|
|
|
+ position: bill.position || brief.position,
|
|
|
+ level: bill.level || brief.level,
|
|
|
+ manager: bill.manager || brief.manager,
|
|
|
+ hireDate: bill.hireDate || brief.hireDate,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fallbackRow ? { ...fallbackRow, ...bill, userId: bill.userId ?? fallbackRow.userId } : bill
|
|
|
+}
|
|
|
+
|
|
|
+/** 转正申请表单选项:试用期员工 + 启用态线上模板 */
|
|
|
+export async function loadRegularizationFormOptions() {
|
|
|
+ const demoResult = {
|
|
|
+ employees: probationEmployees.map((employee) => ({
|
|
|
+ ...adaptEmployeeBrief(employee),
|
|
|
+ id: employee.id,
|
|
|
+ name: employee.name,
|
|
|
+ regularDate: employee.regularDate,
|
|
|
+ })),
|
|
|
+ templates: regularizationTemplates.filter(
|
|
|
+ (item) => String(item.status || 'ENABLED').toUpperCase() === 'ENABLED',
|
|
|
+ ),
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isServerMode()) {
|
|
|
+ await delay(150)
|
|
|
+ return demoResult
|
|
|
+ }
|
|
|
+
|
|
|
+ const [employees, templates] = await Promise.all([
|
|
|
+ fetchProbationEmployees()
|
|
|
+ .then((result) => result.list)
|
|
|
+ .catch(() => []),
|
|
|
+ getRegularizationTemplatePage()
|
|
|
+ .then((result) => result.list)
|
|
|
+ .catch(() => []),
|
|
|
+ ])
|
|
|
+ return {
|
|
|
+ employees: employees.length ? employees : demoResult.employees,
|
|
|
+ templates: templates.length ? templates : demoResult.templates,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 某员工的任职周期,用于带出计划转正日与 employmentPeriodId */
|
|
|
+export async function loadEmploymentPeriod(userId) {
|
|
|
+ if (!isServerMode()) {
|
|
|
+ const employee = probationEmployees.find((item) => String(item.id) === String(userId))
|
|
|
+ if (!employee) return null
|
|
|
+ return {
|
|
|
+ id: null,
|
|
|
+ periodStatus: 'ACTIVE',
|
|
|
+ probationEndDate: employee.regularDate,
|
|
|
+ regularDate: employee.regularDate,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const list = await getEmploymentPeriods(userId)
|
|
|
+ return (
|
|
|
+ list.find((item) => String(item.periodStatus || '').toUpperCase() === 'ACTIVE') ||
|
|
|
+ list[0] ||
|
|
|
+ null
|
|
|
+ )
|
|
|
+ } catch (error) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 提交(或存草稿)转正申请。
|
|
|
+ * 服务器模式:建单 POST /main/regularizations → 提交 POST /{id}/submit
|
|
|
+ * 演示模式:本地落一条转正单,提交时状态置为审批中
|
|
|
+ *
|
|
|
+ * @returns {Promise<string|number>} 转正单主键
|
|
|
+ */
|
|
|
+export async function submitRegularizationApplication({
|
|
|
+ form,
|
|
|
+ submit = true,
|
|
|
+ existingId = null,
|
|
|
+} = {}) {
|
|
|
+ if (!form) throw new Error('申请参数为空')
|
|
|
+ const id = existingId || form.regularizationId || form.id || null
|
|
|
+
|
|
|
+ if (!isServerMode()) {
|
|
|
+ await delay(300)
|
|
|
+ const localId = id || `ZZ${Date.now()}`
|
|
|
+ const record = persistDemoRegularization(localId, form, submit)
|
|
|
+ saveRegularizationBillId(record.userId, record.id)
|
|
|
+ rememberRegularizationId(record.id)
|
|
|
+ return record.id
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = buildRegularizationPayload({ ...form, id })
|
|
|
+ const billId = id || (await createRegularization(payload))
|
|
|
+ if (id) await updateRegularization({ ...payload, id: billId })
|
|
|
+ if (submit && billId != null) await submitRegularization(billId)
|
|
|
+ if (form?.userId != null && billId != null) saveRegularizationBillId(form.userId, billId)
|
|
|
+ return billId
|
|
|
+}
|
|
|
+
|
|
|
+// —— 流程动作:服务器模式走接口,演示模式改本地态 ——
|
|
|
+
|
|
|
+export async function actSubmitRegularization(row) {
|
|
|
+ if (!row?.regularizationId) throw new Error('缺少转正单主键')
|
|
|
+ if (isServerMode()) return submitRegularization(row.regularizationId)
|
|
|
+ return updateDemoRegularization(row.regularizationId, {
|
|
|
+ approvalStatus: 'PENDING',
|
|
|
+ approvalNode: '主管审批',
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+export async function actWithdrawRegularization(row, reason = '') {
|
|
|
+ if (!row?.regularizationId) throw new Error('缺少转正单主键')
|
|
|
+ if (isServerMode()) return withdrawRegularization(row.regularizationId, reason)
|
|
|
+ return updateDemoRegularization(row.regularizationId, {
|
|
|
+ approvalStatus: 'WITHDRAWN',
|
|
|
+ approvalComment: reason,
|
|
|
+ approvalNode: '',
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+export async function actCancelRegularization(row, reason = '') {
|
|
|
+ if (!row?.regularizationId) throw new Error('缺少转正单主键')
|
|
|
+ if (isServerMode()) return cancelRegularization(row.regularizationId, reason)
|
|
|
+ const result = updateDemoRegularization(row.regularizationId, {
|
|
|
+ approvalStatus: 'CANCELLED',
|
|
|
+ effectiveStatus: 'CANCELLED',
|
|
|
+ approvalComment: reason,
|
|
|
+ approvalNode: '',
|
|
|
+ })
|
|
|
+ removeRegularizationBillId(row.userId)
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+export const currentRegularizationUserId = currentUserId
|
|
|
+
|
|
|
+/**
|
|
|
+ * 解析某员工当前的转正单主键:
|
|
|
+ * 优先本机缓存(与 PC 端 billMap 同源),演示模式回落到本地记录,服务器模式回落到人事时间轴。
|
|
|
+ */
|
|
|
+export async function resolveRegularizationId(userId) {
|
|
|
+ if (userId === undefined || userId === null || userId === '') return null
|
|
|
+ const mapped = loadRegularizationBillMap()[String(userId)]
|
|
|
+ if (mapped) return mapped
|
|
|
+ if (!isServerMode()) {
|
|
|
+ const hit = buildDemoRegularizationRows().find(
|
|
|
+ (row) => String(row.userId) === String(userId) && row.regularizationId,
|
|
|
+ )
|
|
|
+ return hit?.regularizationId || null
|
|
|
+ }
|
|
|
+ return resolveRegularizationIdFromHistory(userId)
|
|
|
+}
|