332 lines
8.3 KiB
Vue
Raw Normal View History

2025-04-22 10:22:33 +08:00
<template>
<view class="wh-full">
<!-- Remove :filters and @filter-change -->
<BasicListLayout @register="register">
<!-- Add #top slot for filters -->
<template #top>
<view class="filter-section">
<!-- Group Filter (Assuming 'group' key exists) -->
<view class="filter-item" @click="openFilterPopup('group')">
<text>全部分组</text>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
<!-- Sending Department Filter -->
<view class="filter-item" @click="openFilterPopup('sendingDept')">
<text>发文部门</text>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
<!-- Receiving Department Filter -->
<view class="filter-item" @click="openFilterPopup('receivingDept')">
<text>收文部门</text>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
</view>
</template>
<!-- Define how each item is displayed using the slot -->
<template v-slot:default="{ data }">
<view
class="document-item white-bg-color r-md p-15 mb-15"
@click="goToDetail(data.id)"
>
<view class="item-title font-bold text-lg mb-5">{{
data.title
}}</view>
<view class="item-meta color-9">
<text>发文{{ data.sendingDept }} {{ data.publishDate }}</text>
<text>收文{{ data.receivingDept }}</text>
</view>
</view>
</template>
</BasicListLayout>
<!-- Filter Popup -->
<uni-popup ref="filterPopupRef" type="bottom" background-color="#fff">
<view class="popup-content">
<view class="popup-header">
<text>{{ currentFilterTitle }}</text>
<uni-icons
type="closeempty"
size="20"
@click="closeFilterPopup"
></uni-icons>
</view>
<scroll-view scroll-y class="popup-options">
<view
class="option-item"
v-for="option in currentFilterOptions"
:key="option.value"
:class="{ active: isOptionSelected(option) }"
@click="selectFilterOption(option)"
>
{{ option.label }}
</view>
</scroll-view>
</view>
</uni-popup>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue";
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
// Placeholder types - replace with actual imports if found
interface FilterOption {
label: string;
value: string | number | null;
}
interface FilterConfig {
label: string;
key: string;
options: FilterOption[];
}
type Filters = FilterConfig[];
// Define the structure for a document item
interface DocumentItem {
id: string;
title: string;
sendingDept: string;
receivingDept: string;
publishDate: string;
// Add other relevant fields as needed
}
const mockTodoList = [
{
id: "1",
title: "公文1",
sendingDept: "办公室1",
receivingDept: "教务处1",
publishDate: "2024-01-01",
},
];
const testList = async (param: any): Promise<Requests<any>> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ message: "测试", resultCode: 1, rows: mockTodoList });
}, 1000);
});
};
const [register, { reload, setParam }] = useLayout({
api: testList,
componentProps: {},
});
// --- Event Handlers ---
const goToDetail = (id: string) => {
console.log("Navigating to detail for ID:", id);
uni.navigateTo({
url: `/pages/view/routine/GongWenLiuZhuan/detail?id=${id}`,
});
};
// --- Filter Popup Methods ---
const openFilterPopup = (type: "group" | "sendingDept" | "receivingDept") => {
currentFilterType.value = type;
filterPopupRef.value?.open();
};
const closeFilterPopup = () => {
filterPopupRef.value?.close();
};
const selectFilterOption = (option: FilterOption) => {
let paramsToSet: Record<string, any> = {};
switch (currentFilterType.value) {
case "group":
selectedGroup.value = option;
paramsToSet = { group: option.value };
break;
case "sendingDept":
selectedSendingDept.value = option;
paramsToSet = { sendingDept: option.value };
break;
case "receivingDept":
selectedReceivingDept.value = option;
paramsToSet = { receivingDept: option.value };
break;
}
setParam(paramsToSet);
reload(true); // Reload from page 1
closeFilterPopup();
};
// --- Filter State ---
const groups = ref<FilterOption[]>([
{ label: "全部分组", value: null },
{ label: "分组A", value: "groupA" },
{ label: "分组B", value: "groupB" },
]);
const sendingDepts = ref<FilterOption[]>([
{ label: "发文部门", value: null },
{ label: "办公室1", value: "办公室1" },
{ label: "办公室2", value: "办公室2" },
{ label: "办公室3", value: "办公室3" },
{ label: "办公室4", value: "办公室4" },
{ label: "办公室5", value: "办公室5" },
]);
const receivingDepts = ref<FilterOption[]>([
{ label: "收文部门", value: null },
{ label: "教务处1", value: "教务处1" },
{ label: "教务处2", value: "教务处2" },
{ label: "教务处3", value: "教务处3" },
]);
// --- Filter State ---
const selectedGroup = ref<FilterOption | null>(groups.value[0]);
const selectedSendingDept = ref<FilterOption | null>(sendingDepts.value[0]);
const selectedReceivingDept = ref<FilterOption | null>(receivingDepts.value[0]);
const filterPopupRef = ref<any>(null);
const currentFilterType = ref<"group" | "sendingDept" | "receivingDept" | null>(
null
);
// --- Computed Properties for Popup ---
const currentFilterOptions = computed(() => {
switch (currentFilterType.value) {
case "group":
return groups.value;
case "sendingDept":
return sendingDepts.value;
case "receivingDept":
return receivingDepts.value;
default:
return [];
}
});
const currentFilterTitle = computed(() => {
switch (currentFilterType.value) {
case "group":
return "选择分组";
case "sendingDept":
return "选择发文部门";
case "receivingDept":
return "选择收文部门";
default:
return "选择选项";
}
});
const isOptionSelected = (option: FilterOption) => {
switch (currentFilterType.value) {
case "group":
return selectedGroup.value?.value === option.value;
case "sendingDept":
return selectedSendingDept.value?.value === option.value;
case "receivingDept":
return selectedReceivingDept.value?.value === option.value;
default:
return false;
}
};
</script>
<style lang="scss" scoped>
.document-item {
// Add specific styles for document items if needed
cursor: pointer; // Indicate items are clickable
transition: background-color 0.2s ease;
&:hover {
background-color: #f9f9f9; // Slight hover effect
}
}
.item-title {
// Style for the title
}
.item-meta {
// Style for the metadata line
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
font-size: 24rpx;
}
.filter-section {
display: flex;
justify-content: space-around;
align-items: center;
padding: 20rpx 30rpx;
background-color: #ffffff;
border-bottom: 1rpx solid #e0e0e0;
position: sticky;
top: 0; // Adjust if necessary based on NavBar height
z-index: 10;
.filter-item {
display: flex;
align-items: center;
font-size: 28rpx;
color: #333;
padding: 10rpx;
cursor: pointer;
text {
margin-right: 8rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 180rpx; // Adjust width as needed
}
uni-icons {
color: #999;
}
}
}
.popup-content {
background-color: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
padding: 20rpx;
padding-bottom: 40rpx;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15rpx 10rpx;
font-size: 32rpx;
font-weight: bold;
border-bottom: 1rpx solid #eee;
margin-bottom: 10rpx;
}
.popup-options {
max-height: 60vh;
}
.option-item {
padding: 25rpx 20rpx;
font-size: 28rpx;
color: #333;
border-bottom: 1rpx solid #f5f5f5;
cursor: pointer;
&:last-child {
border-bottom: none;
}
&.active {
color: #409eff;
font-weight: bold;
}
&:hover {
background-color: #f9f9f9;
}
}
</style>