/** * 「我的申请」/「申请记录」列表页共用逻辑 * * 两个页面只有数据源不同: * - 我的申请(pages/hr/apply/list):GET /hr/ess/applications * - 申请记录(pages/hr/apply/record,管理端):GET /hr/ess/admin/applications * 跳转逻辑完全一致——都按 businessType 跳到对应提交页的只读详情; * 区别仅在于管理端恒为只读(调用 openEssApplication 时带 admin: true)。 */ import { APPROVAL_STATUS_FILTERS, adaptEssApplication, listAdminApplications, listMyApplications, openEssApplication, } from "@/api/hr/essApplication"; export const applicationListMixin = { data() { return { // 子页面覆盖:true 使用管理端接口 adminMode: false, loading: false, loadingMore: false, tabs: APPROVAL_STATUS_FILTERS, tabIndex: 0, keyword: "", typeFilter: "", // 类型筛选:与其它选择器同款的底部滚轮(页面里挂 u-picker) typePickerShow: false, typePickerItems: [], list: [], pageNum: 1, size: 20, total: 0, finished: false, }; }, computed: { statusFilter() { return (this.tabs[this.tabIndex] || {}).value || ""; }, /** 类型筛选项来自已加载数据,避免额外请求字典 */ typeOptions() { const map = new Map(); this.list.forEach((item) => { if (!item.businessType) return; if (!map.has(item.businessType)) { map.set(item.businessType, item.businessTypeName || item.businessType); } }); return Array.from(map.entries()).map(([value, label]) => ({ value, label })); }, /** u-picker 的单列选项 */ typePickerColumns() { return this.typePickerItems.map((item) => item.label); }, typeFilterLabel() { if (!this.typeFilter) return "全部类型"; const hit = this.typeOptions.find((item) => item.value === this.typeFilter); return hit ? hit.label : "全部类型"; }, hasMore() { return !this.finished && this.list.length < this.total; }, emptyText() { if (this.loading) return "加载中…"; return this.adminMode ? "暂无申请记录" : "暂无相关申请"; }, }, onShow() { // 从详情页返回时刷新,保证新状态立即可见 if (!this.loading) this.loadList(true); }, onReachBottom() { if (this.hasMore) this.loadList(false); }, onPullDownRefresh() { this.loadList(true).then(() => uni.stopPullDownRefresh()); }, methods: { async loadList(reset = true) { if (reset) { if (this.loading) return; this.loading = true; this.pageNum = 1; this.finished = false; } else { if (this.loadingMore || !this.hasMore) return; this.loadingMore = true; this.pageNum += 1; } const params = { pageNum: this.pageNum, size: this.size, approvalStatus: this.statusFilter || undefined, businessType: this.typeFilter || undefined, keyword: this.keyword ? String(this.keyword).trim() : undefined, }; try { const fetcher = this.adminMode ? listAdminApplications : listMyApplications; const page = await fetcher(params, false); const rows = (page.list || []).map(adaptEssApplication); this.list = reset ? rows : this.list.concat(rows); this.total = page.total || this.list.length; // 本页未满则认为是最后一页 this.finished = rows.length < this.size; } catch (error) { if (reset) this.list = []; this.finished = true; uni.showToast({ title: (error && error.message) || "申请列表加载失败", icon: "none", }); } finally { this.loading = false; this.loadingMore = false; } }, onTabChange(index) { if (this.tabIndex === index) return; this.tabIndex = index; this.loadList(true); }, onKeywordConfirm() { // 想先收起键盘再查。注意别写成 (a && a.b)():当 a 不存在时该表达式是 undefined, // 后面再 () 就 TypeError,会把 loadList 一起中断 —— 表现为「点搜索没反应/报错,列表不变」。 const input = this.$refs && this.$refs.keywordInput; if (input && typeof input.blur === "function") input.blur(); this.loadList(true); }, /** 类型筛选(u-picker 底部滚轮,替代 actionSheet) */ chooseType() { this.typePickerItems = [{ value: "", label: "全部类型" }].concat(this.typeOptions); this.typePickerShow = true; }, onTypeConfirm(e) { const index = (e && e.indexs && e.indexs[0]) || 0; this.typePickerShow = false; const picked = this.typePickerItems[index]; if (!picked) return; this.typeFilter = picked.value; this.loadList(true); }, /** 打开「申请详情」:按 businessType 跳到对应页面的只读详情(管理端恒只读) */ openItem(row) { openEssApplication(row, { admin: this.adminMode }); }, /** * 打开「审批流程」:公共流程详情页(与首页待办点进去的是同一个页面)。 * 没有流程实例时给提示,不跳空白页。 */ openFlow(row) { const processInstanceId = row && row.processInstanceId; if (!processInstanceId) { uni.showToast({ title: "该申请暂无审批流程", icon: "none" }); return; } uni.navigateTo({ url: `/pages/home/wt/components/detail?processInstanceId=${processInstanceId}`, }); }, }, };