<!--
|
业务审批列表筛选弹窗
|
-->
|
<template>
|
<up-popup :show="modelShow"
|
mode="bottom"
|
round
|
@close="closePopup">
|
<view class="oa-filter-popup">
|
<view class="oa-filter-head">筛选条件</view>
|
<scroll-view scroll-y
|
class="oa-filter-scroll">
|
<view v-for="field in fields"
|
:key="field.key"
|
class="oa-filter-field">
|
<text class="oa-field-label">{{ field.label }}</text>
|
|
<up-input v-if="field.type === 'input'"
|
v-model="localForm[field.key]"
|
:placeholder="field.placeholder || `请输入${field.label}`"
|
clearable
|
border="surround" />
|
|
<view v-else-if="field.type === 'daterange'"
|
class="oa-picker-row"
|
@click="openDateRange(field.key)">
|
<text :class="{ placeholder: !dateLabel(field.key) }">
|
{{ dateLabel(field.key) || `请选择${field.label}` }}
|
</text>
|
<up-icon name="calendar"
|
size="18"
|
color="#999" />
|
</view>
|
|
<view v-else-if="field.type === 'user'"
|
class="oa-picker-row"
|
@click="openUserPicker">
|
<text :class="{ placeholder: !userLabel }">
|
{{ userLabel || field.placeholder || '请选择申请人' }}
|
</text>
|
<up-icon name="arrow-down"
|
size="14"
|
color="#999" />
|
</view>
|
|
<view v-else-if="field.type === 'select'"
|
class="oa-picker-row"
|
@click="openSelect(field)">
|
<text :class="{ placeholder: !selectLabel(field) }">
|
{{ selectLabel(field) || `请选择${field.label}` }}
|
</text>
|
<up-icon name="arrow-down"
|
size="14"
|
color="#999" />
|
</view>
|
</view>
|
</scroll-view>
|
|
<view class="oa-filter-actions">
|
<up-button text="重置"
|
shape="circle"
|
@click="handleReset" />
|
<up-button type="primary"
|
text="确定"
|
shape="circle"
|
@click="handleConfirm" />
|
</view>
|
</view>
|
|
<up-calendar :show="calendarShow"
|
mode="range"
|
:maxDate="maxDate"
|
minDate="2020-01-01"
|
:monthNum="24"
|
@confirm="onDateConfirm"
|
@close="calendarShow = false" />
|
|
<up-picker :show="pickerShow"
|
:columns="pickerColumns"
|
keyName="label"
|
@confirm="onPickerConfirm"
|
@cancel="pickerShow = false"
|
@close="pickerShow = false" />
|
|
<up-popup :show="userPickerShow"
|
mode="bottom"
|
round
|
@close="userPickerShow = false">
|
<view class="oa-user-popup">
|
<view class="oa-user-popup-title">选择申请人</view>
|
<up-input v-model="userKeyword"
|
placeholder="搜索姓名或编号"
|
clearable
|
border="surround" />
|
<scroll-view scroll-y
|
class="oa-user-list">
|
<view v-for="u in filteredUsers"
|
:key="u.userId ?? u.id"
|
class="oa-user-item"
|
@click="pickUser(u)">
|
<text>{{ userSelectLabel(u) }}</text>
|
</view>
|
<view v-if="!filteredUsers.length"
|
class="oa-user-empty">暂无匹配用户</view>
|
</scroll-view>
|
</view>
|
</up-popup>
|
</up-popup>
|
</template>
|
|
<script setup>
|
import { computed, reactive, ref, watch } from "vue";
|
import dayjs from "dayjs";
|
import { userListNoPageByTenantId } from "@/api/system/user";
|
import {
|
formatDateRangeLabel,
|
getModuleSearchMeta,
|
resetModuleSearchForm,
|
userSelectLabel,
|
} from "../_utils/approvalModuleListSearch.js";
|
|
const props = defineProps({
|
show: { type: Boolean, default: false },
|
moduleKey: { type: String, required: true },
|
modelValue: { type: Object, default: () => ({}) },
|
});
|
|
const emit = defineEmits(["update:show", "update:modelValue", "search", "reset"]);
|
|
const modelShow = computed({
|
get: () => props.show,
|
set: v => emit("update:show", v),
|
});
|
|
function closePopup() {
|
emit("update:show", false);
|
}
|
|
const localForm = reactive({});
|
const calendarShow = ref(false);
|
const activeDateKey = ref("applyDateRange");
|
const maxDate = dayjs().format("YYYY-MM-DD");
|
const pickerShow = ref(false);
|
const pickerColumns = ref([[]]);
|
const activeSelectField = ref(null);
|
const userPickerShow = ref(false);
|
const userKeyword = ref("");
|
const allUsers = ref([]);
|
|
const fields = computed(() => getModuleSearchMeta(props.moduleKey).fields || []);
|
|
const userLabel = computed(() => {
|
const id = localForm.applicantId;
|
if (!id) return "";
|
const u = allUsers.value.find(x => String(x.userId ?? x.id) === String(id));
|
return u ? userSelectLabel(u) : String(id);
|
});
|
|
const filteredUsers = computed(() => {
|
const q = userKeyword.value.trim().toLowerCase();
|
const list = allUsers.value.filter(u => {
|
if (u.delFlag === "2" || u.delFlag === 2) return false;
|
if (u.status != null && String(u.status) !== "0") return false;
|
return true;
|
});
|
if (!q) return list.slice(0, 50);
|
return list
|
.filter(u => {
|
const nick = (u.nickName || "").toLowerCase();
|
const name = (u.userName || "").toLowerCase();
|
const id = String(u.userId ?? u.id ?? "");
|
return nick.includes(q) || name.includes(q) || id.includes(q);
|
})
|
.slice(0, 50);
|
});
|
|
function unwrapUsers(res) {
|
if (Array.isArray(res)) return res;
|
if (Array.isArray(res?.data)) return res.data;
|
if (Array.isArray(res?.rows)) return res.rows;
|
return [];
|
}
|
|
async function loadUsers() {
|
if (allUsers.value.length) return;
|
try {
|
const res = await userListNoPageByTenantId();
|
allUsers.value = unwrapUsers(res);
|
} catch {
|
allUsers.value = [];
|
}
|
}
|
|
watch(
|
() => props.show,
|
v => {
|
if (!v) return;
|
Object.assign(localForm, props.modelValue || {});
|
}
|
);
|
|
function dateLabel(key) {
|
return formatDateRangeLabel(localForm[key]);
|
}
|
|
function openDateRange(key) {
|
activeDateKey.value = key;
|
calendarShow.value = true;
|
}
|
|
function onDateConfirm(e) {
|
if (!e?.length) {
|
calendarShow.value = false;
|
return;
|
}
|
localForm[activeDateKey.value] = [e[0], e[e.length - 1]];
|
calendarShow.value = false;
|
}
|
|
function selectLabel(field) {
|
const val = localForm[field.key];
|
if (!val) return "";
|
const opt = (field.options || []).find(o => o.value === val);
|
return opt?.label || String(val);
|
}
|
|
function openSelect(field) {
|
activeSelectField.value = field;
|
pickerColumns.value = [field.options || []];
|
pickerShow.value = true;
|
}
|
|
function onPickerConfirm(e) {
|
const item = e?.value?.[0];
|
if (activeSelectField.value?.key && item) {
|
localForm[activeSelectField.value.key] = item.value;
|
}
|
pickerShow.value = false;
|
}
|
|
async function openUserPicker() {
|
await loadUsers();
|
userKeyword.value = "";
|
userPickerShow.value = true;
|
}
|
|
function pickUser(u) {
|
localForm.applicantId = u.userId ?? u.id ?? "";
|
userPickerShow.value = false;
|
}
|
|
function handleReset() {
|
resetModuleSearchForm(props.moduleKey, localForm);
|
emit("update:modelValue", { ...localForm });
|
emit("reset", { ...localForm });
|
emit("update:show", false);
|
}
|
|
function handleConfirm() {
|
emit("update:modelValue", { ...localForm });
|
emit("search", { ...localForm });
|
emit("update:show", false);
|
}
|
</script>
|
|
<style scoped lang="scss">
|
@import "../_styles/oa-approval-list.scss";
|
</style>
|