import { getApiBaseUrl, getServerConfig, request } from '@/utils/auth' // ============ 模式判断 ============ function isServerMode() { return getServerConfig().mode === 'server' } function serverPath() { const base = getApiBaseUrl() if (!base) throw new Error('缺少服务器地址,请先在登录页右上角配置') return base } // ============ 枚举 ============ // 岗位序列状态:1-启用 / 0-停用(与后端约定) export const SEQUENCE_STATUS_LABEL = { 1: '启用', 0: '停用', '1': '启用', '0': '停用', } // 排序方式(与后端 orderBy 枚举一致) export const ORDER_BY = { ASC: 'ascending', DESC: 'descending', } // 常见的 sortName:默认 createTime export const DEFAULT_SORT_NAME = 'createTime' // ============ Demo 数据 ============ // demo 模式内存 mock,避免页面硬编码常量。 // 序列覆盖 管理/专业/技术/操作 4 大类,每类 2-3 个层级。 let demoIdCounter = 1000 const DEMO_SEQUENCES = [ { id: 1, sequence: '管理', status: '1', levelList: [ { id: 11, level: 'M1', levelGrade: 1, sequenceId: 1, status: '1' }, { id: 12, level: 'M2', levelGrade: 2, sequenceId: 1, status: '1' }, { id: 13, level: 'M3', levelGrade: 3, sequenceId: 1, status: '1' }, ], }, { id: 2, sequence: '专业', status: '1', levelList: [ { id: 21, level: 'P1', levelGrade: 1, sequenceId: 2, status: '1' }, { id: 22, level: 'P2', levelGrade: 2, sequenceId: 2, status: '1' }, { id: 23, level: 'P3', levelGrade: 3, sequenceId: 2, status: '0' }, ], }, { id: 3, sequence: '技术', status: '1', levelList: [ { id: 31, level: 'T1', levelGrade: 1, sequenceId: 3, status: '1' }, { id: 32, level: 'T2', levelGrade: 2, sequenceId: 3, status: '1' }, { id: 33, level: 'T3', levelGrade: 3, sequenceId: 3, status: '1' }, { id: 34, level: 'T4', levelGrade: 4, sequenceId: 3, status: '1' }, ], }, { id: 4, sequence: '操作', status: '0', levelList: [ { id: 41, level: 'O1', levelGrade: 1, sequenceId: 4, status: '0' }, { id: 42, level: 'O2', levelGrade: 2, sequenceId: 4, status: '0' }, ], }, ] function matchDemoSequence(query) { const sequence = (query.sequence || '').trim() const status = query.status === undefined || query.status === null ? '' : String(query.status) return DEMO_SEQUENCES.filter((s) => { if (sequence && !String(s.sequence).includes(sequence)) return false if (status && String(s.status) !== status) return false return true }) } function paginate(list, pageNum, size) { const safePage = Math.max(1, Number(pageNum) || 1) const safeSize = Math.max(1, Number(size) || 20) const start = (safePage - 1) * safeSize return list.slice(start, start + safeSize) } function sortDemoSequences(list, sortName, orderBy) { if (!sortName) return list const desc = String(orderBy || 'ascending').toLowerCase() === 'descending' const key = String(sortName) const sorted = [...list].sort((a, b) => { const av = a[key] const bv = b[key] if (av === bv) return 0 if (av === undefined || av === null) return 1 if (bv === undefined || bv === null) return -1 return av > bv ? 1 : -1 }) return desc ? sorted.reverse() : sorted } // ============ 对外 API ============ /** * 分页查询岗位序列 * POST /hr/positionSequence/page * * 请求参数(与后端约定): * - deptId 机构 id(非必填) * - offset 偏移量(非必填,由后端按 pageNum/size 计算) * - orderBy 排序方式 ascending | descending * - pageNum 当前页(从 1 开始) * - sequence 岗位序列名称(模糊匹配) * - size 每页显示数 * - sortName 排序字段(默认 createTime) * - status 状态 1:启用、0:停用 * * 响应:{ code, data: Pagination, message } * Pagination.list 每项为 岗位序列列表:{ id, sequence, status, levelList: [{id, level, levelGrade, sequenceId, status}] } * * @param {object} query 详见 JSDoc * @returns {Promise<{ count: number, list: Array, pageNum: number, size: number, current: number, currentUserId?: number, deptId?: number, extInfo?: object }>} */ export async function pagePositionSequence(query = {}) { // 归一化入参:status / orderBy / sortName 给后端的默认值 const body = { pageNum: Number(query.pageNum) || 1, size: Number(query.size) || 20, sortName: query.sortName || DEFAULT_SORT_NAME, orderBy: query.orderBy || ORDER_BY.ASC, } if (query.deptId !== undefined && query.deptId !== null && query.deptId !== '') { body.deptId = Number(query.deptId) || 0 } if (query.sequence !== undefined && query.sequence !== null) { body.sequence = String(query.sequence) } if (query.status !== undefined && query.status !== null && query.status !== '') { body.status = String(query.status) } if (query.offset !== undefined && query.offset !== null) { body.offset = Number(query.offset) || 0 } if (!isServerMode()) { await new Promise((r) => setTimeout(r, 200)) const filtered = matchDemoSequence(body) const sorted = sortDemoSequences(filtered, body.sortName, body.orderBy) const list = paginate(sorted, body.pageNum, body.size) return { count: sorted.length, current: body.pageNum, currentUserId: 0, deptId: body.deptId || 0, extInfo: {}, list, pageNum: body.pageNum, size: body.size, } } const path = `${serverPath()}/hr/positionSequence/page` const res = await request({ url: path, method: 'POST', data: body }) return res.data || { count: 0, current: body.pageNum, list: [], pageNum: body.pageNum, size: body.size, } } /** * 查询岗位序列列表(仅启用) * GET /hr/positionSequence/getPositionSequenceList * * 接口描述:返回启用的岗位序列及其启用层级集合;层级包含文本、数值级别和主键, * 供岗位管理展示或级联选择。 * * 响应:{ code, data: Array<岗位序列列表>, message } * * @returns {Promise }>>} */ export async function getPositionSequenceList() { if (!isServerMode()) { await new Promise((r) => setTimeout(r, 150)) return DEMO_SEQUENCES .filter((s) => String(s.status) === '1') .map((s) => ({ ...s, levelList: (s.levelList || []).filter((lv) => String(lv.status) === '1'), })) } const path = `${serverPath()}/hr/positionSequence/getPositionSequenceList` const res = await request({ url: path, method: 'GET' }) return Array.isArray(res.data) ? res.data : [] } /** * 把后端 status('0' | '1' | 0 | 1)翻译成中文标签 */ export function translateSequenceStatus(status) { if (status === undefined || status === null || status === '') return '' return SEQUENCE_STATUS_LABEL[status] || String(status) } /** * 把后端层级数组按 levelGrade 升序排序(数值越大层级越高 → 排序时大的在后, * 调用方若要"高层在前"自行 reverse)。 */ export function sortLevelsByGrade(levels) { if (!Array.isArray(levels)) return [] return [...levels].sort((a, b) => (a.levelGrade || 0) - (b.levelGrade || 0)) }