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