From a9d97b150701e634bdb751eab277696abd136cca Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 六月 2026 14:39:47 +0800
Subject: [PATCH] 君歌app 1.依照web端功能修改
---
src/pages/oa/_components/ApprovalModuleSearchPopup.vue | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 268 insertions(+), 0 deletions(-)
diff --git a/src/pages/oa/_components/ApprovalModuleSearchPopup.vue b/src/pages/oa/_components/ApprovalModuleSearchPopup.vue
new file mode 100644
index 0000000..522bd02
--- /dev/null
+++ b/src/pages/oa/_components/ApprovalModuleSearchPopup.vue
@@ -0,0 +1,268 @@
+<!--
+ 涓氬姟瀹℃壒鍒楄〃绛涢�夊脊绐�
+-->
+<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>
--
Gitblit v1.9.3