接龙调整
This commit is contained in:
parent
b578cf8c60
commit
de573ba4b5
@ -248,7 +248,12 @@ export const jlSaveApi = async (params: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 根据接龙ID查询接龙执行情况(学生列表)
|
// 根据接龙ID查询接龙执行情况(学生列表)
|
||||||
export const jlzxFindByJlParamsApi = async (params: { jlId: string }) => {
|
export const jlzxFindByJlParamsApi = async (params: {
|
||||||
|
jlId: string;
|
||||||
|
njId?: string;
|
||||||
|
njmcId?: string;
|
||||||
|
bjId?: string;
|
||||||
|
}) => {
|
||||||
return await get("/api/jlzx/findByJlParams", params);
|
return await get("/api/jlzx/findByJlParams", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -149,8 +149,8 @@ export function getGwFlowByIdApi(id: string) {
|
|||||||
/**
|
/**
|
||||||
* 分页查询某人的待办和已办公文
|
* 分页查询某人的待办和已办公文
|
||||||
*/
|
*/
|
||||||
export function findUserTodosApi(approveStatus: string, jsId: string, pageNum: number = 1, pageSize: number = 20) {
|
export function findUserTodosApi(dbZt: string, jsId: string, page: number = 1, rows: number = 20) {
|
||||||
return get('/api/gw/findUserTodos', { approveStatus, jsId, pageNum, pageSize });
|
return get('/api/gw/findUserTodos', { dbZt, jsId, page, rows });
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 新增:统一的流程接口 =====
|
// ===== 新增:统一的流程接口 =====
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
<YwTransfer ref="transferRef" @submit="handleTransfer" />
|
<YwTransfer ref="transferRef" @submit="handleTransfer" v-if="Transferflag" />
|
||||||
<XtDkJs ref="xtDkJsRef" @submit="handleXtDkJs" />
|
<XtDkJs ref="xtDkJsRef" @submit="handleXtDkJs" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -86,6 +86,7 @@ const dlgFlag = ref(false);
|
|||||||
const dlgType = ref("");
|
const dlgType = ref("");
|
||||||
const dlgTips = ref("");
|
const dlgTips = ref("");
|
||||||
const spRemark = ref("");
|
const spRemark = ref("");
|
||||||
|
const Transferflag = ref(false);
|
||||||
|
|
||||||
const goToMessage = () => {
|
const goToMessage = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -108,7 +109,11 @@ const closeDlg = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const showTransfer = () => {
|
const showTransfer = () => {
|
||||||
transferRef.value.showDlg();
|
Transferflag.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
transferRef.value.showDlg();
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showXtDlg = () => {
|
const showXtDlg = () => {
|
||||||
@ -160,6 +165,7 @@ const handleTransfer = async (data: any) => {
|
|||||||
uni.showLoading({ title: "正在转办..." });
|
uni.showLoading({ title: "正在转办..." });
|
||||||
await props.transferApi(params);
|
await props.transferApi(params);
|
||||||
transferRef.value.closeDlg();
|
transferRef.value.closeDlg();
|
||||||
|
Transferflag.value = false;
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
emit('transfer');
|
emit('transfer');
|
||||||
if (props.autoToMessage) {
|
if (props.autoToMessage) {
|
||||||
|
|||||||
@ -1,7 +1,76 @@
|
|||||||
<!-- src/pages/view/notice/detail.vue -->
|
<!-- src/pages/view/notice/detail.vue -->
|
||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout>
|
||||||
<view class="notice-detail-page">
|
<view class="jl-detail-page">
|
||||||
|
<!-- 顶部Tab -->
|
||||||
|
<view class="tab-container">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'progress' }"
|
||||||
|
@click="switchTab('progress')"
|
||||||
|
>
|
||||||
|
完成情况
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'detail' }"
|
||||||
|
@click="switchTab('detail')"
|
||||||
|
>
|
||||||
|
接龙详情
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 完成情况内容 -->
|
||||||
|
<view v-if="activeTab === 'progress'" class="progress-content">
|
||||||
|
<!-- 班级选择器 -->
|
||||||
|
<view class="section">
|
||||||
|
<text class="section-title">选择班级(可多选)</text>
|
||||||
|
<view class="class-selector" @click="showClassTree">
|
||||||
|
<text :class="{ placeholder: !selectedClassText }">{{ selectedClassText || "请选择班级" }}</text>
|
||||||
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<!-- 班级选择提示 -->
|
||||||
|
<view v-if="selectedClasses.length === 0" class="class-tip">
|
||||||
|
<text class="tip-icon">ℹ️</text>
|
||||||
|
<text class="tip-text">请先选择班级查看接龙完成情况</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 按班级统计信息 -->
|
||||||
|
<view v-if="selectedClasses.length > 0" class="section">
|
||||||
|
<view class="section-title">
|
||||||
|
接龙完成情况
|
||||||
|
<text class="refresh-btn" @click="loadAllClassData">刷新</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 每个班级的统计数据 -->
|
||||||
|
<view v-for="classData in classStatsList" :key="classData.bjId" class="class-stats-card">
|
||||||
|
<view class="class-header">
|
||||||
|
<text class="class-name">{{ classData.displayName }}</text>
|
||||||
|
<text class="class-completion">{{ classData.completionRate }}%</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="class-stats-grid">
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-number">{{ classData.total }}</text>
|
||||||
|
<text class="stat-label">总人数</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item clickable" @click="showStudentDrawer('completed', classData)">
|
||||||
|
<text class="stat-number completed">{{ classData.completed }}</text>
|
||||||
|
<text class="stat-label">已接龙</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item clickable" @click="showStudentDrawer('pending', classData)">
|
||||||
|
<text class="stat-number pending">{{ classData.pending }}</text>
|
||||||
|
<text class="stat-label">未接龙</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 接龙详情内容 -->
|
||||||
|
<view v-if="activeTab === 'detail'" class="detail-content">
|
||||||
<view v-if="isLoading" class="loading-indicator">加载中...</view>
|
<view v-if="isLoading" class="loading-indicator">加载中...</view>
|
||||||
<view v-else-if="noticeDetail" class="detail-container">
|
<view v-else-if="noticeDetail" class="detail-container">
|
||||||
<!-- 1. 主要内容卡片 -->
|
<!-- 1. 主要内容卡片 -->
|
||||||
@ -45,46 +114,104 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 3. 学生完成状态卡片 -->
|
</view>
|
||||||
<view class="info-card feedback-card">
|
<view v-else class="empty-state">通知详情未找到</view>
|
||||||
<text class="feedback-title">接龙完成情况 ({{ receivedCount }}/{{ totalStudents }})</text>
|
</view>
|
||||||
<view class="name-tags">
|
|
||||||
|
<!-- 班级选择树 -->
|
||||||
|
<BasicTree
|
||||||
|
ref="treeRef"
|
||||||
|
:range="treeData"
|
||||||
|
idKey="key"
|
||||||
|
rangeKey="title"
|
||||||
|
title="选择班级(可多选)"
|
||||||
|
:multiple="true"
|
||||||
|
:selectParent="false"
|
||||||
|
@confirm="onTreeConfirm"
|
||||||
|
@cancel="onTreeCancel"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 学生抽屉 -->
|
||||||
|
<view v-if="showDrawer" class="drawer-mask" @click="closeDrawer">
|
||||||
|
<view class="drawer-content" @click.stop>
|
||||||
|
<view class="drawer-header">
|
||||||
|
<text class="drawer-title">{{ drawerTitle }}</text>
|
||||||
|
<view class="drawer-close" @click="closeDrawer">
|
||||||
|
<uni-icons type="close" size="20" color="#666"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="drawer-body">
|
||||||
|
<view v-if="drawerStudents.length === 0" class="empty-state">
|
||||||
|
<text>暂无学生数据</text>
|
||||||
|
</view>
|
||||||
|
<view v-else class="student-list">
|
||||||
<view
|
<view
|
||||||
v-for="stu in studentList"
|
v-for="student in drawerStudents"
|
||||||
:key="stu.id || stu.xsId"
|
:key="student.id || student.xsId"
|
||||||
class="name-tag"
|
class="student-item"
|
||||||
:class="{ received: stu.jlwc_status === 'A' }"
|
|
||||||
>
|
>
|
||||||
<text>{{ stu.xsxm || stu.name }}</text>
|
<view class="student-avatar">
|
||||||
<view v-if="stu.jlwc_status === 'A'" class="checkmark-icon">
|
<image
|
||||||
<uni-icons type="checkmarkempty" size="12" color="#ffffff"></uni-icons>
|
:src="imagUrl(student.xstx) || '/static/images/default-avatar.png'"
|
||||||
|
mode="aspectFill"
|
||||||
|
class="avatar-img"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view class="student-info">
|
||||||
|
<text class="student-name">{{ student.xsxm || student.name }}</text>
|
||||||
|
<view class="student-status">
|
||||||
|
<view
|
||||||
|
class="status-tag"
|
||||||
|
:class="drawerType === 'completed' ? 'completed' : 'pending'"
|
||||||
|
>
|
||||||
|
{{ drawerType === 'completed' ? '已完成' : '未完成' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-else class="empty-state">通知详情未找到</view>
|
|
||||||
</view>
|
</view>
|
||||||
<template #bottom>
|
|
||||||
<view class="bottom-actions">
|
|
||||||
<button class="action-btn publish-btn">接龙</button>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, watch } from "vue";
|
import { ref, computed, watch, onMounted } from "vue";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import { getByJlIdApi, jlzxFindByJlParamsApi } from "@/api/base/server";
|
import { getByJlIdApi, jlzxFindByJlParamsApi, findAllNjBjTree } from "@/api/base/server";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { BASE_IMAGE_URL } from "@/config";
|
import { BASE_IMAGE_URL } from "@/config";
|
||||||
|
import BasicTree from '@/components/BasicTree/Tree.vue';
|
||||||
|
|
||||||
|
// Tab 状态
|
||||||
|
const activeTab = ref('progress');
|
||||||
|
|
||||||
|
// 基本信息
|
||||||
const noticeId = ref<string>("");
|
const noticeId = ref<string>("");
|
||||||
const noticeDetail = ref<any>(null);
|
const noticeDetail = ref<any>(null);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const studentList = ref<any[]>([]);
|
const descExpanded = ref(true);
|
||||||
const descExpanded = ref(false);
|
|
||||||
|
// 班级选择相关
|
||||||
|
const treeData = ref<any[]>([]);
|
||||||
|
const treeRef = ref();
|
||||||
|
const selectedClasses = ref<any[]>([]);
|
||||||
|
const selectedClassText = ref('');
|
||||||
|
|
||||||
|
// 班级统计数据
|
||||||
|
const classStatsList = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 学生抽屉相关
|
||||||
|
const showDrawer = ref(false);
|
||||||
|
const drawerType = ref('');
|
||||||
|
const drawerTitle = ref('');
|
||||||
|
const drawerStudents = ref<any[]>([]);
|
||||||
|
const currentClassData = ref<any>(null);
|
||||||
|
|
||||||
const descPreview = computed(() => {
|
const descPreview = computed(() => {
|
||||||
if (!noticeDetail.value?.jlms) return '';
|
if (!noticeDetail.value?.jlms) return '';
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
@ -99,32 +226,214 @@ const getFileName = (filePath: string) => {
|
|||||||
return parts[parts.length - 1] || filePath;
|
return parts[parts.length - 1] || filePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Computed properties for feedback status
|
// Tab 切换
|
||||||
const receivedCount = computed(() => {
|
const switchTab = (tab: string) => {
|
||||||
return studentList.value.filter((s) => s.jlwc_status === 'A').length;
|
activeTab.value = tab;
|
||||||
});
|
if (tab === 'progress') {
|
||||||
const totalStudents = computed(() => studentList.value.length);
|
loadClassTree();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载班级树数据
|
||||||
|
const loadClassTree = async () => {
|
||||||
|
try {
|
||||||
|
const res = await findAllNjBjTree();
|
||||||
|
console.log('【班级树API响应】', res);
|
||||||
|
|
||||||
|
if (res.resultCode === 1 && res.result) {
|
||||||
|
// 递归转换数据格式以适配 BasicTree 组件
|
||||||
|
const convertTreeData = (items: any[]): any[] => {
|
||||||
|
return items.map((item: any) => ({
|
||||||
|
key: item.key,
|
||||||
|
title: item.title,
|
||||||
|
njmcId: item.njmcId,
|
||||||
|
children: item.children ? convertTreeData(item.children) : [],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
treeData.value = convertTreeData(res.result);
|
||||||
|
console.log('【转换后的树数据】', treeData.value);
|
||||||
|
} else {
|
||||||
|
console.log('【API响应格式不正确】', res);
|
||||||
|
treeData.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载班级树失败:', error);
|
||||||
|
treeData.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示班级选择树
|
||||||
|
const showClassTree = () => {
|
||||||
|
if (treeRef.value) {
|
||||||
|
treeRef.value._show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 班级选择确认
|
||||||
|
const onTreeConfirm = (selectedNodes: any[]) => {
|
||||||
|
if (selectedNodes && selectedNodes.length > 0) {
|
||||||
|
selectedClasses.value = selectedNodes;
|
||||||
|
|
||||||
|
// 更新显示文本
|
||||||
|
if (selectedNodes.length === 1) {
|
||||||
|
selectedClassText.value = selectedNodes[0].title;
|
||||||
|
} else {
|
||||||
|
selectedClassText.value = `已选择${selectedNodes.length}个班级`;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAllClassData();
|
||||||
|
} else {
|
||||||
|
selectedClasses.value = [];
|
||||||
|
selectedClassText.value = '';
|
||||||
|
classStatsList.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 班级选择取消
|
||||||
|
const onTreeCancel = () => {
|
||||||
|
// 取消选择,不做任何操作
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载所有班级数据
|
||||||
|
const loadAllClassData = async () => {
|
||||||
|
if (selectedClasses.value.length === 0 || !noticeId.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
const classStatsPromises = selectedClasses.value.map(async (classNode) => {
|
||||||
|
try {
|
||||||
|
const stuRes = await jlzxFindByJlParamsApi({
|
||||||
|
jlId: noticeId.value,
|
||||||
|
bjId: classNode.key
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const students = stuRes?.rows || stuRes?.result || [];
|
||||||
|
|
||||||
|
// 处理学生状态兼容性
|
||||||
|
students.forEach((stu: any) => {
|
||||||
|
if (stu.jlwcStatus && !stu.jlwc_status) {
|
||||||
|
stu.jlwc_status = stu.jlwcStatus;
|
||||||
|
}
|
||||||
|
if (stu.jlwc_status === '1') {
|
||||||
|
stu.jlwc_status = 'A';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const completed = students.filter((s: any) => s.jlwc_status === 'A').length;
|
||||||
|
const total = students.length;
|
||||||
|
const pending = total - completed;
|
||||||
|
const completionRate = total > 0 ? Math.round((completed / total) * 100) : 0;
|
||||||
|
|
||||||
|
// 从学生数据中获取年级和班级名称
|
||||||
|
let njmc = '';
|
||||||
|
let bjmc = '';
|
||||||
|
if (students.length > 0) {
|
||||||
|
njmc = students[0].njmc || '';
|
||||||
|
bjmc = students[0].bjmc || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bjId: classNode.key,
|
||||||
|
className: classNode.title,
|
||||||
|
njmc,
|
||||||
|
bjmc,
|
||||||
|
displayName: njmc && bjmc ? `${njmc}${bjmc}` : classNode.title,
|
||||||
|
total,
|
||||||
|
completed,
|
||||||
|
pending,
|
||||||
|
completionRate
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`加载班级 ${classNode.title} 数据失败:`, error);
|
||||||
|
return {
|
||||||
|
bjId: classNode.key,
|
||||||
|
className: classNode.title,
|
||||||
|
total: 0,
|
||||||
|
completed: 0,
|
||||||
|
pending: 0,
|
||||||
|
completionRate: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = await Promise.all(classStatsPromises);
|
||||||
|
classStatsList.value = results;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载班级数据失败:', error);
|
||||||
|
uni.showToast({ title: "加载班级数据失败", icon: "none" });
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示学生抽屉
|
||||||
|
const showStudentDrawer = async (type: string, classData: any) => {
|
||||||
|
if (!classData || !noticeId.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
drawerType.value = type;
|
||||||
|
currentClassData.value = classData;
|
||||||
|
|
||||||
|
// 加载该班级的学生数据
|
||||||
|
const stuRes = await jlzxFindByJlParamsApi({
|
||||||
|
jlId: noticeId.value,
|
||||||
|
bjId: classData.bjId
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const students = stuRes?.rows || stuRes?.result || [];
|
||||||
|
|
||||||
|
// 处理学生状态兼容性
|
||||||
|
students.forEach((stu: any) => {
|
||||||
|
if (stu.jlwcStatus && !stu.jlwc_status) {
|
||||||
|
stu.jlwc_status = stu.jlwcStatus;
|
||||||
|
}
|
||||||
|
if (stu.jlwc_status === '1') {
|
||||||
|
stu.jlwc_status = 'A';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 根据类型筛选学生
|
||||||
|
if (type === 'completed') {
|
||||||
|
drawerStudents.value = students.filter((s: any) => s.jlwc_status === 'A');
|
||||||
|
drawerTitle.value = `${classData.displayName} - 已接龙学生 (${drawerStudents.value.length}人)`;
|
||||||
|
} else if (type === 'pending') {
|
||||||
|
drawerStudents.value = students.filter((s: any) => s.jlwc_status !== 'A');
|
||||||
|
drawerTitle.value = `${classData.displayName} - 未接龙学生 (${drawerStudents.value.length}人)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
showDrawer.value = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载学生数据失败:', error);
|
||||||
|
uni.showToast({ title: "加载学生数据失败", icon: "none" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭抽屉
|
||||||
|
const closeDrawer = () => {
|
||||||
|
showDrawer.value = false;
|
||||||
|
drawerStudents.value = [];
|
||||||
|
currentClassData.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (options && options.id) {
|
if (options && options.id) {
|
||||||
noticeId.value = options.id;
|
noticeId.value = options.id;
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
// 1. 获取接龙详情(新接口)
|
|
||||||
|
// 1. 获取接龙详情
|
||||||
try {
|
try {
|
||||||
const detailRes = await getByJlIdApi({ jlId: noticeId.value });
|
const detailRes = await getByJlIdApi({ jlId: noticeId.value });
|
||||||
noticeDetail.value = Array.isArray(detailRes) ? detailRes[0] : {};
|
noticeDetail.value = Array.isArray(detailRes) ? detailRes[0] : {};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
uni.showToast({ title: "加载接龙详情失败", icon: "none" });
|
uni.showToast({ title: "加载接龙详情失败", icon: "none" });
|
||||||
}
|
}
|
||||||
// 2. 获取学生完成状态
|
|
||||||
try {
|
// 2. 加载班级树数据(因为默认显示完成情况)
|
||||||
const stuRes = await jlzxFindByJlParamsApi({ jlId: noticeId.value });
|
await loadClassTree();
|
||||||
studentList.value = stuRes?.rows || stuRes?.result || [];
|
|
||||||
} catch (e) {
|
|
||||||
uni.showToast({ title: "加载学生状态失败", icon: "none" });
|
|
||||||
}
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
uni.setNavigationBarTitle({ title: "接龙情况" });
|
uni.setNavigationBarTitle({ title: "接龙详情" });
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: "加载失败,缺少通知ID", icon: "none" });
|
uni.showToast({ title: "加载失败,缺少通知ID", icon: "none" });
|
||||||
}
|
}
|
||||||
@ -185,82 +494,260 @@ const previewAttachment = (filePath: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(noticeDetail, (val) => {
|
|
||||||
// 监听数据变化
|
|
||||||
}, { immediate: true, deep: true });
|
|
||||||
|
|
||||||
// 添加学生列表数据监听器,处理状态字段兼容性
|
|
||||||
watch(studentList, (list) => {
|
|
||||||
list.forEach(stu => {
|
|
||||||
// 兼容后端返回的驼峰写法
|
|
||||||
if (stu.jlwcStatus && !stu.jlwc_status) {
|
|
||||||
stu.jlwc_status = stu.jlwcStatus;
|
|
||||||
}
|
|
||||||
// 兼容数字状态,将'1'转换为'A'
|
|
||||||
if (stu.jlwc_status === '1') {
|
|
||||||
stu.jlwc_status = 'A';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, { immediate: true, deep: true });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.notice-detail-page {
|
.jl-detail-page {
|
||||||
background-color: #f4f5f7;
|
background-color: #f5f5f5;
|
||||||
padding-bottom: 70px;
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tab 样式
|
||||||
|
.tab-container {
|
||||||
|
display: flex;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #007aff;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 60rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
background-color: #007aff;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 内容区域
|
||||||
|
.detail-content,
|
||||||
|
.progress-content {
|
||||||
|
flex: 1;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-actions {
|
// Section 样式
|
||||||
|
.section {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 15px;
|
}
|
||||||
background-color: #ffffff;
|
|
||||||
border-top: 1px solid #e5e5e5;
|
|
||||||
|
|
||||||
.action-btn {
|
.section-subtitle {
|
||||||
width: 90%;
|
font-size: 14px;
|
||||||
min-width: 90px;
|
color: #666;
|
||||||
margin: 0 5px;
|
margin-bottom: 10px;
|
||||||
font-size: 15px;
|
display: block;
|
||||||
height: 40px;
|
}
|
||||||
line-height: 40px;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 0 20px;
|
|
||||||
|
|
||||||
&::after {
|
.refresh-btn {
|
||||||
border: none;
|
font-size: 12px;
|
||||||
}
|
color: #409eff;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
&.draft-btn {
|
// 班级选择器样式
|
||||||
background-color: #f4f4f5;
|
.class-selector {
|
||||||
color: #909399;
|
display: flex;
|
||||||
border: 1px solid #e9e9eb;
|
justify-content: space-between;
|
||||||
}
|
align-items: center;
|
||||||
&.preview-btn {
|
padding: 12px;
|
||||||
background-color: #ecf5ff;
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-tip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f0f9ff;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-left: 4px solid #409eff;
|
||||||
|
|
||||||
|
.tip-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-text {
|
||||||
|
font-size: 14px;
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
border: 1px solid #d9ecff;
|
}
|
||||||
}
|
}
|
||||||
&.publish-btn {
|
|
||||||
background-color: #409eff;
|
// 班级统计卡片样式
|
||||||
color: #ffffff;
|
.class-stats-card {
|
||||||
border: none;
|
background-color: #f8f9fa;
|
||||||
}
|
border-radius: 8px;
|
||||||
&.draft-btn:active {
|
padding: 15px;
|
||||||
background-color: #e0e0e0;
|
margin-bottom: 12px;
|
||||||
}
|
border: 1px solid #e9ecef;
|
||||||
&.preview-btn:active {
|
}
|
||||||
background-color: #d9ecff;
|
|
||||||
}
|
.class-header {
|
||||||
&.publish-btn:active {
|
display: flex;
|
||||||
background-color: #3a8ee6;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-completion {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计容器样式
|
||||||
|
.stats-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
text-align: center;
|
||||||
|
padding: 15px 8px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
|
||||||
|
&.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
background-color: #e1f3d8;
|
||||||
|
color: #67c23a;
|
||||||
|
border: 1px solid #b3e19d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
background-color: #fef0f0;
|
||||||
|
color: #f56c6c;
|
||||||
|
border: 1px solid #fbc4c4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.r-md {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-12 {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.loading-indicator,
|
.loading-indicator,
|
||||||
.empty-state {
|
.empty-state {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -538,4 +1025,115 @@ watch(studentList, (list) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 抽屉样式 */
|
||||||
|
.drawer-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-content {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 70vh;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20px 20px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-close {
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-body {
|
||||||
|
max-height: calc(70vh - 80px);
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-list {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-bottom: 1px solid #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-avatar {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 15px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-name {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.completed {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.pending {
|
||||||
|
background-color: #fff2f0;
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="gw-list-page">
|
<view class="gw-list-page">
|
||||||
<!-- 搜索和筛选组件 -->
|
<!-- 顶部搜索区域 -->
|
||||||
<view class="query-component">
|
<view class="top-section">
|
||||||
<view class="search-card">
|
<view class="search-card">
|
||||||
<!-- 搜索框和查询按钮 -->
|
<!-- 搜索框和查询按钮 -->
|
||||||
<view class="search-item">
|
<view class="search-item">
|
||||||
@ -37,24 +37,32 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 列表内容 -->
|
<!-- 中间数据区域 -->
|
||||||
<view class="list-content">
|
<view class="middle-section">
|
||||||
<!-- 加载状态 -->
|
<z-paging
|
||||||
<view v-if="loading" class="loading-container">
|
ref="pagingRef"
|
||||||
<view class="loading-text">加载中...</view>
|
v-model="dataList"
|
||||||
</view>
|
@query="queryData"
|
||||||
|
:auto="true"
|
||||||
<!-- 数据列表 -->
|
:refresher-enabled="true"
|
||||||
<view v-else>
|
:loading-more-enabled="true"
|
||||||
|
:loading-more-threshold="50"
|
||||||
|
:default-page-size="10"
|
||||||
|
:show-loading-more-no-more-view="true"
|
||||||
|
:show-empty-view-reload="false"
|
||||||
|
:fixed="false"
|
||||||
|
class="paging-container"
|
||||||
|
>
|
||||||
|
<!-- 列表内容 -->
|
||||||
<view
|
<view
|
||||||
v-for="(data, index) in filteredGwList"
|
v-for="(data, index) in dataList"
|
||||||
:key="data.id || index"
|
:key="data.id || index"
|
||||||
class="gw-card"
|
class="gw-card"
|
||||||
>
|
>
|
||||||
<view class="card-header">
|
<view class="card-header">
|
||||||
<text class="gw-title">{{ data.title }}</text>
|
<text class="gw-title">{{ data.title }}</text>
|
||||||
<text class="gw-status" :class="getStatusClass(data.gwStatus)">
|
<text class="gw-status" :class="getStatusClass(data.spJd)">
|
||||||
{{ getStatusText(data.gwStatus) }}
|
{{ getStatusText(data.spJd) }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -103,12 +111,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</z-paging>
|
||||||
<!-- 空状态 -->
|
|
||||||
<view v-if="!loading && filteredGwList.length === 0" class="empty-container">
|
|
||||||
<view class="empty-text">暂无数据</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -118,7 +121,7 @@ import { ref, computed, watch, onMounted, onUnmounted } from "vue";
|
|||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
import { navigateTo } from "@/utils/uniapp";
|
import { navigateTo } from "@/utils/uniapp";
|
||||||
import BasicSearch from "@/components/BasicSearch/Search.vue";
|
import BasicSearch from "@/components/BasicSearch/Search.vue";
|
||||||
import { gwFindPageApi, findUserTodosApi } from "@/api/routine/gw";
|
import { findUserTodosApi } from "@/api/routine/gw";
|
||||||
import { gwSqApi, gwSpApi, gwTransferApi, gwStopApi, gwCxtjApi, gwXtApi } from "@/api/routine/gw";
|
import { gwSqApi, gwSpApi, gwTransferApi, gwStopApi, gwCxtjApi, gwXtApi } from "@/api/routine/gw";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
@ -143,7 +146,7 @@ interface GwListItem {
|
|||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
docType: string;
|
docType: string;
|
||||||
gwStatus: string;
|
spJd: string; // 审批进度:A-审批中,Z-审批结束
|
||||||
fileUrl?: string;
|
fileUrl?: string;
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
fileFormat?: string;
|
fileFormat?: string;
|
||||||
@ -169,174 +172,108 @@ const userStore = useUserStore();
|
|||||||
|
|
||||||
// 数据列表
|
// 数据列表
|
||||||
const dataList = ref<GwListItem[]>([]);
|
const dataList = ref<GwListItem[]>([]);
|
||||||
const loading = ref(false);
|
const pagingRef = ref<any>(null);
|
||||||
|
|
||||||
// 获取当前教师ID
|
// 获取当前教师ID
|
||||||
const getCurrentTeacherId = () => {
|
const getCurrentTeacherId = () => {
|
||||||
const jsData = userStore.getJs;
|
const jsData = userStore.getJs;
|
||||||
|
console.log('用户store数据:', userStore);
|
||||||
|
console.log('教师数据:', jsData);
|
||||||
return jsData?.id || null;
|
return jsData?.id || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 筛选后的公文列表
|
// z-paging 查询方法
|
||||||
const filteredGwList = computed(() => {
|
const queryData = async (pageNo: number, pageSize: number) => {
|
||||||
let list = dataList.value;
|
console.log('queryData 被调用:', { pageNo, pageSize, activeTab: activeTab.value });
|
||||||
|
|
||||||
// 对于待办/已办标签,数据已经通过API筛选,不需要再次筛选
|
try {
|
||||||
// 只对"全部"标签进行状态筛选
|
const currentTeacherId = getCurrentTeacherId();
|
||||||
if (activeTab.value === "all") {
|
console.log('当前教师ID:', currentTeacherId);
|
||||||
// 这里可以添加额外的筛选逻辑,如果需要的话
|
|
||||||
|
if (!currentTeacherId) {
|
||||||
|
console.log('教师ID为空,停止查询');
|
||||||
|
uni.showToast({
|
||||||
|
title: '无法获取用户信息',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
pagingRef.value?.complete([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let response: any;
|
||||||
|
|
||||||
|
if (activeTab.value === "all") {
|
||||||
|
// 全部:不传 dbZt 参数,查询所有
|
||||||
|
console.log('调用全部API:', { jsId: currentTeacherId, pageNo, pageSize });
|
||||||
|
response = await findUserTodosApi('', currentTeacherId, pageNo, pageSize);
|
||||||
|
console.log('全部API响应:', response);
|
||||||
|
} else if (activeTab.value === "pending") {
|
||||||
|
// 待办:dbZt = 'A'
|
||||||
|
console.log('调用待办API:', { dbZt: 'A', jsId: currentTeacherId, pageNo, pageSize });
|
||||||
|
response = await findUserTodosApi('A', currentTeacherId, pageNo, pageSize);
|
||||||
|
console.log('待办API响应:', response);
|
||||||
|
} else if (activeTab.value === "approved") {
|
||||||
|
// 已办:dbZt = 'B'
|
||||||
|
console.log('调用已办API:', { dbZt: 'B', jsId: currentTeacherId, pageNo, pageSize });
|
||||||
|
response = await findUserTodosApi('B', currentTeacherId, pageNo, pageSize);
|
||||||
|
console.log('已办API响应:', response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理单个API响应
|
||||||
|
const result = (response as any).data || response;
|
||||||
|
let newData: GwListItem[] = [];
|
||||||
|
|
||||||
|
if (result.rows && Array.isArray(result.rows)) {
|
||||||
|
newData = result.rows;
|
||||||
|
} else if (result.resultCode === 1) {
|
||||||
|
newData = result.result || [];
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message || '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
newData = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按关键词搜索
|
||||||
|
if (searchKeyword.value) {
|
||||||
|
const keyword = searchKeyword.value.toLowerCase();
|
||||||
|
newData = newData.filter((item: GwListItem) =>
|
||||||
|
item.title.toLowerCase().includes(keyword) ||
|
||||||
|
(item.gwNo && item.gwNo.toLowerCase().includes(keyword)) ||
|
||||||
|
(item.docType && item.docType.toLowerCase().includes(keyword))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pagingRef.value?.complete(newData);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询数据失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '查询失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
pagingRef.value?.complete([]);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
// 按关键词搜索(对所有标签都适用)
|
|
||||||
if (searchKeyword.value) {
|
|
||||||
const keyword = searchKeyword.value.toLowerCase();
|
|
||||||
list = list.filter((item: GwListItem) =>
|
|
||||||
item.title.toLowerCase().includes(keyword) ||
|
|
||||||
(item.gwNo && item.gwNo.toLowerCase().includes(keyword)) ||
|
|
||||||
(item.docType && item.docType.toLowerCase().includes(keyword))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 切换筛选标签
|
// 切换筛选标签
|
||||||
const switchTab = (tabKey: string) => {
|
const switchTab = (tabKey: string) => {
|
||||||
activeTab.value = tabKey;
|
activeTab.value = tabKey;
|
||||||
|
// 重新加载数据
|
||||||
// 获取当前教师ID
|
pagingRef.value?.reload();
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
|
||||||
|
|
||||||
if (tabKey === "all") {
|
|
||||||
// 全部:调用 findPage API
|
|
||||||
loadAllData();
|
|
||||||
} else if (tabKey === "pending") {
|
|
||||||
// 待办:只调用 findUserTodos API,传 approveStatus = 'pending'
|
|
||||||
if (currentTeacherId) {
|
|
||||||
loadUserTodos('pending', currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (tabKey === "approved") {
|
|
||||||
// 已办:只调用 findUserTodos API,传 approveStatus = 'approved'
|
|
||||||
if (currentTeacherId) {
|
|
||||||
loadUserTodos('approved', currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加载全部数据(调用 findPage 接口)
|
|
||||||
const loadAllData = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
uni.showLoading({ title: '加载中...' });
|
|
||||||
|
|
||||||
const response = await gwFindPageApi({
|
|
||||||
title: searchKeyword.value,
|
|
||||||
docType: searchKeyword.value,
|
|
||||||
gwStatus: ""
|
|
||||||
});
|
|
||||||
|
|
||||||
// 检查响应格式 - 根据实际返回的数据结构
|
|
||||||
const result = (response as any).data || response;
|
|
||||||
|
|
||||||
// 适配分页查询返回的数据结构 {total, page, records, rows}
|
|
||||||
if (result.rows && Array.isArray(result.rows)) {
|
|
||||||
dataList.value = result.rows;
|
|
||||||
} else if (result.resultCode === 1) {
|
|
||||||
// 兼容旧的数据结构
|
|
||||||
dataList.value = result.result || [];
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: result.message || '加载失败',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
dataList.value = [];
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载全部数据失败:', error);
|
|
||||||
uni.showToast({
|
|
||||||
title: '加载失败',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
dataList.value = [];
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
uni.hideLoading();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加载用户待办/已办数据(只调用 findUserTodos 分页接口)
|
|
||||||
const loadUserTodos = async (approveStatus: string, jsId: string) => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
uni.showLoading({ title: '加载中...' });
|
|
||||||
|
|
||||||
// 调用 findUserTodos 分页接口,使用合理的分页大小
|
|
||||||
const response = await findUserTodosApi(approveStatus, jsId, 1, 50); // 使用合理的分页大小
|
|
||||||
|
|
||||||
// 检查响应格式 - 根据实际返回的数据结构
|
|
||||||
const result = (response as any).data || response;
|
|
||||||
|
|
||||||
// 适配分页查询返回的数据结构 {total, page, records, rows}
|
|
||||||
if (result.rows && Array.isArray(result.rows)) {
|
|
||||||
dataList.value = result.rows;
|
|
||||||
} else if (result.resultCode === 1) {
|
|
||||||
// 兼容旧的数据结构
|
|
||||||
dataList.value = result.result || [];
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: result.message || '加载失败',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
dataList.value = [];
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载用户待办/已办数据失败:', error);
|
|
||||||
uni.showToast({
|
|
||||||
title: '加载失败',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
dataList.value = [];
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
uni.hideLoading();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 搜索处理
|
// 搜索处理
|
||||||
const handleSearch = (keyword: string) => {
|
const handleSearch = (keyword: string) => {
|
||||||
searchKeyword.value = keyword;
|
searchKeyword.value = keyword;
|
||||||
|
// 重新加载数据
|
||||||
// 根据当前标签决定搜索方式
|
pagingRef.value?.reload();
|
||||||
if (activeTab.value === "all") {
|
|
||||||
// 全部:使用 findPage API 搜索
|
|
||||||
loadAllData();
|
|
||||||
} else {
|
|
||||||
// 待办/已办:只调用 findUserTodos 接口
|
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
|
||||||
if (currentTeacherId) {
|
|
||||||
loadUserTodos(activeTab.value, currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到详情页面
|
// 跳转到详情页面
|
||||||
const goToDetail = (item: GwListItem) => {
|
const goToDetail = (item: GwListItem) => {
|
||||||
navigateTo(`/pages/view/routine/gwlz/gwFlow?id=${item.id}`);
|
navigateTo(`/pages/view/routine/gwlz/gwFlow?id=${item.id}&openId=${userStore.getUser.openId}&from=db`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 编辑和删除相关函数已删除
|
// 编辑和删除相关函数已删除
|
||||||
@ -355,34 +292,30 @@ const createNewGw = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 获取状态样式类
|
// 获取状态样式类
|
||||||
const getStatusClass = (status: string) => {
|
const getStatusClass = (spJd: string) => {
|
||||||
const statusMap: Record<string, string> = {
|
const statusMap: Record<string, string> = {
|
||||||
'A': "status-draft", // A暂存
|
'A': "status-pending", // A-审批中
|
||||||
'B': "status-submitted", // B提交
|
'Z': "status-completed", // Z-审批结束
|
||||||
'C': "status-pending", // C审批中
|
|
||||||
'D': "status-completed", // D已完结
|
|
||||||
};
|
};
|
||||||
return statusMap[status] || "status-default";
|
return statusMap[spJd] || "status-default";
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取状态文本
|
// 获取状态文本
|
||||||
const getStatusText = (status: string) => {
|
const getStatusText = (spJd: string) => {
|
||||||
const statusMap: Record<string, string> = {
|
const statusMap: Record<string, string> = {
|
||||||
'A': "暂存", // A暂存
|
'A': "审批中", // A-审批中
|
||||||
'B': "提交", // B提交
|
'Z': "审批结束", // Z-审批结束
|
||||||
'C': "审批中", // C审批中
|
|
||||||
'D': "已完结", // D已完结
|
|
||||||
};
|
};
|
||||||
return statusMap[status] || "未知";
|
return statusMap[spJd] || "未知";
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取按钮文本 - 参考教师请假的逻辑
|
// 获取按钮文本 - 参考教师请假的逻辑
|
||||||
const getButtonText = (item: GwListItem) => {
|
const getButtonText = (item: GwListItem) => {
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
const currentTeacherId = getCurrentTeacherId();
|
||||||
const { gwStatus, spZbqd, spResult } = item;
|
const { spJd, spZbqd, spResult } = item;
|
||||||
|
|
||||||
// 如果是待办状态且当前用户是审批人,显示"审批"
|
// 如果是审批中状态且当前用户是审批人,显示"审批"
|
||||||
if (currentTeacherId && spZbqd && gwStatus === 'B' && activeTab.value === 'pending') {
|
if (currentTeacherId && spZbqd && spJd === 'A' && activeTab.value === 'pending') {
|
||||||
const approverIds = spZbqd.split(',').map(id => id.trim());
|
const approverIds = spZbqd.split(',').map(id => id.trim());
|
||||||
if (approverIds.includes(currentTeacherId)) {
|
if (approverIds.includes(currentTeacherId)) {
|
||||||
return '审批';
|
return '审批';
|
||||||
@ -408,7 +341,7 @@ const getButtonText = (item: GwListItem) => {
|
|||||||
const getButtonClass = (item: GwListItem) => {
|
const getButtonClass = (item: GwListItem) => {
|
||||||
const buttonText = getButtonText(item);
|
const buttonText = getButtonText(item);
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
const currentTeacherId = getCurrentTeacherId();
|
||||||
const { gwStatus, spZbqd, spResult } = item;
|
const { spJd, spZbqd, spResult } = item;
|
||||||
|
|
||||||
// 审批按钮样式
|
// 审批按钮样式
|
||||||
if (buttonText === '审批') {
|
if (buttonText === '审批') {
|
||||||
@ -590,58 +523,21 @@ const getFileIcon = (fileType: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听数据变化
|
|
||||||
watch(dataList, (val) => {
|
|
||||||
// 数据变化监听
|
|
||||||
});
|
|
||||||
|
|
||||||
// 页面显示时重新加载数据
|
// 页面显示时重新加载数据
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
if (activeTab.value === "all") {
|
pagingRef.value?.reload();
|
||||||
loadAllData();
|
|
||||||
} else {
|
|
||||||
// 对于待办/已办,只调用 findUserTodos 接口
|
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
|
||||||
if (currentTeacherId) {
|
|
||||||
loadUserTodos(activeTab.value, currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面加载时也加载一次数据
|
// 页面加载时初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 默认加载"待办"数据,只调用 findUserTodos 接口
|
console.log('页面加载完成,z-paging ref:', pagingRef.value);
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
console.log('当前用户store:', userStore);
|
||||||
if (currentTeacherId) {
|
console.log('当前教师ID:', getCurrentTeacherId());
|
||||||
loadUserTodos('pending', currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听来自gwFlow页面的刷新事件
|
// 监听来自gwFlow页面的刷新事件
|
||||||
uni.$on('refreshGwList', () => {
|
uni.$on('refreshGwList', () => {
|
||||||
if (activeTab.value === "all") {
|
console.log('收到刷新事件');
|
||||||
loadAllData();
|
pagingRef.value?.reload();
|
||||||
} else {
|
|
||||||
// 对于待办/已办,只调用 findUserTodos 接口
|
|
||||||
const currentTeacherId = getCurrentTeacherId();
|
|
||||||
if (currentTeacherId) {
|
|
||||||
loadUserTodos(activeTab.value, currentTeacherId);
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '无法获取用户信息',
|
|
||||||
icon: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -659,16 +555,31 @@ onUnmounted(() => {
|
|||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-component {
|
// 顶部搜索区域
|
||||||
flex: 1;
|
.top-section {
|
||||||
overflow: hidden;
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.query-component {
|
// 中间数据区域
|
||||||
padding: 15px;
|
.middle-section {
|
||||||
background-color: white;
|
flex: 1;
|
||||||
border-bottom: 1px solid #eee;
|
margin-top: 140px; // 为顶部区域留出更多空间
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
|
height: calc(100vh - 140px);
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paging-container {
|
||||||
|
height: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-card {
|
.search-card {
|
||||||
@ -780,14 +691,6 @@ onUnmounted(() => {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
&.status-draft {
|
|
||||||
background: linear-gradient(135deg, #ffa726 0%, #ff9800 100%);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
&.status-submitted {
|
|
||||||
background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
&.status-pending {
|
&.status-pending {
|
||||||
background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
|
background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
|
||||||
color: white;
|
color: white;
|
||||||
@ -984,47 +887,9 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列表内容样式
|
// z-paging 组件样式
|
||||||
.list-content {
|
.paging-container {
|
||||||
flex: 1;
|
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载状态样式
|
|
||||||
.loading-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 40px 20px;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 空状态样式
|
|
||||||
.empty-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 60px 20px;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-text {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #999;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载动画
|
// 加载动画
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user