332 lines
8.3 KiB
Vue
332 lines
8.3 KiB
Vue
<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>
|