From 03e1f933ce9771a7cdacddbff5be7186ba1d4718 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 05 二月 2026 17:29:02 +0800
Subject: [PATCH] 安全培训考核更正名字错字
---
src/pages/safeProduction/safetyTrainingAssessment/record.vue | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 546 insertions(+), 0 deletions(-)
diff --git a/src/pages/safeProduction/safetyTrainingAssessment/record.vue b/src/pages/safeProduction/safetyTrainingAssessment/record.vue
new file mode 100644
index 0000000..825b7d6
--- /dev/null
+++ b/src/pages/safeProduction/safetyTrainingAssessment/record.vue
@@ -0,0 +1,546 @@
+<template>
+ <view class="training-record">
+ <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+ <PageHeader title="鍩硅璁板綍"
+ @back="goBack" />
+ <!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+ <view class="search-section">
+ <view class="search-bar">
+ <view class="search-input">
+ <up-input class="search-text"
+ placeholder="浜哄憳鍚嶇О鎼滅储"
+ v-model="searchForm.searchText"
+ @change="searchName"
+ clearable />
+ </view>
+ <view class="filter-button"
+ @click="searchName">
+ <u-icon name="search"
+ size="24"
+ color="#999"></u-icon>
+ </view>
+ </view>
+ </view>
+ <!-- 浜哄憳鍗$墖鍒楄〃 -->
+ <view class="user-card-list"
+ v-if="userList.length > 0">
+ <view v-for="(user, index) in userList"
+ :key="index"
+ class="user-card">
+ <!-- 鍗$墖澶撮儴 -->
+ <view class="card-header"
+ @click="toggleUserCard(index)">
+ <view class="header-left">
+ <text class="user-name">{{ user.nickName }}</text>
+ <text class="user-dept">鎵�灞烇細{{ user.deptNames || '-' }}</text>
+ <text class="user-dept">鑱旂郴鏂瑰紡锛歿{ user.phonenumber || '-' }}</text>
+ <!-- 鍩硅缁熻淇℃伅 -->
+ </view>
+ <u-icon :name="expandedUsers[index] ? 'arrow-up' : 'arrow-down'"
+ size="20"
+ color="#999"></u-icon>
+ </view>
+ <!-- 鍗$墖鍐呭锛堟姌鍙犻儴鍒嗭級 -->
+ <view class="card-content"
+ v-if="expandedUsers[index]">
+ <!-- 骞翠唤绛涢�� -->
+ <view class="year-filter-section">
+ <!-- <text class="filter-label">骞翠唤绛涢��</text> -->
+ <view class="year-options">
+ <u-tag v-for="year in yearOptions"
+ :key="year"
+ :text="year"
+ :type="userYearFilters[user.userId] === year.toString() ? 'primary' : 'info'"
+ @click="() => {
+ userYearFilters[user.userId] = year.toString();
+ filterUserCourses(user.userId);
+ }"
+ :class="{ active: userYearFilters[user.userId] === year.toString() }"
+ style="margin-right: 8px; margin-bottom: 8px;"></u-tag>
+ </view>
+ </view>
+ <!-- 鍩硅璇剧▼鍒楄〃 -->
+ <view class="course-list"
+ v-if="userCourses[user.userId] && userCourses[user.userId].length > 0">
+ <view class="user-stats"
+ v-if="userStats[user.userId]">
+ <text class="stat-item">鍩硅娆℃暟: {{ userStats[user.userId].total }}</text>
+ <text class="stat-item success">鍚堟牸: {{ userStats[user.userId].qualified }}</text>
+ <text class="stat-item danger">涓嶅悎鏍�: {{ userStats[user.userId].unqualified }}</text>
+ </view>
+ <view v-for="(course, courseIndex) in userCourses[user.userId]"
+ :key="courseIndex">
+ <view class="course-item"
+ v-if="userYearFilters[user.userId] === '鍏ㄩ儴' || course.trainingDate.includes(userYearFilters[user.userId])">
+ <view class="course-header">
+ <text class="course-date">{{ course.trainingDate || '-' }}</text>
+ <u-tag :type="course.examinationResults === '鍚堟牸' ? 'success' : 'error'">
+ {{ course.examinationResults || '-' }}
+ </u-tag>
+ </view>
+ <view class="course-info">
+ <text class="info-label">鍩硅鍐呭锛�</text>
+ <text class="info-value">{{ course.trainingContent || '-' }}</text>
+ </view>
+ <view class="course-info">
+ <text class="info-label">鍩硅璇炬椂锛�</text>
+ <text class="info-value">{{ course.classHour || '-' }}</text>
+ </view>
+ </view>
+ </view>
+ <!-- 绛涢�夊悗鏃犳暟鎹� -->
+ <view v-if="userYearFilters[user.userId] === '鍏ㄩ儴' ? userCourses[user.userId].length === 0 : userCourses[user.userId].filter(c => c.trainingDate.includes(userYearFilters[user.userId])).length === 0"
+ class="empty-course">
+ <text class="empty-text">{{ userYearFilters[user.userId] === '鍏ㄩ儴' ? '鏆傛棤鍩硅璁板綍' : '璇ュ勾浠芥殏鏃犲煿璁褰�' }}</text>
+ </view>
+ </view>
+ <!-- 绌虹姸鎬� -->
+ <view v-else
+ class="empty-course">
+ <text class="empty-text">鏆傛棤鍩硅璁板綍</text>
+ </view>
+ </view>
+ <!-- 瀵煎嚭鎸夐挳 -->
+ <!-- <view class="course-export">
+ <u-button type="primary"
+ size="small"
+ @click="exportUserRecord(user.userId)">瀵煎嚭璁板綍</u-button>
+ </view> -->
+ </view>
+ </view>
+ <view v-else
+ class="empty-state">
+ <up-icon name="people"
+ size="64"
+ color="#c0c4cc"></up-icon>
+ <text class="empty-text">鏆傛棤浜哄憳鏁版嵁</text>
+ </view>
+ <!-- 绌虹姸鎬� -->
+ <!-- 骞翠唤閫夋嫨鍣� -->
+ <up-datetime-picker :show="yearPickerVisible"
+ mode="year"
+ @confirm="handleYearConfirm"
+ @cancel="yearPickerVisible = false"
+ title="閫夋嫨骞翠唤" />
+ </view>
+</template>
+
+<script setup>
+ import { ref, onMounted, reactive } from "vue";
+ import { onShow } from "@dcloudio/uni-app";
+ import PageHeader from "@/components/PageHeader.vue";
+ import { safeTrainingDetailListPage } from "@/api/safeProduction/safetyTrainingAssessment";
+ import { userListNoPage } from "@/api/system/user.js";
+ import { getToken } from "@/utils/auth";
+ import config from "@/config";
+
+ // 椤甸潰鐘舵��
+ const userList = ref([]);
+ const userCourses = ref({}); // 瀛樺偍姣忎釜鐢ㄦ埛鐨勫煿璁绋�
+ const userStats = ref({}); // 瀛樺偍姣忎釜鐢ㄦ埛鐨勫煿璁粺璁′俊鎭�
+ const expandedUsers = ref([]); // 鎺у埗鐢ㄦ埛鍗$墖灞曞紑鐘舵��
+ const loading = ref(false);
+ const courseLoading = ref({}); // 鎺у埗姣忎釜鐢ㄦ埛鐨勮绋嬪姞杞界姸鎬�
+ const userYearFilters = ref({}); // 瀛樺偍姣忎釜鐢ㄦ埛鐨勫勾浠界瓫閫夋潯浠�
+ const yearOptions = ref([]); // 骞翠唤閫夐」锛堜粖骞村拰杩囧幓涓夊勾锛�
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ searchText: "",
+ invoiceDate: "",
+ });
+
+ // 骞翠唤閫夋嫨鍣ㄧ姸鎬�
+ const yearPickerVisible = ref(false);
+
+ // 杩斿洖涓婁竴椤�
+ const goBack = () => {
+ uni.navigateBack();
+ };
+
+ // 鐢熸垚骞翠唤閫夐」
+ const generateYearOptions = () => {
+ const currentYear = new Date().getFullYear();
+ const options = [];
+ // 娣诲姞"鍏ㄩ儴"閫夐」
+ options.push("鍏ㄩ儴");
+ for (let i = 0; i < 4; i++) {
+ options.push(currentYear - i);
+ }
+ yearOptions.value = options;
+ };
+
+ // 鎼滅储浜哄憳鍚嶇О
+ const searchName = () => {
+ getUserList();
+ };
+
+ // 鏄剧ず骞翠唤閫夋嫨鍣�
+ const showYearPicker = () => {
+ yearPickerVisible.value = true;
+ };
+
+ // 澶勭悊骞翠唤閫夋嫨纭
+ const handleYearConfirm = e => {
+ searchForm.invoiceDate = e.value;
+ yearPickerVisible.value = false;
+ };
+
+ // 鎸夊勾浠芥悳绱�
+ const searchDate = () => {
+ // 閬嶅巻鎵�鏈夊睍寮�鐨勭敤鎴峰崱鐗囷紝閲嶆柊鍔犺浇鍩硅璁板綍
+ userList.value.forEach((user, index) => {
+ if (expandedUsers.value[index]) {
+ getUserCourses(user.userId, index);
+ }
+ });
+ };
+
+ // 鑾峰彇浜哄憳鍒楄〃
+ const getUserList = () => {
+ loading.value = true;
+ userListNoPage()
+ .then(res => {
+ loading.value = false;
+ if (res.data && res.data.length > 0) {
+ let users = res.data;
+ // 濡傛灉鏈夋悳绱㈠叧閿瘝锛岃繘琛岀瓫閫�
+ if (searchForm.searchText) {
+ users = users.filter(user =>
+ user.nickName.includes(searchForm.searchText)
+ );
+ }
+ userList.value = users;
+ // 鍒濆鍖栨墍鏈夊崱鐗囦负鏀惰捣鐘舵��
+ expandedUsers.value = new Array(userList.value.length).fill(false);
+ } else {
+ userList.value = [];
+ expandedUsers.value = [];
+ }
+ })
+ .catch(() => {
+ loading.value = false;
+ uni.showToast({ title: "鑾峰彇浜哄憳鍒楄〃澶辫触", icon: "none" });
+ });
+ };
+
+ // 鍒囨崲鐢ㄦ埛鍗$墖灞曞紑鐘舵��
+ const toggleUserCard = index => {
+ const user = userList.value[index];
+ expandedUsers.value[index] = !expandedUsers.value[index];
+
+ // 濡傛灉灞曞紑鍗$墖锛屽姞杞藉煿璁褰�
+ if (expandedUsers.value[index]) {
+ // 鍒濆鍖栧勾浠界瓫閫夋潯浠朵负"鍏ㄩ儴"
+ userYearFilters.value[user.userId] = "鍏ㄩ儴";
+ getUserCourses(user.userId, index);
+ }
+ };
+
+ // 绛涢�夌敤鎴峰煿璁绋�
+ const filterUserCourses = userId => {
+ if (!userYearFilters.value[userId]) return;
+ console.log("userYearFilters", userYearFilters.value);
+ const year = userYearFilters.value[userId];
+ const allCourses = userCourses.value[userId] || [];
+
+ // 绛涢�夋寚瀹氬勾浠界殑鍩硅璁板綍
+ let filteredCourses = allCourses;
+ if (year !== "鍏ㄩ儴") {
+ filteredCourses = allCourses.filter(
+ course => course.trainingDate && course.trainingDate.includes(year)
+ );
+ }
+ console.log("filteredCourses", filteredCourses);
+
+ // 鏇存柊缁熻淇℃伅
+ const total = filteredCourses.length;
+ const qualified = filteredCourses.filter(
+ course => course.examinationResults === "鍚堟牸"
+ ).length;
+ const unqualified = filteredCourses.filter(
+ course => course.examinationResults === "涓嶅悎鏍�"
+ ).length;
+ userStats.value[userId] = {
+ total,
+ qualified,
+ unqualified,
+ };
+ };
+
+ // 鑾峰彇鐢ㄦ埛鍩硅璇剧▼
+ const getUserCourses = (userId, index) => {
+ courseLoading.value[userId] = true;
+
+ const params = {
+ userId,
+ // 濡傛灉鏈夊勾浠界瓫閫夛紝娣诲姞骞翠唤鍙傛暟
+ // 杩欓噷闇�瑕佹牴鎹悗绔帴鍙g殑瀹為檯鍙傛暟鍚嶈繘琛岃皟鏁�
+ };
+
+ safeTrainingDetailListPage(params)
+ .then(res => {
+ courseLoading.value[userId] = false;
+ if (res.data && res.data.records) {
+ let courses = res.data.records;
+ // 濡傛灉鏈夊勾浠界瓫閫夛紝杩涜绛涢��
+ if (searchForm.invoiceDate) {
+ const year = searchForm.invoiceDate.substring(0, 4);
+ courses = courses.filter(
+ course => course.trainingDate && course.trainingDate.includes(year)
+ );
+ }
+ userCourses.value[userId] = courses;
+
+ // 璁$畻鍩硅缁熻淇℃伅
+ const total = courses.length;
+ const qualified = courses.filter(
+ course => course.examinationResults === "鍚堟牸"
+ ).length;
+ const unqualified = courses.filter(
+ course => course.examinationResults === "涓嶅悎鏍�"
+ ).length;
+
+ userStats.value[userId] = {
+ total,
+ qualified,
+ unqualified,
+ };
+ } else {
+ userCourses.value[userId] = [];
+ userStats.value[userId] = {
+ total: 0,
+ qualified: 0,
+ unqualified: 0,
+ };
+ }
+ })
+ .catch(() => {
+ courseLoading.value[userId] = false;
+ uni.showToast({ title: "鑾峰彇鍩硅璁板綍澶辫触", icon: "none" });
+ });
+ };
+
+ // 椤甸潰鍔犺浇
+ onMounted(() => {
+ // 鐢熸垚骞翠唤閫夐」
+ generateYearOptions();
+ getUserList();
+ });
+
+ // 椤甸潰鏄剧ず鏃跺埛鏂�
+ onShow(() => {
+ // 鍙互鍦ㄨ繖閲屾坊鍔犲埛鏂伴�昏緫
+ });
+</script>
+
+<style scoped lang="scss">
+ @import "../../../styles/sales-common.scss";
+ .training-record {
+ min-height: 100vh;
+ background: #f8f9fa;
+ padding-bottom: 20px;
+ }
+
+ // 骞翠唤閫夋嫨鍣�
+ .year-picker {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10px 15px;
+ background: #f8f9fa;
+ border-radius: 4px;
+ margin-right: 10px;
+ }
+
+ .picker-text {
+ font-size: 14px;
+ color: #333;
+ }
+
+ // 浜哄憳鍗$墖鍒楄〃
+ .user-card-list {
+ padding: 10px;
+ }
+
+ // 浜哄憳鍗$墖
+ .user-card {
+ background: #fff;
+ border-radius: 8px;
+ margin-bottom: 12px;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ border: 1px solid #e8e8e8;
+ }
+
+ // 鍗$墖澶撮儴
+ .card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px;
+ background: #f5f7fa;
+ border-bottom: 1px solid #e8e8e8;
+ cursor: pointer;
+ }
+
+ .header-left {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .user-name {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 20rpx;
+ }
+
+ .user-dept {
+ font-size: 14px;
+ color: #666;
+ margin-bottom: 8px;
+ }
+
+ // 鍩硅缁熻淇℃伅
+ .user-stats {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-bottom: 8px;
+ }
+
+ .stat-item {
+ font-size: 12px;
+ color: #555;
+ padding: 5px 10px;
+ background: #f0f2f5;
+ border-radius: 4px;
+ border: 1px solid #e0e0e0;
+ font-weight: 500;
+ }
+
+ .stat-item.success {
+ background: #e6f7ff;
+ color: #1890ff;
+ border-color: #91d5ff;
+ }
+
+ .stat-item.danger {
+ background: #fff1f0;
+ color: #ff4d4f;
+ border-color: #ffccc7;
+ }
+
+ // 骞翠唤绛涢�夊尯鍩�
+ .year-filter-section {
+ margin-bottom: 16px;
+ padding-bottom: 12px;
+ border-bottom: 1px solid #e8e8e8;
+ }
+
+ .filter-label {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ margin-bottom: 8px;
+ display: block;
+ }
+
+ .year-options {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ // 鍗$墖鍐呭
+ .card-content {
+ padding: 16px;
+ }
+
+ // 鍩硅璇剧▼鍒楄〃
+ .course-list {
+ margin-bottom: 16px;
+ }
+
+ // 璇剧▼椤�
+ .course-item {
+ background: #fafafa;
+ border-radius: 6px;
+ padding: 14px;
+ margin-bottom: 12px;
+ border: 1px solid #e8e8e8;
+ }
+
+ // 璇剧▼澶撮儴
+ .course-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #f0f0f0;
+ }
+
+ .course-date {
+ font-size: 14px;
+ font-weight: 600;
+ color: #333;
+ }
+
+ // 璇剧▼淇℃伅
+ .course-info {
+ display: flex;
+ margin-bottom: 8px;
+ align-items: flex-start;
+ }
+
+ .info-label {
+ font-size: 14px;
+ color: #666;
+ width: 80px;
+ flex-shrink: 0;
+ }
+
+ .info-value {
+ font-size: 14px;
+ color: #333;
+ flex: 1;
+ line-height: 1.4;
+ }
+
+ // 璇剧▼瀵煎嚭鎸夐挳
+ .course-export {
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ // 绌虹姸鎬�
+ .empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 60px 0;
+ }
+
+ .empty-course {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 30px 0;
+ color: #999;
+ font-size: 14px;
+ }
+
+ .empty-text {
+ font-size: 14px;
+ color: #999;
+ margin-top: 16px;
+ }
+ :deep(.u-tag--info) {
+ background-color: #c1c3c8;
+ border-width: 1px;
+ border-color: #c1c3c8;
+ }
+</style>
\ No newline at end of file
--
Gitblit v1.9.3