| | |
| | | isDynamicOptionSource, |
| | | resolveSelectDisplayLabel, |
| | | } from "../approve-template/selectOptionSource.js"; |
| | | import { |
| | | appendDotNotationQuery, |
| | | buildApprovalInstanceSearchDto, |
| | | } from "../approve-shared/approvalInstanceListSearch.js"; |
| | | |
| | | /** 审æ¹ç±»åï¼ä¸åç«¯åæ®µ approvalType 对é½ï¼åæå¯åæ¥ï¼ */ |
| | | export const APPROVAL_TYPE_OPTIONS = [ |
| | |
| | | }; |
| | | } |
| | | |
| | | export function buildApprovalInstanceListParams({ page, searchForm, businessType, extraParams }) { |
| | | const extra = { ...(extraParams && typeof extraParams === "object" ? extraParams : {}) }; |
| | | if (extra.createTime != null && extra.createTimeStart == null) { |
| | | extra.createTimeStart = extra.createTime; |
| | | export function buildApprovalInstanceListParams({ |
| | | page, |
| | | searchForm, |
| | | businessType, |
| | | extraParams, |
| | | }) { |
| | | const dto = buildApprovalInstanceSearchDto(searchForm, extraParams); |
| | | const bizType = businessType ?? searchForm?.businessType; |
| | | if (bizType != null && bizType !== "") { |
| | | dto.businessType = bizType; |
| | | } |
| | | delete extra.createTime; |
| | | |
| | | const params = { |
| | | current: page.current, |
| | | size: page.size, |
| | | ...extra, |
| | | "page.current": page.current, |
| | | "page.size": page.size, |
| | | ...dto, |
| | | }; |
| | | const bizType = businessType ?? searchForm?.businessType; |
| | | if (bizType != null && bizType !== "") { |
| | | params.businessType = bizType; |
| | | } |
| | | if (searchForm?.status) { |
| | | params.status = searchForm.status; |
| | | } |
| | | const range = |
| | | searchForm?.createTimeRange ?? |
| | | searchForm?.applyDateRange ?? |
| | | searchForm?.transferDateRange; |
| | | if (Array.isArray(range) && range[0]) { |
| | | params.createTimeStart = range[0]; |
| | | } |
| | | if (Array.isArray(range) && range[1]) { |
| | | params.createTimeEnd = range[1]; |
| | | } |
| | | appendDotNotationQuery(params, "approvalInstanceDto", dto); |
| | | return params; |
| | | } |
| | | |
| | |
| | | formatFieldDisplayValue, |
| | | resolveInstanceFormFields, |
| | | } from "../approve-list/approveListConstants.js"; |
| | | import { |
| | | INSTANCE_NO_SEARCH_MODULE_KEYS, |
| | | INSTANCE_NO_TABLE_COLUMN, |
| | | } from "./approvalInstanceListSearch.js"; |
| | | |
| | | /** å表/详æ
ä¸åæ¾ä¸ºç¬ç«åçå¡«æ¥é¡¹ keyï¼é¿å
è¦çå®ä¾ç³»ç»åæ®µï¼ */ |
| | | const DEFAULT_EXCLUDE_KEYS = new Set([ |
| | |
| | | */ |
| | | export function buildInstanceTableColumns(tableDataRef, buildTableActions, options = {}) { |
| | | const { |
| | | moduleKey, |
| | | excludeKeys = DEFAULT_EXCLUDE_KEYS, |
| | | beforeFormColumns = [], |
| | | extraColumns = [], |
| | |
| | | actionWidth = 260, |
| | | } = options; |
| | | |
| | | const leadingCols = |
| | | moduleKey && INSTANCE_NO_SEARCH_MODULE_KEYS.has(moduleKey) |
| | | ? [INSTANCE_NO_TABLE_COLUMN] |
| | | : []; |
| | | |
| | | return computed(() => { |
| | | const formCols = getFormConfigFieldColumns(tableDataRef.value?.[0], { excludeKeys }); |
| | | return [ |
| | | ...leadingCols, |
| | | ...beforeFormColumns, |
| | | ...formCols, |
| | | ...extraColumns, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { APPROVAL_MODULE_KEYS } from "./approvalModuleRegistry.js"; |
| | | |
| | | /** æ¯æå®¡æ¹åå·æ¥è¯¢/主表å±ç¤ºç审æ¹ç³è¯·æ¨¡å */ |
| | | export const INSTANCE_NO_SEARCH_MODULE_KEYS = new Set([ |
| | | APPROVAL_MODULE_KEYS.REGULAR, |
| | | APPROVAL_MODULE_KEYS.TRANSFER, |
| | | APPROVAL_MODULE_KEYS.WORK_HANDOVER, |
| | | APPROVAL_MODULE_KEYS.LEAVE, |
| | | APPROVAL_MODULE_KEYS.OVERTIME, |
| | | ]); |
| | | |
| | | export const INSTANCE_NO_TABLE_COLUMN = { |
| | | label: "审æ¹åå·", |
| | | prop: "instanceNo", |
| | | width: 170, |
| | | showOverflowTooltip: true, |
| | | }; |
| | | |
| | | /** æå¹³å为 Spring GET å¯ç»å®ç queryï¼approvalInstanceDto.xxxï¼å¿ç¨æ¹æ¬å·ï¼ */ |
| | | export function appendDotNotationQuery(target, prefix, fields) { |
| | | if (!fields || typeof fields !== "object") return; |
| | | for (const [key, value] of Object.entries(fields)) { |
| | | if (value == null || value === "") continue; |
| | | target[`${prefix}.${key}`] = value; |
| | | } |
| | | } |
| | | |
| | | function pickApplicantFromSearchForm(searchForm = {}) { |
| | | const out = {}; |
| | | const sf = searchForm || {}; |
| | | const name = (sf.applicantName || "").trim(); |
| | | const kw = (sf.applicantKeyword || "").trim(); |
| | | const id = sf.applicantId; |
| | | |
| | | if (name) out.applicantName = name; |
| | | if (kw) { |
| | | out.applicantName = kw; |
| | | if (/^\d+$/.test(kw)) out.applicantId = Number(kw); |
| | | } |
| | | if (id != null && id !== "") { |
| | | out.applicantId = typeof id === "number" ? id : Number(id) || id; |
| | | } |
| | | return out; |
| | | } |
| | | |
| | | function pickInstanceNoFromSearchForm(searchForm = {}) { |
| | | const no = (searchForm?.instanceNo || "").trim(); |
| | | return no ? { instanceNo: no } : {}; |
| | | } |
| | | |
| | | /** ç»è£
approvalInstanceDto æ¥è¯¢ç段ï¼ç³è¯·äºº + 审æ¹åå·ï¼ */ |
| | | export function buildApprovalInstanceSearchDto(searchForm = {}, extraParams = {}) { |
| | | const dto = { |
| | | ...(extraParams && typeof extraParams === "object" ? extraParams : {}), |
| | | }; |
| | | Object.assign(dto, pickApplicantFromSearchForm(searchForm)); |
| | | Object.assign(dto, pickInstanceNoFromSearchForm(searchForm)); |
| | | delete dto.createTime; |
| | | delete dto.createTimeStart; |
| | | delete dto.createTimeEnd; |
| | | return dto; |
| | | } |
| | | |
| | | function getRowPayloadValue(row, keys) { |
| | | const keyList = Array.isArray(keys) ? keys : [keys]; |
| | | const payload = row?.formPayload || {}; |
| | | for (const k of keyList) { |
| | | if (row?.[k] != null && row[k] !== "") return row[k]; |
| | | if (payload[k] != null && payload[k] !== "") return payload[k]; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | function matchApplicantKeyword(row, keyword) { |
| | | const kw = (keyword || "").trim().toLowerCase(); |
| | | if (!kw) return true; |
| | | const parts = [ |
| | | row?.applicantName, |
| | | row?.applicantNo, |
| | | row?.applicantId, |
| | | getRowPayloadValue(row, ["applicant", "applicantName", "applicantId"]), |
| | | ] |
| | | .filter((v) => v != null && v !== "") |
| | | .map((v) => String(v).toLowerCase()); |
| | | return parts.some((p) => p.includes(kw)); |
| | | } |
| | | |
| | | function matchApplicantId(row, applicantId) { |
| | | if (applicantId == null || applicantId === "") return true; |
| | | const id = String(applicantId); |
| | | if (row?.applicantId != null && String(row.applicantId) === id) return true; |
| | | const payloadApplicant = getRowPayloadValue(row, [ |
| | | "applicant", |
| | | "applicantId", |
| | | "applicantUserId", |
| | | ]); |
| | | return String(payloadApplicant) === id; |
| | | } |
| | | |
| | | function matchSelectValue(row, keys, expected) { |
| | | if (!expected) return true; |
| | | const raw = getRowPayloadValue(row, keys); |
| | | return String(raw) === String(expected); |
| | | } |
| | | |
| | | function matchInstanceNo(row, instanceNo) { |
| | | const kw = (instanceNo || "").trim().toLowerCase(); |
| | | if (!kw) return true; |
| | | const parts = [row?.instanceNo, row?.bizId] |
| | | .filter((v) => v != null && v !== "") |
| | | .map((v) => String(v).toLowerCase()); |
| | | return parts.some((p) => p.includes(kw)); |
| | | } |
| | | |
| | | /** æ¯å¦åå¨å表ç鿡件ï¼ç³è¯·äºº / 审æ¹åå·ï¼ */ |
| | | export function hasActiveModuleSearch(moduleKey, searchForm = {}) { |
| | | const sf = searchForm || {}; |
| | | if ((sf.instanceNo || "").trim()) return true; |
| | | if ((sf.applicantKeyword || "").trim()) return true; |
| | | if ((sf.applicantName || "").trim()) return true; |
| | | return sf.applicantId != null && sf.applicantId !== ""; |
| | | } |
| | | |
| | | /** æç³è¯·äººã审æ¹åå·åå端å
åºçé */ |
| | | export function filterInstanceRowsByModuleSearch(moduleKey, rows, searchForm = {}) { |
| | | const sf = searchForm || {}; |
| | | const list = Array.isArray(rows) ? rows : []; |
| | | if (!hasActiveModuleSearch(moduleKey, sf)) return list; |
| | | |
| | | return list.filter( |
| | | (row) => |
| | | matchInstanceNo(row, sf.instanceNo) && |
| | | matchApplicantId(row, sf.applicantId) && |
| | | matchApplicantKeyword(row, sf.applicantKeyword || sf.applicantName) |
| | | ); |
| | | } |
| | |
| | | } from "../approve-template/selectOptionSource.js"; |
| | | import { enrichInstanceRowFromFormConfig } from "./approvalInstanceFormConfigTable.js"; |
| | | import { |
| | | filterInstanceRowsByModuleSearch, |
| | | hasActiveModuleSearch, |
| | | } from "./approvalInstanceListSearch.js"; |
| | | import { |
| | | getApprovalModuleConfig, |
| | | getModuleListBusinessType, |
| | | resolveModuleBusinessType, |
| | |
| | | const caches = await fetchSelectOptionCaches( |
| | | collectOptionSourcesFromFields(allFields) |
| | | ); |
| | | tableData.value = mapped.map((row) => mapListRow(row, caches)); |
| | | page.total = total; |
| | | let rows = mapped.map((row) => mapListRow(row, caches)); |
| | | if (hasActiveModuleSearch(moduleKey, searchForm)) { |
| | | rows = filterInstanceRowsByModuleSearch(moduleKey, rows, searchForm); |
| | | } |
| | | tableData.value = rows; |
| | | page.total = hasActiveModuleSearch(moduleKey, searchForm) |
| | | ? rows.length |
| | | : total; |
| | | } catch { |
| | | tableData.value = []; |
| | | page.total = 0; |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ç³è¯·äººï¼</span> |
| | | <span class="search_title">审æ¹åå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.instanceNo" |
| | | style="width: 220px" |
| | | placeholder="请è¾å
¥å®¡æ¹åå·" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·äººï¼</span> |
| | | <el-input |
| | | v-model="searchForm.applicantKeyword" |
| | | style="width: 220px" |
| | |
| | | :prefix-icon="Search" |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">请åç±»åï¼</span> |
| | | <el-select v-model="searchForm.leaveType" placeholder="å
¨é¨" clearable style="width: 180px"> |
| | | <el-option v-for="opt in LEAVE_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" /> |
| | | </el-select> |
| | | <el-button type="primary" style="margin-left: 10px" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </div> |
| | |
| | | } |
| | | |
| | | const searchForm = reactive({ |
| | | instanceNo: "", |
| | | applicantKeyword: "", |
| | | leaveType: "", |
| | | }); |
| | | |
| | | function validateLeaveBeforeSave() { |
| | |
| | | } |
| | | ); |
| | | |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions); |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, { |
| | | moduleKey: APPROVAL_MODULE_KEYS.LEAVE, |
| | | }); |
| | | |
| | | function onSearch() { |
| | | handleQuery(searchForm); |
| | | } |
| | | |
| | | function resetSearch() { |
| | | searchForm.instanceNo = ""; |
| | | searchForm.applicantKeyword = ""; |
| | | searchForm.leaveType = ""; |
| | | onSearch(); |
| | | } |
| | | |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ç³è¯·äººï¼</span> |
| | | <span class="search_title">审æ¹åå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.instanceNo" |
| | | style="width: 220px" |
| | | placeholder="请è¾å
¥å®¡æ¹åå·" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·äººï¼</span> |
| | | <el-input |
| | | v-model="searchForm.applicantKeyword" |
| | | style="width: 220px" |
| | |
| | | :prefix-icon="Search" |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">å çç±»åï¼</span> |
| | | <el-select v-model="searchForm.overtimeType" placeholder="å
¨é¨" clearable style="width: 180px"> |
| | | <el-option v-for="opt in OVERTIME_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" /> |
| | | </el-select> |
| | | <el-button type="primary" style="margin-left: 10px" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </div> |
| | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const searchForm = reactive({ |
| | | instanceNo: "", |
| | | applicantKeyword: "", |
| | | overtimeType: "", |
| | | }); |
| | | |
| | | const mod = useApprovalInstanceModule({ |
| | |
| | | } |
| | | } |
| | | |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions); |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, { |
| | | moduleKey: APPROVAL_MODULE_KEYS.OVERTIME, |
| | | }); |
| | | |
| | | function onSearch() { |
| | | handleQuery(searchForm); |
| | | } |
| | | |
| | | function resetSearch() { |
| | | searchForm.instanceNo = ""; |
| | | searchForm.applicantKeyword = ""; |
| | | searchForm.overtimeType = ""; |
| | | onSearch(); |
| | | } |
| | | |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ç³è¯·äººï¼</span> |
| | | <span class="search_title">审æ¹åå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.instanceNo" |
| | | style="width: 220px" |
| | | placeholder="请è¾å
¥å®¡æ¹åå·" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·äººï¼</span> |
| | | <el-input |
| | | v-model="searchForm.applicantName" |
| | | style="width: 220px" |
| | |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·æ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.applyDateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§" |
| | | end-placeholder="ç»æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 260px" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" style="margin-left: 10px" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | |
| | | import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js"; |
| | | |
| | | const searchForm = reactive({ |
| | | instanceNo: "", |
| | | applicantName: "", |
| | | applyDateRange: null, |
| | | }); |
| | | |
| | | const mod = useApprovalInstanceModule({ |
| | |
| | | |
| | | const { flowUserOptions, loadFlowUsers } = useFlowUserOptions(); |
| | | |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions); |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, { |
| | | moduleKey: APPROVAL_MODULE_KEYS.REGULAR, |
| | | }); |
| | | |
| | | function onSearch() { |
| | | handleQuery(searchForm); |
| | | } |
| | | |
| | | function resetSearch() { |
| | | searchForm.instanceNo = ""; |
| | | searchForm.applicantName = ""; |
| | | searchForm.applyDateRange = null; |
| | | onSearch(); |
| | | } |
| | | |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ç³è¯·äººï¼</span> |
| | | <span class="search_title">审æ¹åå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.instanceNo" |
| | | style="width: 220px" |
| | | placeholder="请è¾å
¥å®¡æ¹åå·" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·äººï¼</span> |
| | | <el-select |
| | | v-model="searchForm.applicantId" |
| | | filterable |
| | |
| | | :value="u.userId" |
| | | /> |
| | | </el-select> |
| | | <span class="search_title" style="margin-left: 12px">è½¬å²æ¶é´ï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.transferDateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§" |
| | | end-placeholder="ç»æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 260px" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" style="margin-left: 10px" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </div> |
| | |
| | | } |
| | | |
| | | const searchForm = reactive({ |
| | | instanceNo: "", |
| | | applicantId: "", |
| | | transferDateRange: null, |
| | | }); |
| | | |
| | | const mod = useApprovalInstanceModule({ |
| | | moduleKey: APPROVAL_MODULE_KEYS.TRANSFER, |
| | | buildExtraListParams() { |
| | | return {}; |
| | | }, |
| | | }); |
| | | |
| | | const { |
| | |
| | | } |
| | | ); |
| | | |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions); |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, { |
| | | moduleKey: APPROVAL_MODULE_KEYS.TRANSFER, |
| | | }); |
| | | |
| | | function onSearch() { |
| | | handleQuery(searchForm); |
| | | } |
| | | |
| | | async function resetSearch() { |
| | | searchForm.instanceNo = ""; |
| | | searchForm.applicantId = ""; |
| | | searchForm.transferDateRange = null; |
| | | onSearch(); |
| | | await remoteSearchApplicant(""); |
| | | } |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ç³è¯·äººï¼</span> |
| | | <span class="search_title">审æ¹åå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.instanceNo" |
| | | style="width: 220px" |
| | | placeholder="请è¾å
¥å®¡æ¹åå·" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·äººï¼</span> |
| | | <el-select |
| | | v-model="searchForm.applicantId" |
| | | filterable |
| | |
| | | :label="userSelectLabel(u)" |
| | | :value="u.userId" |
| | | /> |
| | | </el-select> |
| | | <span class="search_title" style="margin-left: 12px">交æ¥ç¶æï¼</span> |
| | | <el-select v-model="searchForm.handoverStatus" placeholder="å
¨é¨" clearable style="width: 140px"> |
| | | <el-option v-for="o in handoverStatusOptions" :key="o.value" :label="o.label" :value="o.value" /> |
| | | </el-select> |
| | | <span class="search_title" style="margin-left: 12px">交æ¥ç±»åï¼</span> |
| | | <el-select v-model="searchForm.handoverType" placeholder="å
¨é¨" clearable style="width: 140px"> |
| | | <el-option v-for="o in handoverTypeOptions" :key="o.value" :label="o.label" :value="o.value" /> |
| | | </el-select> |
| | | <el-button type="primary" style="margin-left: 10px" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | |
| | | ]; |
| | | |
| | | const searchForm = reactive({ |
| | | instanceNo: "", |
| | | applicantId: "", |
| | | handoverStatus: "", |
| | | handoverType: "", |
| | | }); |
| | | |
| | | const mod = useApprovalInstanceModule({ |
| | |
| | | } |
| | | } |
| | | |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions); |
| | | const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, { |
| | | moduleKey: APPROVAL_MODULE_KEYS.WORK_HANDOVER, |
| | | }); |
| | | |
| | | function onSearch() { |
| | | handleQuery(searchForm); |
| | | } |
| | | |
| | | async function resetSearch() { |
| | | searchForm.instanceNo = ""; |
| | | searchForm.applicantId = ""; |
| | | searchForm.handoverStatus = ""; |
| | | searchForm.handoverType = ""; |
| | | onSearch(); |
| | | await remoteSearchApplicant(""); |
| | | } |
| | |
| | | :prefix-icon="Search" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">ç³è¯·æ¶é´ï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.applyTimeFrom" |
| | | type="date" |
| | | placeholder="å¼å§æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 150px" |
| | | clearable |
| | | /> |
| | | <span class="search_title" style="margin-left: 8px">è³</span> |
| | | <el-date-picker |
| | | v-model="searchForm.applyTimeTo" |
| | | type="date" |
| | | placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 150px; margin-left: 8px" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" style="margin-left: 10px" @click="handleQuery">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </div> |
| | |
| | | import { |
| | | buildCostReimbursementSaveDto, |
| | | buildFinReimbursementListParams, |
| | | filterReimbursementRowsBySearch, |
| | | hasActiveReimbursementSearch, |
| | | canDeleteReimbursementRow, |
| | | canEditReimbursementRow, |
| | | enrichReimbursementListRowsWithApprovalFlow, |
| | |
| | | |
| | | const searchForm = reactive({ |
| | | applicantKeyword: "", |
| | | applyTimeFrom: "", |
| | | applyTimeTo: "", |
| | | }); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ current: 1, size: 10, total: 0 }); |
| | |
| | | mapped, |
| | | FIN_REIMBURSEMENT_TYPE.COST |
| | | ); |
| | | if (hasActiveReimbursementSearch(searchForm)) { |
| | | mapped = filterReimbursementRowsBySearch(mapped, searchForm); |
| | | } |
| | | allRows.value = mapped; |
| | | const dropped = records.length - filtered.length; |
| | | page.total = |
| | | let nextTotal = |
| | | dropped > 0 ? Math.max(0, Number(total) - dropped) : Number(total); |
| | | if (hasActiveReimbursementSearch(searchForm)) { |
| | | nextTotal = mapped.length; |
| | | } |
| | | page.total = nextTotal; |
| | | } catch { |
| | | allRows.value = []; |
| | | page.total = 0; |
| | |
| | | |
| | | function resetSearch() { |
| | | searchForm.applicantKeyword = ""; |
| | | searchForm.applyTimeFrom = ""; |
| | | searchForm.applyTimeTo = ""; |
| | | handleQuery(); |
| | | } |
| | | |
| | |
| | | function pickApplicantQuery(searchForm = {}) { |
| | | const kw = (searchForm.applicantKeyword || "").trim(); |
| | | if (!kw) return {}; |
| | | if (/[\u4e00-\u9fa5]/.test(kw)) return { applicantName: kw }; |
| | | return { applicantCode: kw }; |
| | | // å ä½ãå§åæç¼å·ãï¼å§åèµ° applicantNameï¼ç¼å·å¦ä¼ applicantCode |
| | | const out = { applicantName: kw }; |
| | | if (!/[\u4e00-\u9fa5]/.test(kw)) { |
| | | out.applicantCode = kw; |
| | | } |
| | | return out; |
| | | } |
| | | |
| | | /** ç»è£
listPage æ¥è¯¢åæ°ï¼page + finReimbursementDtoï¼ */ |
| | | /** æ¯å¦åå¨å表ç鿡件ï¼ä»
ç³è¯·äººï¼ */ |
| | | export function hasActiveReimbursementSearch(searchForm = {}) { |
| | | return Boolean((searchForm?.applicantKeyword || "").trim()); |
| | | } |
| | | |
| | | /** æå¡ç«¯æªçææ¶ï¼æç³è¯·äººåå端å
åºçé */ |
| | | export function filterReimbursementRowsBySearch(rows, searchForm = {}) { |
| | | const list = Array.isArray(rows) ? rows : []; |
| | | const kw = (searchForm?.applicantKeyword || "").trim().toLowerCase(); |
| | | if (!kw) return list; |
| | | |
| | | return list.filter((row) => { |
| | | const parts = [ |
| | | row.applicantName, |
| | | row.employeeName, |
| | | row.applicantNo, |
| | | row.applicantCode, |
| | | row.employeeNo, |
| | | ] |
| | | .filter((v) => v != null && v !== "") |
| | | .map((v) => String(v).toLowerCase()); |
| | | return parts.some((p) => p.includes(kw)); |
| | | }); |
| | | } |
| | | |
| | | /** æå¹³å为 Spring GET å¯ç»å®ç queryï¼finReimbursementDto.xxxï¼å¿ç¨æ¹æ¬å·ï¼ */ |
| | | function appendDotNotationQuery(target, prefix, fields) { |
| | | if (!fields || typeof fields !== "object") return; |
| | | for (const [key, value] of Object.entries(fields)) { |
| | | if (value == null || value === "") continue; |
| | | target[`${prefix}.${key}`] = value; |
| | | } |
| | | } |
| | | |
| | | /** ç»è£
listPage æ¥è¯¢åæ°ï¼æå¹³ page.* / finReimbursementDto.*ï¼ä¸ detail æ¥å£ä¸è´ï¼ */ |
| | | export function buildFinReimbursementListParams({ |
| | | page, |
| | | searchForm, |
| | |
| | | ...(extraDto && typeof extraDto === "object" ? extraDto : {}), |
| | | }; |
| | | |
| | | if (searchForm?.billStatus) { |
| | | dto.billStatus = searchForm.billStatus; |
| | | } |
| | | |
| | | const range = |
| | | searchForm?.createTimeRange ?? |
| | | searchForm?.applyDateRange ?? |
| | | (searchForm?.applyTimeFrom || searchForm?.applyTimeTo |
| | | ? [searchForm.applyTimeFrom, searchForm.applyTimeTo] |
| | | : null); |
| | | |
| | | if (Array.isArray(range) && range[0]) { |
| | | dto.createTimeStart = range[0]; |
| | | } |
| | | if (Array.isArray(range) && range[1]) { |
| | | dto.createTimeEnd = range[1]; |
| | | } |
| | | |
| | | if (reimbursementType === FIN_REIMBURSEMENT_TYPE.TRAVEL) { |
| | | if (searchForm?.travelStartFrom) { |
| | | dto.startTimeStart = searchForm.travelStartFrom; |
| | | } |
| | | if (searchForm?.travelEndTo) { |
| | | dto.endTimeEnd = searchForm.travelEndTo; |
| | | } |
| | | } |
| | | |
| | | return { |
| | | page: { |
| | | current: page.current, |
| | | size: page.size, |
| | | }, |
| | | finReimbursementDto: dto, |
| | | const params = { |
| | | current: page.current, |
| | | size: page.size, |
| | | "page.current": page.current, |
| | | "page.size": page.size, |
| | | ...dto, |
| | | }; |
| | | appendDotNotationQuery(params, "finReimbursementDto", dto); |
| | | return params; |
| | | } |
| | | |
| | | function pickTravelField(obj, keys) { |
| | |
| | | :prefix-icon="Search" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | <span class="search_title" style="margin-left: 12px">åºå·®å¼å§ï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.travelStartFrom" |
| | | type="date" |
| | | placeholder="å¼å§æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 150px" |
| | | clearable |
| | | /> |
| | | <span class="search_title" style="margin-left: 8px">ç»æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.travelEndTo" |
| | | type="date" |
| | | placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 150px" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" style="margin-left: 10px" @click="handleQuery">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </div> |
| | |
| | | import { computed, getCurrentInstance, nextTick, onMounted, reactive, ref } from "vue"; |
| | | import { |
| | | buildFinReimbursementListParams, |
| | | filterReimbursementRowsBySearch, |
| | | hasActiveReimbursementSearch, |
| | | buildTravelReimbursementSaveDto, |
| | | canDeleteReimbursementRow, |
| | | canEditReimbursementRow, |
| | |
| | | |
| | | const allRows = ref([]); |
| | | |
| | | const searchForm = reactive({ applicantKeyword: "", travelStartFrom: "", travelEndTo: "" }); |
| | | const searchForm = reactive({ applicantKeyword: "" }); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ current: 1, size: 10, total: 0 }); |
| | | const importInputRef = ref(null); |
| | |
| | | mapped, |
| | | FIN_REIMBURSEMENT_TYPE.TRAVEL |
| | | ); |
| | | if (hasActiveReimbursementSearch(searchForm)) { |
| | | mapped = filterReimbursementRowsBySearch(mapped, searchForm); |
| | | } |
| | | allRows.value = mapped; |
| | | const dropped = records.length - filtered.length; |
| | | page.total = |
| | | let nextTotal = |
| | | dropped > 0 ? Math.max(0, Number(total) - dropped) : Number(total); |
| | | if (hasActiveReimbursementSearch(searchForm)) { |
| | | nextTotal = mapped.length; |
| | | } |
| | | page.total = nextTotal; |
| | | } catch { |
| | | allRows.value = []; |
| | | page.total = 0; |
| | |
| | | |
| | | function resetSearch() { |
| | | searchForm.applicantKeyword = ""; |
| | | searchForm.travelStartFrom = ""; |
| | | searchForm.travelEndTo = ""; |
| | | handleQuery(); |
| | | } |
| | | |