| | |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | |
| | | // æ¥è¯¢å
¬åå表 |
| | | export function listNotice(query) { |
| | | return request({ |
| | | url: '/system/notice/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // è·åæªè¯»æ¶æ¯æ°é |
| | | export function getNoticeCount(consigneeId) { |
| | | return request({ |
| | | url: '/system/notice/getCount', |
| | | method: 'get', |
| | | params: { consigneeId } |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // è·åè·¯ç± |
| | | export const getRouters = () => { |
| | | return request({ |
| | | url: '/getRouters', |
| | | method: 'get' |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | |
| | | export function createPersonalAttendanceRecord(params) { |
| | | return request({ |
| | | url: "/personalAttendanceRecords", |
| | | method: "post", |
| | | data: params, |
| | | }); |
| | | } |
| | | |
| | | export function findPersonalAttendanceRecords(query) { |
| | | return request({ |
| | | url: "/personalAttendanceRecords/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function findTodayPersonalAttendanceRecord(query) { |
| | | return request({ |
| | | url: "/personalAttendanceRecords/today", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // 人åèªèµå°è´¦å表 |
| | | export function monthlyStatisticsListPage(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // 人åèªèµå°è´¦è¯¦æ
|
| | | export function monthlyStatisticsGet(id) { |
| | | return request({ |
| | | url: "/monthlyStatistics/get", |
| | | method: "get", |
| | | params: { id }, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢äººåèªèµå°è´¦ |
| | | export function monthlyStatisticsAdd(data) { |
| | | return request({ |
| | | url: "/compensationPerformance/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // ç¼è¾äººåèªèµå°è´¦ |
| | | export function monthlyStatisticsUpdate(data) { |
| | | return request({ |
| | | url: "/compensationPerformance/update", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤äººåèªèµå°è´¦ |
| | | export function monthlyStatisticsDelete(ids) { |
| | | return request({ |
| | | url: "/compensationPerformance/delete", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | // 导åºäººåèªèµå°è´¦ |
| | | export function monthlyStatisticsExport(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/export", |
| | | method: "get", |
| | | params: query, |
| | | responseType: "blob", |
| | | }); |
| | | } |
| | | |
| | | // 人åå表 |
| | | export function staffOnJobList(query) { |
| | | return request({ |
| | | url: "/staff/staffOnJob/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index7", |
| | | "style": { |
| | | "navigationBarTitleText": "åºåºç®¡ç", |
| | | "navigationBarTitleText": "å货审æ¹", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | { |
| | | "path": "pages/safeProduction/safeQualifications/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è§ç¨èµè´¨", |
| | | "navigationBarTitleText": "è§ç¨ä¸èµè´¨", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | { |
| | | "path": "pages/safeProduction/hazardousMaterialsControl/index", |
| | | "style": { |
| | | "navigationBarTitleText": "å±é©ç©æ", |
| | | "navigationBarTitleText": "å±é©ç©æç®¡æ§", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/attendance/checkin", |
| | | "path": "pages/humanResources/attendance/checkin", |
| | | "style": { |
| | | "navigationBarTitleText": "æå¡ç¾å°", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/attendance/report", |
| | | "path": "pages/humanResources/attendance/report", |
| | | "style": { |
| | | "navigationBarTitleText": "è夿¥æ¥", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/humanResources/monthlyStatistics/index", |
| | | "style": { |
| | | "navigationBarTitleText": "èªèµå°è´¦", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/humanResources/monthlyStatistics/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "èªèµå°è´¦è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/message", |
| | | "style": { |
| | | "navigationBarTitleText": "æ¶æ¯ä¸å¿" |
| | | } |
| | | } |
| | | ], |
| | |
| | | "text": "é¦é¡µ" |
| | | }, |
| | | { |
| | | "pagePath": "pages/message", |
| | | "iconPath": "static/images/tabbar/work.png", |
| | | "selectedIconPath": "static/images/tabbar/work_.png", |
| | | "text": "æ¶æ¯" |
| | | }, |
| | | { |
| | | "pagePath": "pages/mine", |
| | | "iconPath": "static/images/tabbar/mine.png", |
| | | "selectedIconPath": "static/images/tabbar/mine_.png", |
| | |
| | | 4: "æ¥é管ç", |
| | | 5: "éè´ç®¡ç", |
| | | 6: "æ¥ä»·ç®¡ç", |
| | | 7: "åºåºç®¡ç", |
| | | 8: "å±é©ä½ä¸ç®¡ç", |
| | | 7: "å货审æ¹", |
| | | 8: "å±é©ä½ä¸å®¡æ¹", |
| | | }; |
| | | return titleMap[type] || "审æ¹ç®¡ç"; |
| | | }; |
| ÎļþÃû´Ó src/pages/attendance/checkin.vue ÐÞ¸Ä |
| | |
| | | <u-icon name="calendar" |
| | | color="#348fe2" |
| | | size="16"></u-icon> |
| | | <text class="shift-text">ç½ç: 09:00-18:00</text> |
| | | <text class="shift-text">ç½ç: {{ workTimeDict.startAt }}-{{ workTimeDict.endAt }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æå¡æé® --> |
| | | <view class="checkin-button-container"> |
| | | <view class="checkin-button-wrapper"> |
| | | <view class="checkin-button" |
| | | :class="{ 'disabled': checkInOutText === 'å·²æå¡' }" |
| | | :class="{ 'disabled': todayRecord.workEndAt }" |
| | | @click="handleCheckInOut"> |
| | | <text class="checkin-button-text">{{ checkInOutText }}</text> |
| | | <text class="checkin-time">{{ nowTime.split(' ')[1] }}</text> |
| | |
| | | <view class="employee-info"> |
| | | <view class="info-item"> |
| | | <text class="info-label">é¨é¨</text> |
| | | <text class="info-value">{{ currentUser.dept }}</text> |
| | | <text class="info-value">{{ todayRecord.deptName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å§å</text> |
| | | <text class="info-value">{{ currentUser.name }}</text> |
| | | <text class="info-value">{{ todayRecord.staffName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å·¥å·</text> |
| | | <text class="info-value">{{ currentUser.no }}</text> |
| | | <text class="info-value">{{ todayRecord.staffNo || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 仿¥èå¤ç¶æ --> |
| | | <view class="today-status"> |
| | | <u-icon :name="todayRecord ? 'checkmark-circle' : 'close-circle'" |
| | | :color="todayRecord ? '#4cd964' : '#ff3b30'" |
| | | <u-icon :name="todayRecord.id ? 'checkmark-circle' : 'close-circle'" |
| | | :color="todayRecord.id ? '#4cd964' : '#ff3b30'" |
| | | size="16"></u-icon> |
| | | <text class="status-text"> |
| | | {{ todayRecord ? `仿¥èå¤: ä¸ç ${todayRecord.checkInTime}` : '仿¥æªæå¡' }} |
| | | {{ todayRecord.id ? `仿¥èå¤: ä¸ç ${todayRecord.workStartAt || '-'}` : '仿¥æªæå¡' }} |
| | | </text> |
| | | </view> |
| | | <!-- ä¸çèå¤ç¶æ --> |
| | | <view v-if="todayRecord && todayRecord.checkOutTime" |
| | | <view v-if="todayRecord.id && todayRecord.workEndAt" |
| | | class="today-status"> |
| | | <u-icon :name="todayRecord ? 'checkmark-circle' : 'close-circle'" |
| | | :color="todayRecord ? '#4cd964' : '#ff3b30'" |
| | | <u-icon name="checkmark-circle" |
| | | color="#4cd964" |
| | | size="16"></u-icon> |
| | | <text class="status-text"> |
| | | {{ `仿¥èå¤: ä¸ç ${todayRecord.checkOutTime}` }} |
| | | {{ `仿¥èå¤: ä¸ç ${todayRecord.workEndAt}` }} |
| | | </text> |
| | | </view> |
| | | <!-- æå¡ç¶æ --> |
| | | <view v-if="todayRecord" |
| | | class="today-status"> |
| | | <u-icon :name="todayRecord.status === 'normal' ? 'checkmark-circle' : 'clock'" |
| | | :color="todayRecord.status === 'normal' ? '#4cd964' : '#ff3b30'" |
| | | <view class="today-status"> |
| | | <u-icon :name="todayRecord.id ? (todayRecord.status === 0 ? 'checkmark-circle' : 'clock') : 'clock'" |
| | | :color="todayRecord.id ? (todayRecord.status === 0 ? '#4cd964' : '#ff3b30') : '#ff3b30'" |
| | | size="16"></u-icon> |
| | | <text class="status-text"> |
| | | {{ `æå¡ç¶æ: ${todayRecord.statusText}` }} |
| | | {{ `æå¡ç¶æ: ${todayStatusText}` }} |
| | | </text> |
| | | </view> |
| | | <view v-else |
| | | <!-- å·¥æ¶ä¿¡æ¯ --> |
| | | <view v-if="todayRecord.id && todayRecord.workHours" |
| | | class="today-status"> |
| | | <u-icon name="clock" |
| | | color="#ff3b30" |
| | | color="#348fe2" |
| | | size="16"></u-icon> |
| | | <text class="status-text"> |
| | | æå¡ç¶æ: ç¼ºå¡ |
| | | {{ `å·¥æ¶(å°æ¶): ${todayRecord.workHours}` }} |
| | | </text> |
| | | </view> |
| | | </view> |
| | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted, onBeforeUnmount } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | // 模æå½åç»å½åå·¥ |
| | | const currentUser = reactive({ |
| | | id: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | }); |
| | | import { getDicts } from "@/api/system/dict/data"; |
| | | import { |
| | | createPersonalAttendanceRecord, |
| | | findTodayPersonalAttendanceRecord, |
| | | } from "@/api/personnelManagement/attendance.js"; |
| | | // 仿¥æå¡è®°å½ |
| | | const todayRecord = ref({}); |
| | | |
| | | // 模æèå¤åå§æ°æ® |
| | | const rawAttendance = ref([ |
| | | { |
| | | id: 2, |
| | | date: "2026-02-08", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "09:15", |
| | | checkOutTime: "18:05", |
| | | workHours: 8.8, |
| | | status: "late", |
| | | statusText: "è¿å°", |
| | | remark: "å äº¤éæ¥å µè¿å°", |
| | | }, |
| | | { |
| | | id: 3, |
| | | date: "2026-02-07", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "08:45", |
| | | checkOutTime: "18:30", |
| | | workHours: 9.7, |
| | | status: "normal", |
| | | statusText: "æ£å¸¸", |
| | | remark: "å ç0.5å°æ¶", |
| | | }, |
| | | ]); |
| | | // çæ¬¡ä¿¡æ¯ |
| | | const workTimeDict = ref({ |
| | | startAt: "09:00", |
| | | endAt: "18:00", |
| | | }); |
| | | |
| | | // å½åæ¶é´å±ç¤º |
| | | const nowTime = ref(""); |
| | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¥è¯¢ä»æ¥æå¡ä¿¡æ¯ |
| | | const fetchTodayData = () => { |
| | | findTodayPersonalAttendanceRecord({}).then(res => { |
| | | todayRecord.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // æå¡èå´ç¶æ |
| | |
| | | // 仿¥æ¥æ |
| | | const todayStr = computed(() => nowTime.value.slice(0, 10)); |
| | | |
| | | // 彿¥å½ååå·¥èå¤è®°å½ |
| | | const todayRecord = computed(() => |
| | | rawAttendance.value.find( |
| | | item => item.userId === currentUser.id && item.date === todayStr.value |
| | | ) |
| | | ); |
| | | |
| | | // æå¡æé®ææ¬ |
| | | const checkInOutText = computed(() => { |
| | | if (!todayRecord.value || !todayRecord.value.checkInTime) { |
| | | if (!todayRecord.value || !todayRecord.value.workStartAt) { |
| | | return "ä¸çæå¡"; |
| | | } |
| | | if (!todayRecord.value.checkOutTime) { |
| | | if (!todayRecord.value.workEndAt) { |
| | | return "ä¸çæå¡"; |
| | | } |
| | | return "å·²æå¡"; |
| | | }); |
| | | |
| | | // 仿¥ç¶ææ ç¾ç±»å |
| | | const todayStatusTag = computed(() => { |
| | | if (!todayRecord.value.id) return "info"; |
| | | if (todayRecord.value.status === 0) return "success"; |
| | | return "danger"; |
| | | }); |
| | | |
| | | // 仿¥ç¶æææ¬ |
| | | const todayStatusText = computed(() => { |
| | | if (!todayRecord.value.id) return "æªæå¡"; |
| | | switch (todayRecord.value.status) { |
| | | case 0: |
| | | return "æ£å¸¸"; |
| | | case 1: |
| | | return "è¿å°"; |
| | | case 2: |
| | | return "æ©é"; |
| | | case 3: |
| | | return "è¿å°ãæ©é"; |
| | | case 4: |
| | | return "缺å¤"; |
| | | } |
| | | }); |
| | | |
| | | // 导èªå°è¯¦ç»æ¥åé¡µé¢ |
| | | const navigateToReport = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/attendance/report", |
| | | url: "/pages/humanResources/attendance/report", |
| | | }); |
| | | }; |
| | | |
| | |
| | | }); |
| | | }; |
| | | |
| | | // æå¡é»è¾ï¼ä»
å端模æï¼ |
| | | // è·åçæ¬¡åå
¸æ°æ® |
| | | const getWorkTimeDict = () => { |
| | | getDicts("sys_work_time") |
| | | .then(res => { |
| | | if (res.data && res.data.length > 0) { |
| | | const dictData = res.data; |
| | | workTimeDict.value = { |
| | | startAt: dictData[0].dictValue || "-", |
| | | endAt: dictData[1].dictValue || "-", |
| | | }; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åçæ¬¡åå
¸å¤±è´¥:", error); |
| | | }); |
| | | }; |
| | | |
| | | // æå¡é»è¾ |
| | | const handleCheckInOut = async () => { |
| | | if (todayRecord.value.workEndAt) { |
| | | uni.showToast({ |
| | | title: "æ¨å·²ç»æè¿å¡äº,æ éé夿å¡!!!", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | // æ£æ¥æ¯å¦å¨æå¡èå´å
|
| | | if (!inCheckRange.value) { |
| | | uni.showToast({ |
| | |
| | | return; |
| | | } |
| | | |
| | | const [dateStr, timeStr] = nowTime.value.split(" "); |
| | | if (!dateStr || !timeStr) return; |
| | | |
| | | // ä¸çæå¡ |
| | | if (!todayRecord.value) { |
| | | const newId = rawAttendance.value.length |
| | | ? Math.max(...rawAttendance.value.map(i => i.id)) + 1 |
| | | : 1; |
| | | const status = timeStr > "09:00:00" ? "late" : "normal"; |
| | | const statusText = status === "late" ? "è¿å°" : "æ£å¸¸"; |
| | | rawAttendance.value.push({ |
| | | id: newId, |
| | | date: dateStr, |
| | | userId: currentUser.id, |
| | | name: currentUser.name, |
| | | no: currentUser.no, |
| | | dept: currentUser.dept, |
| | | checkInTime: timeStr.slice(0, 5), |
| | | checkOutTime: "", |
| | | workHours: null, |
| | | status, |
| | | statusText, |
| | | remark: "", |
| | | // è°ç¨æå¡API |
| | | createPersonalAttendanceRecord({}) |
| | | .then(res => { |
| | | uni.showToast({ |
| | | title: "æå¡æåï¼", |
| | | icon: "success", |
| | | }); |
| | | // éæ°è·å仿¥æå¡ä¿¡æ¯ |
| | | fetchTodayData(); |
| | | }) |
| | | .catch(error => { |
| | | console.error("æå¡å¤±è´¥:", error); |
| | | uni.showToast({ |
| | | title: error.msg || "æå¡å¤±è´¥ï¼è¯·éè¯", |
| | | icon: "none", |
| | | }); |
| | | }); |
| | | uni.showToast({ |
| | | title: "ä¸çæå¡æå", |
| | | icon: "success", |
| | | }); |
| | | } else if (!todayRecord.value.checkOutTime) { |
| | | // ä¸çæå¡ |
| | | todayRecord.value.checkOutTime = timeStr.slice(0, 5); |
| | | // ç®åæ 9:00-18:00 计ç®å·¥æ¶ |
| | | const start = todayRecord.value.checkInTime || "09:00"; |
| | | const [sh, sm] = start.split(":").map(v => parseInt(v, 10)); |
| | | const [eh, em] = todayRecord.value.checkOutTime |
| | | .split(":") |
| | | .map(v => parseInt(v, 10)); |
| | | const diff = (eh * 60 + em - (sh * 60 + sm)) / 60; |
| | | todayRecord.value.workHours = Number(Math.max(diff, 0).toFixed(1)); |
| | | |
| | | // æ©é夿ï¼18:00 å离å¼è§ä¸ºæ©éï¼åªç¤ºæï¼ |
| | | if (timeStr < "18:00:00") { |
| | | if (todayRecord.value.status === "late") { |
| | | // æ¢è¿å°åæ©é |
| | | todayRecord.value.status = "late-early"; |
| | | todayRecord.value.statusText = "è¿å° + æ©é"; |
| | | } else { |
| | | // ä»
æ©é |
| | | todayRecord.value.status = "early"; |
| | | todayRecord.value.statusText = "æ©é"; |
| | | } |
| | | } else if (todayRecord.value.status === "normal") { |
| | | todayRecord.value.statusText = "æ£å¸¸"; |
| | | } |
| | | uni.showToast({ |
| | | title: "ä¸çæå¡æå", |
| | | icon: "success", |
| | | }); |
| | | } else { |
| | | uni.showToast({ |
| | | title: "仿¥å·²å®æä¸ä¸çæå¡", |
| | | icon: "none", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | onMounted(async () => { |
| | | fetchTodayData(); |
| | | updateNowTime(); |
| | | timer = setInterval(updateNowTime, 1000); |
| | | getWorkTimeDict(); |
| | | |
| | | // è·åä½ç½®æéå¹¶æ£æ¥ä½ç½® |
| | | try { |
| ÎļþÃû´Ó src/pages/attendance/report.vue ÐÞ¸Ä |
| | |
| | | @cancel="showDatePicker = false" |
| | | title="æç´¢æ¥æ" /> |
| | | <view class="record-list"> |
| | | <view v-for="(item) in tableData" |
| | | <!-- å è½½ç¶æ --> |
| | | <view v-if="loading" |
| | | class="loading-state"> |
| | | <u-icon name="loading" |
| | | size="40" |
| | | color="#348fe2"></u-icon> |
| | | <text class="loading-text">å è½½ä¸...</text> |
| | | </view> |
| | | <view v-else |
| | | v-for="(item) in tableData" |
| | | :key="item.id" |
| | | class="record-item-card" |
| | | :class="{ 'abnormal': item.status !== 'normal' }"> |
| | | :class="{ 'abnormal': item.status !== 0 }"> |
| | | <view class="record-item-header"> |
| | | <text class="record-date">{{ item.date }}</text> |
| | | <u-tag :type="item.status === 'normal' ? 'success' : 'error'" |
| | | <u-tag :type="item.status === 0 ? 'success' : 'error'" |
| | | size="small"> |
| | | {{ item.statusText }} |
| | | <!-- {{ item.status === 0 ? 'æ£å¸¸' : (item.status === 1 ? 'è¿å°' : (item.status === 2 ? 'æ©é' : 'è¿å°ãæ©é')) }} --> |
| | | {{ getStatusText(item.status) }} |
| | | </u-tag> |
| | | </view> |
| | | <view class="record-item-body"> |
| | | <view class="record-detail"> |
| | | <text class="detail-label">åå·¥</text> |
| | | <text class="detail-value">{{ item.name }} ({{ item.no }})</text> |
| | | <text class="detail-value">{{ item.staffName }} ({{ item.staffNo }})</text> |
| | | </view> |
| | | <view class="record-detail"> |
| | | <text class="detail-label">é¨é¨</text> |
| | | <text class="detail-value">{{ item.dept }}</text> |
| | | <text class="detail-value">{{ item.deptName }}</text> |
| | | </view> |
| | | <view class="record-detail"> |
| | | <text class="detail-label">ä¸çæ¶é´</text> |
| | | <text class="detail-value">{{ item.checkInTime ? item.checkInTime : '缺å¡' }}</text> |
| | | <text class="detail-value">{{ item.workStartAt || '缺å¡' }}</text> |
| | | </view> |
| | | <view class="record-detail"> |
| | | <text class="detail-label">ä¸çæ¶é´</text> |
| | | <text class="detail-value">{{ item.checkOutTime? item.checkOutTime : '缺å¡' }}</text> |
| | | <text class="detail-value">{{ item.workEndAt || '缺å¡' }}</text> |
| | | </view> |
| | | <view class="record-detail"> |
| | | <text class="detail-label">å·¥æ¶</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-if="tableData.length === 0" |
| | | <view v-if="tableData.length === 0 && !loading" |
| | | class="empty-state"> |
| | | <u-icon name="clock-o" |
| | | <!-- <u-icon name="clock-o" |
| | | size="60" |
| | | color="#999"></u-icon> |
| | | color="#999"></u-icon> --> |
| | | <text class="empty-text">ææ èå¤è®°å½</text> |
| | | </view> |
| | | </view> |
| | |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 模æå½åç»å½åå·¥ |
| | | const currentUser = reactive({ |
| | | id: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | }); |
| | | |
| | | // 模æèå¤åå§æ°æ® |
| | | const rawAttendance = ref([ |
| | | { |
| | | id: 1, |
| | | date: "2026-02-09", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "08:58", |
| | | checkOutTime: "", |
| | | workHours: null, |
| | | status: "normal", |
| | | statusText: "æ£å¸¸", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 2, |
| | | date: "2026-02-08", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "09:15", |
| | | checkOutTime: "18:05", |
| | | workHours: 8.8, |
| | | status: "late", |
| | | statusText: "è¿å°", |
| | | remark: "å äº¤éæ¥å µè¿å°", |
| | | }, |
| | | { |
| | | id: 3, |
| | | date: "2026-02-07", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "08:45", |
| | | checkOutTime: "18:30", |
| | | workHours: 9.7, |
| | | status: "normal", |
| | | statusText: "æ£å¸¸", |
| | | remark: "å ç0.5å°æ¶", |
| | | }, |
| | | { |
| | | id: 4, |
| | | date: "2026-02-06", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "08:50", |
| | | checkOutTime: "17:45", |
| | | workHours: 8.9, |
| | | status: "early", |
| | | statusText: "æ©é", |
| | | remark: "å®¶ä¸æäºæå离å¼", |
| | | }, |
| | | { |
| | | id: 5, |
| | | date: "2026-02-05", |
| | | userId: 1, |
| | | name: "å¼ ä¸", |
| | | no: "E10001", |
| | | dept: "ç产ä¸é¨", |
| | | checkInTime: "08:40", |
| | | checkOutTime: "18:20", |
| | | workHours: 9.7, |
| | | status: "normal", |
| | | statusText: "æ£å¸¸", |
| | | remark: "å ç0.5å°æ¶", |
| | | }, |
| | | ]); |
| | | import { findPersonalAttendanceRecords } from "@/api/personnelManagement/attendance.js"; |
| | | |
| | | // æ¥è¯¢è¡¨å |
| | | const searchForm = reactive({ |
| | | date: "", |
| | | }); |
| | | |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: -1, |
| | | size: -1, |
| | | total: 0, |
| | | }); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | |
| | | showDatePicker.value = false; |
| | | handleQuery(); |
| | | }; |
| | | const getStatusText = status => { |
| | | switch (status) { |
| | | case 0: |
| | | return "æ£å¸¸"; |
| | | case 1: |
| | | return "è¿å°"; |
| | | case 2: |
| | | return "æ©é"; |
| | | case 3: |
| | | return "è¿å°ãæ©é"; |
| | | case 4: |
| | | return "缺å¤"; |
| | | } |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const selectDate = () => { |
| | |
| | | |
| | | // æ¸
餿¥æéæ© |
| | | const clearDate = () => { |
| | | resetQuery(); |
| | | }; |
| | | |
| | | // æ¥è¯¢ |
| | | const handleQuery = () => { |
| | | loading.value = true; |
| | | console.log(searchForm, "searchForm"); |
| | | |
| | | findPersonalAttendanceRecords({ |
| | | ...page, |
| | | ...searchForm, |
| | | }) |
| | | .then(res => { |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(error => { |
| | | console.error("æ¥è¯¢å¤±è´¥:", error); |
| | | uni.showToast({ |
| | | title: "æ¥è¯¢å¤±è´¥ï¼è¯·éè¯", |
| | | icon: "none", |
| | | }); |
| | | }) |
| | | .finally(() => { |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | const resetQuery = () => { |
| | | searchForm.date = ""; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // æ¥è¯¢ |
| | | const recomputeTable = () => { |
| | | const list = rawAttendance.value.filter(item => { |
| | | if (searchForm.date && item.date !== searchForm.date) { |
| | | return false; |
| | | } |
| | | return true; |
| | | }); |
| | | tableData.value = list; |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | recomputeTable(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | recomputeTable(); |
| | | handleQuery(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | margin: 0 20rpx 24rpx; |
| | | } |
| | | |
| | | /* å è½½ç¶æ */ |
| | | .loading-state { |
| | | background-color: $card-bg; |
| | | border-radius: 16rpx; |
| | | box-shadow: $shadow-md; |
| | | text-align: center; |
| | | padding: 120rpx 0; |
| | | margin: 0 20rpx; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .loading-text { |
| | | font-size: 14px; |
| | | color: $text-tertiary; |
| | | margin-top: 24rpx; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .record-item-card { |
| | | background-color: $card-bg; |
| | | border-radius: 16rpx; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="hazard-source-detail"> |
| | | <PageHeader :title="isEdit ? 'ç¼è¾èªèµå°è´¦' : 'æ°å¢èªèµå°è´¦'" |
| | | @back="goBack" /> |
| | | <u-form @submit="handleSubmit" |
| | | ref="formRef" |
| | | label-width="110"> |
| | | <!-- èªèµä¿¡æ¯ --> |
| | | <u-cell-group title="èªèµä¿¡æ¯"> |
| | | <u-form-item label="ç»è®¡æä»½" |
| | | prop="payDate" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.payDate" |
| | | placeholder="è¯·éæ©æä»½" |
| | | @click="showDatePicker" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="åå·¥å§å" |
| | | prop="staffId" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.staffName" |
| | | placeholder="è¯·éæ©åå·¥" |
| | | @click="showStaffSheet" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showStaffSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="åºæ¬å·¥èµ" |
| | | prop="basicSalary" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.basicSalary" |
| | | type="number" |
| | | placeholder="请è¾å
¥åºæ¬å·¥èµ" /> |
| | | </u-form-item> |
| | | <u-form-item label="计件工èµ" |
| | | prop="pieceworkSalary" |
| | | border-bottom> |
| | | <u-input v-model="form.pieceworkSalary" |
| | | type="number" |
| | | placeholder="请è¾å
¥è®¡ä»¶å·¥èµ" /> |
| | | </u-form-item> |
| | | <u-form-item label="计æ¶å·¥èµ" |
| | | prop="hourlySalary" |
| | | border-bottom> |
| | | <u-input v-model="form.hourlySalary" |
| | | type="number" |
| | | placeholder="请è¾å
¥è®¡æ¶å·¥èµ" /> |
| | | </u-form-item> |
| | | <u-form-item label="å
¶ä»æ¶å
¥" |
| | | prop="otherIncome" |
| | | border-bottom> |
| | | <u-input v-model="form.otherIncome" |
| | | type="number" |
| | | placeholder="请è¾å
¥å
¶ä»æ¶å
¥" /> |
| | | </u-form-item> |
| | | <u-form-item label="社ä¿ä¸ªäºº" |
| | | prop="socialSecurityIndividuals" |
| | | border-bottom> |
| | | <u-input v-model="form.socialSecurityIndividuals" |
| | | type="number" |
| | | placeholder="请è¾å
¥ç¤¾ä¿ä¸ªäºº" /> |
| | | </u-form-item> |
| | | <u-form-item label="å
¬ç§¯é个人" |
| | | prop="providentFundIndividuals" |
| | | border-bottom> |
| | | <u-input v-model="form.providentFundIndividuals" |
| | | type="number" |
| | | placeholder="请è¾å
¥å
¬ç§¯é个人" /> |
| | | </u-form-item> |
| | | <u-form-item label="个人æå¾ç¨" |
| | | prop="personalIncomeTax" |
| | | border-bottom> |
| | | <u-input v-model="form.personalIncomeTax" |
| | | type="number" |
| | | placeholder="请è¾å
¥ä¸ªäººæå¾ç¨" /> |
| | | </u-form-item> |
| | | <u-form-item label="å
¶ä»æ£æ¬¾" |
| | | prop="otherDeductions" |
| | | border-bottom> |
| | | <u-input v-model="form.otherDeductions" |
| | | type="number" |
| | | placeholder="请è¾å
¥å
¶ä»æ£æ¬¾" /> |
| | | </u-form-item> |
| | | <u-form-item label="夿³¨" |
| | | prop="remark" |
| | | border-bottom> |
| | | <u-textarea v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | :rows="3" |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="sign-btn" |
| | | type="primary" |
| | | @click="handleSubmit" |
| | | :loading="loading">{{ isEdit ? 'æ´æ°' : 'ä¿å' }}</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- åå·¥éæ©å¨ --> |
| | | <up-action-sheet :show="staffSheetVisible" |
| | | :actions="staffOptions" |
| | | @select="handleStaffSelect" |
| | | @close="staffSheetVisible = false" |
| | | title="éæ©åå·¥" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker :show="datePickerVisible" |
| | | v-model="currentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="datePickerVisible = false" |
| | | mode="month" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "monthly-statistics-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | monthlyStatisticsAdd, |
| | | monthlyStatisticsUpdate, |
| | | staffOnJobList, |
| | | } from "@/api/personnelManagement/monthlyStatistics"; |
| | | import dayjs from "dayjs"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | id: "", |
| | | payDate: "", |
| | | staffId: "", |
| | | staffName: "", |
| | | basicSalary: 0, |
| | | pieceworkSalary: 0, |
| | | hourlySalary: 0, |
| | | otherIncome: 0, |
| | | socialSecurityIndividuals: 0, |
| | | providentFundIndividuals: 0, |
| | | personalIncomeTax: 0, |
| | | otherDeductions: 0, |
| | | payableWages: 0, |
| | | deductibleWages: 0, |
| | | actualWages: 0, |
| | | remark: "", |
| | | }); |
| | | |
| | | // 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const isEdit = ref(false); |
| | | |
| | | // åå·¥éæ©å¨ |
| | | const staffSheetVisible = ref(false); |
| | | const staffOptions = ref([]); |
| | | const staffList = ref([]); |
| | | const showStaffSheet = () => { |
| | | if (staffOptions.value.length === 0) { |
| | | loadStaffList(); |
| | | } else { |
| | | staffSheetVisible.value = true; |
| | | } |
| | | }; |
| | | const handleStaffSelect = item => { |
| | | const staff = staffList.value.find(s => s.id === item.value); |
| | | if (staff) { |
| | | form.value.staffId = staff.id; |
| | | form.value.staffName = staff.staffName; |
| | | } |
| | | staffSheetVisible.value = false; |
| | | }; |
| | | const loadStaffList = () => { |
| | | staffOnJobList().then(res => { |
| | | if (res.code === 200) { |
| | | staffList.value = res.data || []; |
| | | staffOptions.value = staffList.value.map(item => ({ |
| | | value: item.id, |
| | | name: item.staffName, |
| | | subname: `å·¥å·: ${item.staffNo}`, |
| | | })); |
| | | staffSheetVisible.value = true; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¥æéæ©å¨ |
| | | const datePickerVisible = ref(false); |
| | | const currentDate = ref(Date.now()); |
| | | const showDatePicker = () => { |
| | | datePickerVisible.value = true; |
| | | }; |
| | | const onDateConfirm = e => { |
| | | form.value.payDate = dayjs(e.value).format("YYYY-MM"); |
| | | currentDate.value = e.value; |
| | | datePickerVisible.value = false; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync("monthlyStatistics"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | if (!form.value.payDate) { |
| | | showToast("è¯·éæ©ç»è®¡æä»½"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.staffId) { |
| | | showToast("è¯·éæ©åå·¥"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.basicSalary) { |
| | | showToast("请è¾å
¥åºæ¬å·¥èµ"); |
| | | return; |
| | | } |
| | | |
| | | // 计ç®åºåå·¥èµãåºæ£å·¥èµåå®åå·¥èµ |
| | | const payableWages = |
| | | Number(form.value.basicSalary) + |
| | | Number(form.value.pieceworkSalary) + |
| | | Number(form.value.hourlySalary) + |
| | | Number(form.value.otherIncome); |
| | | const deductibleWages = |
| | | Number(form.value.socialSecurityIndividuals) + |
| | | Number(form.value.providentFundIndividuals) + |
| | | Number(form.value.personalIncomeTax) + |
| | | Number(form.value.otherDeductions); |
| | | const actualWages = payableWages - deductibleWages; |
| | | |
| | | const submitData = { |
| | | ...form.value, |
| | | payableWages, |
| | | deductibleWages, |
| | | actualWages, |
| | | }; |
| | | |
| | | try { |
| | | loading.value = true; |
| | | |
| | | if (isEdit.value) { |
| | | const { code } = await monthlyStatisticsUpdate(submitData); |
| | | if (code === 200) { |
| | | showToast("æ´æ°æå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("æ´æ°å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } else { |
| | | const { code } = await monthlyStatisticsAdd(submitData); |
| | | if (code === 200) { |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("æäº¤å¤±è´¥:", e); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | onLoad(() => { |
| | | // ç¼è¾èªèµå°è´¦æ¶ï¼ä»æ¬å°åå¨è·åæ°æ® |
| | | const monthlyStatistics = uni.getStorageSync("monthlyStatistics"); |
| | | if (monthlyStatistics.id) { |
| | | form.value = monthlyStatistics; |
| | | isEdit.value = true; |
| | | } else { |
| | | isEdit.value = false; |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | // 设置é»è®¤æ¶é´ |
| | | if (!isEdit.value) { |
| | | form.value.payDate = dayjs().format("YYYY-MM"); |
| | | currentDate.value = Date.now(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | .hazard-source-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0, 0, 0, 0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #666; |
| | | background: #f5f5f5; |
| | | border: 1px solid #ddd; |
| | | width: 45%; |
| | | height: 2.5rem; |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .sign-btn { |
| | | font-weight: 500; |
| | | font-size: 1rem; |
| | | color: #fff; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border: none; |
| | | width: 45%; |
| | | height: 2.5rem; |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="sales-accoun"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="èªèµå°è´¦" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥åå·¥å§å" |
| | | v-model="searchKeyword" |
| | | @blur="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <u-icon name="search" |
| | | size="24" |
| | | color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- èªèµå°è´¦å表 --> |
| | | <view class="ledger-list" |
| | | v-if="ledgerList.length > 0"> |
| | | <view v-for="(item, index) in ledgerList" |
| | | :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.payDate }}</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.staffName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ¬å·¥èµ</text> |
| | | <text class="detail-value">{{ item.basicSalary || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">计件工èµ</text> |
| | | <text class="detail-value">{{ item.pieceworkSalary || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">计æ¶å·¥èµ</text> |
| | | <text class="detail-value">{{ item.hourlySalary || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å
¶ä»æ¶å
¥</text> |
| | | <text class="detail-value">{{ item.otherIncome || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºåå·¥èµ</text> |
| | | <text class="detail-value">{{ item.payableWages || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ£å·¥èµ</text> |
| | | <text class="detail-value">{{ item.deductibleWages || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å®åå·¥èµ</text> |
| | | <text class="detail-value">{{ item.actualWages || 0 }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editItem(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deleteItem(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ èªèµå°è´¦æ°æ®</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addItem"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | monthlyStatisticsListPage, |
| | | monthlyStatisticsDelete, |
| | | } from "@/api/personnelManagement/monthlyStatistics"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "monthly-statistics-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref(""); |
| | | |
| | | // èªèµå°è´¦æ°æ® |
| | | const ledgerList = ref([]); |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | staffName: searchKeyword.value, |
| | | }; |
| | | monthlyStatisticsListPage(params) |
| | | .then(res => { |
| | | ledgerList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢èªèµå°è´¦ |
| | | const addItem = () => { |
| | | uni.setStorageSync("monthlyStatistics", {}); |
| | | uni.navigateTo({ |
| | | url: "/pages/humanResources/monthlyStatistics/detail", |
| | | }); |
| | | }; |
| | | // ç¼è¾èªèµå°è´¦ |
| | | const editItem = item => { |
| | | uni.setStorageSync("monthlyStatistics", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/humanResources/monthlyStatistics/detail", |
| | | }); |
| | | }; |
| | | // å é¤èªèµå°è´¦ |
| | | const deleteItem = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤è¯¥èªèµå°è´¦è®°å½åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteItemById(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤èªèµå°è´¦è®°å½ |
| | | const deleteItemById = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | monthlyStatisticsDelete([id]) |
| | | .then(() => { |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | 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; |
| | | } |
| | | |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | </style> |
| | |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- è¥éç®¡çæ¨¡å --> |
| | | <view class="common-module marketing-module"> |
| | | <view class="common-module marketing-module" |
| | | v-if="hasMarketingItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">è¥é管ç</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- <!– éè´ç®¡çæ¨¡å –>--> |
| | | <view class="common-module purchase-module"> |
| | | <view class="common-module purchase-module" |
| | | v-if="hasPurchaseItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">éè´ç®¡ç</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- <!– åååå
¬æ¨¡å –> --> |
| | | <view class="common-module collaboration-module"> |
| | | <view class="common-module collaboration-module" |
| | | v-if="hasCollaborationItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">åååå
¬</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- å®å
¨ç产模å --> |
| | | <view class="common-module collaboration-module"> |
| | | <view class="common-module collaboration-module" |
| | | v-if="hasSafetyItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">å®å
¨ç产</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 人åèµæºæ¨¡å --> |
| | | <view class="common-module collaboration-module"> |
| | | <view class="common-module collaboration-module" |
| | | v-if="hasHumanResourcesItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">人åèµæº</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- çäº§ç®¡æ§æ¨¡å --> |
| | | <!-- <view class="common-module production-module">--> |
| | | <!-- <view class="module-header">--> |
| | | <!-- <view class="module-title-container">--> |
| | | <!-- <text class="module-title">ç产管æ§</text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="module-content">--> |
| | | <!-- <up-grid--> |
| | | <!-- :border="false"--> |
| | | <!-- col="4"--> |
| | | <!-- >--> |
| | | <!-- <up-grid-item--> |
| | | <!-- v-for="(item, index) in productionItems"--> |
| | | <!-- :key="index"--> |
| | | <!-- @click="handleCommonItemClick(item)"--> |
| | | <!-- >--> |
| | | <!-- <view class="icon-container" :style="{ background: item.bgColor }">--> |
| | | <!-- <up-icon--> |
| | | <!-- :name="item.icon"--> |
| | | <!-- :size="58"--> |
| | | <!-- color="#ffffff"--> |
| | | <!-- ></up-icon>--> |
| | | <!-- </view>--> |
| | | <!-- <text class="item-label">{{item.label}}</text>--> |
| | | <!-- </up-grid-item>--> |
| | | <!-- </up-grid>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- çäº§ç®¡æ§æ¨¡å --> |
| | | <view class="common-module equipment-module"> |
| | | <view class="common-module equipment-module" |
| | | v-if="hasProductionItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">ç产管æ§</text> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 设å¤ç®¡ç模å --> |
| | | <view class="common-module equipment-module"> |
| | | <view class="common-module equipment-module" |
| | | v-if="hasEquipmentItems"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">设å¤ç®¡ç</text> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, nextTick, reactive } from "vue"; |
| | | import { ref, onMounted, nextTick, reactive, computed } from "vue"; |
| | | import { userLoginFacotryList } from "@/api/login"; |
| | | import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting"; |
| | | import modal from "@/plugins/modal"; |
| | |
| | | const safetyItems = reactive([ |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "è§ç¨èµè´¨", |
| | | label: "è§ç¨ä¸èµè´¨", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "å±é©ä½ä¸", |
| | | label: "å±é©ä½ä¸å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "éæ£ææ¥", |
| | | label: "éæ£ææ¥ä¸æ¥", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "å±é©ç©æ", |
| | | label: "å±é©ç©æç®¡æ§", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "åºæ¥é¢æ¡", |
| | | label: "åºæ¥é¢æ¡æ¥é
", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "äºæ
䏿¥", |
| | | label: "äºæ
䏿¥è®°å½", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "å®å
¨å¹è®", |
| | | label: "å®å
¨å¹è®èæ ¸", |
| | | }, |
| | | ]); |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | | { |
| | | icon: "/static/images/icon/gongchuguanli@2x.png", |
| | | label: "èå¤ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/baoxiaoguanli.png", |
| | | label: "è´¢å¡ç®¡ç", |
| | | label: "åå审æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyiliebiao@2x.png", |
| | |
| | | icon: "/static/images/icon/guizhangzhidu@2x.png", |
| | | label: "è§ç« å¶åº¦", |
| | | }, |
| | | // { |
| | | // icon: "/static/images/icon/xietongshenpi@2x.png", |
| | | // label: "åå审æ¹", |
| | | // }, |
| | | { |
| | | icon: "/static/images/icon/kehubaifang@2x.png", |
| | | label: "å®¢æ·æè®¿", |
| | |
| | | { |
| | | icon: "/static/images/icon/shbeibaoyang@2x.png", |
| | | label: "设å¤ä¿å
»", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "åæè¿½æº¯", |
| | | bgColor: "#ff9800", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/zhinengpaidan@2x.png", |
| | | label: "æºè½æ´¾å", |
| | | bgColor: "#ff6b35", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/zuoyezhidao@2x.png", |
| | | label: "ä½ä¸æå¯¼", |
| | | bgColor: "#4caf50", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/jieguoyanzheng@2x.png", |
| | | label: "ç»æéªè¯", |
| | | bgColor: "#9c27b0", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/xunjianshangchuan@2x.png", |
| | |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index4", |
| | | }); |
| | | break; |
| | | case "èå¤ç®¡ç": |
| | | case "åå审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/indexItem?label=èå¤ç®¡ç", |
| | | }); |
| | | break; |
| | | case "è´¢å¡ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/indexItem?label=è´¢å¡ç®¡ç", |
| | | url: "/pages/indexItem?label=åå审æ¹", |
| | | }); |
| | | break; |
| | | case "ä¼è®®ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/indexItem?label=ä¼è®®ç®¡ç", |
| | | }); |
| | | break; |
| | | case "éç¥å
Œ": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/noticeManagement/index", |
| | | }); |
| | | break; |
| | | case "ç¥è¯åº": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/knowledgeBase/index", |
| | | }); |
| | | break; |
| | | case "ç¨å°ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/sealManagement/index", |
| | | }); |
| | | break; |
| | | case "è§ç« å¶åº¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/rulesRegulationsManagement/index", |
| | | }); |
| | | break; |
| | | case "å®¢æ·æè®¿": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/index", |
| | | }); |
| | | break; |
| | | case "éè´ç®¡ç": |
| | |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index6", |
| | | }); |
| | | break; |
| | | case "åºåºç®¡ç": |
| | | case "å货审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index7", |
| | | }); |
| | |
| | | case "ä¼è®®çæ¿": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingBoard/index", |
| | | }); |
| | | break; |
| | | case "éç¥å
Œ": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/noticeManagement/index", |
| | | }); |
| | | break; |
| | | case "ç¥è¯åº": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/knowledgeBase/index", |
| | | }); |
| | | break; |
| | | case "ç¨å°ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/sealManagement/index", |
| | | }); |
| | | break; |
| | | case "è§ç« å¶åº¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/rulesRegulationsManagement/index", |
| | | }); |
| | | break; |
| | | |
| | | case "åå审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index", |
| | | }); |
| | | break; |
| | | case "å®¢æ·æè®¿": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/index", |
| | | }); |
| | | break; |
| | | case "ç产订å": |
| | |
| | | url: "/pages/equipmentManagement/verification/index", |
| | | }); |
| | | break; |
| | | case "è§ç¨èµè´¨": |
| | | case "è§ç¨ä¸èµè´¨": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safeQualifications/index", |
| | | }); |
| | |
| | | url: "/pages/safeProduction/hazardSourceLedger/index", |
| | | }); |
| | | break; |
| | | case "å±é©ä½ä¸": |
| | | case "å±é©ä½ä¸å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index8", |
| | | }); |
| | | break; |
| | | case "éæ£ææ¥": |
| | | case "éæ£ææ¥ä¸æ¥": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/dangerInvestigation/index", |
| | | }); |
| | | break; |
| | | case "å±é©ç©æ": |
| | | case "å±é©ç©æç®¡æ§": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/hazardousMaterialsControl/index", |
| | | }); |
| | | break; |
| | | case "åºæ¥é¢æ¡": |
| | | case "åºæ¥é¢æ¡æ¥é
": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/emergencyPlanReview/index", |
| | | }); |
| | | break; |
| | | case "äºæ
䏿¥": |
| | | case "äºæ
䏿¥è®°å½": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/accidentReportingRecord/index", |
| | | }); |
| | | break; |
| | | case "å®å
¨å¹è®": |
| | | case "å®å
¨å¹è®èæ ¸": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/safetyTrainingAssessment/index", |
| | | }); |
| | | break; |
| | | case "æå¡ç¾å°": |
| | | uni.navigateTo({ |
| | | url: "/pages/attendance/checkin", |
| | | url: "/pages/humanResources/attendance/checkin", |
| | | }); |
| | | break; |
| | | case "人åèªèµ": |
| | | uni.navigateTo({ |
| | | url: "/pages/humanResources/monthlyStatistics/index", |
| | | }); |
| | | break; |
| | | default: |
| | |
| | | return; |
| | | } |
| | | } |
| | | |
| | | console.log(orderRow, "orderRow======@@@@@@@@"); |
| | | // æ«ç æåå跳转å°ç产æ¥å·¥é¡µé¢ï¼å¹¶ä¼ éorderRowåæ° |
| | | uni.navigateTo({ |
| | | url: `/pages/productionManagement/productionReport/index?orderRow=${orderRow}`, |
| | |
| | | }); |
| | | }; |
| | | function loginSuccess(result) { |
| | | // è·åè·¯ç±æé |
| | | userStore |
| | | .getRouters() |
| | | .then(() => { |
| | | console.log("è·¯ç±æéè·åæå"); |
| | | // è¿æ»¤èå项 |
| | | filterMenuItemsByRoutes(); |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åè·¯ç±æé失败:", error); |
| | | }); |
| | | uni.reLaunch({ |
| | | url: "/pages/index", |
| | | }); |
| | |
| | | } |
| | | }; |
| | | |
| | | // æ ¹æ®è·¯ç±æéè¿æ»¤èå项 |
| | | const filterMenuItemsByRoutes = () => { |
| | | const routers = userStore.routers || []; |
| | | |
| | | // å¦ææ²¡æè·¯ç±æéæ°æ®ï¼ä¸è¿è¡è¿æ»¤ï¼æ¾ç¤ºææèåï¼ |
| | | if (!routers || routers.length === 0) { |
| | | console.log("ææ è·¯ç±æéæ°æ®ï¼æ¾ç¤ºææèå"); |
| | | return; |
| | | } |
| | | |
| | | // æ¶éææææéçèåæ é¢ï¼æ ¹æ® meta.titleï¼ |
| | | const allowedMenuTitles = new Set(); |
| | | const collectMenuTitles = routes => { |
| | | if (!Array.isArray(routes)) return; |
| | | routes.forEach(route => { |
| | | // æ¶éå½åè·¯ç±çæ é¢ |
| | | if (route.meta && route.meta.title) { |
| | | allowedMenuTitles.add(route.meta.title); |
| | | } |
| | | // éå½å¤çåè·¯ç± |
| | | if (route.children && route.children.length > 0) { |
| | | collectMenuTitles(route.children); |
| | | } |
| | | }); |
| | | }; |
| | | collectMenuTitles(routers); |
| | | |
| | | // è¿æ»¤è¥é管çèå |
| | | const originalMarketing = [ |
| | | { icon: "/static/images/icon/xiaoshoutaizhang@2x.png", label: "éå®å°è´¦" }, |
| | | { icon: "/static/images/icon/kaipiaodengji@2x.png", label: "å¼ç¥¨ç»è®°" }, |
| | | { icon: "/static/images/icon/kaipiaotaizhang@2x.png", label: "å¼ç¥¨å°è´¦" }, |
| | | { icon: "/static/images/icon/huikuandengji@2x.png", label: "忬¾ç»è®°" }, |
| | | { icon: "/static/images/icon/huikuanliushui@2x.png", label: "忬¾æµæ°´" }, |
| | | { icon: "/static/images/icon/kehuwanglai@2x.png", label: "客æ·å¾æ¥" }, |
| | | ]; |
| | | const filteredMarketing = originalMarketing.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | marketingItems.splice(0, marketingItems.length, ...filteredMarketing); |
| | | |
| | | // è¿æ»¤åååå
¬èå |
| | | const originalCollaboration = [ |
| | | { icon: "/static/images/icon/baoxiaoguanli.png", label: "åå审æ¹" }, |
| | | { icon: "/static/images/icon/huiyiliebiao@2x.png", label: "ä¼è®®ç®¡ç" }, |
| | | { icon: "/static/images/icon/tongzhigonggao@2x.png", label: "éç¥å
Œ" }, |
| | | { icon: "/static/images/icon/zhishiku@2x.png", label: "ç¥è¯åº" }, |
| | | { icon: "/static/images/icon/yongyinguanli@2x.png", label: "ç¨å°ç®¡ç" }, |
| | | { icon: "/static/images/icon/guizhangzhidu@2x.png", label: "è§ç« å¶åº¦" }, |
| | | { icon: "/static/images/icon/kehubaifang@2x.png", label: "å®¢æ·æè®¿" }, |
| | | ]; |
| | | const filteredCollaboration = originalCollaboration.filter(item => { |
| | | // å¤çæ é¢ä¸å®å
¨å¹é
çæ
åµ |
| | | let matched = allowedMenuTitles.has(item.label); |
| | | // ç¹æ®å¤çï¼è§ç« å¶åº¦ -> è§ç« å¶åº¦ç®¡ç |
| | | if (!matched && item.label === "è§ç« å¶åº¦") { |
| | | matched = allowedMenuTitles.has("è§ç« å¶åº¦ç®¡ç"); |
| | | } |
| | | return matched; |
| | | }); |
| | | collaborationItems.splice( |
| | | 0, |
| | | collaborationItems.length, |
| | | ...filteredCollaboration |
| | | ); |
| | | |
| | | // è¿æ»¤éè´ç®¡çèå |
| | | const originalPurchase = [ |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "éè´å°è´¦" }, |
| | | { icon: "/static/images/icon/laipiaodengji@2x.png", label: "æ¥ç¥¨ç»è®°" }, |
| | | { icon: "/static/images/icon/laipiaotaizhang@2x.png", label: "æ¥ç¥¨å°è´¦" }, |
| | | { icon: "/static/images/icon/fukuanjingji@2x.png", label: "仿¬¾ç»è®°" }, |
| | | { icon: "/static/images/icon/fukuanliushui@2x.png", label: "仿¬¾æµæ°´" }, |
| | | { |
| | | icon: "/static/images/icon/gongyingshangwanglai@2x.png", |
| | | label: "ä¾åºå徿¥", |
| | | }, |
| | | ]; |
| | | const filteredPurchase = originalPurchase.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | purchaseItems.splice(0, purchaseItems.length, ...filteredPurchase); |
| | | |
| | | // è¿æ»¤å®å
¨ç产èå |
| | | const originalSafety = [ |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "è§ç¨ä¸èµè´¨" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "å±é©æºå°è´¦" }, |
| | | { |
| | | icon: "/static/images/icon/caigoutaizhang@2x.png", |
| | | label: "å±é©ä½ä¸å®¡æ¹", |
| | | }, |
| | | { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "éæ£ææ¥ä¸æ¥" }, |
| | | { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "å±é©ç©æç®¡æ§" }, |
| | | { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "åºæ¥é¢æ¡æ¥é
" }, |
| | | { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "äºæ
䏿¥è®°å½" }, |
| | | { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "å®å
¨å¹è®èæ ¸" }, |
| | | ]; |
| | | const filteredSafety = originalSafety.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | safetyItems.splice(0, safetyItems.length, ...filteredSafety); |
| | | |
| | | // è¿æ»¤äººåèµæºèå |
| | | const originalHumanResources = [ |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "æå¡ç¾å°" }, |
| | | { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "人åèªèµ" }, |
| | | ]; |
| | | const filteredHumanResources = originalHumanResources.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | humanResourcesItems.splice( |
| | | 0, |
| | | humanResourcesItems.length, |
| | | ...filteredHumanResources |
| | | ); |
| | | |
| | | // è¿æ»¤ç产管æ§èå |
| | | const originalProduction = [ |
| | | { |
| | | icon: "/static/images/icon/shengchanbaogong@2x.png", |
| | | label: "ç产æ¥å·¥", |
| | | bgColor: "#673AB7", |
| | | }, |
| | | ]; |
| | | const filteredProduction = originalProduction.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | productionItems.splice(0, productionItems.length, ...filteredProduction); |
| | | |
| | | // è¿æ»¤è®¾å¤ç®¡çèå |
| | | const originalEquipment = [ |
| | | { icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "è¿è¡ç®¡ç" }, |
| | | { icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "è®¾å¤æ¥ä¿®" }, |
| | | { icon: "/static/images/icon/shbeibaoyang@2x.png", label: "设å¤ä¿å
»" }, |
| | | { icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "å·¡æ£ä¸ä¼ " }, |
| | | ]; |
| | | const filteredEquipment = originalEquipment.filter(item => { |
| | | return allowedMenuTitles.has(item.label); |
| | | }); |
| | | equipmentItems.splice(0, equipmentItems.length, ...filteredEquipment); |
| | | }; |
| | | |
| | | // æ£æ¥æ¨¡åæ¯å¦æèå项éè¦æ¾ç¤º |
| | | const hasMarketingItems = computed(() => marketingItems.length > 0); |
| | | const hasPurchaseItems = computed(() => purchaseItems.length > 0); |
| | | const hasCollaborationItems = computed(() => collaborationItems.length > 0); |
| | | const hasSafetyItems = computed(() => safetyItems.length > 0); |
| | | const hasHumanResourcesItems = computed(() => humanResourcesItems.length > 0); |
| | | const hasProductionItems = computed(() => productionItems.length > 0); |
| | | const hasEquipmentItems = computed(() => equipmentItems.length > 0); |
| | | |
| | | onMounted(() => { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo(); |
| | | // æ¯æ¬¡è¿å
¥é¦é¡µé½å¼ºå¶å·æ°ç¨æ·ä¿¡æ¯åè·¯ç±æéï¼ä¸åæ¬å°ç¼å夿 |
| | | userStore.getInfo().then(() => { |
| | | userStore |
| | | .getRouters() |
| | | .then(() => { |
| | | filterMenuItemsByRoutes(); |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åè·¯ç±æé失败:", error); |
| | | }); |
| | | }); |
| | | getUserLoginFacotryList(); |
| | | // å¯å¨éç¥ç¶æå®æ¶å¨ |
| | | startStatusTimer(); |
| | |
| | | .content { |
| | | background: #f6f7fb; |
| | | min-height: 100vh; |
| | | padding: 12px; |
| | | // padding: 12px; |
| | | /* 为ææè®¾å¤è®¾ç½®åºç¡padding-topï¼å
å«å®å
¨åºï¼ */ |
| | | padding-top: calc(env(safe-area-inset-top) + 30px); |
| | | position: relative; |
| | |
| | | } |
| | | |
| | | .hero-section { |
| | | margin: 0 12px; |
| | | margin-bottom: 12px; |
| | | animation: fadeInUp 0.6s ease-out 0.1s both; |
| | | } |
| | |
| | | .hero-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | |
| | | padding: 14px 14px 18px 14px; |
| | | margin: 0 12px; |
| | | height: 100%; |
| | | } |
| | | .hero-wave { |
| | |
| | | .common-module { |
| | | margin-bottom: 12px; |
| | | background: linear-gradient(135deg, #ffffff 0%, #f9fbff 100%); |
| | | border-radius: 14px; |
| | | // border-radius: 14px; |
| | | padding: 12px; |
| | | box-shadow: 0 8px 22px rgba(17, 24, 39, 0.06); |
| | | border: none; |
| | |
| | | .common-module { |
| | | margin-bottom: 12px; |
| | | background: #ffffff; |
| | | border-radius: 16px; |
| | | padding: 12px; |
| | | // border-radius: 16px; |
| | | // padding: 0px; |
| | | padding: 12px 0; |
| | | box-shadow: 0 10px 28px rgba(15, 23, 42, 0.06); |
| | | border: 1px solid rgba(148, 163, 184, 0.18); |
| | | position: relative; |
| | |
| | | } |
| | | |
| | | .module-header { |
| | | margin-bottom: 10px; |
| | | margin-bottom: 18px; |
| | | padding-left: 18px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | |
| | | } |
| | | |
| | | .icon-container { |
| | | width: 52px; |
| | | height: 52px; |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | } |
| | | |
| | | .item-label { |
| | | font-size: 12px; |
| | | font-size: 22rpx; |
| | | margin-top: 4px; |
| | | margin-bottom: 6px; |
| | | margin-bottom: 20px; |
| | | } |
| | | .grid-text { |
| | | font-size: 0.875rem; |
| | |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigouguanli.png", |
| | | label: "éè´ç®¡ç", |
| | | label: "éè´å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/baojiaguanli.png", |
| | | label: "æ¥ä»·ç®¡ç", |
| | | label: "æ¥ä»·å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chukuguanli@2x.png", |
| | | label: "åºåºç®¡ç", |
| | | label: "å货审æ¹", |
| | | }, |
| | | ]); |
| | | // èå¤è´¢å¡åå¹¶èåï¼èå¤3个 + è´¢å¡4个 = 7ä¸ªï¼ |
| | | const kaoqinCaiwu = reactive([ |
| | | { |
| | | icon: "/static/images/icon/gongchuguanli@2x.png", |
| | | label: "å
¬åºç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | label: "请å管ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | label: "åºå·®ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/baoxiaoguanli.png", |
| | | label: "æ¥é管ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/caigouguanli.png", |
| | | label: "éè´å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/baojiaguanli.png", |
| | | label: "æ¥ä»·å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chukuguanli@2x.png", |
| | | label: "å货审æ¹", |
| | | }, |
| | | ]); |
| | | |
| | |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index4", |
| | | }); |
| | | break; |
| | | case "éè´ç®¡ç": |
| | | case "éè´å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index5", |
| | | }); |
| | | break; |
| | | case "æ¥ä»·ç®¡ç": |
| | | case "æ¥ä»·å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index6", |
| | | }); |
| | | break; |
| | | case "åºåºç®¡ç": |
| | | case "å货审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index7", |
| | | }); |
| | |
| | | commonItems.value = huiyi; |
| | | } else if (operationType.value === "è´¢å¡ç®¡ç") { |
| | | commonItems.value = caiwu; |
| | | } else if (operationType.value === "åå审æ¹") { |
| | | commonItems.value = kaoqinCaiwu; |
| | | operationType.value = "åå审æ¹"; |
| | | } |
| | | } |
| | | console.log(operationType.value); |
| | |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import { userLoginFacotryList, updateClientId } from "@/api/login"; |
| | | import { |
| | | userLoginFacotryList, |
| | | updateClientId, |
| | | getNoticeCount, |
| | | } from "@/api/login"; |
| | | import { ref, onMounted } from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getWxCode } from "@/utils/geek"; |
| | |
| | | function loginSuccess(result) { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo().then(res => { |
| | | const userId = res.user.userId; |
| | | // è·åè·¯ç±æé |
| | | userStore |
| | | .getRouters() |
| | | .then(() => { |
| | | console.log("è·¯ç±æéè·åæå"); |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åè·¯ç±æé失败:", error); |
| | | }); |
| | | // ç»å½æååï¼å°å®¢æ·ç«¯æ¨éæ è¯åéå°æå¡å¨ |
| | | sendClientIdToServer(); |
| | | uni.switchTab({ |
| | | url: "/pages/index", |
| | | }); |
| | | // å¯å¨å®æ¶è·åæªè¯»æ¶æ¯æ°éç宿¶å¨ |
| | | startNoticeCountTimer(userId); |
| | | uni.switchTab({ url: "/pages/index" }); |
| | | }); |
| | | } |
| | | |
| | | // å¯å¨å®æ¶è·åæªè¯»æ¶æ¯æ°éç宿¶å¨ |
| | | function startNoticeCountTimer(userId) { |
| | | // ç«å³è·å䏿¬¡æªè¯»æ¶æ¯æ°é |
| | | updateNoticeCount(userId); |
| | | // è®¾ç½®å®æ¶å¨ï¼æ¯30ç§è·å䏿¬¡ |
| | | setInterval(() => { |
| | | updateNoticeCount(userId); |
| | | }, 30000); |
| | | } |
| | | |
| | | // æ´æ°æªè¯»æ¶æ¯æ°é |
| | | function updateNoticeCount(userId) { |
| | | getNoticeCount(userId) |
| | | .then(res => { |
| | | const count = res.data || 0; |
| | | console.log("æªè¯»æ¶æ¯æ°é:", count); |
| | | // æ´æ°tabbarçè§æ |
| | | if (count > 0) { |
| | | uni.setTabBarBadge({ |
| | | index: 1, // æ¶æ¯æ ç¾é¡µçç´¢å¼ |
| | | text: count.toString(), |
| | | }); |
| | | } else { |
| | | uni.removeTabBarBadge({ |
| | | index: 1, |
| | | }); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæªè¯»æ¶æ¯æ°é失败:", error); |
| | | }); |
| | | } |
| | | |
| | | // å°å®¢æ·ç«¯æ¨éæ è¯åéå°æå¡å¨ |
| | | function sendClientIdToServer() { |
| | | // è·åæ¬å°åå¨ç客æ·ç«¯æ è¯ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="message-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <!-- <PageHeader title="æ¶æ¯ä¸å¿" |
| | | :showBack="false" /> --> |
| | | <!-- çéæ ç¾ --> |
| | | <view class="tabs-container"> |
| | | <up-tabs v-model="activeTab" |
| | | @change="handleTabChange" |
| | | :list="tabList" |
| | | :current="activeTab" |
| | | itemStyle="width: 50%;height: 80rpx;"></up-tabs> |
| | | </view> |
| | | <!-- æ¶æ¯å表 --> |
| | | <scroll-view class="message-list" |
| | | scroll-y="true" |
| | | refresher-enabled="true" |
| | | :refresher-triggered="triggered" |
| | | :refresher-threshold="100" |
| | | refresher-background="#f5f7fa" |
| | | @refresherrefresh="onRefresh" |
| | | @scrolltolower="loadMore"> |
| | | <!-- å è½½ç¶æ --> |
| | | <view v-if="loading" |
| | | class="loading-state"> |
| | | <text class="loading-text">å è½½ä¸...</text> |
| | | </view> |
| | | <!-- æ¶æ¯å表 --> |
| | | <view v-else |
| | | v-for="(item) in messageList" |
| | | :key="item.id" |
| | | class="message-item" |
| | | :class="{ 'unread': !item.read }"> |
| | | <view class="message-content"> |
| | | <view class="message-header"> |
| | | <text class="message-title">{{ item.noticeTitle }}</text> |
| | | <text class="message-time">{{ formatTime(item.createTime) }}</text> |
| | | </view> |
| | | <text class="message-desc">{{ item.noticeContent }}</text> |
| | | <view class="message-footer"> |
| | | <text class="message-view" |
| | | @click="goToDetail(item)"> |
| | | 廿¥ç > |
| | | </text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-if="!loading && messageList.length === 0" |
| | | class="empty-state"> |
| | | <text class="empty-text">ææ æ¶æ¯</text> |
| | | </view> |
| | | <!-- å è½½æ´å¤ç¶æ --> |
| | | <view v-if="loadingMore" |
| | | class="loading-more-state"> |
| | | <text class="loading-more-text">å è½½æ´å¤...</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { listNotice } from "@/api/login.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // æ ç¾é¡µæ°æ® |
| | | const tabList = [ |
| | | { name: "æªè¯»", id: 0 }, |
| | | { name: "已读", id: 1 }, |
| | | ]; |
| | | |
| | | // å½åæ¿æ´»çæ ç¾ |
| | | const activeTab = ref(0); |
| | | |
| | | // æ¶æ¯åè¡¨æ°æ® |
| | | const messageList = ref([]); |
| | | const loading = ref(false); |
| | | const loadingMore = ref(false); |
| | | const total = ref(0); |
| | | const triggered = ref(false); |
| | | |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | const formatTime = time => { |
| | | if (!time) return ""; |
| | | const date = new Date(time); |
| | | const Y = date.getFullYear(); |
| | | const M = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const D = String(date.getDate()).padStart(2, "0"); |
| | | const h = String(date.getHours()).padStart(2, "0"); |
| | | const m = String(date.getMinutes()).padStart(2, "0"); |
| | | return `${Y}-${M}-${D} ${h}:${m}`; |
| | | }; |
| | | |
| | | // 跳转å°è¯¦æ
页 |
| | | const goToDetail = item => { |
| | | if (item.appJumpPath.indexOf("/") === 0) { |
| | | uni.navigateTo({ |
| | | url: item.appJumpPath, |
| | | }); |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: "/" + item.appJumpPath, |
| | | }); |
| | | } |
| | | }; |
| | | const userStore = useUserStore(); |
| | | const userId = ref(""); |
| | | const getUserId = () => { |
| | | return userStore.getInfo().then(res => { |
| | | console.log(res.user.userId, "res@@@@@@@@@@@2"); |
| | | userId.value = res.user.userId; |
| | | }); |
| | | }; |
| | | |
| | | // å¤çæ ç¾é¡µåæ¢ |
| | | const handleTabChange = val => { |
| | | console.log(val); |
| | | activeTab.value = val.id; |
| | | page.current = 1; |
| | | loadMessages(false); |
| | | }; |
| | | |
| | | // å è½½æ¶æ¯å表 |
| | | const loadMessages = (append = false) => { |
| | | if (append) { |
| | | loadingMore.value = true; |
| | | } else { |
| | | loading.value = true; |
| | | } |
| | | |
| | | // æå»ºæ¥è¯¢åæ° |
| | | const params = { |
| | | consigneeId: userId.value, |
| | | current: page.current, |
| | | size: page.size, |
| | | status: activeTab.value, |
| | | }; |
| | | console.log(params, "==========="); |
| | | return listNotice(params) |
| | | .then(res => { |
| | | const records = res?.data?.records || []; |
| | | total.value = res?.data?.total || 0; |
| | | |
| | | if (append) { |
| | | messageList.value = [...messageList.value, ...records]; |
| | | } else { |
| | | messageList.value = records; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åæ¶æ¯å¤±è´¥:", error); |
| | | uni.showToast({ title: "è·åæ¶æ¯å¤±è´¥ï¼è¯·éè¯", icon: "none" }); |
| | | }) |
| | | .finally(() => { |
| | | loading.value = false; |
| | | loadingMore.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å è½½æ´å¤ |
| | | const loadMore = () => { |
| | | console.log("==========="); |
| | | if (loading.value || loadingMore.value) return; |
| | | if (messageList.value.length >= total.value) return; |
| | | |
| | | page.current++; |
| | | loadMessages(true); |
| | | }; |
| | | |
| | | // 䏿巿° |
| | | const onRefresh = () => { |
| | | triggered.value = true; |
| | | // é置页ç |
| | | page.current = 1; |
| | | // éæ°å è½½æ¶æ¯ |
| | | loadMessages(false).finally(() => { |
| | | // å
³éå·æ°ç¶æ |
| | | setTimeout(() => { |
| | | triggered.value = false; |
| | | }, 500); |
| | | }); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ¶æ¯å表 |
| | | onMounted(() => { |
| | | getUserId().then(() => { |
| | | loadMessages(); |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | // å
¨å±åé |
| | | $primary-color: #2c7be5; |
| | | $primary-light: #4a90e2; |
| | | $success-color: #4cd964; |
| | | $warning-color: #ff9500; |
| | | $danger-color: #ff3b30; |
| | | $text-primary: #333333; |
| | | $text-secondary: #666666; |
| | | $text-tertiary: #999999; |
| | | $bg-color: #f5f7fa; |
| | | $card-bg: #ffffff; |
| | | $border-color: #e8e8e8; |
| | | $shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); |
| | | |
| | | .message-page { |
| | | min-height: 100vh; |
| | | background-color: $bg-color; |
| | | padding-bottom: 30rpx; |
| | | } |
| | | |
| | | /* æ ç¾é¡µå®¹å¨ */ |
| | | .tabs-container { |
| | | background-color: #ffffff; |
| | | margin-bottom: 20rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | /* æ¶æ¯å表 */ |
| | | .message-list { |
| | | margin: 0 20rpx 20rpx; |
| | | min-height: 600rpx; |
| | | height: calc(100vh - 200rpx); |
| | | } |
| | | |
| | | /* å è½½ç¶æ */ |
| | | .loading-state { |
| | | background-color: $card-bg; |
| | | border-radius: 16rpx; |
| | | box-shadow: $shadow-sm; |
| | | text-align: center; |
| | | padding: 120rpx 0; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .loading-text { |
| | | font-size: 14px; |
| | | color: $text-tertiary; |
| | | margin-top: 24rpx; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* æ¶æ¯é¡¹ */ |
| | | .message-item { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | background-color: $card-bg; |
| | | border-radius: 16rpx; |
| | | box-shadow: $shadow-sm; |
| | | padding: 24rpx; |
| | | margin-bottom: 20rpx; |
| | | margin-right: 40rpx; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .message-item:hover { |
| | | box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.12); |
| | | transform: translateY(-2rpx); |
| | | } |
| | | |
| | | .message-item.unread { |
| | | border-left: 4rpx solid $primary-color; |
| | | } |
| | | |
| | | /* æ¶æ¯å¾æ */ |
| | | .message-icon { |
| | | margin-right: 20rpx; |
| | | margin-top: 4rpx; |
| | | } |
| | | |
| | | /* æ¶æ¯å
容 */ |
| | | .message-content { |
| | | flex: 1; |
| | | } |
| | | |
| | | /* æ¶æ¯å¤´é¨ */ |
| | | .message-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12rpx; |
| | | } |
| | | |
| | | .message-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: $text-primary; |
| | | flex: 1; |
| | | margin-right: 20rpx; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .message-time { |
| | | font-size: 12px; |
| | | color: $text-tertiary; |
| | | } |
| | | |
| | | /* æ¶æ¯æè¿° */ |
| | | .message-desc { |
| | | font-size: 14px; |
| | | color: $text-secondary; |
| | | line-height: 1.4; |
| | | margin-bottom: 16rpx; |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | /* æ¶æ¯åºé¨ */ |
| | | .message-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | } |
| | | |
| | | .message-creator { |
| | | font-size: 12px; |
| | | color: $text-tertiary; |
| | | } |
| | | |
| | | /* ç©ºç¶æ */ |
| | | .empty-state { |
| | | background-color: $card-bg; |
| | | border-radius: 16rpx; |
| | | box-shadow: $shadow-sm; |
| | | text-align: center; |
| | | padding: 160rpx 0; |
| | | margin: 40rpx 0; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: $text-tertiary; |
| | | margin-top: 24rpx; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* å è½½æ´å¤ç¶æ */ |
| | | .loading-more-state { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 30rpx 0; |
| | | margin-top: 10rpx; |
| | | } |
| | | |
| | | .loading-more-text { |
| | | font-size: 14px; |
| | | color: $text-tertiary; |
| | | margin-left: 10rpx; |
| | | } |
| | | |
| | | /* å è½½æ´å¤ */ |
| | | .load-more { |
| | | text-align: center; |
| | | padding: 30rpx 0; |
| | | font-size: 14px; |
| | | color: $primary-color; |
| | | font-weight: 500; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .load-more-text { |
| | | display: inline-block; |
| | | padding: 10rpx 30rpx; |
| | | background-color: rgba($primary-color, 0.1); |
| | | border-radius: 20rpx; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .load-more-text:hover { |
| | | background-color: rgba($primary-color, 0.2); |
| | | transform: translateY(-2rpx); |
| | | } |
| | | |
| | | /* å¨ç»ææ */ |
| | | @keyframes fadeInUp { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(20rpx); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | .message-item { |
| | | animation: fadeInUp 0.3s ease-out; |
| | | } |
| | | |
| | | .message-item:nth-child(2) { |
| | | animation-delay: 0.1s; |
| | | } |
| | | |
| | | .message-item:nth-child(3) { |
| | | animation-delay: 0.2s; |
| | | } |
| | | |
| | | .message-item:nth-child(4) { |
| | | animation-delay: 0.3s; |
| | | } |
| | | |
| | | .message-item:nth-child(5) { |
| | | animation-delay: 0.4s; |
| | | } |
| | | .message-view { |
| | | float: right; |
| | | color: $primary-color; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="emergency-plan-review"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="åºæ¥é¢æ¡å®¡æ ¸" |
| | | <PageHeader title="åºæ¥é¢æ¡æ¥é
" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | |
| | | // ç»å½æååï¼å¤ç彿° |
| | | const loginSuccess = result => { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | useUserStore() |
| | | const userStore = useUserStore(); |
| | | userStore |
| | | .getInfo() |
| | | .then(res => { |
| | | // è·åè·¯ç±æé |
| | | userStore.getRouters().then(() => { |
| | | console.log("è·¯ç±æéè·åæå"); |
| | | }).catch(error => { |
| | | console.error("è·åè·¯ç±æé失败:", error); |
| | | }); |
| | | // ç»å½æååï¼å°å®¢æ·ç«¯æ¨éæ è¯åéå°æå¡å¨ |
| | | sendClientIdToServer(); |
| | | tab.reLaunch("/pages/index"); |
| | |
| | | import {logout, getInfo, loginCheckFactory} from "@/api/login"; |
| | | import { getRouters as getRoutersApi } from "@/api/menu"; |
| | | import { getToken, setToken, removeToken } from "@/utils/auth"; |
| | | import defAva from "@/static/images/profile.jpg"; |
| | | import { defineStore } from "pinia"; |
| | |
| | | currentLoginTime: "", |
| | | roles: Array(), |
| | | permissions: [], |
| | | routers: [], // è·¯ç±æéæ°æ® |
| | | }), |
| | | actions: { |
| | | // é¨é¨ç»å½ |
| | |
| | | this.token = ""; |
| | | this.roles = []; |
| | | this.permissions = []; |
| | | this.routers = []; |
| | | this.name = ""; |
| | | this.avatar = ""; |
| | | removeToken(); |
| | |
| | | const seconds = String(now.getSeconds()).padStart(2, '0'); // ç§æ°è¡¥é¶ |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | }, |
| | | // è·åè·¯ç±æé |
| | | getRouters() { |
| | | return new Promise((resolve, reject) => { |
| | | getRoutersApi() |
| | | .then((res: any) => { |
| | | // åå¨è·¯ç±æéæ°æ® |
| | | this.routers = res.data || []; |
| | | resolve(res); |
| | | }) |
| | | .catch((error) => { |
| | | reject(error); |
| | | }); |
| | | }); |
| | | }, |
| | | }, |
| | | }); |
| | | |