| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- <template>
- <view class="swh-page">
- <view class="filter-card">
- <view class="filter-title">数据填报</view>
- <view class="filter-subtitle">填报并维护各期生产运营双周会数据</view>
- <view class="filter-field">
- <text>专业公司</text>
- <uni-data-select v-model="deptId" :localdata="companyOptions" placeholder="请选择专业公司" />
- </view>
- <view class="filter-field">
- <text>会议日期</text>
- <uni-datetime-picker v-model="meetingDate" type="daterange" return-type="string" />
- </view>
- <view class="filter-actions">
- <button class="plain-btn" @click="resetQuery">重置</button>
- <button class="primary-btn" @click="search">查询</button>
- </view>
- </view>
- <view class="list-head">
- <text>会议记录({{ total }})</text>
- <button class="create-btn" @click="openForm('create')">+ 新建</button>
- </view>
- <view v-if="loading" class="state"><uni-load-more status="loading" /></view>
- <view v-else-if="!list.length" class="state"><text>暂无会议数据</text></view>
- <view v-else class="card-list">
- <view v-for="item in list" :key="item.id" class="meeting-card">
- <view class="card-head">
- <view class="series">{{ item.meetingSeries || "-" }}</view>
- <view class="date">{{ formatDate(item.meetingDate) }}</view>
- </view>
- <view class="company">
- <uni-icons type="staff" size="16" color="#64748b" />
- <text>{{ item.companyName || "-" }}</text>
- </view>
- <view class="card-actions">
- <text @click="openForm('view', item.id)">查看</text>
- <text class="edit" @click="openForm('edit', item.id)">编辑</text>
- </view>
- </view>
- </view>
- <uni-load-more
- v-if="list.length"
- :status="loadStatus"
- :content-text="loadText"
- @clickLoadMore="loadMore"
- />
- </view>
- </template>
- <script setup>
- import { computed, ref } from "vue";
- import { onLoad, onReachBottom, onShow } from "@dcloudio/uni-app";
- import dayjs from "dayjs";
- import {
- getOperationMeetingCompanies,
- getOperationMeetingPage,
- } from "@/api/operationMeeting";
- const meetingDate = ref([]);
- const deptId = ref("");
- const companyOptions = ref([]);
- const list = ref([]);
- const total = ref(0);
- const pageNo = ref(1);
- const pageSize = 10;
- const loading = ref(false);
- const loadingMore = ref(false);
- const hasMore = computed(() => list.value.length < total.value);
- const loadStatus = computed(() =>
- loadingMore.value ? "loading" : hasMore.value ? "more" : "noMore",
- );
- const loadText = {
- contentdown: "上拉加载更多",
- contentrefresh: "加载中",
- contentnomore: "没有更多数据了",
- };
- const fetchList = async (append = false) => {
- append ? (loadingMore.value = true) : (loading.value = true);
- try {
- const res = await getOperationMeetingPage({
- pageNo: pageNo.value,
- pageSize,
- deptId: deptId.value || undefined,
- meetingDate: meetingDate.value?.length
- ? [
- `${meetingDate.value[0]} 00:00:00`,
- `${meetingDate.value[1]} 23:59:59`,
- ]
- : undefined,
- });
- const data = res?.data || {};
- const rows = data.list || [];
- list.value = append ? [...list.value, ...rows] : rows;
- total.value = data.total || 0;
- } finally {
- loading.value = false;
- loadingMore.value = false;
- }
- };
- const search = () => {
- pageNo.value = 1;
- fetchList();
- };
- const resetQuery = () => {
- meetingDate.value = [];
- deptId.value = "";
- search();
- };
- const loadMore = () => {
- if (!hasMore.value || loadingMore.value) return;
- pageNo.value += 1;
- fetchList(true);
- };
- const openForm = (type, id) => {
- const query = id ? `?type=${type}&id=${id}` : `?type=${type}`;
- uni.navigateTo({ url: `/pages/swh/form${query}` });
- };
- const formatDate = (value) => (value ? dayjs(value).format("YYYY-MM-DD") : "-");
- onLoad(async () => {
- const res = await getOperationMeetingCompanies();
- companyOptions.value = (Array.isArray(res?.data) ? res.data : [])
- .filter((item) => item.type === "1")
- .map((item) => ({ text: item.name, value: item.id }));
- });
- onShow(search);
- onReachBottom(loadMore);
- </script>
- <style lang="scss" scoped>
- .swh-page { min-height: 100vh; padding: 24rpx; box-sizing: border-box; background: #f4f7fb; }
- .filter-card, .meeting-card { background: #fff; border-radius: 20rpx; box-shadow: 0 8rpx 28rpx rgba(30, 64, 175, .05); }
- .filter-card { padding: 30rpx 26rpx; }
- .filter-title { color: #0f172a; font-size: 36rpx; font-weight: 700; }
- .filter-subtitle { margin: 8rpx 0 26rpx; color: #94a3b8; font-size: 24rpx; }
- .filter-field + .filter-field { margin-top: 20rpx; }
- .filter-field > text { display: block; margin-bottom: 10rpx; color: #64748b; font-size: 24rpx; }
- .filter-actions { display: flex; margin-top: 24rpx; }
- .filter-actions button { flex: 1; height: 72rpx; margin: 0; line-height: 72rpx; font-size: 28rpx; border-radius: 14rpx; }
- .filter-actions button + button { margin-left: 18rpx; }
- .plain-btn { color: #475569; background: #f1f5f9; }
- .primary-btn, .create-btn { color: #fff; background: #2563eb; }
- .list-head { display: flex; align-items: center; justify-content: space-between; margin: 30rpx 4rpx 20rpx; color: #172033; font-weight: 700; }
- .create-btn { width: 150rpx; height: 64rpx; line-height: 64rpx; margin: 0; font-size: 26rpx; border-radius: 12rpx; }
- .card-list { padding-bottom: 20rpx; }
- .meeting-card + .meeting-card { margin-top: 20rpx; }
- .meeting-card { padding: 26rpx; }
- .card-head { display: flex; justify-content: space-between; align-items: center; }
- .series { color: #1d4ed8; font-size: 32rpx; font-weight: 700; }
- .date { color: #64748b; font-size: 24rpx; }
- .company { display: flex; align-items: center; margin-top: 22rpx; color: #334155; font-size: 28rpx; }
- .company text { margin-left: 10rpx; }
- .card-actions { display: flex; justify-content: flex-end; margin-top: 24rpx; padding-top: 20rpx; border-top: 1rpx solid #eef2f7; color: #16a34a; font-size: 26rpx; }
- .card-actions .edit { margin-left: 42rpx; color: #2563eb; }
- .state { padding: 100rpx 0; color: #94a3b8; text-align: center; }
- button::after { border: 0; }
- </style>
|