| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="sales-accoun"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="å®å
¨å¹è®èæ ¸" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view @click="selectDate" |
| | | class="search-input"> |
| | | <view class="search-text">{{ searchKeyword? searchKeyword : 'è¯·éæ©å¹è®æ¥æ' }}</view> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="clearDate"> |
| | | <u-icon name="close-circle" |
| | | size="24" |
| | | color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | <!-- å¹è®è®°å½æé® --> |
| | | <view class="record-button"> |
| | | <u-button type="info" |
| | | @click="viewTrainingRecord">å¹è®è®°å½</u-button> |
| | | </view> |
| | | </view> |
| | | <!-- æ ç¾é¡µ --> |
| | | <view class="tabs-section"> |
| | | <up-tabs v-model="searchForm.state" |
| | | :list="tabList" |
| | | itemStyle="width: 33%;height: 80rpx;" |
| | | @change="tabhandleQuery"> |
| | | </up-tabs> |
| | | </view> |
| | | <!-- å¹è®è®°å½å表 --> |
| | | <view class="ledger-list" |
| | | v-if="trainingList.length > 0"> |
| | | <view v-for="(item, index) in trainingList" |
| | | :key="index"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">课ç¨ç¼å·ï¼{{ item.courseCode }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">课ç¨ç¼å·</text> |
| | | <text class="detail-value">{{ item.courseCode || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®æ¥æ</text> |
| | | <text class="detail-value">{{ item.trainingDate || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼å§æ¶é´</text> |
| | | <text class="detail-value">{{ item.openingTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»ææ¶é´</text> |
| | | <text class="detail-value">{{ item.endTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®ç®æ </text> |
| | | <text class="detail-value">{{ item.trainingObjectives || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åå 对象</text> |
| | | <text class="detail-value">{{ item.participants || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®å
容</text> |
| | | <text class="detail-value">{{ item.trainingContent || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®è®²å¸</text> |
| | | <text class="detail-value">{{ item.trainingLecturer || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®å¦å</text> |
| | | <text class="detail-value">{{ item.projectCredits || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®æ¹å¼</text> |
| | | <text class="detail-value">{{ getTrainingModeLabel(item.trainingMode) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¹è®å°ç¹</text> |
| | | <text class="detail-value">{{ item.placeTraining || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">课æ¶</text> |
| | | <text class="detail-value">{{ item.classHour || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.state !== 0" |
| | | @click="editVisit(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewFileList(item)"> |
| | | éä»¶ |
| | | </u-button> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.state !== 1" |
| | | @click="signIn(item)"> |
| | | ç¾å° |
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.state === 0" |
| | | @click="viewResultDetail(item)"> |
| | | ç»ææç» |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ å¹è®è®°å½</text> |
| | | </view> |
| | | <up-datetime-picker :show="trainingDateVisible" |
| | | mode="date" |
| | | @confirm="handleDateConfirm" |
| | | @cancel="handleDateCancel" |
| | | title="éæ©å¹è®æ¥æ" /> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, reactive } from "vue"; |
| | | |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | safeTrainingListPage, |
| | | safeTrainingDel, |
| | | safeTrainingSign, |
| | | safeTrainingGet, |
| | | } from "@/api/safeProduction/safetyTrainingAssessment"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import dayjs from "dayjs"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "safety-training-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // è·ååå
¸æ°æ® |
| | | const { safe_training_methods } = useDict("safe_training_methods"); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref(""); |
| | | // æ¥æéæ©å¨ç¶æ |
| | | const trainingDateVisible = ref(false); |
| | | |
| | | const tabList = reactive([ |
| | | { name: "æªå¼å§", value: 0 }, |
| | | { name: "è¿è¡ä¸", value: 1 }, |
| | | { name: "å·²ç»æ", value: 2 }, |
| | | ]); |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | state: 0, // é»è®¤æ¾ç¤ºå·²ç»æ |
| | | trainingDate: "", |
| | | }); |
| | | const tabhandleQuery = val => { |
| | | searchForm.value.state = val.value; |
| | | getList(); |
| | | }; |
| | | const getTrainingModeLabel = mode => { |
| | | if (!safe_training_methods || !Array.isArray(safe_training_methods.value)) { |
| | | return mode || "-"; |
| | | } |
| | | const dictItem = safe_training_methods.value.find( |
| | | item => String(item.value) === String(mode) |
| | | ); |
| | | return dictItem ? dictItem.label : mode || "-"; |
| | | }; |
| | | |
| | | // å¹è®è®°å½æ°æ® |
| | | const trainingList = ref([]); |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const viewFileList = item => { |
| | | uni.setStorageSync("safetyTrainingFileId", item.id); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/fileList", |
| | | }); |
| | | }; |
| | | const currentUserId = ref(""); |
| | | // ç¾å°åè½ |
| | | const signIn = item => { |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "确认ç¾å°åï¼", |
| | | success: function (res) { |
| | | if (res.confirm) { |
| | | safeTrainingSign({ |
| | | safeTrainingId: item.id, |
| | | userId: currentUserId.value, |
| | | }) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | uni.showToast({ title: "ç¾å°æå", icon: "success" }); |
| | | setTimeout(() => {}, 1000); |
| | | } else { |
| | | uni.showToast({ title: res.msg || "ç¾å°å¤±è´¥", icon: "none" }); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | uni.showToast({ title: "ç¾å°å¤±è´¥ï¼è¯·éè¯", icon: "none" }); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çç»ææç» |
| | | const viewResultDetail = item => { |
| | | uni.setStorageSync("safetyTrainingResultId", item.id); |
| | | uni.setStorageSync("safetyTrainingResultNums", item.nums); |
| | | |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/resultDetail", |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çå¹è®è®°å½ |
| | | const viewTrainingRecord = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/record", |
| | | }); |
| | | }; |
| | | // æ¸
餿¥æéæ© |
| | | const clearDate = () => { |
| | | searchKeyword.value = ""; |
| | | searchForm.value.trainingDate = ""; |
| | | getList(); |
| | | }; |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const selectDate = () => { |
| | | trainingDateVisible.value = true; |
| | | }; |
| | | |
| | | // å¤çæ¥æéæ©ç¡®è®¤ |
| | | const handleDateConfirm = e => { |
| | | searchKeyword.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | searchForm.value.trainingDate = dayjs(e.value).format("YYYY-MM-DD"); |
| | | trainingDateVisible.value = false; |
| | | getList(); |
| | | }; |
| | | |
| | | // å¤çæ¥æéæ©åæ¶ |
| | | const handleDateCancel = () => { |
| | | trainingDateVisible.value = false; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | trainingDate: searchForm.value.trainingDate, |
| | | state: searchForm.value.state, |
| | | }; |
| | | safeTrainingListPage(params) |
| | | .then(res => { |
| | | trainingList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢å¹è® |
| | | const addVisit = () => { |
| | | uni.setStorageSync("safetyTraining", {}); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/detail", |
| | | }); |
| | | }; |
| | | // ç¼è¾å¹è® |
| | | const editVisit = item => { |
| | | uni.setStorageSync("safetyTraining", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/detail", |
| | | }); |
| | | }; |
| | | // å é¤å¹è® |
| | | const deleteVisit = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤è¯¥å¹è®è®°å½åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteClientVisit(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | // å é¤å¹è®è®°å½ |
| | | const deleteClientVisit = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | safeTrainingDel([id]) |
| | | .then(() => { |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.setStorageSync("safetyTraining", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/view", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | userStore.getInfo().then(res => { |
| | | currentUserId.value = res.user.userId; |
| | | }); |
| | | // currentUserId |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | // 页é¢ç¹å®çæ ·å¼è¦ç |
| | | .sales-accoun { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | // å¹è®è®°å½æé® |
| | | .record-button { |
| | | margin-top: 10px; |
| | | text-align: center; |
| | | } |
| | | |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | .action-buttons { |
| | | gap: 4px; |
| | | } |
| | | .action-buttons { |
| | | padding: 0 0 10rpx 0; |
| | | } |
| | | |
| | | .tabs-section { |
| | | background: #fff; |
| | | margin-bottom: 1rem; |
| | | box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.05); |
| | | } |
| | | .search-text { |
| | | // font-size: 24rpx; |
| | | color: #a6a6a6; |
| | | height: 70rpx; |
| | | line-height: 70rpx; |
| | | margin-left: 20rpx; |
| | | } |
| | | </style> |