军泰伟业app
1.添加营销管理模块和采购管理模块并联调
已添加76个文件
已修改45个文件
已删除4个文件
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ä¿®æ¹å®¡æ¹æµç¨ |
| | | export function approveProcessUpdate(query) { |
| | | return request({ |
| | |
| | | // æ¥è¯¢å
¬åå表 |
| | | export function listNotice(query) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/list', |
| | | url: '/collaborativeApproval/notice/page', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | |
| | | // æ°å¢å
Œ |
| | | export function addNotice(data) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice', |
| | | url: '/collaborativeApproval/notice/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | |
| | | // ä¿®æ¹å
Œ |
| | | export function updateNotice(data) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice', |
| | | url: '/collaborativeApproval/notice/update', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // å é¤å
Œ |
| | | export function delNotice(noticeId) { |
| | | export function delNotice(ids) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/' + noticeId, |
| | | method: 'delete' |
| | | }) |
| | | } |
| | | |
| | | // æ¹éå é¤å
Œ |
| | | export function delNoticeBatch(noticeIds) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/batch', |
| | | url: '/collaborativeApproval/notice/' + ids, |
| | | method: 'delete', |
| | | data: noticeIds |
| | | }) |
| | | } |
| | | |
| | | // åå¸å
Œ |
| | | export function publishNotice(noticeId) { |
| | | // è·åå
¬åæ°é |
| | | export function getCount() { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/publish/' + noticeId, |
| | | method: 'put' |
| | | }) |
| | | } |
| | | |
| | | // ä¸çº¿å
Œ |
| | | export function offlineNotice(noticeId) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/offline/' + noticeId, |
| | | method: 'put' |
| | | url: '/collaborativeApproval/notice/count', |
| | | method: 'get', |
| | | }) |
| | | } |
| | |
| | | data: data |
| | | }) |
| | | } |
| | | // å®¢æ·æè®¿ç¾å° |
| | | export function clientVisitUpdate(data) { |
| | | return request({ |
| | | url: '/customerVisits/update', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // è·åæè®¿è®°å½å表 |
| | | export function getVisitRecords(query) { |
| | |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // å é¤å®¢æ·æ¡£æ¡ |
| | | export function delCustomer(ids) { |
| | | return request({ |
| | | url: '/customerVisits/'+ids, |
| | | method: 'delete', |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢å®¢æ·æ¡£æ¡è¯¦ç» |
| | | export function getCustomer(id) { |
| | | return request({ |
| | | url: '/basic/customer/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç¥è¯åºç¸å
³ API |
| | | import request from '@/utils/request'; |
| | | |
| | | |
| | | export function listKnowledgeBase(params) { |
| | | return request({ |
| | | url: '/knowledgeBase/getList', |
| | | method: 'get', |
| | | params |
| | | }); |
| | | } |
| | | // æ°å¢ç¥è¯åº |
| | | export function addKnowledgeBase(data) { |
| | | return request({ |
| | | url: "/knowledgeBase/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹ç¥è¯åº |
| | | export function updateKnowledgeBase(data) { |
| | | return request({ |
| | | url: "/knowledgeBase/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // å é¤ç¥è¯åº |
| | | export function delKnowledgeBase(query) { |
| | | return request({ |
| | | url: "/knowledgeBase/delete", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | export function getExamineList(data) { |
| | | return request({ |
| | | url: "/meeting/applicationList", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function getRoomEnum() { |
| | | return request({ |
| | | url: "/meeting/roomEnum", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function saveMeetingApplication(data){ |
| | | return request({ |
| | | url: "/meeting/saveMeetingApplication", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function getMeetingPublish(data){ |
| | | return request({ |
| | | url: "/meeting/meetingPublishList", |
| | | method: "post", |
| | | data: data |
| | | }); |
| | | } |
| | | |
| | | export function getMeetingMinutesByMeetingId(id){ |
| | | return request({ |
| | | url: "/meeting/getMeetingMinutesByMeetingId/"+id, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function saveMeetingMinutes(data){ |
| | | return request({ |
| | | url: "/meeting/saveMeetingMinutes", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | export function getMeetSummary(){ |
| | | return request({ |
| | | url: "/meeting/getMeetSummary", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function getMeetSummaryItems(){ |
| | | return request({ |
| | | url: "/meeting/getMeetSummaryItems", |
| | | method: "get", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | // è·åä¼è®®ä½¿ç¨å表 |
| | | export function getMeetingUseList(data){ |
| | | return request({ |
| | | url: "/meeting/meetingUseList", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿åä¼è®®ç³è¯· |
| | | export function saveMeetingApplication(data){ |
| | | return request({ |
| | | url: "/meeting/saveMeetingApplication", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function getRoomEnum() { |
| | | return request({ |
| | | url: "/meeting/roomEnum", |
| | | method: "get", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ä¼è®®ç®¡ç |
| | | import request from "@/utils/request"; |
| | | |
| | | export function getMeetingRoomList(data) { |
| | | return request({ |
| | | url: "/meeting/roomList", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function saveRoom(data) { |
| | | return request({ |
| | | url: "/meeting/saveRoom", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | export function delRoom(id) { |
| | | return request({ |
| | | url: "/meeting/delRoom/"+id, |
| | | method: "delete", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | // æ¥è¯¢è§ç« å¶åº¦å表 |
| | | export function listRuleManagement(page,query) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagement/getList", |
| | | method: "get", |
| | | params: { |
| | | ...page, |
| | | ...query}, |
| | | }); |
| | | } |
| | | // æ¥è¯¢é
è¯»ç¶æå表 |
| | | export function getReadingStatusList(page,query) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagement/getReadingStatusList", |
| | | method: "get", |
| | | params: { |
| | | ...page, |
| | | ...query}, |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®è§åidæ¥è¯¢é
è¯»ç¶æå表 |
| | | export function getReadingStatusByRuleId(id) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagement/getReadingStatusByRuleId/"+id, |
| | | method: "get" |
| | | }); |
| | | } |
| | | // ä¿®æ¹è§ç« å¶åº¦ |
| | | export function updateRuleManagement(data) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagement/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // æ°å¢è§ç« å¶åº¦ |
| | | export function addRuleManagement(data) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagement/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // éä»¶å表 |
| | | export function listRuleFiles(query) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagementFile/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢éä»¶ |
| | | export function addRuleFile(data) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagementFile/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤éä»¶ï¼æ¯æä¼ é id æ°ç»ï¼ |
| | | export function delRuleFile(ids) { |
| | | return request({ |
| | | url: "/rulesRegulationsManagementFile/del", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | // ä¸ä¼ éä»¶ |
| | | export function upload(query) { |
| | | return request({ |
| | | url: "/file/upload", |
| | | method: "post", |
| | | data: query, |
| | | responseType: "blob", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å°ç« ç³è¯·å表 |
| | | export function listSealApplication(page,query) { |
| | | return request({ |
| | | url: "/sealApplicationManagement/getList", |
| | | method: "get", |
| | | params: { |
| | | ...page, |
| | | ...query}, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹å°ç« ç³è¯· |
| | | export function updateSealApplication(data) { |
| | | return request({ |
| | | url: "/sealApplicationManagement/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | export function addSealApplication(data) { |
| | | return request({ |
| | | url: "/sealApplicationManagement/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | }); |
| | | } |
| | |
| | | method: "get", |
| | | }); |
| | | } |
| | | // æ¥è¯¢å¨èåå·¥å°è´¦ |
| | | export function staffOnJobListPage(query) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // åè´§å°è´¦é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function deliveryLedgerListPage(query) { |
| | | return request({ |
| | | url: "/shippingInfo/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹åè´§å°è´¦ |
| | | export function addOrUpdateDeliveryLedger(query) { |
| | | return request({ |
| | | url: "/shippingInfo/update", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹åè´§å°è´¦ |
| | | export function deductStock(query) { |
| | | return request({ |
| | | url: "/shippingInfo/deductStock", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // å é¤åè´§å°è´¦ |
| | | export function delDeliveryLedger(query) { |
| | | return request({ |
| | | url: "/shippingInfo/delete", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢åè´§ä¿¡æ¯ |
| | | export function addShippingInfo(data) { |
| | | return request({ |
| | | url: "/shippingInfo/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // åè´§æç»æ¥å£ |
| | | |
| | | // å页æ¥è¯¢åè´§æç» |
| | | export function shippingInfoDetailListPage(query) { |
| | | return request({ |
| | | url: "/shippingInfoDetail/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢åè´§æç» |
| | | export function addShippingInfoDetail(data) { |
| | | return request({ |
| | | url: "/shippingInfoDetail/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹åè´§æç» |
| | | export function updateShippingInfoDetail(data) { |
| | | return request({ |
| | | url: "/shippingInfoDetail/update", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤åè´§æç» |
| | | export function delShippingInfoDetail(ids) { |
| | | return request({ |
| | | url: "/shippingInfoDetail/delete", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/sales/deliveryLedger/index", |
| | | "style": { |
| | | "navigationBarTitleText": "åè´§å°è´¦", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/sales/salesAccount/out", |
| | | "style": { |
| | | "navigationBarTitleText": "åè´§ç¶æ", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/sales/salesAccount/goOut", |
| | | "style": { |
| | | "navigationBarTitleText": "åè´§", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/sales/salesAccount/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¿®æ¹å°è´¦", |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index", |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index1", |
| | | "style": { |
| | | "navigationBarTitleText": "审æ¹ç®¡ç", |
| | | "navigationBarTitleText": "å
¬åºç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index2", |
| | | "style": { |
| | | "navigationBarTitleText": "请å管ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index3", |
| | | "style": { |
| | | "navigationBarTitleText": "åºå·®ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index4", |
| | | "style": { |
| | | "navigationBarTitleText": "æ¥é管ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/indexItem", |
| | | "style": { |
| | | "navigationBarTitleText": "èå¤ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index5", |
| | | "style": { |
| | | "navigationBarTitleText": "éè´ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index6", |
| | | "style": { |
| | | "navigationBarTitleText": "æ¥ä»·ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index7", |
| | | "style": { |
| | | "navigationBarTitleText": "å货审æ¹", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetingSettings/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®è®¾ç½®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetingSettings/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®å®¤è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetingList/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®å表", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetApplication/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®ç³è¯·", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetExamine/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®å®¡æ¹", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetExamine/approve", |
| | | "style": { |
| | | "navigationBarTitleText": "审æ¹", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetPublish/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®åå¸", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetPublish/approve", |
| | | "style": { |
| | | "navigationBarTitleText": "åå¸", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetSummary/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®æ»ç»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetingBoard/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¼è®®çæ¿", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/meetSummary/approve", |
| | | "style": { |
| | | "navigationBarTitleText": "æ»ç»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/knowledgeBase/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ç¥è¯åº", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/sealManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "ç¨å°ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/sealManagement/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "ç¨å°è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/rulesRegulationsManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è§ç« å¶åº¦ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/rulesRegulationsManagement/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "è§ç« å¶åº¦è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/rulesRegulationsManagement/fileList", |
| | | "style": { |
| | | "navigationBarTitleText": "è§ç« å¶åº¦æä»¶ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/managementMeetings/knowledgeBase/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "ç¥è¯åºè¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/noticeManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "éç¥å
Œ", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/ledger/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦", |
| | |
| | | "path": "pages/equipmentManagement/ledger/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/runManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿è¡ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | "path": "pages/equipmentManagement/upkeep/maintain", |
| | | "style": { |
| | | "navigationBarTitleText": "ç»´ä¿®ä¿å
»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/upkeep/fileList", |
| | | "style": { |
| | | "navigationBarTitleText": "ä¿å
»æä»¶ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | { |
| | | "pagePath": "pages/index", |
| | | "iconPath": "static/images/tabbar/home.png", |
| | | "selectedIconPath": "static/images/tabbar/home_.png", |
| | | "selectedIconPath": "static/images/tabbar/homeBlue.png", |
| | | "text": "é¦é¡µ" |
| | | }, |
| | | { |
| | | "pagePath": "pages/mine", |
| | | "iconPath": "static/images/tabbar/mine.png", |
| | | "selectedIconPath": "static/images/tabbar/mine_.png", |
| | | "iconPath": "static/images/tabbar/my.png", |
| | | "selectedIconPath": "static/images/tabbar/myBlue.png", |
| | | "text": "æç" |
| | | } |
| | | ] |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" @back="goBack" /> |
| | | |
| | | <u-form @submit="handleSignIn" ref="formRef" label-width="90"> |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" |
| | | @back="goBack" /> |
| | | <u-form @submit="handleSignIn" |
| | | ref="formRef" |
| | | label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <u-cell-group title="客æ·ä¿¡æ¯"> |
| | | <u-form-item label="客æ·åç§°" prop="customerName" required border-bottom> |
| | | <u-input |
| | | v-model="form.customerName" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | /> |
| | | <u-form-item label="客æ·åç§°" |
| | | prop="customerName" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.customerName" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" /> |
| | | </u-form-item> |
| | | <u-form-item label="è系人" prop="contact" border-bottom> |
| | | <u-input |
| | | v-model="form.contact" |
| | | placeholder="请è¾å
¥è系人" |
| | | /> |
| | | <u-form-item label="è系人" |
| | | prop="contact" |
| | | border-bottom> |
| | | <u-input v-model="form.contact" |
| | | placeholder="请è¾å
¥è系人" /> |
| | | </u-form-item> |
| | | <u-form-item label="èç³»çµè¯" prop="contactPhone" border-bottom> |
| | | <u-input |
| | | v-model="form.contactPhone" |
| | | placeholder="请è¾å
¥èç³»çµè¯" |
| | | /> |
| | | <u-form-item label="èç³»çµè¯" |
| | | prop="contactPhone" |
| | | border-bottom> |
| | | <u-input v-model="form.contactPhone" |
| | | placeholder="请è¾å
¥èç³»çµè¯" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æè®¿ä¿¡æ¯ --> |
| | | <u-cell-group title="æè®¿ä¿¡æ¯"> |
| | | <u-form-item label="æè®¿ç®ç" prop="purposeVisit" required border-bottom> |
| | | <u-input |
| | | v-model="form.purposeVisit" |
| | | placeholder="请è¾å
¥æè®¿ç®ç" |
| | | /> |
| | | <u-form-item label="æè®¿ç®ç" |
| | | prop="purposeVisit" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.purposeVisit" |
| | | placeholder="请è¾å
¥æè®¿ç®ç" /> |
| | | </u-form-item> |
| | | <u-form-item label="æè®¿æ¶é´" prop="purposeDate" required border-bottom> |
| | | <u-input |
| | | v-model="form.purposeDate" |
| | | placeholder="è¯·éæ©æè®¿æ¶é´" |
| | | @click="showTimePicker" |
| | | /> |
| | | <u-form-item label="æè®¿æ¶é´" |
| | | prop="purposeDate" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.purposeDate" |
| | | placeholder="è¯·éæ©æè®¿æ¶é´" |
| | | @click="showTimePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showTimePicker" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showTimePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æè®¿å°ç¹" prop="visitAddress" required border-bottom> |
| | | <u-input |
| | | v-model="form.visitAddress" |
| | | placeholder="请è¾å
¥æè®¿å°ç¹" |
| | | > |
| | | <u-form-item label="æè®¿å°ç¹" |
| | | prop="visitAddress" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.visitAddress" |
| | | placeholder="请è¾å
¥æè®¿å°ç¹"> |
| | | <template #suffix> |
| | | <u-icon name="map" @click="getCurrentLocation" class="location-icon" /> |
| | | <u-icon name="map" |
| | | @click="getCurrentLocation" |
| | | class="location-icon" /> |
| | | </template> |
| | | </u-input> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- 夿³¨ä¿¡æ¯ --> |
| | | <u-cell-group title="夿³¨ä¿¡æ¯"> |
| | | <u-form-item label="夿³¨" prop="remark" border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" |
| | | /> |
| | | <u-form-item label="夿³¨" |
| | | prop="remark" |
| | | border-bottom> |
| | | <u-textarea v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | :maxlength="200" |
| | | count |
| | | :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="handleSignIn" :loading="loading">ç¾å°</u-button> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="sign-btn" |
| | | type="primary" |
| | | @click="handleSignIn" |
| | | :loading="loading">ç¾å°</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- æ¶é´éæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showTime" |
| | | v-model="currentTime" |
| | | @confirm="onTimeConfirm" |
| | | @cancel="showTime = false" |
| | | mode="datetime" |
| | | /> |
| | | <up-datetime-picker :show="showTime" |
| | | v-model="currentTime" |
| | | @confirm="onTimeConfirm" |
| | | @cancel="showTime = false" |
| | | mode="datetime" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({name: 'client-visit-detail'}) |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "client-visit-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted } from 'vue' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { clientVisitSignIn } from '@/api/cooperativeOffice/clientVisit' |
| | | import useUserStore from "@/store/modules/user" |
| | | import dayjs from "dayjs" |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | clientVisitSignIn, |
| | | clientVisitUpdate, |
| | | } from "@/api/cooperativeOffice/clientVisit"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | customerName: '', |
| | | contact: '', |
| | | contactPhone: '', |
| | | visitingPeople: '', |
| | | purposeVisit: '', |
| | | purposeDate: '', |
| | | visitAddress: '', |
| | | latitude: '', |
| | | longitude: '', |
| | | locationAddress: '', |
| | | remark: '' |
| | | }) |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | customerName: "", |
| | | contact: "", |
| | | contactPhone: "", |
| | | visitingPeople: "", |
| | | purposeVisit: "", |
| | | purposeDate: "", |
| | | visitAddress: "", |
| | | latitude: "", |
| | | longitude: "", |
| | | locationAddress: "", |
| | | remark: "", |
| | | }); |
| | | |
| | | // 页é¢ç¶æ |
| | | const loading = ref(false) |
| | | const formRef = ref(null) |
| | | // 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | |
| | | // æ¶é´ç¸å
³ |
| | | const currentTime = ref(Date.now()) |
| | | const showTime = ref(false) |
| | | // æ¶é´ç¸å
³ |
| | | const currentTime = ref(Date.now()); |
| | | const showTime = ref(false); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çID |
| | | uni.removeStorageSync('clientVisit') |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çID |
| | | uni.removeStorageSync("clientVisit"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¶é´éæ©å¨ |
| | | const showTimePicker = () => { |
| | | showTime.value = true |
| | | } |
| | | // æ¾ç¤ºæ¶é´éæ©å¨ |
| | | const showTimePicker = () => { |
| | | showTime.value = true; |
| | | }; |
| | | |
| | | // 确认æ¶é´éæ© |
| | | const onTimeConfirm = (e) => { |
| | | console.log(e) |
| | | form.value.purposeDate = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | currentTime.value = e.value |
| | | showTime.value = false; |
| | | } |
| | | // 确认æ¶é´éæ© |
| | | const onTimeConfirm = e => { |
| | | console.log(e); |
| | | form.value.purposeDate = dayjs(e.value).format("YYYY-MM-DD HH:mm:ss"); |
| | | currentTime.value = e.value; |
| | | showTime.value = false; |
| | | }; |
| | | |
| | | // è·åå½åä½ç½® |
| | | const getCurrentLocation = () => { |
| | | uni.showLoading({ title: 'è·åä½ç½®ä¸...' }) |
| | | |
| | | uni.getLocation({ |
| | | type: 'gcj02', |
| | | success: (res) => { |
| | | form.value.latitude = res.latitude |
| | | form.value.longitude = res.longitude |
| | | |
| | | // 使ç¨éå°çç¼ç è·åå°åä¿¡æ¯ |
| | | uni.request({ |
| | | url: `https://restapi.amap.com/v3/geocode/regeo?key=c120a5dc69a9f61839f7763e6057005f&location=${res.longitude},${res.latitude}&radius=1000&extensions=all`, |
| | | success: (geoRes) => { |
| | | uni.hideLoading() |
| | | if (geoRes.data.status === '1' && geoRes.data.regeocode) { |
| | | const regeocode = geoRes.data.regeocode |
| | | const address = regeocode.formatted_address |
| | | |
| | | // ä¼å
æ¾ç¤ºè¯¦ç»å°å |
| | | if (address) { |
| | | form.value.visitAddress = address |
| | | showToast('ä½ç½®è·åæå') |
| | | // è·åå½åä½ç½® |
| | | const getCurrentLocation = () => { |
| | | uni.showLoading({ title: "è·åä½ç½®ä¸..." }); |
| | | |
| | | uni.getLocation({ |
| | | type: "gcj02", |
| | | success: res => { |
| | | form.value.latitude = res.latitude; |
| | | form.value.longitude = res.longitude; |
| | | |
| | | // 使ç¨éå°çç¼ç è·åå°åä¿¡æ¯ |
| | | uni.request({ |
| | | url: `https://restapi.amap.com/v3/geocode/regeo?key=c120a5dc69a9f61839f7763e6057005f&location=${res.longitude},${res.latitude}&radius=1000&extensions=all`, |
| | | success: geoRes => { |
| | | uni.hideLoading(); |
| | | if (geoRes.data.status === "1" && geoRes.data.regeocode) { |
| | | const regeocode = geoRes.data.regeocode; |
| | | const address = regeocode.formatted_address; |
| | | |
| | | // ä¼å
æ¾ç¤ºè¯¦ç»å°å |
| | | if (address) { |
| | | form.value.visitAddress = address; |
| | | showToast("ä½ç½®è·åæå"); |
| | | } else { |
| | | // å¦ææ²¡æè¯¦ç»å°åï¼å°è¯ç»åå°åä¿¡æ¯ |
| | | const addressComponent = regeocode.addressComponent; |
| | | const combinedAddress = `${addressComponent.province}${addressComponent.city}${addressComponent.district}${addressComponent.township}`; |
| | | form.value.visitAddress = combinedAddress; |
| | | showToast("ä½ç½®è·åæå"); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡æè¯¦ç»å°åï¼å°è¯ç»åå°åä¿¡æ¯ |
| | | const addressComponent = regeocode.addressComponent |
| | | const combinedAddress = `${addressComponent.province}${addressComponent.city}${addressComponent.district}${addressComponent.township}` |
| | | form.value.visitAddress = combinedAddress |
| | | showToast('ä½ç½®è·åæå') |
| | | // APIè°ç¨æå使²¡æè¿åå°åä¿¡æ¯ |
| | | const fallbackAddress = `ä½ç½®: ${res.latitude.toFixed( |
| | | 4 |
| | | )}, ${res.longitude.toFixed(4)}`; |
| | | form.value.visitAddress = fallbackAddress; |
| | | showToast("è·åå°ä½ç½®ï¼ä½å°åè§£æå¤±è´¥"); |
| | | } |
| | | } else { |
| | | // APIè°ç¨æå使²¡æè¿åå°åä¿¡æ¯ |
| | | const fallbackAddress = `ä½ç½®: ${res.latitude.toFixed(4)}, ${res.longitude.toFixed(4)}` |
| | | form.value.visitAddress = fallbackAddress |
| | | showToast('è·åå°ä½ç½®ï¼ä½å°åè§£æå¤±è´¥') |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | uni.hideLoading() |
| | | console.error('éå°çç¼ç 失败:', err) |
| | | |
| | | // éå°çç¼ç 失败æ¶ï¼æ¾ç¤ºç®åçä½ç½®ä¿¡æ¯ |
| | | const fallbackAddress = `ä½ç½®: ${res.latitude.toFixed(4)}, ${res.longitude.toFixed(4)}` |
| | | form.value.visitAddress = fallbackAddress |
| | | showToast('ä½ç½®è·åæåï¼ä½å°åè§£æå¤±è´¥') |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("éå°çç¼ç 失败:", err); |
| | | |
| | | // éå°çç¼ç 失败æ¶ï¼æ¾ç¤ºç®åçä½ç½®ä¿¡æ¯ |
| | | const fallbackAddress = `ä½ç½®: ${res.latitude.toFixed( |
| | | 4 |
| | | )}, ${res.longitude.toFixed(4)}`; |
| | | form.value.visitAddress = fallbackAddress; |
| | | showToast("ä½ç½®è·åæåï¼ä½å°åè§£æå¤±è´¥"); |
| | | }, |
| | | }); |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("è·åä½ç½®å¤±è´¥:", err); |
| | | |
| | | // æ¾ç¤ºé误æç¤ºå¹¶å¼å¯¼ç¨æ·æ£æ¥æé |
| | | showToast("è·åä½ç½®å¤±è´¥ï¼è¯·æ£æ¥å®ä½æé"); |
| | | |
| | | // å¼å¯¼ç¨æ·æ£æ¥æé设置 |
| | | uni.showModal({ |
| | | title: "ä½ç½®æéæç¤º", |
| | | content: |
| | | "è·åä½ç½®å¤±è´¥ï¼å¯è½æ¯å 为ä½ç½®æéæªå¼å¯ï¼è¯·å¨è®¾å¤è®¾ç½®ä¸æ£æ¥å¹¶å¼å¯ä½ç½®æéã", |
| | | confirmText: "ç¥éäº", |
| | | cancelText: "åæ¶", |
| | | success: res => { |
| | | if (res.confirm) { |
| | | // å¯ä»¥å°è¯æå¼è®¾ç½®é¡µé¢ï¼å¦ææ¯æï¼ |
| | | if (uni.openSetting) { |
| | | uni.openSetting({ |
| | | success: settingRes => { |
| | | console.log("è®¾ç½®ç»æ:", settingRes); |
| | | }, |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | }); |
| | | |
| | | // å¤±è´¥æ¶æ¾ç¤ºéè¯¯ä¿¡æ¯ |
| | | form.value.visitAddress = "ä½ç½®è·å失败"; |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤ç¾å° |
| | | const handleSignIn = async () => { |
| | | if (!form.value.customerName) { |
| | | showToast("请è¾å
¥å®¢æ·åç§°"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.purposeVisit) { |
| | | showToast("请è¾å
¥æè®¿ç®ç"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.purposeDate) { |
| | | showToast("è¯·éæ©æè®¿æ¶é´"); |
| | | return; |
| | | } |
| | | if (!form.value.visitAddress) { |
| | | showToast("请è·åå½åä½ç½®"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | loading.value = true; |
| | | |
| | | // 使ç¨å®å
¨æµ
æ·è´ï¼é¿å
对象å±å¼å¨æäºè¿è¡æ¶æé |
| | | const source = |
| | | form.value && typeof form.value === "object" ? form.value : {}; |
| | | const submitData = {}; |
| | | Object.keys(source).forEach(k => { |
| | | submitData[k] = source[k]; |
| | | }); |
| | | console.log("submitData", submitData); |
| | | if (isEdit.value) { |
| | | const { code } = await clientVisitUpdate(submitData); |
| | | if (code === 200) { |
| | | showToast("ä¿®æ¹æå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("ç¾å°å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }) |
| | | }, |
| | | fail: (err) => { |
| | | uni.hideLoading() |
| | | showToast('è·åä½ç½®å¤±è´¥ï¼è¯·æ£æ¥å®ä½æé') |
| | | console.error('è·åä½ç½®å¤±è´¥:', err) |
| | | |
| | | // å¤±è´¥æ¶æ¾ç¤ºéè¯¯ä¿¡æ¯ |
| | | form.value.visitAddress = 'ä½ç½®è·å失败' |
| | | } else { |
| | | const { code } = await clientVisitSignIn(submitData); |
| | | if (code === 200) { |
| | | showToast("ç¾å°æå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("ç¾å°å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("ç¾å°å¤±è´¥:", e); |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æäº¤ç¾å° |
| | | const handleSignIn = async () => { |
| | | if (!form.value.customerName) { |
| | | showToast('请è¾å
¥å®¢æ·åç§°') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.purposeVisit) { |
| | | showToast('请è¾å
¥æè®¿ç®ç') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.purposeDate) { |
| | | showToast('è¯·éæ©æè®¿æ¶é´') |
| | | return |
| | | } |
| | | if (!form.value.visitAddress) { |
| | | showToast('请è·åå½åä½ç½®') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | loading.value = true |
| | | |
| | | // 使ç¨å®å
¨æµ
æ·è´ï¼é¿å
对象å±å¼å¨æäºè¿è¡æ¶æé |
| | | const source = (form.value && typeof form.value === 'object') ? form.value : {} |
| | | const submitData = {} |
| | | Object.keys(source).forEach((k) => { |
| | | submitData[k] = source[k] |
| | | }) |
| | | console.log('submitData', submitData) |
| | | |
| | | const { code } = await clientVisitSignIn(submitData) |
| | | |
| | | if (code === 200) { |
| | | showToast('ç¾å°æå') |
| | | setTimeout(() => { |
| | | goBack() |
| | | }, 500) |
| | | }; |
| | | const isEdit = ref(false); |
| | | onLoad(() => { |
| | | // ç¼è¾æè®¿æ¶ï¼ä»æ¬å°åå¨è·åæè®¿è®°å½ |
| | | const visit = uni.getStorageSync("clientVisit"); |
| | | if (visit) { |
| | | form.value = visit; |
| | | isEdit.value = true; |
| | | console.log("form.value", form.value); |
| | | } else { |
| | | loading.value = false |
| | | showToast('ç¾å°å¤±è´¥ï¼è¯·éè¯') |
| | | isEdit.value = false; |
| | | } |
| | | } catch (e) { |
| | | loading.value = false |
| | | console.error('ç¾å°å¤±è´¥:', e) |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 设置é»è®¤æè®¿æ¶é´ä¸ºå½åæ¶é´ |
| | | form.value.purposeDate = dayjs().format('YYYY-MM-DD HH:mm:ss') |
| | | currentTime.value = Date.now() |
| | | |
| | | // 设置æè®¿äººä¸ºå½åç»å½ç¨æ·çæµç§° |
| | | form.value.visitingPeople = userStore.nickName || '' |
| | | } |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 设置é»è®¤æè®¿æ¶é´ä¸ºå½åæ¶é´ |
| | | form.value.purposeDate = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | currentTime.value = Date.now(); |
| | | |
| | | onMounted(() => { |
| | | initPageData() |
| | | }) |
| | | // 设置æè®¿äººä¸ºå½åç»å½ç¨æ·çæµç§° |
| | | form.value.visitingPeople = userStore.nickName || ""; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initPageData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .client-visit { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import "@/static/scss/form-common.scss"; |
| | | .client-visit { |
| | | 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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | |
| | | .location-icon { |
| | | color: #1989fa; |
| | | font-size: 1.2rem; |
| | | } |
| | | .location-icon { |
| | | color: #1989fa; |
| | | font-size: 1.2rem; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-accoun"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="å®¢æ·æè®¿" @back="goBack" /> |
| | | |
| | | <PageHeader title="å®¢æ·æè®¿" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | v-model="customerName" |
| | | @blur="getList" |
| | | clearable |
| | | /> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | v-model="customerName" |
| | | @blur="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <u-icon name="search" size="24" color="#999"></u-icon> |
| | | <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="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" :key="index"> |
| | | <view class="ledger-list" |
| | | v-if="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" |
| | | :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> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">客æ·ï¼{{ item.customerName }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è系人</text> |
| | |
| | | <text class="detail-label">æè®¿äºº</text> |
| | | <text class="detail-value">{{ item.visitingPeople || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" v-if="item.remark"> |
| | | <view class="detail-row" |
| | | v-if="item.remark"> |
| | | <text class="detail-label">夿³¨</text> |
| | | <text class="detail-value">{{ item.remark }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)" |
| | | > |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | æ¥ç详æ
|
| | | </u-button> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editVisit(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deleteVisit(item)"> |
| | | å é¤ |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ æè®¿è®°å½</text> |
| | | </view> |
| | | |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" @click="addVisit"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | <view class="fab-button" |
| | | @click="addVisit"> |
| | | <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 { getVisitRecords } from '@/api/cooperativeOffice/clientVisit' |
| | | import useUserStore from "@/store/modules/user" |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({name: 'client-visit-index'}) |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getVisitRecords, |
| | | delCustomer, |
| | | } from "@/api/cooperativeOffice/clientVisit"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "client-visit-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import dayjs from "dayjs" |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const customerName = ref('') |
| | | // æç´¢å
³é®è¯ |
| | | const customerName = ref(""); |
| | | |
| | | // æè®¿è®°å½æ°æ® |
| | | const visitList = ref([]) |
| | | // æè®¿è®°å½æ°æ® |
| | | const visitList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | customerName: customerName.value, |
| | | } |
| | | getVisitRecords(params) |
| | | .then((res) => { |
| | | visitList.value = res.records || res.data?.records || [] |
| | | closeToast() |
| | | }) |
| | | .catch(() => { |
| | | closeToast() |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | } |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | customerName: customerName.value, |
| | | }; |
| | | getVisitRecords(params) |
| | | .then(res => { |
| | | visitList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const addVisit = () => { |
| | | uni.removeStorageSync("clientVisit"); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/detail", |
| | | }); |
| | | }; |
| | | // ç¼è¾æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const editVisit = item => { |
| | | uni.setStorageSync("clientVisit", item); |
| | | // ç¼è¾æè®¿è·³è½¬å°ç»è®°é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/detail", |
| | | }); |
| | | }; |
| | | // å é¤æè®¿ |
| | | const deleteVisit = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤è¯¥æè®¿è®°å½åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteClientVisit(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | // å é¤æè®¿è®°å½ |
| | | const deleteClientVisit = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | delCustomer(id) |
| | | .then(() => { |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.setStorageSync("clientVisit", item); |
| | | // æ¥ç详æ
跳转å°åªè¯»å±ç¤ºé¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/view", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const addVisit = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/clientVisit/detail' |
| | | }) |
| | | } |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = (item) => { |
| | | uni.setStorageSync('clientVisit', item) |
| | | // æ¥ç详æ
跳转å°åªè¯»å±ç¤ºé¡µé¢ |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/clientVisit/view' |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | // 页é¢ç¹å®çæ ·å¼è¦ç |
| | | .sales-accoun { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | // 页é¢ç¹å®çæ ·å¼è¦ç |
| | | .sales-accoun { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | } |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | </style> |
| | | |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" @back="goBack" /> |
| | | |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- å
å®¹å®¹å¨ --> |
| | | <view class="content-container"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | |
| | | <text class="info-value">{{ form.contactPhone || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æè®¿ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">æè®¿ä¿¡æ¯</view> |
| | |
| | | <text class="info-label">æè®¿äºº</text> |
| | | <text class="info-value">{{ form.visitingPeople || '-' }}</text> |
| | | </view> |
| | | <view class="info-item" v-if="form.latitude && form.longitude"> |
| | | <view class="info-item" |
| | | v-if="form.latitude && form.longitude"> |
| | | <text class="info-label">ç»çº¬åº¦</text> |
| | | <text class="info-value">{{ form.latitude }}, {{ form.longitude }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 夿³¨ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">夿³¨ä¿¡æ¯</view> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted } from 'vue' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import useUserStore from "@/store/modules/user" |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | customerName: '', |
| | | contact: '', |
| | | contactPhone: '', |
| | | visitingPeople: '', |
| | | purposeVisit: '', |
| | | purposeDate: '', |
| | | visitAddress: '', |
| | | latitude: '', |
| | | longitude: '', |
| | | locationAddress: '', |
| | | remark: '' |
| | | }) |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | customerName: "", |
| | | contact: "", |
| | | contactPhone: "", |
| | | visitingPeople: "", |
| | | purposeVisit: "", |
| | | purposeDate: "", |
| | | visitAddress: "", |
| | | latitude: "", |
| | | longitude: "", |
| | | locationAddress: "", |
| | | remark: "", |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çID |
| | | uni.removeStorageSync('clientVisit') |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çID |
| | | uni.removeStorageSync("clientVisit"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨è·åæè®¿è®°å½è¯¦æ
|
| | | const row = uni.getStorageSync('clientVisit') |
| | | if (row) { |
| | | form.value = { ...row } |
| | | } else { |
| | | showToast('ææ æè®¿è®°å½æ°æ®') |
| | | } |
| | | } |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨è·åæè®¿è®°å½è¯¦æ
|
| | | const row = uni.getStorageSync("clientVisit"); |
| | | if (row) { |
| | | form.value = { ...row }; |
| | | } else { |
| | | showToast("ææ æè®¿è®°å½æ°æ®"); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initPageData() |
| | | }) |
| | | onMounted(() => { |
| | | initPageData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .client-visit-detail { |
| | | min-height: 100vh; |
| | | background-color: #f8f9fa; |
| | | } |
| | | .client-visit-detail { |
| | | min-height: 100vh; |
| | | background-color: #f8f9fa; |
| | | } |
| | | |
| | | .content-container { |
| | | padding: 16px; |
| | | } |
| | | .content-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .section { |
| | | background-color: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); |
| | | } |
| | | .section { |
| | | background-color: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333333; |
| | | padding: 16px 16px 12px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333333; |
| | | padding: 16px 16px 12px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | padding: 14px 16px; |
| | | border-bottom: 1px solid #f8f8f8; |
| | | align-items: flex-start; |
| | | } |
| | | .info-item { |
| | | display: flex; |
| | | padding: 14px 16px; |
| | | border-bottom: 1px solid #f8f8f8; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .info-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | .info-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666666; |
| | | min-width: 80px; |
| | | flex-shrink: 0; |
| | | line-height: 22px; |
| | | } |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666666; |
| | | min-width: 80px; |
| | | flex-shrink: 0; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333333; |
| | | flex: 1; |
| | | line-height: 22px; |
| | | text-align: right; |
| | | } |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333333; |
| | | flex: 1; |
| | | line-height: 22px; |
| | | text-align: right; |
| | | } |
| | | |
| | | .multi-line { |
| | | text-align: left; |
| | | word-break: break-all; |
| | | line-height: 1.6; |
| | | } |
| | | .multi-line { |
| | | text-align: left; |
| | | word-break: break-all; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .remark-item { |
| | | padding-bottom: 16px; |
| | | } |
| | | .remark-item { |
| | | padding-bottom: 16px; |
| | | } |
| | | </style> |
| | |
| | | <text class="info-label">ç³è¯·æ¥æ</text> |
| | | <text class="info-value">{{ approvalData.approveTime }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="approvalData.approveType === 2"> |
| | | <view class="info-row"> |
| | | <text class="info-label">请åå¼å§æ¶é´</text> |
| | | <text class="info-value">{{ approvalData.startDate || '-' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">请åç»ææ¶é´</text> |
| | | <text class="info-value">{{ approvalData.endDate || '-' }}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <view v-if="approvalData.approveType === 3" class="info-row"> |
| | | <text class="info-label">åºå·®å°ç¹</text> |
| | | <text class="info-value">{{ approvalData.location || '-' }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <view v-if="approvalData.approveType === 4" class="info-row"> |
| | | <text class="info-label">æ¥ééé¢</text> |
| | | <text class="info-value">{{ approvalData.price ? `Â¥${approvalData.price}` : '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | <template> |
| | | <view class="contact-select"> |
| | | <!-- 顶鍿 颿 --> |
| | | <view class="header"> |
| | | <up-icon name="arrow-left" size="20" color="#333" @click="goBack" /> |
| | | <text class="title">éæ©è系人</text> |
| | | <text class="confirm-btn" @click="confirmSelect">ç¡®å®</text> |
| | | </view> |
| | | <PageHeader title="éæ©è系人" @back="goBack"> |
| | | <template #right> |
| | | <text class="confirm-btn" @click="confirmSelect">ç¡®å®</text> |
| | | </template> |
| | | </PageHeader> |
| | | |
| | | <!-- æç´¢æ¡ --> |
| | | <!-- <view class="search-section">--> |
| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <PageHeader title="å®¡æ¹æµç¨" @back="goBack" /> |
| | | |
| | | <PageHeader title="å®¡æ¹æµç¨" |
| | | @back="goBack" /> |
| | | <!-- 表ååºå --> |
| | | <u-form ref="formRef" @submit="submitForm" :rules="rules" :model="form" label-width="140rpx"> |
| | | <u-form-item prop="approveReason" label="ç³è¯·äºç±" required> |
| | | <u-input |
| | | v-model="form.approveReason" |
| | | type="textarea" |
| | | rows="2" |
| | | auto-height |
| | | maxlength="200" |
| | | placeholder="请è¾å
¥ç³è¯·äºç±" |
| | | show-word-limit |
| | | /> |
| | | <u-form ref="formRef" |
| | | @submit="submitForm" |
| | | :rules="rules" |
| | | :model="form" |
| | | label-width="140rpx"> |
| | | <u-form-item prop="approveReason" |
| | | label="æµç¨ç¼å·"> |
| | | <u-input v-model="form.approveId" |
| | | disabled |
| | | placeholder="èªå¨ç¼å·" /> |
| | | </u-form-item> |
| | | <u-form-item prop="approveDeptName" label="ç³è¯·é¨é¨" required> |
| | | <u-input |
| | | v-model="form.approveDeptName" |
| | | readonly |
| | | placeholder="è¯·éæ©ç³è¯·é¨é¨" |
| | | @click="showPicker = true" |
| | | /> |
| | | <u-form-item prop="approveReason" |
| | | :label="approveType === 5 ? 'éè´äºç±' : 'ç³è¯·äºç±'" |
| | | required> |
| | | <u-input v-model="form.approveReason" |
| | | type="textarea" |
| | | rows="2" |
| | | auto-height |
| | | maxlength="200" |
| | | :placeholder="approveType === 5 ? '请è¾å
¥éè´äºç±' : '请è¾å
¥ç³è¯·äºç±'" |
| | | show-word-limit /> |
| | | </u-form-item> |
| | | <u-form-item prop="approveDeptName" |
| | | label="ç³è¯·é¨é¨" |
| | | required> |
| | | <!-- <u-input v-model="form.approveDeptName" |
| | | placeholder="è¯·éæ©ç³è¯·é¨é¨" /> --> |
| | | <u-input v-model="form.approveDeptName" |
| | | readonly |
| | | placeholder="è¯·éæ©ç³è¯·é¨é¨" |
| | | @click="showPicker = true" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showPicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item prop="approveUser" label="ç³è¯·äºº" required> |
| | | <u-input |
| | | v-model="form.approveUserName" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | readonly |
| | | /> |
| | | <u-form-item prop="approveUser" |
| | | label="ç³è¯·äºº" |
| | | required> |
| | | <u-input v-model="form.approveUserName" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item prop="approveTime" label="ç³è¯·æ¥æ" required> |
| | | <u-input |
| | | v-model="form.approveTime" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <u-form-item prop="approveTime" |
| | | label="ç³è¯·æ¥æ" |
| | | required> |
| | | <u-input v-model="form.approveTime" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="showDatePicker" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="approveType === 2"> |
| | | <u-form-item prop="startDate" |
| | | label="å¼å§æ¶é´" |
| | | required> |
| | | <u-input v-model="form.startDate" |
| | | readonly |
| | | placeholder="请åå¼å§æ¶é´" |
| | | @click="showStartDatePicker" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showStartDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item prop="endDate" |
| | | label="ç»ææ¶é´" |
| | | required> |
| | | <u-input v-model="form.endDate" |
| | | readonly |
| | | placeholder="请åç»ææ¶é´" |
| | | @click="showEndDatePicker" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showEndDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </template> |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <u-form-item v-if="approveType === 3" |
| | | prop="location" |
| | | label="åºå·®å°ç¹" |
| | | required> |
| | | <u-input v-model="form.location" |
| | | placeholder="请è¾å
¥åºå·®å°ç¹" |
| | | clearable /> |
| | | </u-form-item> |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <u-form-item v-if="approveType === 4" |
| | | prop="price" |
| | | label="æ¥ééé¢" |
| | | required> |
| | | <u-input v-model="form.price" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ¥ééé¢" |
| | | clearable /> |
| | | </u-form-item> |
| | | </u-form> |
| | | |
| | | <!-- éæ©å¨å¼¹çª --> |
| | | <up-action-sheet |
| | | :show="showPicker" |
| | | :actions="productOptions" |
| | | title="éæ©é¨é¨" |
| | | @select="onConfirm" |
| | | @close="showPicker = false" |
| | | /> |
| | | |
| | | <up-action-sheet :show="showPicker" |
| | | :actions="productOptions" |
| | | title="éæ©é¨é¨" |
| | | @select="onConfirm" |
| | | @close="showPicker = false" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | mode="date" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </u-popup> |
| | | <up-popup :show="showDate" |
| | | mode="bottom" |
| | | @close="showDate = false"> |
| | | <up-datetime-picker :show="true" |
| | | v-model="currentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" /> |
| | | </up-popup> |
| | | <!-- 请åå¼å§æ¶é´éæ©å¨ --> |
| | | <up-popup :show="showStartDate" |
| | | mode="bottom" |
| | | @close="showStartDate = false"> |
| | | <up-datetime-picker :show="true" |
| | | v-model="startDateValue" |
| | | @confirm="onStartDateConfirm" |
| | | @cancel="showStartDate = false" |
| | | mode="date" /> |
| | | </up-popup> |
| | | <!-- 请åç»ææ¶é´éæ©å¨ --> |
| | | <up-popup :show="showEndDate" |
| | | mode="bottom" |
| | | @close="showEndDate = false"> |
| | | <up-datetime-picker :show="true" |
| | | v-model="endDateValue" |
| | | @confirm="onEndDateConfirm" |
| | | @cancel="showEndDate = false" |
| | | mode="date" /> |
| | | </up-popup> |
| | | <!-- å®¡æ ¸æµç¨åºå --> |
| | | <view class="approval-process"> |
| | | <view class="approval-header"> |
| | | <text class="approval-title">å®¡æ ¸æµç¨</text> |
| | | <text class="approval-desc">æ¯ä¸ªæ¥éª¤åªè½éæ©ä¸ä¸ªå®¡æ¹äºº</text> |
| | | </view> |
| | | |
| | | <view class="approval-steps"> |
| | | <view v-for="(step, stepIndex) in approverNodes" :key="stepIndex" class="approval-step"> |
| | | <view v-for="(step, stepIndex) in approverNodes" |
| | | :key="stepIndex" |
| | | class="approval-step"> |
| | | <view class="step-dot"></view> |
| | | <view class="step-title"> |
| | | <text>审æ¹äºº</text> |
| | | </view> |
| | | <view class="approver-container"> |
| | | <view v-if="step.nickName" class="approver-item"> |
| | | <view v-if="step.nickName" |
| | | class="approver-item"> |
| | | <view class="approver-avatar"> |
| | | <text class="avatar-text">{{ step.nickName.charAt(0) }}</text> |
| | | <view class="status-dot"></view> |
| | |
| | | <view class="approver-info"> |
| | | <text class="approver-name">{{ step.nickName }}</text> |
| | | </view> |
| | | <view class="delete-approver-btn" @click="removeApprover(stepIndex)">Ã</view> |
| | | <view class="delete-approver-btn" |
| | | @click="removeApprover(stepIndex)">Ã</view> |
| | | </view> |
| | | <view v-else class="add-approver-btn" @click="addApprover(stepIndex)"> |
| | | <view v-else |
| | | class="add-approver-btn" |
| | | @click="addApprover(stepIndex)"> |
| | | <view class="add-circle">+</view> |
| | | <text class="add-label">鿩审æ¹äºº</text> |
| | | </view> |
| | | </view> |
| | | <view class="step-line" v-if="stepIndex < approverNodes.length - 1"></view> |
| | | <view class="delete-step-btn" v-if="approverNodes.length > 1" @click="removeApprovalStep(stepIndex)">å é¤èç¹</view> |
| | | <view class="step-line" |
| | | v-if="stepIndex < approverNodes.length - 1"></view> |
| | | <view class="delete-step-btn" |
| | | v-if="approverNodes.length > 1" |
| | | @click="removeApprovalStep(stepIndex)">å é¤èç¹</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="add-step-btn"> |
| | | <u-button icon="plus" plain type="primary" style="width: 100%" @click="addApprovalStep">æ°å¢èç¹</u-button> |
| | | <u-button icon="plus" |
| | | plain |
| | | type="primary" |
| | | style="width: 100%" |
| | | @click="addApprovalStep">æ°å¢èç¹</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- åºé¨æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm">ä¿å</u-button> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" |
| | | @click="submitForm">ä¿å</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import {getDept, approveProcessGetInfo, approveProcessAdd, approveProcessUpdate} from "@/api/collaborativeApproval/approvalProcess"; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import {userListNoPageByTenantId} from "@/api/system/user"; |
| | | import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | import { |
| | | getDept, |
| | | approveProcessGetInfo, |
| | | approveProcessAdd, |
| | | approveProcessUpdate, |
| | | } from "@/api/collaborativeApproval/approvalProcess"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import { userListNoPageByTenantId } from "@/api/system/user"; |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | approveTime: "", |
| | | approveId: "", |
| | | approveUser: "", |
| | | approveUserName: "", |
| | | approveDeptName: "", |
| | | approveDeptId: "", |
| | | approveReason: "", |
| | | checkResult: "", |
| | | tempFileIds: [], |
| | | approverList: [] // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | }, |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" },], |
| | | approveId: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const result = ref(""); |
| | | const showPicker = ref(false); |
| | | const productOptions = ref([]); |
| | | const operationType = ref(""); |
| | | const currentApproveStatus = ref(""); |
| | | const approverNodes = ref([]); |
| | | const userList = ref([]); |
| | | const formRef = ref(null); |
| | | const message = ref(""); |
| | | const showDate = ref(false) |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | const userStore = useUserStore() |
| | | |
| | | const getProductOptions = () => { |
| | | getDept().then((res) => { |
| | | productOptions.value = res.data.map(item => ({ |
| | | value: item.deptId, |
| | | name: item.deptName |
| | | })) |
| | | }); |
| | | }; |
| | | const fileList = ref([]); |
| | | let nextApproverId = 2; |
| | | |
| | | onMounted(async () => { |
| | | try { |
| | | getProductOptions() |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data |
| | | }) |
| | | form.value.approveUser = userStore.id |
| | | form.value.approveUserName = userStore.nickName |
| | | form.value.approveTime = getCurrentDate(); |
| | | |
| | | // 仿¬å°åå¨è·ååæ° |
| | | operationType.value = uni.getStorageSync('operationType') || 'add'; |
| | | |
| | | // 妿æ¯ç¼è¾æ¨¡å¼ï¼ä»æ¬å°åå¨è·åæ°æ® |
| | | if (operationType.value === 'edit') { |
| | | const storedData = uni.getStorageSync('invoiceLedgerEditRow'); |
| | | if (storedData) { |
| | | const row = JSON.parse(storedData); |
| | | fileList.value = row.commonFileList || []; |
| | | form.value.tempFileIds = fileList.value.map(file => file.id); |
| | | currentApproveStatus.value = row.approveStatus; |
| | | |
| | | approveProcessGetInfo({id: row.approveId, approveReason: '1'}).then(res => { |
| | | form.value = {...res.data}; |
| | | // 忾审æ¹äºº |
| | | if (res.data && res.data.approveUserIds) { |
| | | const userIds = res.data.approveUserIds.split(','); |
| | | approverNodes.value = userIds.map((userId, idx) => { |
| | | const userIdNum = parseInt(userId.trim()); |
| | | // ä»userList䏿¾å°å¯¹åºçç¨æ·ä¿¡æ¯ |
| | | const userInfo = userList.value.find(user => user.userId === userIdNum); |
| | | return { |
| | | id: idx + 1, |
| | | userId: userIdNum, |
| | | nickName: userInfo ? userInfo.nickName : null |
| | | }; |
| | | }); |
| | | nextApproverId = userIds.length + 1; |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§åä¸ä¸ªç©ºç审æ¹èç¹ |
| | | approverNodes.value = [{ id: 1, userId: null, nickName: null }]; |
| | | nextApproverId = 2; |
| | | } |
| | | }); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§åä¸ä¸ªç©ºç审æ¹èç¹ |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | } |
| | | |
| | | // çå¬èç³»äººéæ©äºä»¶ |
| | | uni.$on('selectContact', handleSelectContact); |
| | | } catch (error) { |
| | | console.error("è·åé¨é¨æ°æ®å¤±è´¥:", error); |
| | | } |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | // ç§»é¤äºä»¶çå¬ |
| | | uni.$off('selectContact', handleSelectContact); |
| | | }); |
| | | |
| | | const onConfirm = (item) => { |
| | | // 设置éä¸çé¨é¨ |
| | | form.value.approveDeptName = item.name; |
| | | // ç¡®ä¿è®¾ç½®çæ¯å符串类åçé¨é¨ID |
| | | form.value.approveDeptId = String(item.value || ''); |
| | | console.log('é¨é¨éæ©åçå¼:', { |
| | | approveDeptId: form.value.approveDeptId, |
| | | approveDeptName: form.value.approveDeptName |
| | | const data = reactive({ |
| | | form: { |
| | | approveTime: "", |
| | | approveId: "", |
| | | approveUser: "", |
| | | approveUserName: "", |
| | | approveDeptName: "", |
| | | approveDeptId: "", |
| | | approveReason: "", |
| | | checkResult: "", |
| | | tempFileIds: [], |
| | | approverList: [], // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | startDate: "", |
| | | endDate: "", |
| | | location: "", |
| | | price: "", |
| | | }, |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" }], |
| | | approveId: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | startDate: [ |
| | | { required: false, message: "è¯·éæ©å¼å§æ¶é´", trigger: "change" }, |
| | | ], |
| | | endDate: [ |
| | | { required: false, message: "è¯·éæ©ç»ææ¶é´", trigger: "change" }, |
| | | ], |
| | | location: [{ required: false, message: "请è¾å
¥åºå·®å°ç¹", trigger: "blur" }], |
| | | price: [{ required: false, message: "请è¾å
¥æ¥ééé¢", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | showPicker.value = false; |
| | | }; |
| | | const { form, rules } = toRefs(data); |
| | | const result = ref(""); |
| | | const showPicker = ref(false); |
| | | const productOptions = ref([]); |
| | | const operationType = ref(""); |
| | | const currentApproveStatus = ref(""); |
| | | const approverNodes = ref([]); |
| | | const userList = ref([]); |
| | | const formRef = ref(null); |
| | | const message = ref(""); |
| | | const showDate = ref(false); |
| | | const currentDate = ref(Date.now()); |
| | | const showStartDate = ref(false); |
| | | const startDateValue = ref(Date.now()); |
| | | const showEndDate = ref(false); |
| | | const endDateValue = ref(Date.now()); |
| | | const userStore = useUserStore(); |
| | | const approveType = ref(0); |
| | | |
| | | const goBack = () => { |
| | | // æ¸
餿¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync('operationType'); |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack(); |
| | | }; |
| | | const getProductOptions = () => { |
| | | getDept().then(res => { |
| | | productOptions.value = res.data.map(item => ({ |
| | | value: item.deptId, |
| | | name: item.deptName, |
| | | })); |
| | | }); |
| | | }; |
| | | const fileList = ref([]); |
| | | let nextApproverId = 2; |
| | | const getCurrentinfo = () => { |
| | | userStore.getInfo().then(res => { |
| | | form.value.approveDeptId = res.user.tenantId; |
| | | console.log(res.user.tenantId, "res.user.tenantId"); |
| | | }); |
| | | }; |
| | | onMounted(async () => { |
| | | try { |
| | | getProductOptions(); |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | form.value.approveUser = userStore.id; |
| | | form.value.approveUserName = userStore.nickName; |
| | | form.value.approveTime = getCurrentDate(); |
| | | getCurrentinfo(); |
| | | // 仿¬å°åå¨è·ååæ° |
| | | operationType.value = uni.getStorageSync("operationType") || "add"; |
| | | approveType.value = uni.getStorageSync("approveType") || 0; |
| | | |
| | | const submitForm = () => { |
| | | // æ£æ¥æ¯ä¸ªå®¡æ¹æ¥éª¤æ¯å¦é½æå®¡æ¹äºº |
| | | const hasEmptyStep = approverNodes.value.some(step => !step.nickName); |
| | | if (hasEmptyStep) { |
| | | showToast('请为æ¯ä¸ªå®¡æ¹æ¥éª¤éæ©å®¡æ¹äºº'); |
| | | return; |
| | | } |
| | | |
| | | // æå¨æ£æ¥å¿
å¡«åæ®µï¼é²æ¢å æ°æ®ç±»åé®é¢å¯¼è´çæ ¡éªå¤±è´¥ |
| | | if (!form.value.approveReason || !form.value.approveReason.trim()) { |
| | | showToast('请è¾å
¥ç³è¯·äºç±'); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.approveDeptId || String(form.value.approveDeptId).trim() === '') { |
| | | showToast('è¯·éæ©ç³è¯·é¨é¨'); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.approveTime) { |
| | | showToast('è¯·éæ©ç³è¯·æ¥æ'); |
| | | return; |
| | | } |
| | | |
| | | formRef.value.validate().then((valid) => { |
| | | if (valid) { |
| | | // è¡¨åæ ¡éªéè¿ï¼å¯ä»¥æäº¤æ°æ® |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | console.log('approverNodes---', approverNodes.value) |
| | | form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',') |
| | | form.value.approveType = 0 |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } else { |
| | | approveProcessUpdate(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } |
| | | } |
| | | }).catch((error) => { |
| | | console.error("è¡¨åæ ¡éªå¤±è´¥:", error); |
| | | // å°è¯è·åå
·ä½çéè¯¯åæ®µ |
| | | if (error && error.errors) { |
| | | const firstError = error.errors[0]; |
| | | if (firstError) { |
| | | uni.showToast({ |
| | | title: firstError.message || 'è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | // 妿æ¯ç¼è¾æ¨¡å¼ï¼ä»æ¬å°åå¨è·åæ°æ® |
| | | if (operationType.value === "edit") { |
| | | const storedData = uni.getStorageSync("invoiceLedgerEditRow"); |
| | | if (storedData) { |
| | | const row = JSON.parse(storedData); |
| | | fileList.value = row.commonFileList || []; |
| | | form.value.tempFileIds = fileList.value.map(file => file.id); |
| | | currentApproveStatus.value = row.approveStatus; |
| | | |
| | | approveProcessGetInfo({ id: row.approveId, approveReason: "1" }).then( |
| | | res => { |
| | | form.value = { ...res.data }; |
| | | // 忾审æ¹äºº |
| | | if (res.data && res.data.approveUserIds) { |
| | | const userIds = res.data.approveUserIds.split(","); |
| | | approverNodes.value = userIds.map((userId, idx) => { |
| | | const userIdNum = parseInt(userId.trim()); |
| | | // ä»userList䏿¾å°å¯¹åºçç¨æ·ä¿¡æ¯ |
| | | const userInfo = userList.value.find( |
| | | user => user.userId === userIdNum |
| | | ); |
| | | return { |
| | | id: idx + 1, |
| | | userId: userIdNum, |
| | | nickName: userInfo ? userInfo.nickName : null, |
| | | }; |
| | | }); |
| | | nextApproverId = userIds.length + 1; |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§åä¸ä¸ªç©ºç审æ¹èç¹ |
| | | approverNodes.value = [{ id: 1, userId: null, nickName: null }]; |
| | | nextApproverId = 2; |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼åå§åä¸ä¸ªç©ºç审æ¹èç¹ |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | } |
| | | |
| | | // çå¬èç³»äººéæ©äºä»¶ |
| | | uni.$on("selectContact", handleSelectContact); |
| | | } catch (error) { |
| | | console.error("è·åé¨é¨æ°æ®å¤±è´¥:", error); |
| | | } |
| | | // æ¾ç¤ºéç¨éè¯¯ä¿¡æ¯ |
| | | uni.showToast({ |
| | | title: 'è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // å¤çèç³»äººéæ©ç»æ |
| | | const handleSelectContact = (data) => { |
| | | const { stepIndex, contact } = data; |
| | | // å°éä¸çè系人设置为对åºå®¡æ¹æ¥éª¤ç审æ¹äºº |
| | | approverNodes.value[stepIndex].userId = contact.userId; |
| | | approverNodes.value[stepIndex].nickName = contact.nickName; |
| | | }; |
| | | |
| | | const addApprover = (stepIndex) => { |
| | | // 跳转å°èç³»äººéæ©é¡µé¢ |
| | | uni.setStorageSync('stepIndex', stepIndex); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect" |
| | | onUnmounted(() => { |
| | | // ç§»é¤äºä»¶çå¬ |
| | | uni.$off("selectContact", handleSelectContact); |
| | | }); |
| | | }; |
| | | |
| | | const addApprovalStep = () => { |
| | | // æ·»å æ°çå®¡æ¹æ¥éª¤ |
| | | approverNodes.value.push({ userId: null, nickName: null }); |
| | | }; |
| | | |
| | | const removeApprover = (stepIndex) => { |
| | | // ç§»é¤å®¡æ¹äºº |
| | | approverNodes.value[stepIndex].userId = null; |
| | | approverNodes.value[stepIndex].nickName = null; |
| | | }; |
| | | |
| | | const removeApprovalStep = (stepIndex) => { |
| | | // ç¡®ä¿è³å°ä¿çä¸ä¸ªå®¡æ¹æ¥éª¤ |
| | | if (approverNodes.value.length > 1) { |
| | | approverNodes.value.splice(stepIndex, 1); |
| | | } else { |
| | | uni.showToast({ |
| | | title: 'è³å°éè¦ä¸ä¸ªå®¡æ¹æ¥éª¤', |
| | | icon: 'none' |
| | | const onConfirm = item => { |
| | | // 设置éä¸çé¨é¨ |
| | | form.value.approveDeptName = item.name; |
| | | // ç¡®ä¿è®¾ç½®çæ¯å符串类åçé¨é¨ID |
| | | form.value.approveDeptId = String(item.value || ""); |
| | | console.log("é¨é¨éæ©åçå¼:", { |
| | | approveDeptId: form.value.approveDeptId, |
| | | approveDeptName: form.value.approveDeptName, |
| | | }); |
| | | showPicker.value = false; |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | // æ¸
餿¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync("operationType"); |
| | | uni.removeStorageSync("invoiceLedgerEditRow"); |
| | | uni.removeStorageSync("approveType"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | // æ£æ¥æ¯ä¸ªå®¡æ¹æ¥éª¤æ¯å¦é½æå®¡æ¹äºº |
| | | const hasEmptyStep = approverNodes.value.some(step => !step.nickName); |
| | | if (hasEmptyStep) { |
| | | showToast("请为æ¯ä¸ªå®¡æ¹æ¥éª¤éæ©å®¡æ¹äºº"); |
| | | return; |
| | | } |
| | | |
| | | // æå¨æ£æ¥å¿
å¡«åæ®µï¼é²æ¢å æ°æ®ç±»åé®é¢å¯¼è´çæ ¡éªå¤±è´¥ |
| | | if (!form.value.approveReason || !form.value.approveReason.trim()) { |
| | | showToast("请è¾å
¥ç³è¯·äºç±"); |
| | | return; |
| | | } |
| | | |
| | | if ( |
| | | !form.value.approveDeptId || |
| | | String(form.value.approveDeptId).trim() === "" |
| | | ) { |
| | | showToast("è¯·éæ©ç³è¯·é¨é¨"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.approveTime) { |
| | | showToast("è¯·éæ©ç³è¯·æ¥æ"); |
| | | return; |
| | | } |
| | | |
| | | formRef.value |
| | | .validate() |
| | | .then(valid => { |
| | | if (valid) { |
| | | // è¡¨åæ ¡éªéè¿ï¼å¯ä»¥æäº¤æ°æ® |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | console.log("approverNodes---", approverNodes.value); |
| | | form.value.approveUserIds = approverNodes.value |
| | | .map(node => node.userId) |
| | | .join(","); |
| | | form.value.approveType = approveType.value; |
| | | form.value.approveDeptId = Number(form.value.approveDeptId); |
| | | // const submitForm = { |
| | | // approveDeptId: form.value.approveDeptId, |
| | | // approveDeptName: form.value.approveDeptName, |
| | | // approveReason: form.value.approveReason, |
| | | // approveTime: form.value.approveTime, |
| | | // approveType: form.value.approveType, |
| | | // approveUser: form.value.approveUser, |
| | | // approveUserIds: form.value.approveUserIds, |
| | | // endDate: form.value.endDate, |
| | | // startDate: form.value.startDate, |
| | | // }; |
| | | // console.log("form.value---", form.value); |
| | | // console.log("submitForm", submitForm); |
| | | |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack(); |
| | | }); |
| | | } else { |
| | | approveProcessUpdate(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack(); |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è¡¨åæ ¡éªå¤±è´¥:", error); |
| | | // å°è¯è·åå
·ä½çéè¯¯åæ®µ |
| | | if (error && error.errors) { |
| | | const firstError = error.errors[0]; |
| | | if (firstError) { |
| | | uni.showToast({ |
| | | title: firstError.message || "è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | // æ¾ç¤ºéç¨éè¯¯ä¿¡æ¯ |
| | | uni.showToast({ |
| | | title: "è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项", |
| | | icon: "none", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // å¤çèç³»äººéæ©ç»æ |
| | | const handleSelectContact = data => { |
| | | const { stepIndex, contact } = data; |
| | | // å°éä¸çè系人设置为对åºå®¡æ¹æ¥éª¤ç审æ¹äºº |
| | | approverNodes.value[stepIndex].userId = contact.userId; |
| | | approverNodes.value[stepIndex].nickName = contact.nickName; |
| | | }; |
| | | |
| | | const addApprover = stepIndex => { |
| | | // 跳转å°èç³»äººéæ©é¡µé¢ |
| | | uni.setStorageSync("stepIndex", stepIndex); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect", |
| | | }); |
| | | }; |
| | | |
| | | const addApprovalStep = () => { |
| | | // æ·»å æ°çå®¡æ¹æ¥éª¤ |
| | | approverNodes.value.push({ userId: null, nickName: null }); |
| | | }; |
| | | |
| | | const removeApprover = stepIndex => { |
| | | // ç§»é¤å®¡æ¹äºº |
| | | approverNodes.value[stepIndex].userId = null; |
| | | approverNodes.value[stepIndex].nickName = null; |
| | | }; |
| | | |
| | | const removeApprovalStep = stepIndex => { |
| | | // ç¡®ä¿è³å°ä¿çä¸ä¸ªå®¡æ¹æ¥éª¤ |
| | | if (approverNodes.value.length > 1) { |
| | | approverNodes.value.splice(stepIndex, 1); |
| | | } else { |
| | | uni.showToast({ |
| | | title: "è³å°éè¦ä¸ä¸ªå®¡æ¹æ¥éª¤", |
| | | icon: "none", |
| | | }); |
| | | } |
| | | }; |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.approveTime = formatDateToYMD(e.value); |
| | | currentDate.value = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | | // æ¾ç¤ºè¯·åå¼å§æ¶é´éæ©å¨ |
| | | const showStartDatePicker = () => { |
| | | showStartDate.value = true; |
| | | }; |
| | | |
| | | // 确认请åå¼å§æ¶é´éæ© |
| | | const onStartDateConfirm = e => { |
| | | form.value.startDate = formatDateToYMD(e.value); |
| | | showStartDate.value = false; |
| | | }; |
| | | |
| | | const showEndDatePicker = () => { |
| | | showEndDate.value = true; |
| | | }; |
| | | |
| | | // 确认请åç»ææ¶é´éæ© |
| | | const onEndDateConfirm = e => { |
| | | form.value.endDate = formatDateToYMD(e.value); |
| | | showEndDate.value = false; |
| | | }; |
| | | |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | }; |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.approveTime = formatDateToYMD(e.value) |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); |
| | | } |
| | | |
| | | .approval-header { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .approval-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .approval-desc { |
| | | font-size: 12px; |
| | | color: #999; |
| | | } |
| | | |
| | | /* æ ·å¼å¢å¼ºä¸ºâç®æ´å°åå飿 ¼â */ |
| | | .approval-steps { |
| | | padding-left: 22px; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: 11px; |
| | | top: 40px; |
| | | bottom: 40px; |
| | | width: 2px; |
| | | background: linear-gradient(to bottom, #e6f7ff 0%, #bae7ff 50%, #91d5ff 100%); |
| | | border-radius: 1px; |
| | | } |
| | | } |
| | | |
| | | .approval-step { |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: -18px; |
| | | top: 14px; // ä» 8px è°æ´ä¸º 14pxï¼ä¸æåä¸å¿å¯¹é½ |
| | | width: 12px; |
| | | height: 12px; |
| | | .approval-process { |
| | | background: #fff; |
| | | border: 3px solid #006cfb; |
| | | border-radius: 50%; |
| | | z-index: 2; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | margin: 16px; |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); |
| | | } |
| | | } |
| | | |
| | | .step-title { |
| | | top: 12px; |
| | | margin-bottom: 12px; |
| | | position: relative; |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | .step-title text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | background: #f0f0f0; |
| | | padding: 4px 12px; |
| | | border-radius: 12px; |
| | | position: relative; |
| | | line-height: 1.4; // ç¡®ä¿æåè¡é«ä¸è´ |
| | | } |
| | | |
| | | .approver-item { |
| | | display: flex; |
| | | align-items: center; |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | gap: 12px; |
| | | position: relative; |
| | | border: 1px solid #e6f7ff; |
| | | box-shadow: 0 4px 12px rgba(0, 108, 251, 0.08); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .approver-avatar { |
| | | width: 48px; |
| | | height: 48px; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: relative; |
| | | box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); |
| | | } |
| | | |
| | | .avatar-text { |
| | | color: #fff; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .approver-info { |
| | | flex: 1; |
| | | position: relative; |
| | | } |
| | | |
| | | .approver-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | position: relative; |
| | | } |
| | | |
| | | .approver-dept { |
| | | font-size: 12px; |
| | | color: #999; |
| | | background: rgba(0, 108, 251, 0.05); |
| | | padding: 2px 8px; |
| | | border-radius: 8px; |
| | | display: inline-block; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: 4px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 2px; |
| | | height: 2px; |
| | | background: #006cfb; |
| | | border-radius: 50%; |
| | | .approval-header { |
| | | margin-bottom: 16px; |
| | | } |
| | | } |
| | | |
| | | .delete-approver-btn { |
| | | font-size: 16px; |
| | | color: #ff4d4f; |
| | | background: linear-gradient(135deg, rgba(255, 77, 79, 0.1) 0%, rgba(255, 77, 79, 0.05) 100%); |
| | | width: 28px; |
| | | height: 28px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: all 0.3s ease; |
| | | position: relative; |
| | | } |
| | | .approval-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .add-approver-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: linear-gradient(135deg, #f0f8ff 0%, #e6f7ff 100%); |
| | | border: 2px dashed #006cfb; |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | color: #006cfb; |
| | | font-size: 14px; |
| | | position: relative; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | width: 32px; |
| | | height: 32px; |
| | | border: 2px solid #006cfb; |
| | | border-radius: 50%; |
| | | opacity: 0; |
| | | .approval-desc { |
| | | font-size: 12px; |
| | | color: #999; |
| | | } |
| | | |
| | | /* æ ·å¼å¢å¼ºä¸ºâç®æ´å°åå飿 ¼â */ |
| | | .approval-steps { |
| | | padding-left: 22px; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 11px; |
| | | top: 40px; |
| | | bottom: 40px; |
| | | width: 2px; |
| | | background: linear-gradient( |
| | | to bottom, |
| | | #e6f7ff 0%, |
| | | #bae7ff 50%, |
| | | #91d5ff 100% |
| | | ); |
| | | border-radius: 1px; |
| | | } |
| | | } |
| | | |
| | | .approval-step { |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: -18px; |
| | | top: 14px; // ä» 8px è°æ´ä¸º 14pxï¼ä¸æåä¸å¿å¯¹é½ |
| | | width: 12px; |
| | | height: 12px; |
| | | background: #fff; |
| | | border: 3px solid #006cfb; |
| | | border-radius: 50%; |
| | | z-index: 2; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | } |
| | | |
| | | .step-title { |
| | | top: 12px; |
| | | margin-bottom: 12px; |
| | | position: relative; |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | .step-title text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | background: #f0f0f0; |
| | | padding: 4px 12px; |
| | | border-radius: 12px; |
| | | position: relative; |
| | | line-height: 1.4; // ç¡®ä¿æåè¡é«ä¸è´ |
| | | } |
| | | |
| | | .approver-item { |
| | | display: flex; |
| | | align-items: center; |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | gap: 12px; |
| | | position: relative; |
| | | border: 1px solid #e6f7ff; |
| | | box-shadow: 0 4px 12px rgba(0, 108, 251, 0.08); |
| | | transition: all 0.3s ease; |
| | | } |
| | | } |
| | | |
| | | .delete-step-btn { |
| | | color: #ff4d4f; |
| | | font-size: 12px; |
| | | background: linear-gradient(135deg, rgba(255, 77, 79, 0.1) 0%, rgba(255, 77, 79, 0.05) 100%); |
| | | padding: 6px 12px; |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | position: relative; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | left: 6px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 4px; |
| | | height: 4px; |
| | | background: #ff4d4f; |
| | | .approver-avatar { |
| | | width: 48px; |
| | | height: 48px; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: relative; |
| | | box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); |
| | | } |
| | | } |
| | | |
| | | .step-line { |
| | | display: none; // éè忥ç线æ¡ï¼ä½¿ç¨ä¼ªå
ç´ ä»£æ¿ |
| | | } |
| | | |
| | | .add-step-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .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: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // å¨ç»å®ä¹ |
| | | @keyframes pulse { |
| | | 0% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | .avatar-text { |
| | | color: #fff; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); |
| | | } |
| | | 50% { |
| | | transform: scale(1.2); |
| | | opacity: 0.7; |
| | | |
| | | .approver-info { |
| | | flex: 1; |
| | | position: relative; |
| | | } |
| | | 100% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | |
| | | .approver-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | position: relative; |
| | | } |
| | | } |
| | | |
| | | @keyframes rotate { |
| | | 0% { |
| | | transform: rotate(0deg); |
| | | .approver-dept { |
| | | font-size: 12px; |
| | | color: #999; |
| | | background: rgba(0, 108, 251, 0.05); |
| | | padding: 2px 8px; |
| | | border-radius: 8px; |
| | | display: inline-block; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 4px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 2px; |
| | | height: 2px; |
| | | background: #006cfb; |
| | | border-radius: 50%; |
| | | } |
| | | } |
| | | 100% { |
| | | transform: rotate(360deg); |
| | | |
| | | .delete-approver-btn { |
| | | font-size: 16px; |
| | | color: #ff4d4f; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(255, 77, 79, 0.1) 0%, |
| | | rgba(255, 77, 79, 0.05) 100% |
| | | ); |
| | | width: 28px; |
| | | height: 28px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: all 0.3s ease; |
| | | position: relative; |
| | | } |
| | | } |
| | | |
| | | @keyframes ripple { |
| | | 0% { |
| | | transform: translate(-50%, -50%) scale(0.8); |
| | | opacity: 1; |
| | | .add-approver-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: linear-gradient(135deg, #f0f8ff 0%, #e6f7ff 100%); |
| | | border: 2px dashed #006cfb; |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | color: #006cfb; |
| | | font-size: 14px; |
| | | position: relative; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | width: 32px; |
| | | height: 32px; |
| | | border: 2px solid #006cfb; |
| | | border-radius: 50%; |
| | | opacity: 0; |
| | | transition: all 0.3s ease; |
| | | } |
| | | } |
| | | 100% { |
| | | transform: translate(-50%, -50%) scale(1.6); |
| | | opacity: 0; |
| | | |
| | | .delete-step-btn { |
| | | color: #ff4d4f; |
| | | font-size: 12px; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(255, 77, 79, 0.1) 0%, |
| | | rgba(255, 77, 79, 0.05) 100% |
| | | ); |
| | | padding: 6px 12px; |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | position: relative; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 6px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 4px; |
| | | height: 4px; |
| | | background: #ff4d4f; |
| | | border-radius: 50%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* 妿已æ .step-lineï¼è¿éæ´ç²¾åå®ä½å°å·¦ä¾§ä¸å°åç¹å¯¹é½ */ |
| | | .step-line { |
| | | position: absolute; |
| | | left: 4px; |
| | | top: 48px; |
| | | width: 2px; |
| | | height: calc(100% - 48px); |
| | | background: #E5E7EB; |
| | | } |
| | | .step-line { |
| | | display: none; // éè忥ç线æ¡ï¼ä½¿ç¨ä¼ªå
ç´ ä»£æ¿ |
| | | } |
| | | |
| | | .approver-container { |
| | | display: flex; |
| | | align-items: center; |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); |
| | | border-radius: 16px; |
| | | gap: 12px; |
| | | padding: 10px 0; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | .add-step-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .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; |
| | | } |
| | | |
| | | .approver-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 8px 10px; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | border-radius: 0; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 6.375rem; |
| | | background: #c7c9cc; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .approver-avatar { |
| | | position: relative; |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 50%; |
| | | background: #F3F4F6; |
| | | border: 2px solid #E5E7EB; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | animation: none; /* ç¦ç¨æè½¬çå¨ç»ï¼åå½ç®æ´ */ |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 14rem; |
| | | background: linear-gradient(140deg, #00baff 0%, #006cfb 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .avatar-text { |
| | | font-size: 14px; |
| | | color: #374151; |
| | | font-weight: 600; |
| | | } |
| | | // å¨ç»å®ä¹ |
| | | @keyframes pulse { |
| | | 0% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | 50% { |
| | | transform: scale(1.2); |
| | | opacity: 0.7; |
| | | } |
| | | 100% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | .add-approver-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | padding: 0; |
| | | } |
| | | @keyframes rotate { |
| | | 0% { |
| | | transform: rotate(0deg); |
| | | } |
| | | 100% { |
| | | transform: rotate(360deg); |
| | | } |
| | | } |
| | | |
| | | .add-approver-btn .add-circle { |
| | | width: 40px; |
| | | height: 40px; |
| | | border: 2px dashed #A0AEC0; |
| | | border-radius: 50%; |
| | | color: #6B7280; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 22px; |
| | | line-height: 1; |
| | | } |
| | | @keyframes ripple { |
| | | 0% { |
| | | transform: translate(-50%, -50%) scale(0.8); |
| | | opacity: 1; |
| | | } |
| | | 100% { |
| | | transform: translate(-50%, -50%) scale(1.6); |
| | | opacity: 0; |
| | | } |
| | | } |
| | | |
| | | .add-approver-btn .add-label { |
| | | color: #3B82F6; |
| | | font-size: 14px; |
| | | } |
| | | /* 妿已æ .step-lineï¼è¿éæ´ç²¾åå®ä½å°å·¦ä¾§ä¸å°åç¹å¯¹é½ */ |
| | | .step-line { |
| | | position: absolute; |
| | | left: 4px; |
| | | top: 48px; |
| | | width: 2px; |
| | | height: calc(100% - 48px); |
| | | background: #e5e7eb; |
| | | } |
| | | |
| | | .approver-container { |
| | | display: flex; |
| | | align-items: center; |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); |
| | | border-radius: 16px; |
| | | gap: 12px; |
| | | padding: 10px 0; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .approver-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 8px 10px; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | border-radius: 0; |
| | | } |
| | | |
| | | .approver-avatar { |
| | | position: relative; |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 50%; |
| | | background: #f3f4f6; |
| | | border: 2px solid #e5e7eb; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | animation: none; /* ç¦ç¨æè½¬çå¨ç»ï¼åå½ç®æ´ */ |
| | | } |
| | | |
| | | .avatar-text { |
| | | font-size: 14px; |
| | | color: #374151; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .add-approver-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | background: transparent; |
| | | border: none; |
| | | box-shadow: none; |
| | | padding: 0; |
| | | } |
| | | |
| | | .add-approver-btn .add-circle { |
| | | width: 40px; |
| | | height: 40px; |
| | | border: 2px dashed #a0aec0; |
| | | border-radius: 50%; |
| | | color: #6b7280; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 22px; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .add-approver-btn .add-label { |
| | | color: #3b82f6; |
| | | font-size: 14px; |
| | | } |
| | | </style> |
| | |
| | | // 审æ¹ç®¡çä¸»é¡µé¢ |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="审æ¹ç®¡ç" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请è¾å
¥æµç¨ç¼å·" |
| | | v-model="searchForm.approveId" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-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.approveId }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.approveStatus)">{{ formatReceiptType(item.approveStatus) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·äºº</text> |
| | | <text class="detail-value">{{ item.approveUserName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·é¨é¨</text> |
| | | <text class="detail-value">{{ item.approveDeptName }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">审æ¹äºç±</text> |
| | | <text class="detail-value highlightBlue">{{ item.approveReason }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·æ¥æ</text> |
| | | <text class="detail-value">{{ item.approveTime }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»ææ¥æ</text> |
| | | <text class="detail-value">{{ item.approveOverTime }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row-user"> |
| | | <text class="detail-label">å½å审æ¹äºº</text> |
| | | <view class="detail-value approver-value"> |
| | | <view class="approver-chip"> |
| | | <text class="approver-name">{{ item.approveUserCurrentName || 'æªåé
' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <view class="actions"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn edit" |
| | | :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4" |
| | | @click="handleItemClick(item)" |
| | | > |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button |
| | | type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | | :disabled="item.approveUserCurrentId == null || item.approveStatus == 2 || item.approveStatus == 3 || item.approveStatus == 4 || item.approveUserCurrentId !== userStore.id" |
| | | @click="approve(item)" |
| | | > |
| | | å®¡æ ¸ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ å®¡æ¹æ°æ®</text> |
| | | </view> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" @click="handleAdd"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="pageTitle" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥æµç¨ç¼å·" |
| | | v-model="searchForm.approveId" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-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.approveId }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.approveStatus)">{{ formatReceiptType(item.approveStatus) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·äºº</text> |
| | | <text class="detail-value">{{ item.approveUserName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·é¨é¨</text> |
| | | <text class="detail-value">{{ item.approveDeptName }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">审æ¹äºç±</text> |
| | | <text class="detail-value highlightBlue">{{ item.approveReason }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·æ¥æ</text> |
| | | <text class="detail-value">{{ item.approveTime }}</text> |
| | | </view> |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="item.approveType === 2"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">请åå¼å§æ¶é´</text> |
| | | <text class="detail-value">{{ item.startDate || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">请åç»ææ¶é´</text> |
| | | <text class="detail-value">{{ item.endDate || '-' }}</text> |
| | | </view> |
| | | </template> |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <view v-if="item.approveType === 3" |
| | | class="detail-row"> |
| | | <text class="detail-label">åºå·®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location || '-' }}</text> |
| | | </view> |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <view v-if="item.approveType === 4" |
| | | class="detail-row"> |
| | | <text class="detail-label">æ¥ééé¢</text> |
| | | <text class="detail-value highlightYellow">{{ item.price ? `Â¥${item.price}` : '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»ææ¥æ</text> |
| | | <text class="detail-value">{{ item.approveOverTime }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row-user"> |
| | | <text class="detail-label">å½å审æ¹äºº</text> |
| | | <view class="detail-value approver-value"> |
| | | <view class="approver-chip"> |
| | | <text class="approver-name">{{ item.approveUserCurrentName || 'æªåé
' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <view class="actions"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn edit" |
| | | :disabled="item.approveStatus == 2 || item.approveStatus == 1 || item.approveStatus == 4 || item.approveStatus == 8" |
| | | @click="handleItemClick(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | | :disabled="item.approveUserCurrentId == null || item.approveStatus == 2 || item.approveStatus == 3 || item.approveStatus == 4 || item.approveStatus == 8 || item.approveUserCurrentId !== userStore.id" |
| | | @click="approve(item)"> |
| | | å®¡æ ¸ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ å®¡æ¹æ°æ®</text> |
| | | </view> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" |
| | | v-if="props.approveType != 5 && props.approveType != 6 && props.approveType != 7" |
| | | @click="handleAdd"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | ref, |
| | | toRefs, |
| | | reactive |
| | | } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import {approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess"; |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const userStore = useUserStore() |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | approveId: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | import { ref, toRefs, reactive } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { approveProcessListPage } from "@/api/collaborativeApproval/approvalProcess"; |
| | | import { onLoad, onShow } from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | approveProcessListPage({ |
| | | ...page,approveType: 0,...searchForm.value |
| | | }) |
| | | .then((res) => { |
| | | ledgerList.value = res.data.records; |
| | | closeToast() |
| | | }) |
| | | .catch(() => { |
| | | closeToast() |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¥æ¶ç¶ç»ä»¶ä¼ éç approveType åæ° |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | }); |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // æ å° approveType å°å¯¹åºç页颿 é¢ |
| | | const getPageTitle = type => { |
| | | const titleMap = { |
| | | 1: "å
¬åºç®¡ç", |
| | | 2: "请å管ç", |
| | | 3: "åºå·®ç®¡ç", |
| | | 4: "æ¥é管ç", |
| | | 5: "éè´ç®¡ç", |
| | | 6: "æ¥ä»·ç®¡ç", |
| | | 7: "å货审æ¹", |
| | | 8: "å±é©ä½ä¸å®¡æ¹", |
| | | }; |
| | | return titleMap[type] || "审æ¹ç®¡ç"; |
| | | }; |
| | | |
| | | // æ¾ç¤ºçéé项 |
| | | const showFilterOptions = () => { |
| | | uni.showActionSheet({ |
| | | itemList: ["ææ¥æçé", "æç¶æçé", "æéé¢çé"], |
| | | success: (res) => { |
| | | console.log("éæ©äºçéé项:", res.tapIndex); |
| | | }, |
| | | }); |
| | | }; |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = (params) => { |
| | | if (params == 0) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params == 1) { |
| | | return "å®¡æ ¸ä¸"; |
| | | } else if (params == 2) { |
| | | return "å®¡æ ¸å®æ"; |
| | | } else if (params == 4) { |
| | | return "已鿰æäº¤"; |
| | | } else { |
| | | return 'ä¸éè¿'; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = (type) => { |
| | | if (type == 0) { |
| | | return "warning"; |
| | | } else if (type == 1) { |
| | | return "primary"; |
| | | } else if (type == 2) { |
| | | return "success"; |
| | | } else if (type == 4) { |
| | | return "primary"; |
| | | } else { |
| | | return "error"; |
| | | } |
| | | }; |
| | | const pageTitle = getPageTitle(props.approveType); |
| | | |
| | | // ç¹å»å表项 |
| | | const handleItemClick = (item) => { |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éæ°æ® |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)); |
| | | uni.setStorageSync('operationType', 'edit'); |
| | | uni.setStorageSync('approveId', item.approveId); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/detail", |
| | | }); |
| | | }; |
| | | const userStore = useUserStore(); |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | approveId: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // æ·»å æ°è®°å½ |
| | | const handleAdd = () => { |
| | | uni.setStorageSync('operationType', 'add'); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/detail", |
| | | }); |
| | | }; |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = (item) => { |
| | | uni.setStorageSync('approveId', item.approveId); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/approve" |
| | | }) |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | approveProcessListPage({ |
| | | ...page, |
| | | approveType: props.approveType, |
| | | ...searchForm.value, |
| | | }) |
| | | .then(res => { |
| | | ledgerList.value = res.data.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | getList(); |
| | | }); |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºçéé项 |
| | | const showFilterOptions = () => { |
| | | uni.showActionSheet({ |
| | | itemList: ["ææ¥æçé", "æç¶æçé", "æéé¢çé"], |
| | | success: res => { |
| | | console.log("éæ©äºçéé项:", res.tapIndex); |
| | | }, |
| | | }); |
| | | }; |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params == 1) { |
| | | return "å®¡æ ¸ä¸"; |
| | | } else if (params == 2) { |
| | | return "å®¡æ ¸å®æ"; |
| | | } else if (params == 4) { |
| | | return "已鿰æäº¤"; |
| | | } else { |
| | | return "ä¸éè¿"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "warning"; |
| | | } else if (type == 1) { |
| | | return "primary"; |
| | | } else if (type == 2) { |
| | | return "success"; |
| | | } else if (type == 4) { |
| | | return "primary"; |
| | | } else { |
| | | return "error"; |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»å表项 |
| | | const handleItemClick = item => { |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éæ°æ® |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item)); |
| | | uni.setStorageSync("operationType", "edit"); |
| | | uni.setStorageSync("approveId", item.approveId); |
| | | uni.setStorageSync("approveType", props.approveType); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/detail", |
| | | }); |
| | | }; |
| | | |
| | | // æ·»å æ°è®°å½ |
| | | const handleAdd = () => { |
| | | uni.setStorageSync("operationType", "add"); |
| | | uni.setStorageSync("approveType", props.approveType); |
| | | uni.navigateTo({ |
| | | url: `/pages/cooperativeOffice/collaborativeApproval/detail?approveType=${props.approveType}`, |
| | | }); |
| | | }; |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = item => { |
| | | uni.setStorageSync("approveId", item.approveId); |
| | | uni.setStorageSync("approveType", props.approveType); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/cooperativeOffice/collaborativeApproval/approve?approveType=" + |
| | | props.approveType, |
| | | }); |
| | | }; |
| | | |
| | | onLoad(options => { |
| | | // è§£æapproveId |
| | | if (options.approveId) { |
| | | searchForm.value.approveId = options.approveId; |
| | | } |
| | | }); |
| | | |
| | | onShow(() => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="1" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="2" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="3" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="4" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="5" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from "./index.vue"; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="6" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from "./index.vue"; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="7" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from "./index.vue"; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="8" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from "./index.vue"; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="customer-detail-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="客æ·è¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- 详æ
å
容 --> |
| | | <view class="detail-content"> |
| | | <!-- 客æ·åºæ¬ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">客æ·åºæ¬ä¿¡æ¯</view> |
| | | <view class="info-list"> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·åç§°</text> |
| | | <text class="info-value">{{ detailData.customerName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·ç±»å</text> |
| | | <text class="info-value">{{ detailData.customerType || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">纳ç¨äººè¯å«å·</text> |
| | | <text class="info-value">{{ detailData.taxpayerIdentificationNumber || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å
¬å¸å°å</text> |
| | | <text class="info-value">{{ detailData.companyAddress || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å
¬å¸çµè¯</text> |
| | | <text class="info-value">{{ detailData.companyPhone || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">è系人</text> |
| | | <text class="info-value">{{ detailData.contactPerson || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">èç³»çµè¯</text> |
| | | <text class="info-value">{{ detailData.contactPhone || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- è·è¿è®°å½ --> |
| | | <view class="section"> |
| | | <view class="section-title"> |
| | | <view class="title-left"> |
| | | <up-icon name="clock-fill" |
| | | size="16" |
| | | color="#409eff" /> |
| | | <text>è·è¿è®°å½</text> |
| | | </view> |
| | | <text class="record-count" |
| | | v-if="detailData.followUpList && detailData.followUpList.length > 0"> |
| | | å
±{{ detailData.followUpList.length }}æ¡ |
| | | </text> |
| | | </view> |
| | | <view v-if="detailData.followUpList && detailData.followUpList.length > 0" |
| | | class="follow-up-list"> |
| | | <view v-for="(item, index) in detailData.followUpList" |
| | | :key="index" |
| | | class="follow-up-item"> |
| | | <!-- æ¶é´è½´å·¦ä¾§çº¿æ¡ --> |
| | | <view class="timeline-left"> |
| | | <view class="timeline-dot"></view> |
| | | <view class="timeline-line" |
| | | v-if="index !== detailData.followUpList.length - 1"></view> |
| | | </view> |
| | | <!-- å
容åºå --> |
| | | <view class="follow-up-content-wrapper"> |
| | | <view class="follow-up-header"> |
| | | <view class="follow-up-info"> |
| | | <view class="user-info"> |
| | | <up-icon name="account-fill" |
| | | size="14" |
| | | color="#909399" /> |
| | | <text class="follow-up-name">{{ item.followerUserName || '-' }}</text> |
| | | </view> |
| | | <view class="time-info"> |
| | | <up-icon name="clock" |
| | | size="12" |
| | | color="#c0c4cc" /> |
| | | <text class="follow-up-time">{{ formatDateTime(item.followUpTime) }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="follow-up-tags"> |
| | | <up-tag type="primary" |
| | | size="mini">{{ item.followUpMethod || '-' }}</up-tag> |
| | | <up-tag :type="getFollowUpLevelType(item.followUpLevel)" |
| | | size="mini">{{ item.followUpLevel || '-' }}</up-tag> |
| | | </view> |
| | | </view> |
| | | <view class="follow-up-content"> |
| | | <view class="content-label"> |
| | | <up-icon name="edit-pen-fill" |
| | | size="12" |
| | | color="#c0c4cc" /> |
| | | <text>è·è¿å
容</text> |
| | | </view> |
| | | <view class="content-box"> |
| | | <text class="content-text">{{ item.content || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- <view v-if="item.fileList && item.fileList.length > 0" |
| | | class="follow-up-files"> |
| | | <view class="files-header"> |
| | | <up-icon name="folder-open" |
| | | size="12" |
| | | color="#c0c4cc" /> |
| | | <text class="files-label">éä»¶ ({{ item.fileList.length }})</text> |
| | | </view> |
| | | <view class="files-list"> |
| | | <view v-for="(file, fileIndex) in item.fileList" |
| | | :key="fileIndex" |
| | | class="file-item"> |
| | | <up-icon name="attach" |
| | | size="14" |
| | | color="#409eff" /> |
| | | <text class="file-name">{{ file.name || 'éä»¶' + (fileIndex + 1) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ è·è¿è®°å½" /> |
| | | </view> |
| | | </view> |
| | | <!-- é¶è¡ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">é¶è¡ä¿¡æ¯</view> |
| | | <view class="info-list"> |
| | | <view class="info-item"> |
| | | <text class="info-label">åºæ¬é¶è¡è´¦æ·</text> |
| | | <text class="info-value">{{ detailData.basicBankAccount || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">弿·è¡</text> |
| | | <text class="info-value">{{ detailData.bankAccount || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">é¶è¡è´¦å·</text> |
| | | <text class="info-value">{{ detailData.bankCode || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç»´æ¤ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">ç»´æ¤ä¿¡æ¯</view> |
| | | <view class="info-list"> |
| | | <view class="info-item"> |
| | | <text class="info-label">ç»´æ¤äºº</text> |
| | | <text class="info-value">{{ detailData.maintainer || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">ç»´æ¤æ¶é´</text> |
| | | <text class="info-value">{{ formatDateTime(detailData.maintenanceTime) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getCustomer } from "@/api/cooperativeOffice/clientVisit"; |
| | | import { onLoad, onShow } from "@dcloudio/uni-app"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options || {}; |
| | | return options.id || ""; |
| | | }; |
| | | |
| | | // 详æ
æ°æ® |
| | | const detailData = ref({}); |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return "-"; |
| | | return dayjs(dateStr).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | // è·åè·è¿çº§å«æ ç¾ç±»å |
| | | const getFollowUpLevelType = level => { |
| | | switch (level) { |
| | | case "é常çæ": |
| | | return "success"; |
| | | case "çæ": |
| | | return "primary"; |
| | | case "ä¸è¬": |
| | | return "warning"; |
| | | case "ä¸çæ": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const customerId = ref(""); |
| | | // customerId |
| | | onLoad(options => { |
| | | // è§£æcustomerId |
| | | if (options.customerId) { |
| | | customerId.value = options.customerId; |
| | | getDetail(); |
| | | } |
| | | }); |
| | | |
| | | // è·å详æ
æ°æ® |
| | | const getDetail = async () => { |
| | | if (!customerId.value) { |
| | | uni.showToast({ |
| | | title: "åæ°é误", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | }); |
| | | |
| | | const res = await getCustomer(customerId.value); |
| | | |
| | | if (res.code === 200) { |
| | | detailData.value = res.data; |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg || "è·å详æ
失败", |
| | | icon: "none", |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("å 载详æ
æ°æ®å¤±è´¥:", error); |
| | | uni.showToast({ |
| | | title: "ç½ç»é误", |
| | | icon: "none", |
| | | }); |
| | | } finally { |
| | | uni.hideLoading(); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => {}); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .customer-detail-page { |
| | | min-height: 100vh; |
| | | background-color: #f5f5f5; |
| | | } |
| | | |
| | | .detail-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .section { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .section-title { |
| | | padding: 16px; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .info-list { |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | padding: 12px 16px; |
| | | border-bottom: 1px solid #f8f8f8; |
| | | } |
| | | |
| | | .info-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .info-label { |
| | | width: 120px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .info-value { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | text-align: right; |
| | | } |
| | | |
| | | .section-title { |
| | | padding: 16px; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .title-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .record-count { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | font-weight: normal; |
| | | background: #f5f7fa; |
| | | padding: 2px 8px; |
| | | border-radius: 10px; |
| | | } |
| | | |
| | | .follow-up-list { |
| | | padding: 0; |
| | | } |
| | | |
| | | .follow-up-item { |
| | | display: flex; |
| | | padding: 16px; |
| | | position: relative; |
| | | } |
| | | |
| | | .timeline-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | margin-right: 12px; |
| | | padding-top: 4px; |
| | | } |
| | | |
| | | .timeline-dot { |
| | | width: 10px; |
| | | height: 10px; |
| | | border-radius: 50%; |
| | | background: #409eff; |
| | | border: 2px solid #e6f2ff; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .timeline-line { |
| | | width: 2px; |
| | | flex: 1; |
| | | background: #e4e7ed; |
| | | margin-top: 4px; |
| | | min-height: 40px; |
| | | } |
| | | |
| | | .follow-up-content-wrapper { |
| | | flex: 1; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | padding: 12px; |
| | | } |
| | | |
| | | .follow-up-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .follow-up-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .user-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .time-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .follow-up-name { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .follow-up-time { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .follow-up-tags { |
| | | display: flex; |
| | | gap: 6px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .follow-up-content { |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .content-label { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .content-box { |
| | | background: #ffffff; |
| | | border-radius: 6px; |
| | | padding: 10px 12px; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .content-text { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | line-height: 1.6; |
| | | word-break: break-all; |
| | | word-wrap: break-word; |
| | | } |
| | | |
| | | .follow-up-files { |
| | | margin-top: 12px; |
| | | padding-top: 12px; |
| | | border-top: 1px dashed #e4e7ed; |
| | | } |
| | | |
| | | .files-header { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .files-label { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .files-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .file-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | padding: 6px 10px; |
| | | background: #ffffff; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .file-name { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 20px; |
| | | text-align: center; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="notice-page"> |
| | | <PageHeader title="éç¥å
Œ" |
| | | @back="goBack" /> |
| | | <!-- æç´¢è¡¨å --> |
| | | <!-- <view class="search_form"> |
| | | <up-button type="primary" size="small" @click="openForm('add')">æ°å¢å
Œ</up-button> |
| | | <up-button type="error" size="small" plain @click="handleDeleteBatch" :disabled="!selectedIds.length"> |
| | | å é¤ |
| | | </up-button> |
| | | </view> --> |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <view class="notice-board"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <view class="notice-section" |
| | | v-if="totalNoticeCount > 0"> |
| | | <view class="section-header"> |
| | | <h3>� éç¥å
Œ</h3> |
| | | <text class="section-count">{{ totalNoticeCount }}æ¡</text> |
| | | </view> |
| | | <view class="notice-cards"> |
| | | <!-- æ¾åéç¥ --> |
| | | <view v-for="notice in holidayNotices" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': notice.priority === '3' }"> |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="holiday-icon"> |
| | | <up-icon name="calendar" |
| | | size="18" |
| | | color="#67c23a" /> |
| | | </view> |
| | | <text>{{ notice.title }}</text> |
| | | </view> |
| | | <!-- <view class="card-actions">--> |
| | | <!-- <up-button--> |
| | | <!-- text--> |
| | | <!-- type="primary"--> |
| | | <!-- size="mini"--> |
| | | <!-- @click="handleEdit(notice)"--> |
| | | <!-- :disabled="isNoticeExpired(notice)"--> |
| | | <!-- >--> |
| | | <!-- ç¼è¾--> |
| | | <!-- </up-button>--> |
| | | <!-- <up-button--> |
| | | <!-- text--> |
| | | <!-- type="error"--> |
| | | <!-- size="mini"--> |
| | | <!-- @click="handleDelete(notice.id)"--> |
| | | <!-- >--> |
| | | <!-- å é¤--> |
| | | <!-- </up-button>--> |
| | | <!-- </view>--> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>{{ notice.content }}</text> |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="card-meta"> |
| | | <text class="type" |
| | | :class="'type-' + notice.type"> |
| | | {{ notice.type }} |
| | | </text> |
| | | <text class="priority" |
| | | :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" |
| | | :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </text> |
| | | </view> |
| | | <view class="card-info"> |
| | | <text class="creator">{{ notice.createUserName }}</text> |
| | | <text class="expiration" |
| | | v-if="notice.expirationDate">æªæ¢æ¥æï¼{{ notice.expirationDate }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-remark" |
| | | v-if="notice.remark"> |
| | | <up-icon name="info-circle" |
| | | size="16" |
| | | color="#409eff" /> |
| | | <text>{{ notice.remark }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 设å¤ç»´ä¿®éç¥ --> |
| | | <view v-for="notice in maintenanceNotices" |
| | | :key="'maintenance-' + notice.id" |
| | | class="notice-card maintenance-card" |
| | | :class="{ 'urgent': notice.priority === '3' }"> |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="maintenance-icon"> |
| | | <up-icon name="wrench" |
| | | size="18" |
| | | color="#e6a23c" /> |
| | | </view> |
| | | <text>{{ notice.title }}</text> |
| | | </view> |
| | | <view class="card-actions"> |
| | | <!-- <up-button text |
| | | type="primary" |
| | | size="mini" |
| | | @click="handleEdit(notice)" |
| | | :disabled="isNoticeExpired(notice)"> |
| | | ç¼è¾ |
| | | </up-button> |
| | | <up-button text |
| | | type="error" |
| | | size="mini" |
| | | @click="handleDelete(notice.id)"> |
| | | å é¤ |
| | | </up-button> --> |
| | | </view> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>{{ notice.content }}</text> |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="card-meta"> |
| | | <text class="priority" |
| | | :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" |
| | | :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </text> |
| | | </view> |
| | | <view class="card-info"> |
| | | <text class="creator">{{ notice.createUserName }}</text> |
| | | <text class="expiration" |
| | | v-if="notice.expirationDate">æªæ¢æ¥æï¼{{ notice.expirationDate }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-remark" |
| | | v-if="notice.remark"> |
| | | <up-icon name="info-circle" |
| | | size="16" |
| | | color="#409eff" /> |
| | | <text>{{ notice.remark }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view class="empty-state" |
| | | v-if="holidayNotices.length === 0 && maintenanceNotices.length === 0"> |
| | | <text>ææ éç¥å
Œ</text> |
| | | </view> |
| | | </view> |
| | | <!-- æ°å¢/ç¼è¾å¼¹çª --> |
| | | <up-popup v-model:show="dialogVisible" |
| | | mode="bottom" |
| | | :round="18" |
| | | :safeAreaInsetBottom="true" |
| | | @close="resetForm"> |
| | | <view class="dialog-container"> |
| | | <view class="dialog-header"> |
| | | <text class="dialog-title">{{ dialogTitle }}</text> |
| | | </view> |
| | | <view class="dialog-body"> |
| | | <up-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | labelWidth="80"> |
| | | <up-form-item label="å
¬åæ é¢" |
| | | prop="title"> |
| | | <up-input v-model="form.title" |
| | | placeholder="请è¾å
¥å
¬åæ é¢" /> |
| | | </up-form-item> |
| | | <up-form-item label="å
¬åç±»å" |
| | | prop="type"> |
| | | <up-input v-model="form.type" |
| | | placeholder="请è¾å
¥å
¬åç±»å" /> |
| | | </up-form-item> |
| | | <up-form-item label="ç¶æ"> |
| | | <up-radio-group v-model="form.status"> |
| | | <up-radio :name="0">è稿</up-radio> |
| | | <up-radio :name="1">æ£å¼åå¸</up-radio> |
| | | </up-radio-group> |
| | | </up-form-item> |
| | | <up-form-item label="ä¼å
级" |
| | | prop="priority"> |
| | | <up-select v-model="form.priority" |
| | | :options="priorityOptions" |
| | | placeholder="è¯·éæ©ä¼å
级" /> |
| | | </up-form-item> |
| | | <up-form-item label="è¿ææ¶é´" |
| | | prop="expirationDate"> |
| | | <up-datetime-picker v-model="form.expirationDate" |
| | | mode="date" |
| | | @confirm="onExpireConfirm"> |
| | | <up-input :value="form.expirationDate" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | readonly /> |
| | | </up-datetime-picker> |
| | | </up-form-item> |
| | | <up-form-item label="å
¬åå
容" |
| | | prop="content"> |
| | | <up-textarea v-model="form.content" |
| | | placeholder="请è¾å
¥å
¬åå
容" |
| | | :maxlength="500" |
| | | count /> |
| | | </up-form-item> |
| | | <up-form-item label="夿³¨"> |
| | | <up-textarea v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | :maxlength="200" |
| | | count /> |
| | | </up-form-item> |
| | | </up-form> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <up-button text="åæ¶" |
| | | type="info" |
| | | plain |
| | | @click="dialogVisible = false" |
| | | :customStyle="{ marginRight: '10px', flex: 1 }" /> |
| | | <up-button text="ç¡®å®" |
| | | type="primary" |
| | | @click="submitForm" |
| | | :customStyle="{ flex: 1 }" /> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onReachBottom } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | addNotice, |
| | | delNotice, |
| | | getCount, |
| | | listNotice, |
| | | updateNotice, |
| | | } from "@/api/collaborativeApproval/noticeManagement.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: undefined, |
| | | status: undefined, |
| | | }, |
| | | form: { |
| | | id: undefined, |
| | | title: "", |
| | | type: null, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }, |
| | | rules: { |
| | | title: [{ required: true, message: "å
¬åæ é¢ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©å
¬åç±»å", trigger: "change" }], |
| | | content: [{ required: true, message: "å
¬åå
容ä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | expirationDate: [ |
| | | { required: true, message: "è¯·éæ©æ¥æ", trigger: "change" }, |
| | | ], |
| | | }, |
| | | }); |
| | | |
| | | const { searchForm, form, rules } = toRefs(data); |
| | | |
| | | // 页é¢ç¶æ |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const selectedIds = ref([]); |
| | | const formRef = ref(); |
| | | |
| | | const priorityOptions = [ |
| | | { label: "æ®é", value: 1 }, |
| | | { label: "éè¦", value: 2 }, |
| | | { label: "ç´§æ¥", value: 3 }, |
| | | ]; |
| | | |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const onExpireConfirm = e => { |
| | | if (!e) return; |
| | | // uview-plus datetime-picker confirm äºä»¶è¿åç value |
| | | const value = e.value || e; |
| | | form.value.expirationDate = value; |
| | | }; |
| | | |
| | | const getPriorityText = priority => { |
| | | const priorityMap = { 1: "æ®é", 2: "éè¦", 3: "ç´§æ¥" }; |
| | | return priorityMap[priority] || "æ®é"; |
| | | }; |
| | | |
| | | const getStatusText = status => { |
| | | const statusMap = { 0: "è稿", 1: "å·²åå¸", 2: "å·²è¿æ" }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | const isNoticeExpired = notice => { |
| | | if (!notice || !notice.expirationDate) { |
| | | return false; |
| | | } |
| | | |
| | | const expiration = new Date(notice.expirationDate); |
| | | |
| | | if (Number.isNaN(expiration.getTime())) { |
| | | return false; |
| | | } |
| | | |
| | | expiration.setHours(23, 59, 59, 999); |
| | | |
| | | return new Date() > expiration; |
| | | }; |
| | | |
| | | const getNoticeStatus = notice => { |
| | | const normalizedStatus = |
| | | notice && notice.status !== undefined && notice.status !== null |
| | | ? String(notice.status) |
| | | : "0"; |
| | | |
| | | return isNoticeExpired(notice) ? "2" : normalizedStatus; |
| | | }; |
| | | |
| | | const openForm = type => { |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ°å¢å
Œ"; |
| | | form.value = { |
| | | id: undefined, |
| | | title: "", |
| | | type: undefined, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }; |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = row => { |
| | | if (isNoticeExpired(row)) { |
| | | uni.showToast({ |
| | | title: "å·²è¿æçå
¬åä¸å¯ç¼è¾", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | dialogTitle.value = "ç¼è¾å
Œ"; |
| | | form.value = { ...row }; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = id => { |
| | | if (!id) return; |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "确认å é¤è¿æ¡å
¬ååï¼", |
| | | success: res => { |
| | | if (res.confirm) { |
| | | delNotice(id).then(() => { |
| | | uni.showToast({ |
| | | title: "å 餿å", |
| | | icon: "success", |
| | | }); |
| | | resetTable(); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // é¢çæ¹éå é¤ï¼ç®åæªå®ç°éä¸é»è¾ï¼ä»
å ä½ï¼ |
| | | const handleDeleteBatch = () => { |
| | | if (!selectedIds.value.length) return; |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "确认å é¤éä¸çå
¬ååï¼", |
| | | success: res => { |
| | | if (res.confirm) { |
| | | // æ ¹æ®selectedIdsæ§è¡æ¹éå é¤é»è¾ï¼å¯æéæ©å±ï¼ |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | if (form.value.id) { |
| | | // ç¼è¾æ¨¡å¼ |
| | | updateNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "ä¿®æ¹æå", |
| | | icon: "success", |
| | | }); |
| | | resetTable(); |
| | | }); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "æ°å¢æå", |
| | | icon: "success", |
| | | }); |
| | | resetTable(); |
| | | }); |
| | | } |
| | | dialogVisible.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const totalNoticeCount = ref(0); |
| | | const fetchCount = () => { |
| | | getCount().then(res => { |
| | | totalNoticeCount.value = res.data.reduce( |
| | | (total, item) => total + item.count, |
| | | 0 |
| | | ); |
| | | }); |
| | | }; |
| | | |
| | | const holidayNotices = ref([]); |
| | | const maintenanceNotices = ref([]); |
| | | const holidayNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 9, |
| | | }); |
| | | |
| | | const maintenanceNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 9, |
| | | }); |
| | | |
| | | const isLoadingMore = ref(false); |
| | | |
| | | const fetchHolidayNotices = (append = false) => { |
| | | listNotice({ ...holidayNoticePage.value }).then(res => { |
| | | const records = res?.data?.records || []; |
| | | holidayNoticePage.value.total = res?.data?.total || 0; |
| | | if (append && holidayNotices.value.length) { |
| | | holidayNotices.value = [...holidayNotices.value, ...records]; |
| | | } else { |
| | | holidayNotices.value = records; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const fetchMaintenanceNotices = (append = false) => { |
| | | listNotice({ ...holidayNoticePage.value, type: 2 }).then(res => { |
| | | const records = res?.data?.records || []; |
| | | maintenanceNoticePage.value.total = res?.data?.total || 0; |
| | | if (append && maintenanceNotices.value.length) { |
| | | maintenanceNotices.value = [...maintenanceNotices.value, ...records]; |
| | | } else { |
| | | maintenanceNotices.value = records; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleCurrentChange = val => { |
| | | holidayNoticePage.value.size = val.limit; |
| | | holidayNoticePage.value.current = val.page; |
| | | maintenanceNoticePage.value.size = val.limit; |
| | | maintenanceNoticePage.value.current = val.page; |
| | | fetchHolidayNotices(); |
| | | fetchMaintenanceNotices(); |
| | | }; |
| | | |
| | | const resetTable = () => { |
| | | holidayNoticePage.value.current = 1; |
| | | holidayNoticePage.value.size = 9; |
| | | maintenanceNoticePage.value.current = 1; |
| | | maintenanceNoticePage.value.size = 9; |
| | | fetchHolidayNotices(); |
| | | fetchMaintenanceNotices(); |
| | | fetchCount(); |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | fetchCount(); |
| | | fetchHolidayNotices(); |
| | | fetchMaintenanceNotices(); |
| | | }); |
| | | |
| | | // ä¸åå è½½æ´å¤ |
| | | onReachBottom(() => { |
| | | if (isLoadingMore.value) return; |
| | | isLoadingMore.value = true; |
| | | |
| | | holidayNoticePage.value.current += 1; |
| | | maintenanceNoticePage.value.current += 1; |
| | | |
| | | Promise.all([ |
| | | new Promise(resolve => { |
| | | fetchHolidayNotices(true); |
| | | resolve(); |
| | | }), |
| | | new Promise(resolve => { |
| | | fetchMaintenanceNotices(true); |
| | | resolve(); |
| | | }), |
| | | ]).finally(() => { |
| | | isLoadingMore.value = false; |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .notice-page { |
| | | min-height: 100vh; |
| | | background: #f5f7fa; |
| | | padding-bottom: 16px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .search_form { |
| | | background: #ffffff; |
| | | padding: 12px 16px; |
| | | margin: 8px 12px 12px; |
| | | border-radius: 10px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04); |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | } |
| | | |
| | | .search_title { |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .notice-board { |
| | | padding: 0 12px 16px; |
| | | } |
| | | |
| | | .notice-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 4px 4px 12px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .section-count { |
| | | margin-left: 10px; |
| | | background: #409eff; |
| | | color: white; |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .notice-cards { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .notice-card { |
| | | background: white; |
| | | border-radius: 12px; |
| | | padding: 14px 14px 10px; |
| | | box-shadow: 0 4px 10px rgba(15, 23, 42, 0.06); |
| | | transition: all 0.3s ease; |
| | | border-left: 4px solid transparent; |
| | | } |
| | | |
| | | .notice-card:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .holiday-card { |
| | | border-left-color: #67c23a; |
| | | } |
| | | |
| | | .maintenance-card { |
| | | border-left-color: #e6a23c; |
| | | } |
| | | |
| | | .urgent { |
| | | border-left-color: #f56c6c; |
| | | background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-title { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | flex: 1; |
| | | } |
| | | |
| | | .holiday-icon { |
| | | color: #67c23a; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .maintenance-icon { |
| | | color: #e6a23c; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .card-content { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-content text { |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-meta { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .type, |
| | | .priority, |
| | | .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .type-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .priority-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-3 { |
| | | background: #fef2f2; |
| | | color: #dc2626; |
| | | } |
| | | |
| | | .status-0 { |
| | | background: #f3f4f6; |
| | | color: #6b7280; |
| | | } |
| | | |
| | | .status-1 { |
| | | background: #d1fae5; |
| | | color: #059669; |
| | | } |
| | | |
| | | .status-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .card-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .creator { |
| | | font-weight: 500; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .expiration { |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .card-remark { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .empty-state { |
| | | text-align: center; |
| | | padding: 48px 16px; |
| | | color: #999; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | /* ç§»å¨ç«¯å¼¹çªæ ·å¼ */ |
| | | .dialog-container { |
| | | background: #ffffff; |
| | | border-radius: 18px 18px 0 0; |
| | | max-height: 80vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .dialog-header { |
| | | padding: 16px 20px 8px 20px; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-body { |
| | | flex: 1; |
| | | padding: 0 16px 12px 16px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | padding: 12px 16px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .search_form > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="inspection-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="设å¤å·¡æ£è¯¦æ
" @back="goBack" /> |
| | | |
| | | <PageHeader title="设å¤å·¡æ£è¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- 设å¤ä¿¡æ¯å¡ç --> |
| | | <view class="device-card"> |
| | | <view class="device-header"> |
| | | <view class="device-icon"> |
| | | <up-icon name="settings" size="24" color="#1890ff"></up-icon> |
| | | <up-icon name="settings" |
| | | size="24" |
| | | color="#1890ff"></up-icon> |
| | | </view> |
| | | <view class="device-info"> |
| | | <text class="device-name">{{ deviceInfo.deviceName }}</text> |
| | | <text class="device-code">{{ deviceInfo.deviceCode }}</text> |
| | | </view> |
| | | <view class="qr-scan" @click="scanDeviceQR"> |
| | | <up-icon name="scan" size="20" color="#1890ff"></up-icon> |
| | | <view class="qr-scan" |
| | | @click="scanDeviceQR"> |
| | | <up-icon name="scan" |
| | | size="20" |
| | | color="#1890ff"></up-icon> |
| | | <text class="scan-text">æ«ç </text> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å·¡æ£é¡¹ç®æ¸
å --> |
| | | <view class="inspection-items"> |
| | | <view class="section-title"> |
| | | <up-icon name="list" size="18" color="#333"></up-icon> |
| | | <up-icon name="list" |
| | | size="18" |
| | | color="#333"></up-icon> |
| | | <text class="title-text">å·¡æ£é¡¹ç®æ¸
å</text> |
| | | <text class="progress-text">({{ completedItems }}/{{ totalItems }})</text> |
| | | </view> |
| | | |
| | | <view class="items-list"> |
| | | <view |
| | | v-for="(item, index) in inspectionItems" |
| | | :key="index" |
| | | class="inspection-item" |
| | | :class="{ 'completed': item.completed, 'abnormal': item.isAbnormal }" |
| | | > |
| | | <view class="item-header" @click="toggleItem(index)"> |
| | | <view v-for="(item, index) in inspectionItems" |
| | | :key="index" |
| | | class="inspection-item" |
| | | :class="{ 'completed': item.completed, 'abnormal': item.isAbnormal }"> |
| | | <view class="item-header" |
| | | @click="toggleItem(index)"> |
| | | <view class="item-left"> |
| | | <view class="checkbox" :class="{ 'checked': item.completed }"> |
| | | <up-icon v-if="item.completed" name="checkmark" size="14" color="#ffffff"></up-icon> |
| | | <view class="checkbox" |
| | | :class="{ 'checked': item.completed }"> |
| | | <up-icon v-if="item.completed" |
| | | name="checkmark" |
| | | size="14" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-name">{{ item.name }}</text> |
| | | </view> |
| | | <view class="item-status"> |
| | | <u-tag v-if="item.isAbnormal" type="error" size="mini">å¼å¸¸</u-tag> |
| | | <u-tag v-else-if="item.completed" type="success" size="mini">æ£å¸¸</u-tag> |
| | | <u-tag v-else type="info" size="mini">å¾
æ£</u-tag> |
| | | <u-tag v-if="item.isAbnormal" |
| | | type="error" |
| | | size="mini">å¼å¸¸</u-tag> |
| | | <u-tag v-else-if="item.completed" |
| | | type="success" |
| | | size="mini">æ£å¸¸</u-tag> |
| | | <u-tag v-else |
| | | type="info" |
| | | size="mini">å¾
æ£</u-tag> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å±å¼ç详æ
å
容 --> |
| | | <view v-if="item.expanded" class="item-content"> |
| | | <view v-if="item.expanded" |
| | | class="item-content"> |
| | | <view class="item-description"> |
| | | <text class="desc-text">{{ item.description }}</text> |
| | | </view> |
| | | |
| | | <!-- å·¡æ£ç»æéæ© --> |
| | | <view class="result-section"> |
| | | <text class="section-label">å·¡æ£ç»æï¼</text> |
| | | <view class="result-options"> |
| | | <u-radio-group v-model="item.result" @change="onResultChange(index, $event)"> |
| | | <u-radio |
| | | v-for="option in resultOptions" |
| | | :key="option.value" |
| | | :label="option.value" |
| | | :name="option.label" |
| | | size="small" |
| | | > |
| | | <u-radio-group v-model="item.result" |
| | | @change="onResultChange(index, $event)"> |
| | | <u-radio v-for="option in resultOptions" |
| | | :key="option.value" |
| | | :label="option.value" |
| | | :name="option.label" |
| | | size="small"> |
| | | {{ option.label }} |
| | | </u-radio> |
| | | </u-radio-group> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å¼å¸¸æ
åµæè¿° --> |
| | | <view v-if="item.result === 'abnormal'" class="abnormal-section"> |
| | | <view v-if="item.result === 'abnormal'" |
| | | class="abnormal-section"> |
| | | <text class="section-label">å¼å¸¸æè¿°ï¼</text> |
| | | <up-textarea |
| | | v-model="item.abnormalDesc" |
| | | placeholder="è¯·è¯¦ç»æè¿°å¼å¸¸æ
åµ" |
| | | :maxlength="200" |
| | | count |
| | | height="80" |
| | | ></up-textarea> |
| | | <up-textarea v-model="item.abnormalDesc" |
| | | placeholder="è¯·è¯¦ç»æè¿°å¼å¸¸æ
åµ" |
| | | :maxlength="200" |
| | | count |
| | | height="80"></up-textarea> |
| | | </view> |
| | | |
| | | <!-- å¾çä¸ä¼ --> |
| | | <view class="upload-section"> |
| | | <text class="section-label">ç°åºç
§çï¼</text> |
| | | <up-upload |
| | | :fileList="item.images" |
| | | @afterRead="(event) => afterRead(event, index, 'images')" |
| | | @delete="(event) => deleteFile(event, index, 'images')" |
| | | name="images" |
| | | multiple |
| | | :maxCount="5" |
| | | :previewImage="true" |
| | | > |
| | | <up-upload :fileList="item.images" |
| | | @afterRead="(event) => afterRead(event, index, 'images')" |
| | | @delete="(event) => deleteFile(event, index, 'images')" |
| | | name="images" |
| | | multiple |
| | | :maxCount="5" |
| | | :previewImage="true"> |
| | | <view class="upload-btn"> |
| | | <up-icon name="camera" size="20" color="#999"></up-icon> |
| | | <up-icon name="camera" |
| | | size="20" |
| | | color="#999"></up-icon> |
| | | <text class="upload-text">æ·»å ç
§ç</text> |
| | | </view> |
| | | </up-upload> |
| | | </view> |
| | | |
| | | <!-- è§é¢ä¸ä¼ --> |
| | | <view class="upload-section"> |
| | | <text class="section-label">ç°åºè§é¢ï¼</text> |
| | | <up-upload |
| | | :fileList="item.videos" |
| | | @afterRead="(event) => afterRead(event, index, 'videos')" |
| | | @delete="(event) => deleteFile(event, index, 'videos')" |
| | | name="videos" |
| | | :maxCount="2" |
| | | accept="video" |
| | | > |
| | | <up-upload :fileList="item.videos" |
| | | @afterRead="(event) => afterRead(event, index, 'videos')" |
| | | @delete="(event) => deleteFile(event, index, 'videos')" |
| | | name="videos" |
| | | :maxCount="2" |
| | | accept="video"> |
| | | <view class="upload-btn"> |
| | | <up-icon name="play-circle" size="20" color="#999"></up-icon> |
| | | <up-icon name="play-circle" |
| | | size="20" |
| | | color="#999"></up-icon> |
| | | <text class="upload-text">æ·»å è§é¢</text> |
| | | </view> |
| | | </up-upload> |
| | | </view> |
| | | |
| | | <!-- 夿³¨ --> |
| | | <view class="remark-section"> |
| | | <text class="section-label">夿³¨ï¼</text> |
| | | <up-textarea |
| | | v-model="item.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯ï¼å¯éï¼" |
| | | :maxlength="100" |
| | | count |
| | | height="60" |
| | | ></up-textarea> |
| | | <up-textarea v-model="item.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯ï¼å¯éï¼" |
| | | :maxlength="100" |
| | | count |
| | | height="60"></up-textarea> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- åºé¨æä½æé® --> |
| | | <view class="bottom-actions"> |
| | | <u-button |
| | | type="primary" |
| | | size="large" |
| | | :disabled="!canSubmit" |
| | | @click="submitInspection" |
| | | :loading="submitting" |
| | | > |
| | | <u-button type="primary" |
| | | size="large" |
| | | :disabled="!canSubmit" |
| | | @click="submitInspection" |
| | | :loading="submitting"> |
| | | {{ allCompleted ? 'æäº¤å·¡æ£è®°å½' : `ç»§ç»å·¡æ£ (${completedItems}/${totalItems})` }} |
| | | </u-button> |
| | | </view> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { submitInspectionRecord } from '@/api/equipmentManagement/inspection' |
| | | import dayjs from 'dayjs' |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { submitInspectionRecord } from "@/api/equipmentManagement/inspection"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 设å¤ä¿¡æ¯ |
| | | const deviceInfo = ref({}) |
| | | // 设å¤ä¿¡æ¯ |
| | | const deviceInfo = ref({}); |
| | | |
| | | // å·¡æ£é¡¹ç®å表 |
| | | const inspectionItems = ref([]) |
| | | // å·¡æ£é¡¹ç®å表 |
| | | const inspectionItems = ref([]); |
| | | |
| | | // æäº¤ç¶æ |
| | | const submitting = ref(false) |
| | | // æäº¤ç¶æ |
| | | const submitting = ref(false); |
| | | |
| | | // å·¡æ£ç»æé项 |
| | | const resultOptions = [ |
| | | { label: 'æ£å¸¸', value: 'normal' }, |
| | | { label: 'å¼å¸¸', value: 'abnormal' } |
| | | ] |
| | | // å·¡æ£ç»æé项 |
| | | const resultOptions = [ |
| | | { label: "æ£å¸¸", value: "normal" }, |
| | | { label: "å¼å¸¸", value: "abnormal" }, |
| | | ]; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 计ç®å±æ§ |
| | | const totalItems = computed(() => inspectionItems.value.length) |
| | | const completedItems = computed(() => inspectionItems.value.filter(item => item.completed).length) |
| | | const allCompleted = computed(() => completedItems.value === totalItems.value && totalItems.value > 0) |
| | | const canSubmit = computed(() => completedItems.value > 0) |
| | | // 计ç®å±æ§ |
| | | const totalItems = computed(() => inspectionItems.value.length); |
| | | const completedItems = computed( |
| | | () => inspectionItems.value.filter(item => item.completed).length |
| | | ); |
| | | const allCompleted = computed( |
| | | () => completedItems.value === totalItems.value && totalItems.value > 0 |
| | | ); |
| | | const canSubmit = computed(() => completedItems.value > 0); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | if (completedItems.value > 0) { |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: 'å½åææªä¿åçå·¡æ£è®°å½ï¼ç¡®å®è¦ç¦»å¼åï¼', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | uni.navigateBack() |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | if (completedItems.value > 0) { |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "å½åææªä¿åçå·¡æ£è®°å½ï¼ç¡®å®è¦ç¦»å¼åï¼", |
| | | success: res => { |
| | | if (res.confirm) { |
| | | uni.navigateBack(); |
| | | } |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.navigateBack(); |
| | | } |
| | | }; |
| | | |
| | | // æ«æè®¾å¤äºç»´ç |
| | | const scanDeviceQR = () => { |
| | | uni.scanCode({ |
| | | success: res => { |
| | | console.log("æ«ç ç»æï¼", res); |
| | | if (res.result.includes(deviceInfo.value.deviceCode)) { |
| | | showToast("设å¤ç¡®è®¤æå"); |
| | | // è®°å½æ«ç æ¶é´ |
| | | deviceInfo.value.scanTime = new Date().toISOString(); |
| | | } else { |
| | | showToast("设å¤äºç»´ç ä¸å¹é
"); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | console.log("æ«ç 失败ï¼", err); |
| | | showToast("æ«ç 失败"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 忢巡æ£é¡¹ç® |
| | | const toggleItem = index => { |
| | | inspectionItems.value[index].expanded = |
| | | !inspectionItems.value[index].expanded; |
| | | }; |
| | | |
| | | // å·¡æ£ç»ææ¹å |
| | | const onResultChange = (index, value) => { |
| | | const item = inspectionItems.value[index]; |
| | | item.result = value; |
| | | item.completed = true; |
| | | item.isAbnormal = value === "abnormal"; |
| | | |
| | | // 妿鿩æ£å¸¸ï¼æ¸
空å¼å¸¸æè¿° |
| | | if (value === "normal") { |
| | | item.abnormalDesc = ""; |
| | | } |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ åå¤ç |
| | | const afterRead = async (event, index, type) => { |
| | | const { file } = event; |
| | | const item = inspectionItems.value[index]; |
| | | |
| | | // 模æä¸ä¼ è¿ç¨ |
| | | uni.showLoading({ title: "ä¸ä¼ ä¸..." }); |
| | | |
| | | try { |
| | | // è¿éåºè¯¥è°ç¨å®é
çä¸ä¼ API |
| | | await new Promise(resolve => setTimeout(resolve, 1000)); |
| | | |
| | | // æ·»å å°å¯¹åºçæä»¶å表 |
| | | if (type === "images") { |
| | | item.images = item.images || []; |
| | | item.images.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size, |
| | | }); |
| | | } else if (type === "videos") { |
| | | item.videos = item.videos || []; |
| | | item.videos.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size, |
| | | }); |
| | | } |
| | | }) |
| | | } else { |
| | | uni.navigateBack() |
| | | } |
| | | } |
| | | |
| | | // æ«æè®¾å¤äºç»´ç |
| | | const scanDeviceQR = () => { |
| | | uni.scanCode({ |
| | | success: (res) => { |
| | | console.log('æ«ç ç»æï¼', res) |
| | | if (res.result.includes(deviceInfo.value.deviceCode)) { |
| | | showToast('设å¤ç¡®è®¤æå') |
| | | // è®°å½æ«ç æ¶é´ |
| | | deviceInfo.value.scanTime = new Date().toISOString() |
| | | } else { |
| | | showToast('设å¤äºç»´ç ä¸å¹é
') |
| | | uni.hideLoading(); |
| | | showToast("ä¸ä¼ æå"); |
| | | } catch (error) { |
| | | uni.hideLoading(); |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (event, index, type) => { |
| | | const item = inspectionItems.value[index]; |
| | | if (type === "images") { |
| | | item.images.splice(event.index, 1); |
| | | } else if (type === "videos") { |
| | | item.videos.splice(event.index, 1); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤å·¡æ£è®°å½ |
| | | const submitInspection = async () => { |
| | | if (!canSubmit.value) { |
| | | showToast("请è³å°å®æä¸é¡¹å·¡æ£"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥å¼å¸¸é¡¹ç®æ¯å¦å¡«åäºæè¿° |
| | | const abnormalItems = inspectionItems.value.filter(item => item.isAbnormal); |
| | | for (const item of abnormalItems) { |
| | | if (!item.abnormalDesc || item.abnormalDesc.trim() === "") { |
| | | showToast(`请填å"${item.name}"çå¼å¸¸æè¿°`); |
| | | return; |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.log('æ«ç 失败ï¼', err) |
| | | showToast('æ«ç 失败') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // 忢巡æ£é¡¹ç® |
| | | const toggleItem = (index) => { |
| | | inspectionItems.value[index].expanded = !inspectionItems.value[index].expanded |
| | | } |
| | | submitting.value = true; |
| | | |
| | | // å·¡æ£ç»ææ¹å |
| | | const onResultChange = (index, value) => { |
| | | const item = inspectionItems.value[index] |
| | | item.result = value |
| | | item.completed = true |
| | | item.isAbnormal = value === 'abnormal' |
| | | |
| | | // 妿鿩æ£å¸¸ï¼æ¸
空å¼å¸¸æè¿° |
| | | if (value === 'normal') { |
| | | item.abnormalDesc = '' |
| | | } |
| | | } |
| | | try { |
| | | const recordData = { |
| | | deviceId: deviceInfo.value.id, |
| | | deviceCode: deviceInfo.value.deviceCode, |
| | | inspectionDate: dayjs().format("YYYY-MM-DD"), |
| | | inspector: deviceInfo.value.inspector, |
| | | scanTime: deviceInfo.value.scanTime, |
| | | items: inspectionItems.value.map(item => ({ |
| | | name: item.name, |
| | | result: item.result, |
| | | completed: item.completed, |
| | | isAbnormal: item.isAbnormal, |
| | | abnormalDesc: item.abnormalDesc, |
| | | images: item.images || [], |
| | | videos: item.videos || [], |
| | | remark: item.remark, |
| | | })), |
| | | completedAt: new Date().toISOString(), |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ åå¤ç |
| | | const afterRead = async (event, index, type) => { |
| | | const { file } = event |
| | | const item = inspectionItems.value[index] |
| | | |
| | | // 模æä¸ä¼ è¿ç¨ |
| | | uni.showLoading({ title: 'ä¸ä¼ ä¸...' }) |
| | | |
| | | try { |
| | | // è¿éåºè¯¥è°ç¨å®é
çä¸ä¼ API |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | |
| | | // æ·»å å°å¯¹åºçæä»¶å表 |
| | | if (type === 'images') { |
| | | item.images = item.images || [] |
| | | item.images.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size |
| | | }) |
| | | } else if (type === 'videos') { |
| | | item.videos = item.videos || [] |
| | | item.videos.push({ |
| | | url: file.url, |
| | | name: file.name, |
| | | size: file.size |
| | | }) |
| | | // 模æAPIè°ç¨ |
| | | await new Promise(resolve => setTimeout(resolve, 2000)); |
| | | |
| | | // å®é
APIè°ç¨ |
| | | // await submitInspectionRecord(recordData) |
| | | |
| | | showToast("å·¡æ£è®°å½æäº¤æå"); |
| | | |
| | | // è¿ååè¡¨é¡µé¢ |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } catch (error) { |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } finally { |
| | | submitting.value = false; |
| | | } |
| | | |
| | | uni.hideLoading() |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (error) { |
| | | uni.hideLoading() |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (event, index, type) => { |
| | | const item = inspectionItems.value[index] |
| | | if (type === 'images') { |
| | | item.images.splice(event.index, 1) |
| | | } else if (type === 'videos') { |
| | | item.videos.splice(event.index, 1) |
| | | } |
| | | } |
| | | |
| | | // æäº¤å·¡æ£è®°å½ |
| | | const submitInspection = async () => { |
| | | if (!canSubmit.value) { |
| | | showToast('请è³å°å®æä¸é¡¹å·¡æ£') |
| | | return |
| | | } |
| | | |
| | | // æ£æ¥å¼å¸¸é¡¹ç®æ¯å¦å¡«åäºæè¿° |
| | | const abnormalItems = inspectionItems.value.filter(item => item.isAbnormal) |
| | | for (const item of abnormalItems) { |
| | | if (!item.abnormalDesc || item.abnormalDesc.trim() === '') { |
| | | showToast(`请填å"${item.name}"çå¼å¸¸æè¿°`) |
| | | return |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | // ä»åå¨ä¸è·åå½åå·¡æ£ä¿¡æ¯ |
| | | const currentInspection = uni.getStorageSync("currentInspection"); |
| | | if (currentInspection) { |
| | | deviceInfo.value = currentInspection; |
| | | } |
| | | } |
| | | |
| | | submitting.value = true |
| | | |
| | | try { |
| | | const recordData = { |
| | | deviceId: deviceInfo.value.id, |
| | | deviceCode: deviceInfo.value.deviceCode, |
| | | inspectionDate: dayjs().format('YYYY-MM-DD'), |
| | | inspector: deviceInfo.value.inspector, |
| | | scanTime: deviceInfo.value.scanTime, |
| | | items: inspectionItems.value.map(item => ({ |
| | | name: item.name, |
| | | result: item.result, |
| | | completed: item.completed, |
| | | isAbnormal: item.isAbnormal, |
| | | abnormalDesc: item.abnormalDesc, |
| | | images: item.images || [], |
| | | videos: item.videos || [], |
| | | remark: item.remark |
| | | })), |
| | | completedAt: new Date().toISOString() |
| | | } |
| | | |
| | | // 模æAPIè°ç¨ |
| | | await new Promise(resolve => setTimeout(resolve, 2000)) |
| | | |
| | | // å®é
APIè°ç¨ |
| | | // await submitInspectionRecord(recordData) |
| | | |
| | | showToast('å·¡æ£è®°å½æäº¤æå') |
| | | |
| | | // è¿ååè¡¨é¡µé¢ |
| | | setTimeout(() => { |
| | | uni.navigateBack() |
| | | }, 1500) |
| | | |
| | | } catch (error) { |
| | | showToast('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | // ä»åå¨ä¸è·åå½åå·¡æ£ä¿¡æ¯ |
| | | const currentInspection = uni.getStorageSync('currentInspection') |
| | | if (currentInspection) { |
| | | deviceInfo.value = currentInspection |
| | | } |
| | | |
| | | // 模æå·¡æ£é¡¹ç®æ°æ® |
| | | inspectionItems.value = [ |
| | | { |
| | | name: '设å¤å¤è§æ£æ¥', |
| | | description: 'æ£æ¥è®¾å¤å¤è§æ¯å¦ææåãéèãåå½¢çå¼å¸¸æ
åµ', |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | }, |
| | | { |
| | | name: 'è¿è¡ç¶ææ£æ¥', |
| | | description: 'æ£æ¥è®¾å¤è¿è¡æ¯å¦æ£å¸¸ï¼ææ å¼å¸¸å£°é³ãæ¯å¨ç', |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | }, |
| | | { |
| | | name: 'å®å
¨è£
ç½®æ£æ¥', |
| | | description: 'æ£æ¥åç±»å®å
¨è£
ç½®æ¯å¦å®å¥½ï¼å®å
¨æ è¯æ¯å¦æ¸
æ°', |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | }, |
| | | { |
| | | name: 'ç¯å¢æ¡ä»¶æ£æ¥', |
| | | description: 'æ£æ¥è®¾å¤å¨å´ç¯å¢æ¯å¦ç¬¦åè¦æ±ï¼éé£ãç
§æçæ¯å¦æ£å¸¸', |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | }, |
| | | { |
| | | name: '仪表读æ°è®°å½', |
| | | description: 'è®°å½ç¸å
³ä»ªè¡¨ç读æ°ï¼æ£æ¥æ¯å¦å¨æ£å¸¸èå´å
', |
| | | completed: false, |
| | | expanded: false, |
| | | result: '', |
| | | isAbnormal: false, |
| | | abnormalDesc: '', |
| | | images: [], |
| | | videos: [], |
| | | remark: '' |
| | | } |
| | | ] |
| | | } |
| | | // 模æå·¡æ£é¡¹ç®æ°æ® |
| | | inspectionItems.value = [ |
| | | { |
| | | name: "设å¤å¤è§æ£æ¥", |
| | | description: "æ£æ¥è®¾å¤å¤è§æ¯å¦ææåãéèãåå½¢çå¼å¸¸æ
åµ", |
| | | completed: false, |
| | | expanded: false, |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: "è¿è¡ç¶ææ£æ¥", |
| | | description: "æ£æ¥è®¾å¤è¿è¡æ¯å¦æ£å¸¸ï¼ææ å¼å¸¸å£°é³ãæ¯å¨ç", |
| | | completed: false, |
| | | expanded: false, |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: "å®å
¨è£
ç½®æ£æ¥", |
| | | description: "æ£æ¥åç±»å®å
¨è£
ç½®æ¯å¦å®å¥½ï¼å®å
¨æ è¯æ¯å¦æ¸
æ°", |
| | | completed: false, |
| | | expanded: false, |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: "ç¯å¢æ¡ä»¶æ£æ¥", |
| | | description: "æ£æ¥è®¾å¤å¨å´ç¯å¢æ¯å¦ç¬¦åè¦æ±ï¼éé£ãç
§æçæ¯å¦æ£å¸¸", |
| | | completed: false, |
| | | expanded: false, |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: "", |
| | | }, |
| | | { |
| | | name: "仪表读æ°è®°å½", |
| | | description: "è®°å½ç¸å
³ä»ªè¡¨ç读æ°ï¼æ£æ¥æ¯å¦å¨æ£å¸¸èå´å
", |
| | | completed: false, |
| | | expanded: false, |
| | | result: "", |
| | | isAbnormal: false, |
| | | abnormalDesc: "", |
| | | images: [], |
| | | videos: [], |
| | | remark: "", |
| | | }, |
| | | ]; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initData() |
| | | }) |
| | | onMounted(() => { |
| | | initData(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°æ°æ® |
| | | }) |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°æ°æ® |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .inspection-detail { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | min-height: 100vh; |
| | | padding-bottom: 80px; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | height: 200px; |
| | | background: linear-gradient(135deg, rgba(102, 126, 234, 0.8) 0%, rgba(118, 75, 162, 0.8) 100%); |
| | | z-index: 0; |
| | | .inspection-detail { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | min-height: 100vh; |
| | | padding-bottom: 80px; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | height: 200px; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(102, 126, 234, 0.8) 0%, |
| | | rgba(118, 75, 162, 0.8) 100% |
| | | ); |
| | | z-index: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .device-card { |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | margin: 10px 20px; |
| | | border-radius: 20px; |
| | | padding: 24px; |
| | | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | position: relative; |
| | | z-index: 1; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); |
| | | } |
| | | } |
| | | .device-card { |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | margin: 10px 20px; |
| | | border-radius: 20px; |
| | | padding: 24px; |
| | | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | position: relative; |
| | | z-index: 1; |
| | | transition: all 0.3s ease; |
| | | |
| | | .device-header { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .device-icon { |
| | | width: 56px; |
| | | height: 56px; |
| | | background: linear-gradient(135deg, #667eea, #764ba2); |
| | | border-radius: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | |
| | | .device-info { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .device-name { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | line-height: 1.3; |
| | | } |
| | | |
| | | .device-code { |
| | | font-size: 13px; |
| | | color: #8c8c8c; |
| | | font-weight: 500; |
| | | padding: 4px 12px; |
| | | background: rgba(140, 140, 140, 0.1); |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | width: fit-content; |
| | | } |
| | | |
| | | .qr-scan { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 12px 16px; |
| | | background: linear-gradient(135deg, #52c41a, #389e0d); |
| | | border-radius: 12px; |
| | | box-shadow: 0 4px 15px rgba(82, 196, 26, 0.3); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | box-shadow: 0 6px 20px rgba(82, 196, 26, 0.4); |
| | | } |
| | | |
| | | &:active { |
| | | transform: scale(0.98); |
| | | } |
| | | } |
| | | |
| | | .scan-text { |
| | | font-size: 13px; |
| | | color: #ffffff; |
| | | font-weight: 600; |
| | | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .device-details { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | background: rgba(248, 250, 252, 0.8); |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | backdrop-filter: blur(10px); |
| | | } |
| | | |
| | | .detail-item { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 14px; |
| | | padding: 8px 0; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | background: rgba(255, 255, 255, 0.5); |
| | | margin: 0 -8px; |
| | | padding-left: 8px; |
| | | padding-right: 8px; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .label { |
| | | color: #595959; |
| | | min-width: 80px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .value { |
| | | color: #262626; |
| | | flex: 1; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .inspection-items { |
| | | margin: 10px 20px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 20px 0; |
| | | border-bottom: 1px solid rgba(255, 255, 255, 0.2); |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | margin-bottom: 16px; |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .title-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | flex: 1; |
| | | } |
| | | |
| | | .progress-text { |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | background: linear-gradient(135deg, #667eea, #764ba2); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | |
| | | .items-list { |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | border-radius: 20px; |
| | | overflow: hidden; |
| | | margin-top: 0; |
| | | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | } |
| | | |
| | | .inspection-item { |
| | | border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | &.completed { |
| | | background: rgba(82, 196, 26, 0.05); |
| | | border-left: 4px solid #52c41a; |
| | | } |
| | | |
| | | &.abnormal { |
| | | background: rgba(255, 77, 79, 0.05); |
| | | border-left: 4px solid #ff4d4f; |
| | | } |
| | | |
| | | &:hover { |
| | | background: rgba(102, 126, 234, 0.05); |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 15px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .checkbox { |
| | | width: 20px; |
| | | height: 20px; |
| | | border: 2px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: all 0.3s; |
| | | |
| | | &.checked { |
| | | background: #52c41a; |
| | | border-color: #52c41a; |
| | | } |
| | | } |
| | | |
| | | .item-name { |
| | | font-size: 15px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-status { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .item-content { |
| | | padding: 0 15px 20px; |
| | | border-top: 1px solid #f5f5f5; |
| | | } |
| | | |
| | | .item-description { |
| | | padding: 15px 0; |
| | | } |
| | | |
| | | .desc-text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .result-section, |
| | | .abnormal-section, |
| | | .upload-section, |
| | | .remark-section { |
| | | margin-top: 15px; |
| | | } |
| | | |
| | | .section-label { |
| | | display: block; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .result-options { |
| | | display: flex; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .upload-btn { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 88px; |
| | | height: 88px; |
| | | border: 2px dashed rgba(102, 126, 234, 0.3); |
| | | border-radius: 16px; |
| | | background: rgba(102, 126, 234, 0.05); |
| | | gap: 8px; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | border-color: rgba(102, 126, 234, 0.5); |
| | | background: rgba(102, 126, 234, 0.1); |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 13px; |
| | | color: #667eea; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .bottom-actions { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(20px); |
| | | padding: 20px; |
| | | border-top: 1px solid rgba(255, 255, 255, 0.2); |
| | | box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.1); |
| | | z-index: 10; |
| | | |
| | | button { |
| | | height: 48px; |
| | | border-radius: 16px; |
| | | font-weight: 600; |
| | | font-size: 16px; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | } |
| | | |
| | | .device-header { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .device-icon { |
| | | width: 56px; |
| | | height: 56px; |
| | | background: linear-gradient(135deg, #667eea, #764ba2); |
| | | border-radius: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | |
| | | .device-info { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .device-name { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | line-height: 1.3; |
| | | } |
| | | |
| | | .device-code { |
| | | font-size: 13px; |
| | | color: #8c8c8c; |
| | | font-weight: 500; |
| | | padding: 4px 12px; |
| | | background: rgba(140, 140, 140, 0.1); |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | width: fit-content; |
| | | } |
| | | |
| | | .qr-scan { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 12px 16px; |
| | | background: linear-gradient(135deg, #52c41a, #389e0d); |
| | | border-radius: 12px; |
| | | box-shadow: 0 4px 15px rgba(82, 196, 26, 0.3); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | box-shadow: 0 6px 20px rgba(82, 196, 26, 0.4); |
| | | } |
| | | |
| | | &:active { |
| | | transform: scale(0.98); |
| | | } |
| | | } |
| | | |
| | | .scan-text { |
| | | font-size: 13px; |
| | | color: #ffffff; |
| | | font-weight: 600; |
| | | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .device-details { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | background: rgba(248, 250, 252, 0.8); |
| | | border-radius: 16px; |
| | | padding: 16px; |
| | | backdrop-filter: blur(10px); |
| | | } |
| | | |
| | | .detail-item { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 14px; |
| | | padding: 8px 0; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | background: rgba(255, 255, 255, 0.5); |
| | | margin: 0 -8px; |
| | | padding-left: 8px; |
| | | padding-right: 8px; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .label { |
| | | color: #595959; |
| | | min-width: 80px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .value { |
| | | color: #262626; |
| | | flex: 1; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .inspection-items { |
| | | margin: 10px 20px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 20px 0; |
| | | border-bottom: 1px solid rgba(255, 255, 255, 0.2); |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | margin-bottom: 16px; |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .title-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | flex: 1; |
| | | } |
| | | |
| | | .progress-text { |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | background: linear-gradient(135deg, #667eea, #764ba2); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | |
| | | .items-list { |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(15px); |
| | | border-radius: 20px; |
| | | overflow: hidden; |
| | | margin-top: 0; |
| | | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | } |
| | | |
| | | .inspection-item { |
| | | border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | &.completed { |
| | | background: rgba(82, 196, 26, 0.05); |
| | | border-left: 4px solid #52c41a; |
| | | } |
| | | |
| | | &.abnormal { |
| | | background: rgba(255, 77, 79, 0.05); |
| | | border-left: 4px solid #ff4d4f; |
| | | } |
| | | |
| | | &:hover { |
| | | background: rgba(102, 126, 234, 0.05); |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 15px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .checkbox { |
| | | width: 20px; |
| | | height: 20px; |
| | | border: 2px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: all 0.3s; |
| | | |
| | | &.checked { |
| | | background: #52c41a; |
| | | border-color: #52c41a; |
| | | } |
| | | } |
| | | |
| | | .item-name { |
| | | font-size: 15px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-status { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .item-content { |
| | | padding: 0 15px 20px; |
| | | border-top: 1px solid #f5f5f5; |
| | | } |
| | | |
| | | .item-description { |
| | | padding: 15px 0; |
| | | } |
| | | |
| | | .desc-text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .result-section, |
| | | .abnormal-section, |
| | | .upload-section, |
| | | .remark-section { |
| | | margin-top: 15px; |
| | | } |
| | | |
| | | .section-label { |
| | | display: block; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .result-options { |
| | | display: flex; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .upload-btn { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 88px; |
| | | height: 88px; |
| | | border: 2px dashed rgba(102, 126, 234, 0.3); |
| | | border-radius: 16px; |
| | | background: rgba(102, 126, 234, 0.05); |
| | | gap: 8px; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | border-color: rgba(102, 126, 234, 0.5); |
| | | background: rgba(102, 126, 234, 0.1); |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 13px; |
| | | color: #667eea; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .bottom-actions { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background: rgba(255, 255, 255, 0.95); |
| | | backdrop-filter: blur(20px); |
| | | padding: 20px; |
| | | border-top: 1px solid rgba(255, 255, 255, 0.2); |
| | | box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.1); |
| | | z-index: 10; |
| | | |
| | | button { |
| | | height: 48px; |
| | | border-radius: 16px; |
| | | font-weight: 600; |
| | | font-size: 16px; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="inspection-page"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="设å¤å·¡æ£" @back="goBack" /> |
| | | |
| | | <PageHeader title="设å¤å·¡æ£" |
| | | @back="goBack" /> |
| | | <!-- ç»è®¡ä¿¡æ¯å¡ç --> |
| | | <view class="stats-cards"> |
| | | <view class="stat-card"> |
| | |
| | | <text class="stat-label">å¾
å·¡æ£</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å·¡æ£æ¸
å --> |
| | | <view class="inspection-list" v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" :key="index"> |
| | | <view class="inspection-item" @click="startInspection(item)"> |
| | | <view class="inspection-list" |
| | | v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" |
| | | :key="index"> |
| | | <view class="inspection-item" |
| | | @click="startInspection(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="device-icon" :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" size="16" color="#ffffff"></up-icon> |
| | | <view class="device-icon" |
| | | :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <view class="device-info"> |
| | | <text class="device-name">{{ item.deviceName }}</text> |
| | |
| | | </view> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag :type="getTagType(item.status)" size="mini"> |
| | | <u-tag :type="getTagType(item.status)" |
| | | size="mini"> |
| | | {{ getStatusText(item.status) }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设å¤ç¼å·</text> |
| | |
| | | <text class="detail-label">è´è´£äºº</text> |
| | | <text class="detail-value">{{ item.inspector || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" v-if="item.status === 2"> |
| | | <view class="detail-row" |
| | | v-if="item.status === 2"> |
| | | <text class="detail-label">宿æ¶é´</text> |
| | | <text class="detail-value">{{ formatDateTime(item.completedTime) || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 2" |
| | | @click.stop="startInspection(item)" |
| | | > |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 2" |
| | | @click.stop="startInspection(item)"> |
| | | {{ item.status === 0 ? 'å¼å§å·¡æ£' : item.status === 1 ? 'ç»§ç»å·¡æ£' : 'æ¥ç详æ
' }} |
| | | </u-button> |
| | | <u-button |
| | | type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status !== 1" |
| | | @click.stop="scanQRCode(item)" |
| | | > |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status !== 1" |
| | | @click.stop="scanQRCode(item)"> |
| | | æ«ç æå¡ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <up-empty mode="data" text="ææ å·¡æ£ä»»å¡"></up-empty> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ å·¡æ£ä»»å¡"></up-empty> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | // import { getInspectionList } from '@/api/inspectionUpload/index' |
| | | import dayjs from 'dayjs' |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | // import { getInspectionList } from '@/api/inspectionUpload/index' |
| | | import dayjs from "dayjs"; |
| | | |
| | | // éä¸çæ¥æ |
| | | const selectedDate = ref(Date.now()) |
| | | // éä¸çæ¥æ |
| | | const selectedDate = ref(Date.now()); |
| | | |
| | | // å·¡æ£æ¸
åæ°æ® |
| | | const inspectionList = ref([]) |
| | | // å·¡æ£æ¸
åæ°æ® |
| | | const inspectionList = ref([]); |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 计ç®ç»è®¡æ°æ® |
| | | const totalCount = computed(() => inspectionList.value.length) |
| | | const completedCount = computed(() => inspectionList.value.filter(item => item.status === 2).length) |
| | | const pendingCount = computed(() => inspectionList.value.filter(item => item.status === 0).length) |
| | | // 计ç®ç»è®¡æ°æ® |
| | | const totalCount = computed(() => inspectionList.value.length); |
| | | const completedCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 2).length |
| | | ); |
| | | const pendingCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 0).length |
| | | ); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¥ææ ¼å¼åå¨ |
| | | const dateFormatter = (type, value) => { |
| | | if (type === 'year') { |
| | | return `${value}å¹´` |
| | | } |
| | | if (type === 'month') { |
| | | return `${value}æ` |
| | | } |
| | | if (type === 'day') { |
| | | return `${value}æ¥` |
| | | } |
| | | return value |
| | | } |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (timestamp) => { |
| | | return dayjs(timestamp).format('YYYYå¹´MMæDDæ¥') |
| | | } |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | return dayjs(dateStr).format('MM-DD HH:mm') |
| | | } |
| | | |
| | | // æ¥ææ¹åäºä»¶ |
| | | const onDateChange = (value) => { |
| | | selectedDate.value = value.value |
| | | getList() |
| | | } |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | const getStatusClass = (status) => { |
| | | switch (status) { |
| | | case 0: return 'status-pending' |
| | | case 1: return 'status-progress' |
| | | case 2: return 'status-completed' |
| | | default: return 'status-pending' |
| | | } |
| | | } |
| | | |
| | | // è·åç¶æå¾æ |
| | | const getStatusIcon = (status) => { |
| | | switch (status) { |
| | | case 0: return 'clock' |
| | | case 1: return 'play-circle' |
| | | case 2: return 'checkmark-circle' |
| | | default: return 'clock' |
| | | } |
| | | } |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = (status) => { |
| | | switch (status) { |
| | | case 0: return 'warning' |
| | | case 1: return 'primary' |
| | | case 2: return 'success' |
| | | default: return 'info' |
| | | } |
| | | } |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | switch (status) { |
| | | case 0: return 'å¾
å·¡æ£' |
| | | case 1: return 'å·¡æ£ä¸' |
| | | case 2: return '已宿' |
| | | default: return 'æªç¥' |
| | | } |
| | | } |
| | | |
| | | // å¼å§å·¡æ£ |
| | | const startInspection = (item) => { |
| | | // åå¨å½åå·¡æ£é¡¹ç®ä¿¡æ¯ |
| | | uni.setStorageSync('currentInspection', item) |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/inspection/detail' |
| | | }) |
| | | } |
| | | |
| | | // æ«ç æå¡ |
| | | const scanQRCode = (item) => { |
| | | uni.scanCode({ |
| | | success: (res) => { |
| | | console.log('æ«ç ç»æï¼', res) |
| | | // éªè¯äºç»´ç å
容 |
| | | if (res.result.includes(item.deviceCode)) { |
| | | showToast('æå¡æå') |
| | | // æ´æ°æå¡ç¶æ |
| | | updateCheckInStatus(item.id) |
| | | } else { |
| | | showToast('äºç»´ç ä¸å¹é
ï¼è¯·æ«ææ£ç¡®ç设å¤äºç»´ç ') |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.log('æ«ç 失败ï¼', err) |
| | | showToast('æ«ç 失败') |
| | | // æ¥ææ ¼å¼åå¨ |
| | | const dateFormatter = (type, value) => { |
| | | if (type === "year") { |
| | | return `${value}å¹´`; |
| | | } |
| | | }) |
| | | } |
| | | if (type === "month") { |
| | | return `${value}æ`; |
| | | } |
| | | if (type === "day") { |
| | | return `${value}æ¥`; |
| | | } |
| | | return value; |
| | | }; |
| | | |
| | | // æ´æ°æå¡ç¶æ |
| | | const updateCheckInStatus = (id) => { |
| | | // è¿éåºè¯¥è°ç¨APIæ´æ°æå¡ç¶æ |
| | | // ææ¶æ¨¡ææ´æ°æ¬å°æ°æ® |
| | | const item = inspectionList.value.find(item => item.id === id) |
| | | if (item) { |
| | | item.checkInTime = new Date().toISOString() |
| | | } |
| | | } |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = timestamp => { |
| | | return dayjs(timestamp).format("YYYYå¹´MMæDDæ¥"); |
| | | }; |
| | | |
| | | // æ¥è¯¢å·¡æ£æ¸
å |
| | | const getList = () => { |
| | | uni.showLoading({ |
| | | title: 'å è½½ä¸...', |
| | | mask: true |
| | | }) |
| | | |
| | | const params = { |
| | | date: dayjs(selectedDate.value).format('YYYY-MM-DD') |
| | | } |
| | | |
| | | // æ¨¡ææ°æ®ï¼å®é
åºè¯¥è°ç¨API |
| | | setTimeout(() => { |
| | | inspectionList.value = [ |
| | | { |
| | | id: 1, |
| | | deviceName: 'ç©ºåæºA01', |
| | | deviceCode: 'KYJ-A01', |
| | | location: 'ç产车é´Aåº', |
| | | inspectionTime: '08:00-09:00', |
| | | inspector: 'å¼ ä¸', |
| | | status: 0, // 0:å¾
å·¡æ£ 1:å·¡æ£ä¸ 2:已宿 |
| | | completedTime: null |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("MM-DD HH:mm"); |
| | | }; |
| | | |
| | | // æ¥ææ¹åäºä»¶ |
| | | const onDateChange = value => { |
| | | selectedDate.value = value.value; |
| | | getList(); |
| | | }; |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | const getStatusClass = status => { |
| | | switch (status) { |
| | | case 0: |
| | | return "status-pending"; |
| | | case 1: |
| | | return "status-progress"; |
| | | case 2: |
| | | return "status-completed"; |
| | | default: |
| | | return "status-pending"; |
| | | } |
| | | }; |
| | | |
| | | // è·åç¶æå¾æ |
| | | const getStatusIcon = status => { |
| | | switch (status) { |
| | | case 0: |
| | | return "clock"; |
| | | case 1: |
| | | return "play-circle"; |
| | | case 2: |
| | | return "checkmark-circle"; |
| | | default: |
| | | return "clock"; |
| | | } |
| | | }; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = status => { |
| | | switch (status) { |
| | | case 0: |
| | | return "warning"; |
| | | case 1: |
| | | return "primary"; |
| | | case 2: |
| | | return "success"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | switch (status) { |
| | | case 0: |
| | | return "å¾
å·¡æ£"; |
| | | case 1: |
| | | return "å·¡æ£ä¸"; |
| | | case 2: |
| | | return "已宿"; |
| | | default: |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | |
| | | // å¼å§å·¡æ£ |
| | | const startInspection = item => { |
| | | // åå¨å½åå·¡æ£é¡¹ç®ä¿¡æ¯ |
| | | uni.setStorageSync("currentInspection", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/inspection/detail", |
| | | }); |
| | | }; |
| | | |
| | | // æ«ç æå¡ |
| | | const scanQRCode = item => { |
| | | uni.scanCode({ |
| | | success: res => { |
| | | console.log("æ«ç ç»æï¼", res); |
| | | // éªè¯äºç»´ç å
容 |
| | | if (res.result.includes(item.deviceCode)) { |
| | | showToast("æå¡æå"); |
| | | // æ´æ°æå¡ç¶æ |
| | | updateCheckInStatus(item.id); |
| | | } else { |
| | | showToast("äºç»´ç ä¸å¹é
ï¼è¯·æ«ææ£ç¡®ç设å¤äºç»´ç "); |
| | | } |
| | | }, |
| | | { |
| | | id: 2, |
| | | deviceName: 'å·å´å¡B02', |
| | | deviceCode: 'LQT-B02', |
| | | location: 'ç产车é´Båº', |
| | | inspectionTime: '09:00-10:00', |
| | | inspector: 'æå', |
| | | status: 1, |
| | | completedTime: null |
| | | fail: err => { |
| | | console.log("æ«ç 失败ï¼", err); |
| | | showToast("æ«ç 失败"); |
| | | }, |
| | | { |
| | | id: 3, |
| | | deviceName: 'ååå¨C03', |
| | | deviceCode: 'BYQ-C03', |
| | | location: 'é
çµæ¿', |
| | | inspectionTime: '10:00-11:00', |
| | | inspector: 'çäº', |
| | | status: 2, |
| | | completedTime: '2024-01-15T10:30:00' |
| | | } |
| | | ] |
| | | uni.hideLoading() |
| | | }, 1000) |
| | | |
| | | // å®é
APIè°ç¨ |
| | | // getInspectionList(params) |
| | | // .then((res) => { |
| | | // inspectionList.value = res.records || res.data?.records || [] |
| | | // uni.hideLoading() |
| | | // }) |
| | | // .catch(() => { |
| | | // uni.hideLoading() |
| | | // showToast('è·åæ°æ®å¤±è´¥') |
| | | // }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | // æ´æ°æå¡ç¶æ |
| | | const updateCheckInStatus = id => { |
| | | // è¿éåºè¯¥è°ç¨APIæ´æ°æå¡ç¶æ |
| | | // ææ¶æ¨¡ææ´æ°æ¬å°æ°æ® |
| | | const item = inspectionList.value.find(item => item.id === id); |
| | | if (item) { |
| | | item.checkInTime = new Date().toISOString(); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | // æ¥è¯¢å·¡æ£æ¸
å |
| | | const getList = () => { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | const params = { |
| | | date: dayjs(selectedDate.value).format("YYYY-MM-DD"), |
| | | }; |
| | | |
| | | // æ¨¡ææ°æ®ï¼å®é
åºè¯¥è°ç¨API |
| | | setTimeout(() => { |
| | | inspectionList.value = [ |
| | | { |
| | | id: 1, |
| | | deviceName: "ç©ºåæºA01", |
| | | deviceCode: "KYJ-A01", |
| | | location: "ç产车é´Aåº", |
| | | inspectionTime: "08:00-09:00", |
| | | inspector: "å¼ ä¸", |
| | | status: 0, // 0:å¾
å·¡æ£ 1:å·¡æ£ä¸ 2:已宿 |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 2, |
| | | deviceName: "å·å´å¡B02", |
| | | deviceCode: "LQT-B02", |
| | | location: "ç产车é´Båº", |
| | | inspectionTime: "09:00-10:00", |
| | | inspector: "æå", |
| | | status: 1, |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 3, |
| | | deviceName: "ååå¨C03", |
| | | deviceCode: "BYQ-C03", |
| | | location: "é
çµæ¿", |
| | | inspectionTime: "10:00-11:00", |
| | | inspector: "çäº", |
| | | status: 2, |
| | | completedTime: "2024-01-15T10:30:00", |
| | | }, |
| | | ]; |
| | | uni.hideLoading(); |
| | | }, 1000); |
| | | |
| | | // å®é
APIè°ç¨ |
| | | // getInspectionList(params) |
| | | // .then((res) => { |
| | | // inspectionList.value = res.records || res.data?.records || [] |
| | | // uni.hideLoading() |
| | | // }) |
| | | // .catch(() => { |
| | | // uni.hideLoading() |
| | | // showToast('è·åæ°æ®å¤±è´¥') |
| | | // }) |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | .inspection-page { |
| | | background: #ffffff; |
| | | min-height: 100vh; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | .stats-cards { |
| | | display: flex; |
| | | gap: 10px; |
| | | padding: 0 15px; |
| | | margin: 15px 0; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 15px 12px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 6px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid #f0f0f0; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | .inspection-page { |
| | | background: #ffffff; |
| | | min-height: 100vh; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: 700; |
| | | color: #1890ff; |
| | | |
| | | .stats-cards { |
| | | display: flex; |
| | | gap: 10px; |
| | | padding: 0 15px; |
| | | margin: 15px 0; |
| | | } |
| | | |
| | | .stat-label { |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 15px 12px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 6px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid #f0f0f0; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: 700; |
| | | color: #1890ff; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 13px; |
| | | color: #666; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .inspection-list { |
| | | padding: 0 15px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 15px; |
| | | margin-bottom: 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid #f0f0f0; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 12px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .device-icon { |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-shrink: 0; |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s ease; |
| | | |
| | | &.status-pending { |
| | | background: linear-gradient(135deg, #faad14, #fa8c16); |
| | | box-shadow: 0 4px 16px rgba(250, 173, 20, 0.3); |
| | | } |
| | | |
| | | &.status-progress { |
| | | background: linear-gradient(135deg, #1890ff, #096dd9); |
| | | box-shadow: 0 4px 16px rgba(24, 144, 255, 0.3); |
| | | } |
| | | |
| | | &.status-completed { |
| | | background: linear-gradient(135deg, #52c41a, #389e0d); |
| | | box-shadow: 0 4px 16px rgba(82, 196, 26, 0.3); |
| | | } |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | |
| | | .device-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .device-name { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | line-height: 1.3; |
| | | } |
| | | |
| | | .device-location { |
| | | font-size: 13px; |
| | | color: #666; |
| | | color: #8c8c8c; |
| | | font-weight: 500; |
| | | padding: 2px 8px; |
| | | background: rgba(140, 140, 140, 0.1); |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | width: fit-content; |
| | | } |
| | | |
| | | .status-tag { |
| | | flex-shrink: 0; |
| | | transform: scale(1.1); |
| | | } |
| | | |
| | | .item-details { |
| | | margin: 15px 0; |
| | | background: rgba(248, 250, 252, 0.8); |
| | | border-radius: 12px; |
| | | padding: 12px; |
| | | backdrop-filter: blur(10px); |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10px 0; |
| | | border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
| | | transition: all 0.2s ease; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | &:hover { |
| | | background: rgba(255, 255, 255, 0.5); |
| | | margin: 0 -8px; |
| | | padding-left: 8px; |
| | | padding-right: 8px; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 14px; |
| | | color: #595959; |
| | | min-width: 80px; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .inspection-list { |
| | | padding: 0 15px; |
| | | } |
| | | |
| | | .inspection-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 15px; |
| | | margin-bottom: 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | border: 1px solid #f0f0f0; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | .detail-value { |
| | | font-size: 14px; |
| | | color: #262626; |
| | | text-align: right; |
| | | flex: 1; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 12px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .device-icon { |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-shrink: 0; |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s ease; |
| | | |
| | | &.status-pending { |
| | | background: linear-gradient(135deg, #faad14, #fa8c16); |
| | | box-shadow: 0 4px 16px rgba(250, 173, 20, 0.3); |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 10px; |
| | | margin-top: 15px; |
| | | padding-top: 15px; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.06); |
| | | } |
| | | |
| | | &.status-progress { |
| | | background: linear-gradient(135deg, #1890ff, #096dd9); |
| | | box-shadow: 0 4px 16px rgba(24, 144, 255, 0.3); |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | height: 44px; |
| | | border-radius: 12px; |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | &.status-completed { |
| | | background: linear-gradient(135deg, #52c41a, #389e0d); |
| | | box-shadow: 0 4px 16px rgba(82, 196, 26, 0.3); |
| | | |
| | | .no-data { |
| | | padding: 80px 20px; |
| | | text-align: center; |
| | | } |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | |
| | | .device-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .device-name { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1a1a1a; |
| | | line-height: 1.3; |
| | | } |
| | | |
| | | .device-location { |
| | | font-size: 13px; |
| | | color: #8c8c8c; |
| | | font-weight: 500; |
| | | padding: 2px 8px; |
| | | background: rgba(140, 140, 140, 0.1); |
| | | border-radius: 12px; |
| | | display: inline-block; |
| | | width: fit-content; |
| | | } |
| | | |
| | | .status-tag { |
| | | flex-shrink: 0; |
| | | transform: scale(1.1); |
| | | } |
| | | |
| | | .item-details { |
| | | margin: 15px 0; |
| | | background: rgba(248, 250, 252, 0.8); |
| | | border-radius: 12px; |
| | | padding: 12px; |
| | | backdrop-filter: blur(10px); |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10px 0; |
| | | border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
| | | transition: all 0.2s ease; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | &:hover { |
| | | background: rgba(255, 255, 255, 0.5); |
| | | margin: 0 -8px; |
| | | padding-left: 8px; |
| | | padding-right: 8px; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 14px; |
| | | color: #595959; |
| | | min-width: 80px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 14px; |
| | | color: #262626; |
| | | text-align: right; |
| | | flex: 1; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 10px; |
| | | margin-top: 15px; |
| | | padding-top: 15px; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.06); |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | height: 44px; |
| | | border-radius: 12px; |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | |
| | | &:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 80px 20px; |
| | | text-align: center; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="repair-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾æ¥ä¿®' : 'æ°å¢æ¥ä¿®'" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="sendForm" ref="formRef" :rules="formRules" :model="form" label-width="110"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" prop="deviceLedgerId" required border-bottom> |
| | | <u-input |
| | | v-model="deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | @click="showDevicePicker" |
| | | clearable |
| | | readonly="" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="scan" @click="startScan" class="scan-icon" /> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" prop="deviceModel" border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®æ¥æ" prop="repairTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®äºº" prop="repairName" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ
éç°è±¡" prop="remark" required border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | count |
| | | maxlength="200" |
| | | /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showDevice" |
| | | :actions="deviceActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onDeviceSelect" |
| | | @close="showDevice = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </view> |
| | | <view class="repair-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾æ¥ä¿®' : 'æ°å¢æ¥ä¿®'" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="sendForm" |
| | | ref="formRef" |
| | | :rules="formRules" |
| | | :model="form" |
| | | label-width="110"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" |
| | | prop="deviceLedgerId" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | @click="showDevicePicker" |
| | | clearable |
| | | readonly="" /> |
| | | <template #right> |
| | | <u-icon name="scan" |
| | | @click="startScan" |
| | | class="scan-icon" /> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" |
| | | prop="deviceModel" |
| | | border-bottom> |
| | | <u-input v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®æ¥æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®ç¶æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="repairStatusText" |
| | | placeholder="è¯·éæ©æ¥ä¿®ç¶æ" |
| | | readonly |
| | | @click="openRepairStatusPicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="openRepairStatusPicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®äºº" |
| | | prop="repairName" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="æ
éç°è±¡" |
| | | prop="remark" |
| | | required |
| | | border-bottom> |
| | | <u-textarea v-model="form.remark" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | count |
| | | maxlength="200" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" |
| | | type="primary" |
| | | @click="sendForm" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <up-action-sheet :show="showDevice" |
| | | :actions="deviceActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onDeviceSelect" |
| | | @close="showDevice = false" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, onUnmounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import { getDeviceLedger } from '@/api/equipmentManagement/ledger'; |
| | | import { addRepair, editRepair, getRepairById } from '@/api/equipmentManagement/repair'; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi'; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import { ref, computed, onMounted, onUnmounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | | }); |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | | }); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const operationType = ref('add'); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const showDate = ref(false); |
| | | const pickerDateValue = ref(Date.now()); |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const operationType = ref("add"); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const showDate = ref(false); |
| | | const pickerDateValue = ref(Date.now()); |
| | | |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(''); |
| | | const deviceActionList = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | name: item.deviceName, |
| | | value: item.id |
| | | })); |
| | | }); |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(""); |
| | | const deviceActionList = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | name: item.deviceName, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | | const scanTimer = ref(null); |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | | const scanTimer = ref(null); |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | deviceLedgerId: [{ required: true, trigger: "change", message: "è¯·éæ©è®¾å¤åç§°" }], |
| | | repairTime: [{ required: true, trigger: "change", message: "è¯·éæ©æ¥ä¿®æ¥æ" }], |
| | | repairName: [{ required: true, trigger: "blur", message: "请è¾å
¥æ¥ä¿®äºº" }], |
| | | remark: [{ required: true, trigger: "blur", message: "请è¾å
¥æ
éç°è±¡" }], |
| | | }; |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | deviceLedgerId: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©è®¾å¤åç§°" }, |
| | | ], |
| | | repairTime: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©æ¥ä¿®æ¥æ" }, |
| | | ], |
| | | repairName: [{ required: true, trigger: "blur", message: "请è¾å
¥æ¥ä¿®äºº" }], |
| | | remark: [{ required: true, trigger: "blur", message: "请è¾å
¥æ
éç°è±¡" }], |
| | | }; |
| | | |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | deviceLedgerId: undefined, // 设å¤ID |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æ |
| | | repairName: undefined, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | }); |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | deviceLedgerId: undefined, // 设å¤ID |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æ |
| | | repairName: undefined, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | const loadDeviceName = async () => { |
| | | try { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data || []; |
| | | } catch (e) { |
| | | showToast('è·å设å¤å表失败'); |
| | | } |
| | | }; |
| | | // æ¥ä¿®ç¶æé项 |
| | | const repairStatusOptions = ref([ |
| | | { name: "å¾
ç»´ä¿®", value: "0" }, |
| | | { name: "å®ç»", value: "1" }, |
| | | { name: "失败", value: "2" }, |
| | | ]); |
| | | const repairStatusText = ref(""); |
| | | |
| | | // 设置设å¤è§æ ¼åå· |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.deviceModel = option.deviceModel; |
| | | deviceNameText.value = option.deviceName; |
| | | } |
| | | }; |
| | | // æå¼æ¥ä¿®ç¶æéæ©å¨ |
| | | const openRepairStatusPicker = () => { |
| | | uni.showActionSheet({ |
| | | itemList: repairStatusOptions.value.map(item => item.name), |
| | | success: res => { |
| | | form.value.status = repairStatusOptions.value[res.tapIndex].value; |
| | | repairStatusText.value = repairStatusOptions.value[res.tapIndex].name; |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å è½½è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const loadForm = async (id) => { |
| | | if (id) { |
| | | operationType.value = 'edit'; |
| | | try { |
| | | const { code, data } = await getRepairById(id); |
| | | if (code == 200) { |
| | | form.value.deviceLedgerId = data.deviceLedgerId; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD"); |
| | | form.value.repairName = data.repairName; |
| | | form.value.remark = data.remark; |
| | | // 设置设å¤åç§°æ¾ç¤º |
| | | const device = deviceOptions.value.find(item => item.id === data.deviceLedgerId); |
| | | if (device) { |
| | | deviceNameText.value = device.deviceName; |
| | | } |
| | | } |
| | | } catch (e) { |
| | | showToast('è·å详æ
失败'); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | operationType.value = 'add'; |
| | | } |
| | | }; |
| | | // å 载设å¤å表 |
| | | const loadDeviceName = async () => { |
| | | try { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data || []; |
| | | } catch (e) { |
| | | showToast("è·å设å¤å表失败"); |
| | | } |
| | | }; |
| | | |
| | | // æ«æäºç»´ç åè½ |
| | | const startScan = () => { |
| | | if (isScanning.value) { |
| | | showToast('æ£å¨æ«æä¸ï¼è¯·ç¨å...'); |
| | | return; |
| | | } |
| | | |
| | | // è°ç¨uni-appçæ«ç API |
| | | uni.scanCode({ |
| | | scanType: ['qrCode', 'barCode'], |
| | | success: (res) => { |
| | | handleScanResult(res.result); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('æ«ç 失败:', err); |
| | | showToast('æ«ç 失败ï¼è¯·éè¯'); |
| | | } |
| | | }); |
| | | }; |
| | | // 设置设å¤è§æ ¼åå· |
| | | const setDeviceModel = id => { |
| | | const option = deviceOptions.value.find(item => item.id === id); |
| | | if (option) { |
| | | form.value.deviceModel = option.deviceModel; |
| | | deviceNameText.value = option.deviceName; |
| | | } |
| | | }; |
| | | |
| | | // å¤çæ«ç ç»æ |
| | | const handleScanResult = (scanResult) => { |
| | | if (!scanResult) { |
| | | showToast('æ«ç ç»æä¸ºç©º'); |
| | | return; |
| | | } |
| | | |
| | | isScanning.value = true; |
| | | showToast('æ«ç æå'); |
| | | |
| | | // 3ç§åå¤çæ«ç ç»æ |
| | | scanTimer.value = setTimeout(() => { |
| | | processScanResult(scanResult); |
| | | isScanning.value = false; |
| | | }, 100); |
| | | }; |
| | | function getDeviceIdByRegExp(url) { |
| | | // å¹é
deviceId=åé¢çæ°å |
| | | const reg = /deviceId=(\d+)/; |
| | | const match = url.match(reg); |
| | | // 妿å¹é
å°ç»æï¼è¿åæ°åç±»åï¼å¦åè¿ånull |
| | | return match ? Number(match[1]) : null; |
| | | } |
| | | // å è½½è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const loadForm = async id => { |
| | | if (id) { |
| | | operationType.value = "edit"; |
| | | try { |
| | | const { code, data } = await getRepairById(id); |
| | | if (code == 200) { |
| | | form.value.deviceLedgerId = data.deviceLedgerId; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD"); |
| | | form.value.repairName = data.repairName; |
| | | form.value.remark = data.remark; |
| | | repairStatusText.value = |
| | | repairStatusOptions.value.find(item => item.value == data.status) |
| | | ?.name || ""; |
| | | // 设置设å¤åç§°æ¾ç¤º |
| | | const device = deviceOptions.value.find( |
| | | item => item.id === data.deviceLedgerId |
| | | ); |
| | | if (device) { |
| | | deviceNameText.value = device.deviceName; |
| | | } |
| | | } |
| | | } catch (e) { |
| | | showToast("è·å详æ
失败"); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | operationType.value = "add"; |
| | | } |
| | | }; |
| | | |
| | | // å¤çæ«ç ç»æå¹¶å¹é
è®¾å¤ |
| | | const processScanResult = (scanResult) => { |
| | | const deviceId = getDeviceIdByRegExp(scanResult); |
| | | const matchedDevice = deviceOptions.value.find(item => item.id == deviceId); |
| | | |
| | | if (matchedDevice) { |
| | | // æ¾å°å¹é
ç设å¤ï¼èªå¨å¡«å
|
| | | form.value.deviceLedgerId = matchedDevice.id; |
| | | deviceNameText.value = matchedDevice.deviceName; |
| | | form.value.deviceModel = matchedDevice.deviceModel; |
| | | showToast('设å¤ä¿¡æ¯å·²èªå¨å¡«å
'); |
| | | } else { |
| | | // æªæ¾å°å¹é
çè®¾å¤ |
| | | showToast('æªæ¾å°å¹é
ç设å¤ï¼è¯·æå¨éæ©'); |
| | | } |
| | | }; |
| | | // æ«æäºç»´ç åè½ |
| | | const startScan = () => { |
| | | if (isScanning.value) { |
| | | showToast("æ£å¨æ«æä¸ï¼è¯·ç¨å..."); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºè®¾å¤éæ©å¨ |
| | | const showDevicePicker = () => { |
| | | showDevice.value = true; |
| | | }; |
| | | // è°ç¨uni-appçæ«ç API |
| | | uni.scanCode({ |
| | | scanType: ["qrCode", "barCode"], |
| | | success: res => { |
| | | handleScanResult(res.result); |
| | | }, |
| | | fail: err => { |
| | | console.error("æ«ç 失败:", err); |
| | | showToast("æ«ç 失败ï¼è¯·éè¯"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 确认设å¤éæ© |
| | | const onDeviceSelect = (e) => { |
| | | form.value.deviceLedgerId = e.value; |
| | | setDeviceModel(e.value); |
| | | showDevice.value = false; |
| | | }; |
| | | // å¤çæ«ç ç»æ |
| | | const handleScanResult = scanResult => { |
| | | if (!scanResult) { |
| | | showToast("æ«ç ç»æä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | isScanning.value = true; |
| | | showToast("æ«ç æå"); |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showDate.value = false; |
| | | }; |
| | | // 3ç§åå¤çæ«ç ç»æ |
| | | scanTimer.value = setTimeout(() => { |
| | | processScanResult(scanResult); |
| | | isScanning.value = false; |
| | | }, 100); |
| | | }; |
| | | function getDeviceIdByRegExp(url) { |
| | | // å¹é
deviceId=åé¢çæ°å |
| | | const reg = /deviceId=(\d+)/; |
| | | const match = url.match(reg); |
| | | // 妿å¹é
å°ç»æï¼è¿åæ°åç±»åï¼å¦åè¿ånull |
| | | return match ? Number(match[1]) : null; |
| | | } |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ° |
| | | getPageParams(); |
| | | }); |
| | | // å¤çæ«ç ç»æå¹¶å¹é
è®¾å¤ |
| | | const processScanResult = scanResult => { |
| | | const deviceId = getDeviceIdByRegExp(scanResult); |
| | | const matchedDevice = deviceOptions.value.find(item => item.id == deviceId); |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·å设å¤å表ååæ° |
| | | loadDeviceName(); |
| | | getPageParams(); |
| | | }); |
| | | if (matchedDevice) { |
| | | // æ¾å°å¹é
ç设å¤ï¼èªå¨å¡«å
|
| | | form.value.deviceLedgerId = matchedDevice.id; |
| | | deviceNameText.value = matchedDevice.deviceName; |
| | | form.value.deviceModel = matchedDevice.deviceModel; |
| | | showToast("设å¤ä¿¡æ¯å·²èªå¨å¡«å
"); |
| | | } else { |
| | | // æªæ¾å°å¹é
çè®¾å¤ |
| | | showToast("æªæ¾å°å¹é
ç设å¤ï¼è¯·æå¨éæ©"); |
| | | } |
| | | }; |
| | | |
| | | // ç»ä»¶å¸è½½æ¶æ¸
ç宿¶å¨ |
| | | onUnmounted(() => { |
| | | if (scanTimer.value) { |
| | | clearTimeout(scanTimer.value); |
| | | } |
| | | }); |
| | | // æ¾ç¤ºè®¾å¤éæ©å¨ |
| | | const showDevicePicker = () => { |
| | | showDevice.value = true; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | try { |
| | | // æå¨éªè¯è¡¨å |
| | | let isValid = true; |
| | | let errorMessage = ''; |
| | | if (!form.value.deviceLedgerId) { |
| | | isValid = false; |
| | | errorMessage = 'è¯·éæ©è®¾å¤åç§°'; |
| | | } else if (!form.value.repairTime || form.value.repairTime.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = 'è¯·éæ©æ¥ä¿®æ¥æ'; |
| | | } else if (!form.value.repairName || form.value.repairName.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请è¾å
¥æ¥ä¿®äºº'; |
| | | } else if (!form.value.remark || form.value.remark.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请è¾å
¥æ
éç°è±¡'; |
| | | } |
| | | // 确认设å¤éæ© |
| | | const onDeviceSelect = e => { |
| | | form.value.deviceLedgerId = e.value; |
| | | setDeviceModel(e.value); |
| | | showDevice.value = false; |
| | | }; |
| | | |
| | | if (!isValid) { |
| | | showToast(errorMessage); |
| | | return; |
| | | } |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | | // åå¤æäº¤æ°æ® |
| | | const submitData = { ...form.value }; |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ° |
| | | getPageParams(); |
| | | }); |
| | | |
| | | const { code } = id |
| | | ? await editRepair({ id: id, ...submitData }) |
| | | : await addRepair(submitData); |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·å设å¤å表ååæ° |
| | | loadDeviceName(); |
| | | getPageParams(); |
| | | }); |
| | | |
| | | if (code == 200) { |
| | | showToast(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | | }; |
| | | // ç»ä»¶å¸è½½æ¶æ¸
ç宿¶å¨ |
| | | onUnmounted(() => { |
| | | if (scanTimer.value) { |
| | | clearTimeout(scanTimer.value); |
| | | } |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | try { |
| | | // æå¨éªè¯è¡¨å |
| | | let isValid = true; |
| | | let errorMessage = ""; |
| | | if (!form.value.deviceLedgerId) { |
| | | isValid = false; |
| | | errorMessage = "è¯·éæ©è®¾å¤åç§°"; |
| | | } else if (!form.value.repairTime || form.value.repairTime.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "è¯·éæ©æ¥ä¿®æ¥æ"; |
| | | } else if (!form.value.repairName || form.value.repairName.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "请è¾å
¥æ¥ä¿®äºº"; |
| | | } else if (!form.value.remark || form.value.remark.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "请è¾å
¥æ
éç°è±¡"; |
| | | } |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync('repairId'); |
| | | |
| | | // æ ¹æ®æ¯å¦æidåæ°æ¥å¤ææ¯æ°å¢è¿æ¯ç¼è¾ |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼è·å详æ
|
| | | loadForm(id); |
| | | // å¯éï¼è·å忏
é¤åå¨çidï¼é¿å
å½±ååç»æä½ |
| | | uni.removeStorageSync('repairId'); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | loadForm(); |
| | | } |
| | | }; |
| | | if (!isValid) { |
| | | showToast(errorMessage); |
| | | return; |
| | | } |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | // åå¤æäº¤æ°æ® |
| | | const submitData = { ...form.value }; |
| | | |
| | | const { code } = id |
| | | ? await editRepair({ id: id, ...submitData }) |
| | | : await addRepair(submitData); |
| | | |
| | | if (code == 200) { |
| | | showToast(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | showToast("表åéªè¯å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("repairId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync("repairId"); |
| | | |
| | | // æ ¹æ®æ¯å¦æidåæ°æ¥å¤ææ¯æ°å¢è¿æ¯ç¼è¾ |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼è·å详æ
|
| | | loadForm(id); |
| | | // å¯éï¼è·å忏
é¤åå¨çidï¼é¿å
å½±ååç»æä½ |
| | | uni.removeStorageSync("repairId"); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | loadForm(); |
| | | } |
| | | }; |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync("repairId"); |
| | | return id; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import "@/static/scss/form-common.scss"; |
| | | .repair-add { |
| | | 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; |
| | | } |
| | | .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: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 6.375rem; |
| | | background: #c7c9cc; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 14rem; |
| | | background: linear-gradient(140deg, #00baff 0%, #006cfb 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | |
| | | .scan-icon { |
| | | color: #1989fa; |
| | | font-size: 18px; |
| | | margin-left: 8px; |
| | | cursor: pointer; |
| | | } |
| | | .scan-icon { |
| | | color: #1989fa; |
| | | font-size: 18px; |
| | | margin-left: 8px; |
| | | cursor: pointer; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="è®¾å¤æ¥ä¿®" @back="goBack" /> |
| | | |
| | | <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" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°æç´¢" |
| | | v-model="searchKeyword" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- è®¾å¤æ¥ä¿®å表 --> |
| | | <view class="ledger-list" v-if="repairList.length > 0"> |
| | | <view v-for="(item, index) in repairList" :key="index"> |
| | | <view class="ledger-list" |
| | | v-if="repairList.length > 0"> |
| | | <view v-for="(item, index) in repairList" |
| | | :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> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">设å¤åç§°ï¼{{ item.deviceName }}</text> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag v-if="item.status === 1" type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" type="error">å¾
ç»´ä¿®</u-tag> |
| | | <u-tag v-if="item.status === 1" |
| | | type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" |
| | | type="error">å¾
ç»´ä¿®</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | |
| | | <text class="detail-value">{{ formatDate(item.maintenanceTime) || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="edit(item.id)" |
| | | > |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="edit(item.id)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button |
| | | type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="addMaintain(item.id)" |
| | | > |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="addMaintain(item.id)"> |
| | | æ°å¢ç»´ä¿® |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click="delRepairByIds(item.id)" |
| | | > |
| | | <u-button type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click="delRepairByIds(item.id)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ è®¾å¤æ¥ä¿®æ°æ®</text> |
| | | </view> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" @click="addRepair"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | <view class="fab-button" |
| | | @click="addRepair"> |
| | | <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 { getRepairPage, delRepair } from '@/api/equipmentManagement/repair' |
| | | import useUserStore from "@/store/modules/user" |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref('') |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref(""); |
| | | |
| | | // è®¾å¤æ¥ä¿®æ°æ® |
| | | const repairList = ref([]) |
| | | // è®¾å¤æ¥ä¿®æ°æ® |
| | | const repairList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | const date = new Date(dateStr) |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | return `${year}-${month}-${day}` |
| | | } |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = dateStr => { |
| | | if (!dateStr) return ""; |
| | | const date = new Date(dateStr); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | deviceName: searchKeyword.value || undefined |
| | | } |
| | | getRepairPage(params) |
| | | .then((res) => { |
| | | repairList.value = res.records || res.data?.records || [] |
| | | closeToast() |
| | | }) |
| | | .catch(() => { |
| | | closeToast() |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | } |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | deviceName: searchKeyword.value || undefined, |
| | | }; |
| | | getRepairPage(params) |
| | | .then(res => { |
| | | repairList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢ç»´ä¿® - 跳转å°ç»´ä¿®é¡µé¢ |
| | | const addMaintain = (id) => { |
| | | if (!id) { |
| | | showToast('åæ°é误') |
| | | return |
| | | } |
| | | // 使ç¨uni.setStorageSyncåå¨id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/maintain' |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢æ¥ä¿® - è·³è½¬å°æ¥ä¿®é¡µé¢ |
| | | const addRepair = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/add' |
| | | }) |
| | | } |
| | | |
| | | // ç¼è¾ - 跳转å°add页é¢ï¼éè¿idåºåæ°å¢è¿æ¯ç¼è¾ |
| | | const edit = (id) => { |
| | | if (!id) return |
| | | // 使ç¨uni.setStorageSyncåå¨id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/repair/add' |
| | | }) |
| | | } |
| | | |
| | | // å 餿¥ä¿®æ°æ® |
| | | const delRepairByIds = async (ids) => { |
| | | uni.showModal({ |
| | | title: 'è¦å', |
| | | content: '确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?', |
| | | confirmText: 'ç¡®å®', |
| | | cancelText: 'åæ¶', |
| | | success: async (res) => { |
| | | if (!res.confirm) return |
| | | try { |
| | | const response = await delRepair(ids) |
| | | if (response.code === 200) { |
| | | showToast('å 餿å') |
| | | getList() |
| | | } else { |
| | | showToast('å é¤å¤±è´¥') |
| | | } |
| | | } catch (e) { |
| | | showToast('å é¤å¤±è´¥') |
| | | } |
| | | // æ°å¢ç»´ä¿® - 跳转å°ç»´ä¿®é¡µé¢ |
| | | const addMaintain = id => { |
| | | if (!id) { |
| | | showToast("åæ°é误"); |
| | | return; |
| | | } |
| | | }) |
| | | } |
| | | // 使ç¨uni.setStorageSyncåå¨id |
| | | uni.setStorageSync("repairId", id); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/repair/maintain", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | // æ°å¢æ¥ä¿® - è·³è½¬å°æ¥ä¿®é¡µé¢ |
| | | const addRepair = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/repair/add", |
| | | }); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | // ç¼è¾ - 跳转å°add页é¢ï¼éè¿idåºåæ°å¢è¿æ¯ç¼è¾ |
| | | const edit = id => { |
| | | if (!id) return; |
| | | // 使ç¨uni.setStorageSyncåå¨id |
| | | uni.setStorageSync("repairId", id); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/repair/add", |
| | | }); |
| | | }; |
| | | |
| | | // å 餿¥ä¿®æ°æ® |
| | | const delRepairByIds = async ids => { |
| | | uni.showModal({ |
| | | title: "è¦å", |
| | | content: "确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?", |
| | | confirmText: "ç¡®å®", |
| | | cancelText: "åæ¶", |
| | | success: async res => { |
| | | if (!res.confirm) return; |
| | | try { |
| | | const response = await delRepair(ids); |
| | | if (response.code === 200) { |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | } catch (e) { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 设å¤ç»´ä¿®ç¹ææ ·å¼ |
| | | .sales-account { |
| | | padding-bottom: 80px; // ä¸ºæµ®å¨æé®çåºç©ºé´ |
| | | } |
| | | // 设å¤ç»´ä¿®ç¹ææ ·å¼ |
| | | .sales-account { |
| | | padding-bottom: 80px; // ä¸ºæµ®å¨æé®çåºç©ºé´ |
| | | } |
| | | |
| | | .status-tag { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .status-tag { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | } |
| | | .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="repair-maintain"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢ç»´ä¿®" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <u-form ref="formRef" :model="form" :rules="formRules" label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="维修信æ¯" inset> |
| | | <u-form-item prop="maintenanceName" label="维修人" required> |
| | | <u-input |
| | | v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="maintenanceResult" label="ç»´ä¿®ç»æ" required> |
| | | <u-input |
| | | v-model="form.maintenanceResult" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®æ¥æ" prop="maintenanceTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="datetime" |
| | | title="éæ©æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | /> |
| | | </view> |
| | | <view class="repair-maintain"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢ç»´ä¿®" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form ref="formRef" |
| | | :model="form" |
| | | :rules="formRules" |
| | | label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="维修信æ¯" |
| | | inset> |
| | | <u-form-item prop="maintenanceName" |
| | | label="维修人" |
| | | required> |
| | | <u-input v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item prop="maintenanceResult" |
| | | label="ç»´ä¿®ç»æ" |
| | | required> |
| | | <u-input v-model="form.maintenanceResult" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®ç¶æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="repairStatusText" |
| | | placeholder="è¯·éæ©ç»´ä¿®ç¶æ" |
| | | readonly |
| | | @click="openRepairStatusPicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="openRepairStatusPicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®æ¥æ" |
| | | prop="maintenanceTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="showDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" |
| | | @click="submitForm" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="datetime" |
| | | title="éæ©æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import { addMaintain } from '@/api/equipmentManagement/repair'; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { addMaintain } from "@/api/equipmentManagement/repair"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ç»´ä¿®è¡¨å", |
| | | }); |
| | | defineOptions({ |
| | | name: "设å¤ç»´ä¿®è¡¨å", |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const loading = ref(false); |
| | | const showDatePicker = ref(false); |
| | | const pickerDateValue = ref(Date.now());; // ä½¿ç¨æ¶é´æ³ |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const loading = ref(false); |
| | | const showDatePicker = ref(false); |
| | | const pickerDateValue = ref(Date.now()); // ä½¿ç¨æ¶é´æ³ |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | maintenanceName: [{ required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®äºº" }], |
| | | maintenanceResult: [{ required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®ç»æ" }], |
| | | maintenanceTime: [{ required: true, trigger: "change", message: "è¯·éæ©ç»´ä¿®æ¥æ" }], |
| | | }; |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | maintenanceName: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®äºº" }, |
| | | ], |
| | | maintenanceResult: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®ç»æ" }, |
| | | ], |
| | | maintenanceTime: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©ç»´ä¿®æ¥æ" }, |
| | | ], |
| | | }; |
| | | const repairStatusOptions = ref([ |
| | | { name: "å¾
ç»´ä¿®", value: "0" }, |
| | | { name: "å®ç»", value: "1" }, |
| | | { name: "失败", value: "2" }, |
| | | ]); |
| | | const repairStatusText = ref("å®ç»"); |
| | | // æå¼æ¥ä¿®ç¶æéæ©å¨ |
| | | const openRepairStatusPicker = () => { |
| | | uni.showActionSheet({ |
| | | itemList: repairStatusOptions.value.map(item => item.name), |
| | | success: res => { |
| | | form.value.status = repairStatusOptions.value[res.tapIndex].value; |
| | | repairStatusText.value = repairStatusOptions.value[res.tapIndex].name; |
| | | }, |
| | | }); |
| | | }; |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | maintenanceName: userStore.nickName || "", // é»è®¤ä½¿ç¨å½åç¨æ·æµç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // ç»´ä¿®æ¥æï¼åªæ¾ç¤ºæ¥æï¼ |
| | | }); |
| | | |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | maintenanceName: userStore.nickName || '', // é»è®¤ä½¿ç¨å½åç¨æ·æµç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // ç»´ä¿®æ¥æï¼åªæ¾ç¤ºæ¥æï¼ |
| | | }); |
| | | // èªå®ä¹showToast彿° |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // èªå®ä¹showToast彿° |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | | const resetForm = () => { |
| | | form.value = { |
| | | maintenanceName: userStore.nickName || "", |
| | | maintenanceResult: undefined, |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | | const resetForm = () => { |
| | | form.value = { |
| | | maintenanceName: userStore.nickName || '', |
| | | maintenanceResult: undefined, |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | }; |
| | | |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (valid) { |
| | | submitFormData(); |
| | | } |
| | | } catch (e) { |
| | | showToast("表åéªè¯å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (valid) { |
| | | submitFormData(); |
| | | } |
| | | } catch (e) { |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | | }; |
| | | // æäº¤è¡¨åæ°æ® |
| | | const submitFormData = async () => { |
| | | try { |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | // æäº¤è¡¨åæ°æ® |
| | | const submitFormData = async () => { |
| | | try { |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | if (!id) { |
| | | showToast('åæ°é误'); |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // åå¤æäº¤æ°æ®ï¼maintenanceTime å ä¸å½åæ¶åç§ |
| | | const submitData = { ...form.value }; |
| | | |
| | | const { code } = await addMaintain({ id: id, ...submitData }); |
| | | |
| | | if (code == 200) { |
| | | showToast('æ°å¢ç»´ä¿®æå'); |
| | | resetFormAndValidate(); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | |
| | | loading.value = false; |
| | | showToast('æä½å¤±è´¥'); |
| | | } |
| | | }; |
| | | if (!id) { |
| | | showToast("åæ°é误"); |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | form.value.status = Number(form.value.status); |
| | | // åå¤æäº¤æ°æ®ï¼maintenanceTime å ä¸å½åæ¶åç§ |
| | | const submitData = { ...form.value }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | const { code } = await addMaintain({ id: id, ...submitData }); |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | if (code == 200) { |
| | | showToast("æ°å¢ç»´ä¿®æå"); |
| | | resetFormAndValidate(); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.maintenanceTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | pickerDateValue.value = e.value |
| | | showDatePicker.value = false; |
| | | }; |
| | | loading.value = false; |
| | | showToast("æä½å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // åå§åè¡¨åæ°æ® |
| | | const initForm = () => { |
| | | // 设置维修人为å½åç¨æ·æµç§° |
| | | form.value.maintenanceName = userStore.nickName || ''; |
| | | // 设置å½åæ¥æï¼åªå
å«å¹´ææ¥ï¼ |
| | | form.value.maintenanceTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("repairId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const id = uni.getStorageSync("repairId"); |
| | | return id; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.maintenanceTime = dayjs(e.value).format("YYYY-MM-DD HH:mm:ss"); |
| | | pickerDateValue.value = e.value; |
| | | showDatePicker.value = false; |
| | | }; |
| | | |
| | | // åå§åè¡¨åæ°æ® |
| | | const initForm = () => { |
| | | form.value.status = "1"; |
| | | // 设置维修人为å½åç¨æ·æµç§° |
| | | form.value.maintenanceName = userStore.nickName || ""; |
| | | // 设置å½åæ¥æï¼åªå
å«å¹´ææ¥ï¼ |
| | | form.value.maintenanceTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-maintain { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import "@/static/scss/form-common.scss"; |
| | | .repair-maintain { |
| | | 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; |
| | | } |
| | | .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: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 6.375rem; |
| | | background: #c7c9cc; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 14rem; |
| | | background: linear-gradient(140deg, #00baff 0%, #006cfb 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="notice-page"> |
| | | <PageHeader title="è¿è¡ç®¡ç" |
| | | @back="goBack" /> |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <view class="notice-board"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <view v-if="holidayNotices.length > 0" |
| | | class="notice-section"> |
| | | <view class="section-header"> |
| | | <h3>设å¤è¿è¡è®°å½</h3> |
| | | </view> |
| | | <view class="notice-cards"> |
| | | <!-- æ¾åéç¥ --> |
| | | <view v-for="notice in holidayNotices" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': isOverdue(notice) }"> |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="holiday-icon"> |
| | | <up-icon name="calendar" |
| | | size="18" |
| | | color="#67c23a" /> |
| | | </view> |
| | | <text>设å¤åç§°ï¼{{ notice.deviceName }}</text> |
| | | </view> |
| | | <view class="card-actions warning" |
| | | v-if="isOverdue(notice)"> |
| | | <up-icon name="info-circle" |
| | | size="16" |
| | | color="#fff" /> |
| | | <text>{{ 'è¶
æ¶æªå¯å¨' }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="card-actions" |
| | | :class="getTagType(notice.status)"> |
| | | <up-icon :name="getIconName(notice.status)" |
| | | size="16" |
| | | color="#fff" /> |
| | | <text>{{ notice.status || 'æªç¥' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>è§æ ¼åå·ï¼{{ notice.deviceModel || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>计åè¿è¡æ¶é´ï¼{{ notice.planRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>å¼å§è¿è¡æ¶é´ï¼{{ notice.startRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>ç»æè¿è¡æ¶é´ï¼{{ notice.endRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>è¿è¡æ¶é¿ï¼{{ notice.runtimeDuration || "-" }}</text> |
| | | </view> |
| | | <up-button text |
| | | v-if="isOverdue(notice)" |
| | | type="warning" |
| | | size="small" |
| | | @click="handleEdit(notice, 'å¯å¨è¿è¡')" |
| | | :disabled="isNoticeExpired(notice)"> |
| | | <up-icon name="play-circle" |
| | | size="16" |
| | | style="margin-right: 10rpx;" |
| | | color="#fff" /> |
| | | ç«å³å¯å¨ |
| | | </up-button> |
| | | <up-button text |
| | | v-else-if="notice.status" |
| | | :type="getTagType2(notice.status)" |
| | | size="small" |
| | | @click="handleEdit(notice, notice.status === 'è¿è¡ä¸' ? '忢è¿è¡' : 'å¯å¨è¿è¡')" |
| | | :disabled="isNoticeExpired(notice)"> |
| | | <up-icon :name="getIconName2(notice.status)" |
| | | size="16" |
| | | color="#fff" /> |
| | | {{ notice.status === 'è¿è¡ä¸' ? '忢è¿è¡' : 'ç«å³å¯å¨' }} |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view class="empty-state" |
| | | v-if="holidayNotices.length === 0 && maintenanceNotices.length === 0"> |
| | | <text>ææ è¿è¡è®°å½</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getLedgerPage, |
| | | editLedger, |
| | | } from "@/api/equipmentManagement/runManagement.js"; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = status => { |
| | | switch (status) { |
| | | case "è¿è¡ä¸": |
| | | return "success"; |
| | | case "忢è¿è¡": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | const getTagType2 = status => { |
| | | switch (status) { |
| | | case "忢è¿è¡": |
| | | return "success"; |
| | | case "è¿è¡ä¸": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | // è·å徿 åç§° |
| | | const getIconName = status => { |
| | | switch (status) { |
| | | case "è¿è¡ä¸": |
| | | return "play-circle"; |
| | | case "忢è¿è¡": |
| | | return "pause-circle"; |
| | | default: |
| | | return "question-circle"; |
| | | } |
| | | }; |
| | | // è·å徿 åç§°2 |
| | | const getIconName2 = status => { |
| | | switch (status) { |
| | | case "忢è¿è¡": |
| | | return "play-circle"; |
| | | case "è¿è¡ä¸": |
| | | return "pause-circle"; |
| | | default: |
| | | return "question-circle"; |
| | | } |
| | | }; |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const isOverdue = notice => { |
| | | if ( |
| | | notice.status == "è¿è¡ä¸" || |
| | | !notice.planRuntimeTime || |
| | | notice.startRuntimeTime |
| | | ) { |
| | | return false; |
| | | } |
| | | const planTime = new Date(notice.planRuntimeTime).getTime(); |
| | | const currentTime = new Date().getTime(); |
| | | return currentTime > planTime; |
| | | }; |
| | | |
| | | const isNoticeExpired = notice => { |
| | | if (!notice || !notice.expirationDate) { |
| | | return false; |
| | | } |
| | | |
| | | const expiration = new Date(notice.expirationDate); |
| | | |
| | | if (Number.isNaN(expiration.getTime())) { |
| | | return false; |
| | | } |
| | | |
| | | expiration.setHours(23, 59, 59, 999); |
| | | |
| | | return new Date() > expiration; |
| | | }; |
| | | |
| | | const handleEdit = async (device, status) => { |
| | | try { |
| | | const currentTime = new Date() |
| | | .toLocaleString("zh-CN", { |
| | | year: "numeric", |
| | | month: "2-digit", |
| | | day: "2-digit", |
| | | hour: "2-digit", |
| | | minute: "2-digit", |
| | | second: "2-digit", |
| | | hour12: false, |
| | | }) |
| | | .replace(/\//g, "-"); |
| | | |
| | | // æ´æ°è®¾å¤ç¶æåç¸å
³æ¶é´å段 |
| | | if (status === "å¯å¨è¿è¡") { |
| | | device.status = "è¿è¡ä¸"; |
| | | device.startRuntimeTime = currentTime; |
| | | device.endRuntimeTime = null; // æ¸
ç©ºç»ææ¶é´ |
| | | device.runtimeDuration = null; // æ¸
空è¿è¡æ¶é¿ |
| | | } else { |
| | | device.status = "忢è¿è¡"; |
| | | device.endRuntimeTime = currentTime; |
| | | // 计ç®è¿è¡æ¶é¿ |
| | | if (device.startRuntimeTime) { |
| | | const startTime = new Date(device.startRuntimeTime); |
| | | const endTime = new Date(currentTime); |
| | | const duration = endTime - startTime; |
| | | const hours = Math.floor(duration / (1000 * 60 * 60)); |
| | | const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60)); |
| | | device.runtimeDuration = `${hours}å°æ¶${minutes}åé`; |
| | | } |
| | | } |
| | | const params = { |
| | | id: device.id, |
| | | status: device.status, |
| | | planRuntimeTime: device.planRuntimeTime, |
| | | startRuntimeTime: device.startRuntimeTime, |
| | | endRuntimeTime: device.endRuntimeTime, |
| | | runtimeDuration: device.runtimeDuration, |
| | | }; |
| | | // è°ç¨APIæ´æ°è®¾å¤ç¶æ |
| | | const response = await editLedger(params); |
| | | if (response.code === 200) { |
| | | showToast(`${device.deviceName} ${status}æå`); |
| | | // å·æ°å表 |
| | | await fetchHolidayNotices(); |
| | | } else { |
| | | showToast(response.msg || "æä½å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | console.error("æ´æ°è®¾å¤ç¶æå¤±è´¥:", error); |
| | | showToast("æä½å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | const holidayNotices = ref([]); |
| | | const maintenanceNotices = ref([]); |
| | | |
| | | const fetchHolidayNotices = (append = false) => { |
| | | getLedgerPage({}).then(res => { |
| | | holidayNotices.value = res?.data?.records || []; |
| | | }); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | fetchHolidayNotices(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .notice-page { |
| | | min-height: 100vh; |
| | | background: #f5f7fa; |
| | | padding-bottom: 16px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .search_form { |
| | | background: #ffffff; |
| | | padding: 12px 16px; |
| | | margin: 8px 12px 12px; |
| | | border-radius: 10px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04); |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | } |
| | | |
| | | .search_title { |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .notice-board { |
| | | padding: 0 12px 16px; |
| | | } |
| | | |
| | | .notice-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 4px 4px 12px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .section-count { |
| | | margin-left: 10px; |
| | | background: #409eff; |
| | | color: white; |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .notice-cards { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .notice-card { |
| | | background: white; |
| | | border-radius: 12px; |
| | | padding: 14px 14px 10px; |
| | | box-shadow: 0 4px 10px rgba(15, 23, 42, 0.06); |
| | | transition: all 0.3s ease; |
| | | border-left: 4px solid transparent; |
| | | } |
| | | |
| | | .notice-card:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .holiday-card { |
| | | border-left-color: #bec4c3; |
| | | } |
| | | |
| | | .maintenance-card { |
| | | border-left-color: #e6a23c; |
| | | } |
| | | |
| | | .urgent { |
| | | border-left-color: #f56c6c; |
| | | background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-title { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | flex: 1; |
| | | } |
| | | |
| | | .holiday-icon { |
| | | color: #67c23a; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .maintenance-icon { |
| | | color: #e6a23c; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | padding: 4rpx 8rpx; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .card-content { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-content text { |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-meta { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .type, |
| | | .priority, |
| | | .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .type-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .priority-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | .success { |
| | | background: #67c23a; |
| | | color: #fff; |
| | | } |
| | | .error { |
| | | background: #f56c6c; |
| | | color: #fff; |
| | | } |
| | | .info { |
| | | background: #a8a9aa; |
| | | color: #fff; |
| | | } |
| | | .warning { |
| | | background: #e6a23c; |
| | | color: #fff; |
| | | } |
| | | |
| | | .priority-3 { |
| | | background: #fef2f2; |
| | | color: #dc2626; |
| | | } |
| | | |
| | | .status-0 { |
| | | background: #f3f4f6; |
| | | color: #6b7280; |
| | | } |
| | | |
| | | .status-1 { |
| | | background: #d1fae5; |
| | | color: #059669; |
| | | } |
| | | |
| | | .status-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .card-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .creator { |
| | | font-weight: 500; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .expiration { |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .card-remark { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .empty-state { |
| | | text-align: center; |
| | | padding: 48px 16px; |
| | | color: #999; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | /* ç§»å¨ç«¯å¼¹çªæ ·å¼ */ |
| | | .dialog-container { |
| | | background: #ffffff; |
| | | border-radius: 18px 18px 0 0; |
| | | max-height: 80vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .dialog-header { |
| | | padding: 16px 20px 8px 20px; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-body { |
| | | flex: 1; |
| | | padding: 0 16px 12px 16px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | padding: 12px 16px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .search_form > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="file-list-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="é件管ç" |
| | | @back="goBack" /> |
| | | <!-- éä»¶å表 --> |
| | | <view class="file-list-container"> |
| | | <view v-if="fileList.length > 0" |
| | | class="file-list"> |
| | | <view v-for="(file, index) in fileList" |
| | | :key="file.id || index" |
| | | class="file-item"> |
| | | <!-- æä»¶å¾æ --> |
| | | <!-- <view class="file-icon" |
| | | :class="getFileIconClass(file.fileType)"> |
| | | <up-icon :name="getFileIcon(file.fileType)" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | </view> --> |
| | | <!-- æä»¶ä¿¡æ¯ --> |
| | | <view class="file-info"> |
| | | <text class="file-name">{{ file.name }}</text> |
| | | <!-- <text class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ file.uploadTime || file.createTime }}</text> --> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="file-actions"> |
| | | <!-- <u-button size="small" |
| | | type="primary" |
| | | plain |
| | | @click="previewFile(file)">é¢è§</u-button> --> |
| | | <u-button size="small" |
| | | type="info" |
| | | plain |
| | | @click="downloadFile(file)">ä¸è½½å¹¶é¢è§</u-button> |
| | | <u-button size="small" |
| | | type="error" |
| | | plain |
| | | @click="confirmDelete(file, index)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-else |
| | | class="empty-state"> |
| | | <up-icon name="document" |
| | | size="64" |
| | | color="#c0c4cc" /> |
| | | <text class="empty-text">ææ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | <!-- <a rel="nofollow" |
| | | id="downloadLink" |
| | | href="#" |
| | | style="display:none;">ä¸è½½ææ¬æä»¶</a> --> |
| | | <!-- ä¸ä¼ æé® --> |
| | | <view class="upload-button" |
| | | @click="chooseFile"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | <text class="upload-text">ä¸ä¼ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import config from "@/config"; |
| | | import { getToken } from "@/utils/auth"; |
| | | // import { saveAs } from "file-saver"; |
| | | import { |
| | | listMaintenanceTaskFiles, |
| | | addMaintenanceTaskFile, |
| | | delMaintenanceTaskFile, |
| | | } from "@/api/equipmentManagement/upkeep"; |
| | | import { blobValidate } from "@/utils/ruoyi"; |
| | | |
| | | // éä»¶å表 |
| | | const fileList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // const request = axios.create({ |
| | | // baseURL: "URL.com", |
| | | // adapter: axiosAdapterUniapp, |
| | | // }); |
| | | // è·åæä»¶å¾æ |
| | | const getFileIcon = fileType => { |
| | | const iconMap = { |
| | | doc: "document", |
| | | docx: "document", |
| | | xls: "grid", |
| | | xlsx: "grid", |
| | | pdf: "document", |
| | | ppt: "copy", |
| | | pptx: "copy", |
| | | txt: "document", |
| | | jpg: "image", |
| | | jpeg: "image", |
| | | png: "image", |
| | | gif: "image", |
| | | zip: "folder", |
| | | rar: "folder", |
| | | }; |
| | | return iconMap[fileType.toLowerCase()] || "document"; |
| | | }; |
| | | |
| | | // è·åæä»¶å¾æ æ ·å¼ç±» |
| | | const getFileIconClass = fileType => { |
| | | const colorMap = { |
| | | doc: "blue", |
| | | docx: "blue", |
| | | xls: "green", |
| | | xlsx: "green", |
| | | pdf: "red", |
| | | ppt: "orange", |
| | | pptx: "orange", |
| | | txt: "gray", |
| | | jpg: "purple", |
| | | jpeg: "purple", |
| | | png: "purple", |
| | | gif: "purple", |
| | | zip: "yellow", |
| | | rar: "yellow", |
| | | }; |
| | | return colorMap[fileType.toLowerCase()] || "gray"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæä»¶å¤§å° |
| | | const formatFileSize = bytes => { |
| | | if (bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }; |
| | | |
| | | // éæ©æä»¶ |
| | | const chooseFile = () => { |
| | | uni.chooseImage({ |
| | | count: 9, |
| | | sizeType: ["original", "compressed"], |
| | | sourceType: ["album", "camera"], |
| | | success: res => { |
| | | console.log(res, "éæ©å¾çæå"); |
| | | uploadFiles(res.tempFiles); |
| | | }, |
| | | fail: err => { |
| | | console.error("éæ©å¾ç失败:", err); |
| | | showToast("éæ©æä»¶å¤±è´¥"); |
| | | }, |
| | | }); |
| | | // uni.chooseFile({ |
| | | // count: 9, |
| | | // extension: [ |
| | | // ".doc", |
| | | // ".docx", |
| | | // ".xls", |
| | | // ".xlsx", |
| | | // ".pdf", |
| | | // ".ppt", |
| | | // ".pptx", |
| | | // ".txt", |
| | | // ".jpg", |
| | | // ".jpeg", |
| | | // ".png", |
| | | // ".gif", |
| | | // ".zip", |
| | | // ".rar", |
| | | // ], |
| | | // success: res => { |
| | | // console.log(res, "éæ©æä»¶æå"); |
| | | // uploadFiles(res.tempFiles); |
| | | // }, |
| | | // fail: err => { |
| | | // showToast("éæ©æä»¶å¤±è´¥"); |
| | | // }, |
| | | // }); |
| | | }; |
| | | |
| | | // ä¸ä¼ æä»¶ |
| | | const uploadFiles = tempFiles => { |
| | | console.log(tempFiles, "ä¸ä¼ æä»¶1"); |
| | | tempFiles.forEach((tempFile, index) => { |
| | | // æ¾ç¤ºä¸ä¼ ä¸æç¤º |
| | | uni.showLoading({ |
| | | title: "ä¸ä¼ ä¸...", |
| | | mask: true, |
| | | }); |
| | | console.log(tempFile, "ä¸ä¼ æä»¶2"); |
| | | // 1. ç´æ¥ä½¿ç¨ uni.uploadFile ä¸ä¼ æä»¶ |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + "/file/upload", |
| | | filePath: tempFile.path, |
| | | name: "file", |
| | | header: { |
| | | Authorization: "Bearer " + getToken(), |
| | | }, |
| | | success: uploadRes => { |
| | | uni.hideLoading(); |
| | | console.log(uploadRes, "ä¸ä¼ æä»¶3"); |
| | | |
| | | try { |
| | | const res = JSON.parse(uploadRes.data); |
| | | console.log(res, "ä¸ä¼ æä»¶4"); |
| | | if (res.code === 200) { |
| | | // 2. æåæä»¶ä¿¡æ¯ |
| | | const fileName = tempFile.name |
| | | ? tempFile.name |
| | | : tempFile.path.split("/").pop(); |
| | | // const fileType = fileName.split(".").pop(); |
| | | // 3. æé ä¿åæä»¶ä¿¡æ¯çåæ° |
| | | const saveData = { |
| | | name: fileName, |
| | | deviceMaintenanceId: upkeepId.value, |
| | | url: res.data.tempPath || "", |
| | | }; |
| | | console.log(saveData, "ä¿åæä»¶ä¿¡æ¯åæ°"); |
| | | // 4. è°ç¨ addRuleFile æ¥å£ä¿åæä»¶ä¿¡æ¯ |
| | | addMaintenanceTaskFile(saveData) |
| | | .then(addRes => { |
| | | if (addRes.code === 200) { |
| | | // 5. æ·»å å°æä»¶å表 |
| | | const newFile = { |
| | | ...addRes.data, |
| | | uploadTime: new Date().toLocaleString(), |
| | | }; |
| | | // fileList.value.push(newFile); |
| | | getFileList(); |
| | | showToast("ä¸ä¼ æå"); |
| | | } else { |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¿åæä»¶ä¿¡æ¯å¤±è´¥:", err); |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | showToast("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è§£æä¸ä¼ ç»æå¤±è´¥:", e); |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("ä¸ä¼ 失败:", err); |
| | | showToast("ä¸ä¼ 失败"); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | // ä¸è½½æä»¶ |
| | | const downloadFile = file => { |
| | | var url = |
| | | config.baseUrl + |
| | | "/common/download?fileName=" + |
| | | encodeURIComponent(file.url) + |
| | | "&delete=true"; |
| | | console.log(url, "url"); |
| | | |
| | | uni |
| | | .downloadFile({ |
| | | url: url, |
| | | responseType: "blob", |
| | | header: { Authorization: "Bearer " + getToken() }, |
| | | }) |
| | | .then(res => { |
| | | let osType = uni.getStorageSync("deviceInfo").osName; |
| | | let filePath = res.tempFilePath; |
| | | if (osType === "ios") { |
| | | uni.openDocument({ |
| | | filePath: filePath, |
| | | showMenu: true, |
| | | success: res => {}, |
| | | fail: err => { |
| | | console.log("uni.openDocument--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.saveFile({ |
| | | tempFilePath: filePath, |
| | | success: fileRes => { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | mask: true, |
| | | title: |
| | | "æä»¶å·²ä¿åï¼Android/data/uni.UNI720216F/apps/__UNI__720216F/" + |
| | | fileRes.savedFilePath, //ä¿åè·¯å¾ |
| | | duration: 3000, |
| | | }); |
| | | setTimeout(() => { |
| | | //æå¼ææ¡£æ¥ç |
| | | uni.openDocument({ |
| | | filePath: fileRes.savedFilePath, |
| | | success: function (res) {}, |
| | | }); |
| | | }, 1000); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.save--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } |
| | | // const isBlob = blobValidate(res.data); |
| | | // if (isBlob) { |
| | | // const blob = new Blob([res.data], { type: "text/plain" }); |
| | | // const url = URL.createObjectURL(blob); |
| | | // const downloadLink = document.getElementById("downloadLink"); |
| | | // downloadLink.href = url; |
| | | // downloadLink.download = file.name; |
| | | // downloadLink.click(); |
| | | // showToast("ä¸è½½æå"); |
| | | // } else { |
| | | // showToast("ä¸è½½å¤±è´¥"); |
| | | // } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¸è½½å¤±è´¥:", err); |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // 确认å é¤ |
| | | const confirmDelete = (file, index) => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤éä»¶ "${file.name}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteFile(file.id, index); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (fileId, index) => { |
| | | uni.showLoading({ |
| | | title: "å é¤ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | delMaintenanceTaskFile([fileId]) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | // fileList.value.splice(index, 1); |
| | | getFileList(); |
| | | showToast("å 餿å"); |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæç¤º |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | const rulesRegulationsManagementId = ref(""); |
| | | const upkeepId = ref(""); |
| | | // 页é¢å è½½æ¶ |
| | | onMounted(() => { |
| | | // ä» API è·åéä»¶å表 |
| | | |
| | | // 仿¬å°åå¨è·å rulesRegulationsManagementId |
| | | rulesRegulationsManagementId.value = uni.getStorageSync( |
| | | "rulesRegulationsManagement" |
| | | ); |
| | | upkeepId.value = uni.getStorageSync("upkeepId"); |
| | | getFileList(); |
| | | }); |
| | | |
| | | // è·åéä»¶å表 |
| | | const getFileList = () => { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | listMaintenanceTaskFiles({ |
| | | current: 1, |
| | | size: 100, |
| | | deviceMaintenanceId: upkeepId.value, |
| | | rulesRegulationsManagementId: upkeepId.value, |
| | | }) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | fileList.value = res.data.records || []; |
| | | } else { |
| | | showToast("è·åéä»¶å表失败"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("è·åéä»¶å表失败"); |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .file-list-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100rpx; |
| | | } |
| | | |
| | | .file-list-container { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .file-list { |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .file-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | |
| | | .file-icon { |
| | | width: 56rpx; |
| | | height: 56rpx; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 20rpx; |
| | | |
| | | &.blue { |
| | | background: #409eff; |
| | | } |
| | | |
| | | &.green { |
| | | background: #67c23a; |
| | | } |
| | | |
| | | &.red { |
| | | background: #f56c6c; |
| | | } |
| | | |
| | | &.orange { |
| | | background: #e6a23c; |
| | | } |
| | | |
| | | &.gray { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.purple { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.yellow { |
| | | background: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #303133; |
| | | margin-bottom: 8rpx; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | display: flex; |
| | | gap: 12rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 100rpx 0; |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .upload-button { |
| | | position: fixed; |
| | | bottom: 40rpx; |
| | | right: 40rpx; |
| | | width: 130rpx; |
| | | height: 130rpx; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.4); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 10px; |
| | | color: #ffffff; |
| | | margin-top: 4rpx; |
| | | } |
| | | |
| | | .upload-progress { |
| | | padding: 40rpx 0; |
| | | } |
| | | |
| | | .upload-progress-text { |
| | | display: block; |
| | | text-align: center; |
| | | margin-top: 20rpx; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="设å¤ä¿å
»" @back="goBack" /> |
| | | |
| | | <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" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°æç´¢" |
| | | v-model="searchKeyword" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 设å¤ä¿å
»å表 --> |
| | | <view class="ledger-list" v-if="upkeepList.length > 0"> |
| | | <view v-for="(item, index) in upkeepList" :key="index"> |
| | | <view class="ledger-item" @click="toggleSelection(item)"> |
| | | <view class="ledger-list" |
| | | v-if="upkeepList.length > 0"> |
| | | <view v-for="(item, index) in upkeepList" |
| | | :key="index"> |
| | | <view class="ledger-item" |
| | | @click="toggleSelection(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">设å¤åç§°ï¼{{ item.deviceName }}</text> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag v-if="item.status === 1" type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" type="error">å¾
ä¿å
»</u-tag> |
| | | <u-tag v-if="item.status === 1" |
| | | type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" |
| | | type="error">å¾
ä¿å
»</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¿å
ȍȾ</text> |
| | | <view class="detail-value"> |
| | | <u-tag v-if="item.maintenanceResult === 1" type="success" size="mini"> |
| | | å®å¥½ |
| | | </u-tag> |
| | | <u-tag v-if="item.maintenanceResult === 0" type="error" size="mini"> |
| | | ç»´ä¿® |
| | | </u-tag> |
| | | <text v-if="item.maintenanceResult === undefined || item.maintenanceResult === null">-</text> |
| | | </view> |
| | | <u-tag v-if="item.maintenanceResult === 1" |
| | | type="success" |
| | | size="mini"> |
| | | å®å¥½ |
| | | </u-tag> |
| | | <u-tag v-if="item.maintenanceResult === 0" |
| | | type="error" |
| | | size="mini"> |
| | | ç»´ä¿® |
| | | </u-tag> |
| | | <text v-if="item.maintenanceResult === undefined || item.maintenanceResult === null">-</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click.stop="edit(item.id)" |
| | | > |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click.stop="edit(item.id)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button |
| | | type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click.stop="addMaintain(item.id)" |
| | | > |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click.stop="addMaintain(item.id)"> |
| | | ä¿å
» |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click.stop="delUpkeepByIds(item.id)" |
| | | > |
| | | <u-button type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click.stop="delUpkeepByIds(item.id)"> |
| | | å é¤ |
| | | </u-button> |
| | | <u-button type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="addFile(item.id)"> |
| | | éä»¶ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ è®¾å¤ä¿å
»æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" @click="addPlan"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | <view class="fab-button" |
| | | @click="addPlan"> |
| | | <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 { getUpkeepPage, delUpkeep } from '@/api/equipmentManagement/upkeep' |
| | | import useUserStore from "@/store/modules/user" |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | import dayjs from "dayjs" |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getUpkeepPage, delUpkeep } from "@/api/equipmentManagement/upkeep"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref('') |
| | | // æç´¢å
³é®è¯ |
| | | const searchKeyword = ref(""); |
| | | |
| | | // 设å¤ä¿å
»æ°æ® |
| | | const upkeepList = ref([]) |
| | | // 设å¤ä¿å
»æ°æ® |
| | | const upkeepList = ref([]); |
| | | |
| | | // å¤éå表 |
| | | const multipleList = ref([]) |
| | | // å¤éå表 |
| | | const multipleList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | return dayjs(dateStr).format("YYYY-MM-DD") |
| | | } |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | return dayjs(dateStr).format("YYYY-MM-DD HH:mm:ss") |
| | | } |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | deviceName: searchKeyword.value || undefined |
| | | } |
| | | getUpkeepPage(params) |
| | | .then((res) => { |
| | | // 妿res.data䏿¯æ°ç»ï¼è®¾ç½®ä¸ºç©ºæ°ç» |
| | | upkeepList.value = res.records || res.data?.records || [] |
| | | closeToast() |
| | | }) |
| | | .catch(() => { |
| | | closeToast() |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | } |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | deviceName: searchKeyword.value || undefined, |
| | | }; |
| | | getUpkeepPage(params) |
| | | .then(res => { |
| | | // 妿res.data䏿¯æ°ç»ï¼è®¾ç½®ä¸ºç©ºæ°ç» |
| | | upkeepList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | // æ°å¢éä»¶ - 跳转å°éä»¶é¡µé¢ |
| | | const addFile = id => { |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éid |
| | | uni.setStorageSync("upkeepId", id); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/upkeep/fileList", |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // åæ¢éæ©ç¶æ |
| | | const toggleSelection = (item) => { |
| | | const index = multipleList.value.findIndex(selected => selected.id === item.id) |
| | | if (index > -1) { |
| | | multipleList.value.splice(index, 1) |
| | | } else { |
| | | multipleList.value.push(item) |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦å·²éæ© |
| | | const isSelected = (item) => { |
| | | return multipleList.value.some(selected => selected.id === item.id) |
| | | } |
| | | |
| | | // æ°å¢ä¿å
» - 跳转å°ä¿å
»é¡µé¢ |
| | | const addMaintain = (id) => { |
| | | if (!id && multipleList.value.length !== 1) { |
| | | showToast('è¯·éæ©ä¸æ¡è®°å½') |
| | | return |
| | | } |
| | | const targetId = id || multipleList.value[0].id |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éid |
| | | uni.setStorageSync('repairId', targetId) |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/upkeep/maintain' |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢è®¡å - è·³è½¬å°æ°å¢é¡µé¢ |
| | | const addPlan = () => { |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/upkeep/add' |
| | | }) |
| | | } |
| | | |
| | | // ç¼è¾ - 跳转å°add页é¢ï¼éè¿idåºåæ°å¢è¿æ¯ç¼è¾ |
| | | const edit = (id) => { |
| | | if (!id) return |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éid |
| | | uni.setStorageSync('repairId', id) |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/upkeep/add' |
| | | }) |
| | | } |
| | | |
| | | // å é¤ä¿å
»æ°æ® |
| | | const delUpkeepByIds = async (ids) => { |
| | | const deleteIds = Array.isArray(ids) ? ids : [ids] |
| | | if (deleteIds.length === 0) { |
| | | showToast('è¯·éæ©è¦å é¤çè®°å½') |
| | | return |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: 'è¦å', |
| | | content: '确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?', |
| | | confirmText: 'ç¡®å®', |
| | | cancelText: 'åæ¶', |
| | | success: async (res) => { |
| | | if (!res.confirm) return |
| | | try { |
| | | // é个å é¤ |
| | | for (const id of deleteIds) { |
| | | const response = await delUpkeep(id) |
| | | if (response.code !== 200) { |
| | | showToast('å é¤å¤±è´¥') |
| | | return |
| | | } |
| | | } |
| | | showToast('å 餿å') |
| | | multipleList.value = [] |
| | | getList() |
| | | } catch (e) { |
| | | showToast('å é¤å¤±è´¥') |
| | | } |
| | | // åæ¢éæ©ç¶æ |
| | | const toggleSelection = item => { |
| | | const index = multipleList.value.findIndex( |
| | | selected => selected.id === item.id |
| | | ); |
| | | if (index > -1) { |
| | | multipleList.value.splice(index, 1); |
| | | } else { |
| | | multipleList.value.push(item); |
| | | } |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | // æ£æ¥æ¯å¦å·²éæ© |
| | | const isSelected = item => { |
| | | return multipleList.value.some(selected => selected.id === item.id); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | // æ°å¢ä¿å
» - 跳转å°ä¿å
»é¡µé¢ |
| | | const addMaintain = id => { |
| | | if (!id && multipleList.value.length !== 1) { |
| | | showToast("è¯·éæ©ä¸æ¡è®°å½"); |
| | | return; |
| | | } |
| | | const targetId = id || multipleList.value[0].id; |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éid |
| | | uni.setStorageSync("repairId", targetId); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/upkeep/maintain", |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢è®¡å - è·³è½¬å°æ°å¢é¡µé¢ |
| | | const addPlan = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/upkeep/add", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ - 跳转å°add页é¢ï¼éè¿idåºåæ°å¢è¿æ¯ç¼è¾ |
| | | const edit = id => { |
| | | if (!id) return; |
| | | // ä½¿ç¨æ¬å°åå¨ä¼ éid |
| | | uni.setStorageSync("repairId", id); |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/upkeep/add", |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ä¿å
»æ°æ® |
| | | const delUpkeepByIds = async ids => { |
| | | const deleteIds = Array.isArray(ids) ? ids : [ids]; |
| | | if (deleteIds.length === 0) { |
| | | showToast("è¯·éæ©è¦å é¤çè®°å½"); |
| | | return; |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: "è¦å", |
| | | content: "确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?", |
| | | confirmText: "ç¡®å®", |
| | | cancelText: "åæ¶", |
| | | success: async res => { |
| | | if (!res.confirm) return; |
| | | try { |
| | | // é个å é¤ |
| | | for (const id of deleteIds) { |
| | | const response = await delUpkeep(id); |
| | | if (response.code !== 200) { |
| | | showToast("å é¤å¤±è´¥"); |
| | | return; |
| | | } |
| | | } |
| | | showToast("å 餿å"); |
| | | multipleList.value = []; |
| | | getList(); |
| | | } catch (e) { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 设å¤ä¿å
»ç¹ææ ·å¼ |
| | | .sales-account { |
| | | padding-bottom: 80px; // ä¸ºæµ®å¨æé®çåºç©ºé´ |
| | | } |
| | | // 设å¤ä¿å
»ç¹ææ ·å¼ |
| | | .sales-account { |
| | | padding-bottom: 80px; // ä¸ºæµ®å¨æé®çåºç©ºé´ |
| | | } |
| | | |
| | | .action-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | .action-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .action-section .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | justify-content: flex-start; |
| | | } |
| | | .action-section .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .checkbox-wrapper { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .checkbox-wrapper { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .status-tag { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .status-tag { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-label { |
| | | min-width: 80px; // ä¸å
Œ
±æ ·å¼ä¸ç 60px ä¸å |
| | | } |
| | | .detail-label { |
| | | min-width: 80px; // ä¸å
Œ
±æ ·å¼ä¸ç 60px ä¸å |
| | | } |
| | | |
| | | .detail-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | } |
| | | .detail-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | } |
| | | |
| | | .ledger-item .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | } |
| | | .ledger-item .action-buttons { |
| | | gap: 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 12px ä¸å |
| | | } |
| | | </style> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- åååå
¬æ¨¡å --> |
| | | <view class="common-module collaboration-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 collaborationItems" |
| | | :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 collaboration-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 collaborationItems" |
| | | :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 production-module">--> |
| | | <!-- <view class="module-header">--> |
| | |
| | | label: "å¼ç¥¨å°è´¦", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/kaipiaotaizhang@2x.png", |
| | | label: "åè´§å°è´¦", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huikuandengji@2x.png", |
| | | label: "忬¾ç»è®°", |
| | | }, |
| | |
| | | ]); |
| | | |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | | { |
| | | icon: "/static/images/icon/xietongshenpi@2x.png", |
| | | label: "åå审æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/kehubaifang@2x.png", |
| | | label: "å®¢æ·æè®¿", |
| | | }, |
| | | ]); |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | | { |
| | | 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 productionItems = reactive([ |
| | |
| | | url: "/pages/sales/invoiceLedger/index", |
| | | }); |
| | | break; |
| | | case "åè´§å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/deliveryLedger/index", |
| | | }); |
| | | break; |
| | | case "忬¾ç»è®°": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/receiptPayment/index", |
| | |
| | | url: "/pages/procurementManagement/paymentLedger/index", |
| | | }); |
| | | break; |
| | | case "åå审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index", |
| | | }); |
| | | break; |
| | | case "å®¢æ·æè®¿": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/clientVisit/index", |
| | | }); |
| | | break; |
| | | case "åå审æ¹": |
| | | uni.navigateTo({ |
| | | 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 "ç产订å": |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/productionOrder/index", |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="content"> |
| | | <PageHeader :title="operationType" |
| | | @back="goBack" /> |
| | | <view class="common-module collaboration-module"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">{{ operationType }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="module-content"> |
| | | <up-grid :border="false" |
| | | col="4"> |
| | | <up-grid-item v-for="(item, index) in commonItems" |
| | | :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> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, reactive, ref } from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const kaoqin = 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: "åºå·®ç®¡ç", |
| | | }, |
| | | ]); |
| | | const caiwu = reactive([ |
| | | { |
| | | 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: "å货审æ¹", |
| | | }, |
| | | ]); |
| | | // èå¤è´¢å¡åå¹¶èåï¼èå¤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: "å货审æ¹", |
| | | }, |
| | | ]); |
| | | |
| | | const huiyi = reactive([ |
| | | { |
| | | icon: "/static/images/icon/huiyishezhi@2x.png", |
| | | label: "ä¼è®®è®¾ç½®", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyiliebiao@2x.png", |
| | | label: "ä¼è®®å表", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyishenqing@2x.png", |
| | | label: "ä¼è®®ç³è¯·", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyishenpi@2x.png", |
| | | label: "ä¼è®®å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyifabu@2x.png", |
| | | label: "ä¼è®®åå¸", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyizongjie@2x.png", |
| | | label: "ä¼è®®æ»ç»", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/huiyikanban@2x.png", |
| | | label: "ä¼è®®çæ¿", |
| | | }, |
| | | ]); |
| | | const commonItems = ref([]); |
| | | // å¤ç常ç¨åè½ç¹å» |
| | | const handleCommonItemClick = item => { |
| | | // æ ¹æ®ä¸åçåè½é¡¹è¿è¡è·³è½¬ |
| | | switch (item.label) { |
| | | case "éå®å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/salesAccount/index", |
| | | }); |
| | | break; |
| | | case "å¼ç¥¨ç»è®°": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/invoicingRegistration/index", |
| | | }); |
| | | break; |
| | | case "å¼ç¥¨å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/invoiceLedger/index", |
| | | }); |
| | | break; |
| | | case "忬¾ç»è®°": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/receiptPayment/index", |
| | | }); |
| | | break; |
| | | case "忬¾æµæ°´": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/receiptPaymentHistory/index", |
| | | }); |
| | | break; |
| | | case "客æ·å¾æ¥": |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/receiptPaymentLedger/index", |
| | | }); |
| | | break; |
| | | case "éè´å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/procurementLedger/index", |
| | | }); |
| | | break; |
| | | case "æ¥ç¥¨ç»è®°": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/invoiceEntry/index", |
| | | }); |
| | | break; |
| | | case "æ¥ç¥¨å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/procurementInvoiceLedger/index", |
| | | }); |
| | | break; |
| | | case "仿¬¾ç»è®°": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/paymentEntry/index", |
| | | }); |
| | | break; |
| | | case "仿¬¾æµæ°´": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/receiptPaymentHistory/index", |
| | | }); |
| | | break; |
| | | case "ä¾åºå徿¥": |
| | | uni.navigateTo({ |
| | | url: "/pages/procurementManagement/paymentLedger/index", |
| | | }); |
| | | break; |
| | | case "å
¬åºç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index1", |
| | | }); |
| | | break; |
| | | case "请å管ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index2", |
| | | }); |
| | | break; |
| | | case "åºå·®ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index3", |
| | | }); |
| | | break; |
| | | case "æ¥é管ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index4", |
| | | }); |
| | | break; |
| | | case "éè´å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index5", |
| | | }); |
| | | break; |
| | | case "æ¥ä»·å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index6", |
| | | }); |
| | | break; |
| | | case "å货审æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/index7", |
| | | }); |
| | | break; |
| | | case "ä¼è®®è®¾ç½®": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingSettings/index", |
| | | }); |
| | | break; |
| | | case "ä¼è®®å表": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingList/index", |
| | | }); |
| | | break; |
| | | case "ä¼è®®ç³è¯·": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetApplication/index", |
| | | }); |
| | | break; |
| | | case "ä¼è®®å®¡æ¹": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetExamine/index", |
| | | }); |
| | | break; |
| | | case "ä¼è®®åå¸": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetPublish/index", |
| | | }); |
| | | break; |
| | | case "ä¼è®®æ»ç»": |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetSummary/index", |
| | | }); |
| | | break; |
| | | 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 "ç产订å": |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/productionOrder/index", |
| | | }); |
| | | break; |
| | | case "ç产派工": |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/productionDispatching/index", |
| | | }); |
| | | break; |
| | | case "å·¥åºæäº§": |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/processScheduling/index", |
| | | }); |
| | | break; |
| | | case "çäº§æ ¸ç®": |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/productionAccounting/index", |
| | | }); |
| | | break; |
| | | case "设å¤å°è´¦": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/ledger/index", |
| | | }); |
| | | break; |
| | | case "è®¾å¤æ¥ä¿®": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/repair/index", |
| | | }); |
| | | break; |
| | | case "设å¤ä¿å
»": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/upkeep/index", |
| | | }); |
| | | break; |
| | | case "设å¤å·¡æ£": |
| | | uni.navigateTo({ |
| | | url: "/pages/inspectionUpload/index", |
| | | }); |
| | | break; |
| | | case "åæè¿½æº¯": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/faultAnalysis/index", |
| | | }); |
| | | break; |
| | | case "æºè½æ´¾å": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/smartDispatch/index", |
| | | }); |
| | | break; |
| | | case "ä½ä¸æå¯¼": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/sop/index", |
| | | }); |
| | | break; |
| | | case "ç»æéªè¯": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/verification/index", |
| | | }); |
| | | break; |
| | | default: |
| | | uni.showToast({ |
| | | title: `ç¹å»äº${item.label}`, |
| | | icon: "none", |
| | | }); |
| | | } |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo(); |
| | | }); |
| | | const operationType = ref(""); |
| | | onLoad(options => { |
| | | if (options.label) { |
| | | // å¤ç URL åæ°å¯è½å
å«å
¶ä»æ¥è¯¢åæ°çæ
åµï¼å¦ï¼åå审æ¹?approveType=6ï¼ |
| | | // åªæå label åæ°çå¼ï¼å»é¤å¯è½éå çæ¥è¯¢åæ° |
| | | let labelValue = options.label; |
| | | // 妿 label å
å« ? 符å·ï¼åªå ? ä¹åçé¨å |
| | | if (labelValue.includes("?")) { |
| | | labelValue = labelValue.split("?")[0]; |
| | | } |
| | | operationType.value = labelValue; |
| | | if (operationType.value === "èå¤ç®¡ç") { |
| | | commonItems.value = kaoqin; |
| | | } else if (operationType.value === "ä¼è®®ç®¡ç") { |
| | | commonItems.value = huiyi; |
| | | } else if (operationType.value === "è´¢å¡ç®¡ç") { |
| | | commonItems.value = caiwu; |
| | | } else if (operationType.value === "åå审æ¹") { |
| | | commonItems.value = kaoqinCaiwu; |
| | | operationType.value = "åå审æ¹"; |
| | | } |
| | | } |
| | | console.log(operationType.value); |
| | | console.log(commonItems.value); |
| | | }); |
| | | </script> |
| | | |
| | | |
| | | <style scoped lang="scss"> |
| | | .content { |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #e3f2fd 100%); |
| | | min-height: 100vh; |
| | | padding: 1.25rem; |
| | | /* 为ææè®¾å¤è®¾ç½®åºç¡padding-top */ |
| | | padding-top: 40px; |
| | | position: relative; |
| | | |
| | | /* iOS设å¤ä½¿ç¨env()彿°å¤çå®å
¨åºå */ |
| | | padding-top: env(safe-area-inset-top); |
| | | |
| | | /* 为å®å设å¤è®¾ç½®æ´å¤§çé¡¶é¨å
è¾¹è· */ |
| | | /* #ifdef APP-PLUS && !MP && !H5 */ |
| | | padding-top: 45px; |
| | | /* #endif */ |
| | | |
| | | /* H5åå°ç¨åºå¹³å°çéç¨æ ·å¼ */ |
| | | /* #ifdef H5 || MP */ |
| | | padding-top: 30px; |
| | | /* #endif */ |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="rgba(41, 121, 255, 0.03)"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>'); |
| | | pointer-events: none; |
| | | z-index: -1; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: radial-gradient( |
| | | circle at 20% 80%, |
| | | rgba(41, 121, 255, 0.02) 0%, |
| | | transparent 50% |
| | | ), |
| | | radial-gradient( |
| | | circle at 80% 20%, |
| | | rgba(156, 39, 176, 0.02) 0%, |
| | | transparent 50% |
| | | ); |
| | | pointer-events: none; |
| | | z-index: -1; |
| | | } |
| | | } |
| | | |
| | | .header-section { |
| | | margin-bottom: 1rem; |
| | | animation: fadeInDown 0.6s ease-out; |
| | | /* 为å®å设å¤é¢å¤è°æ´å¤´é¨ä½ç½® */ |
| | | /* #ifdef APP-PLUS && !MP && !H5 */ |
| | | margin-top: 10px; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .currentFactory { |
| | | margin-top: 0.5rem; |
| | | margin-left: 0.25rem; |
| | | font-weight: 500; |
| | | display: flex; |
| | | } |
| | | |
| | | .factoryName { |
| | | width: auto; |
| | | } |
| | | |
| | | :deep(.u-text) { |
| | | align-items: center; |
| | | } |
| | | |
| | | .hero-section { |
| | | margin-bottom: 1rem; |
| | | animation: fadeInUp 0.6s ease-out 0.1s both; |
| | | } |
| | | |
| | | .bg-img { |
| | | width: 100%; |
| | | height: 8.75rem; |
| | | background-image: url("../static/images/banner/backview.png"); |
| | | background-size: cover; |
| | | border-radius: 0.75rem; |
| | | position: relative; |
| | | overflow: hidden; |
| | | box-shadow: 0 0.25rem 1.25rem rgba(41, 121, 255, 0.15); |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | top: -50%; |
| | | left: -50%; |
| | | width: 200%; |
| | | height: 200%; |
| | | background: conic-gradient( |
| | | from 0deg, |
| | | transparent, |
| | | rgba(255, 255, 255, 0.1), |
| | | transparent, |
| | | rgba(255, 255, 255, 0.05), |
| | | transparent |
| | | ); |
| | | animation: rotate 20s linear infinite; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | width: 7.5rem; |
| | | height: 7.5rem; |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(255, 255, 255, 0.15) 0%, |
| | | transparent 70% |
| | | ); |
| | | border-radius: 50%; |
| | | transform: translate(2.5rem, -2.5rem); |
| | | } |
| | | } |
| | | |
| | | .hero-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | padding: 1.25rem 1.25rem 1.6rem 1.25rem; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .hero-title { |
| | | color: #ffffff; |
| | | font-size: 1.625rem; |
| | | font-weight: 700; |
| | | letter-spacing: 0.03125rem; |
| | | text-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.5); |
| | | } |
| | | .hero-subtitle { |
| | | font-size: 0.8125rem; |
| | | margin-top: 0.375rem; |
| | | } |
| | | .hero-wave { |
| | | height: 2.75rem; |
| | | } |
| | | |
| | | .hero-subtitle { |
| | | color: rgba(255, 255, 255, 0.9); |
| | | font-size: 0.8125rem; |
| | | margin-top: 0.375rem; |
| | | font-weight: 400; |
| | | text-shadow: 0 0.0625rem 0.125rem rgba(0, 0, 0, 0.5); |
| | | } |
| | | |
| | | .hero-wave { |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | height: 2.75rem; |
| | | background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 320' preserveAspectRatio='none'><path fill='%23ffffff' fill-opacity='0.2' d='M0,224L48,218.7C96,213,192,203,288,197.3C384,192,480,192,576,176C672,160,768,128,864,122.7C960,117,1056,139,1152,144C1248,149,1344,139,1392,133.3L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z'></path></svg>") |
| | | no-repeat bottom center/cover; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .notice-section { |
| | | margin-bottom: 1rem; |
| | | animation: fadeInUp 0.6s ease-out 0.2s both; |
| | | } |
| | | |
| | | .notice { |
| | | width: 100%; |
| | | background: linear-gradient(135deg, #eaf2ff 0%, #bbdefb 100%); |
| | | border: 0.0625rem solid #e3f2fd; |
| | | border-radius: 0.75rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.25rem 1.25rem rgba(41, 121, 255, 0.08); |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | top: -50%; |
| | | left: -50%; |
| | | width: 200%; |
| | | height: 200%; |
| | | background: linear-gradient( |
| | | 45deg, |
| | | transparent, |
| | | rgba(255, 255, 255, 0.6), |
| | | transparent |
| | | ); |
| | | animation: shine 4s infinite; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | width: 5rem; |
| | | height: 5rem; |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(255, 255, 255, 0.2) 0%, |
| | | transparent 70% |
| | | ); |
| | | border-radius: 50%; |
| | | transform: translate(1.875rem, -1.875rem); |
| | | } |
| | | |
| | | &:hover { |
| | | transform: translateY(-0.125rem); |
| | | box-shadow: 0 0.5rem 1.875rem rgba(0, 0, 0, 0.1); |
| | | } |
| | | } |
| | | |
| | | @keyframes shine { |
| | | 0% { |
| | | transform: translateX(-100%) translateY(-100%) rotate(45deg); |
| | | } |
| | | 100% { |
| | | transform: translateX(100%) translateY(100%) rotate(45deg); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInDown { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(-1.25rem); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInUp { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(1.25rem); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInScale { |
| | | 0% { |
| | | opacity: 0; |
| | | transform: translateY(0.5rem) scale(0.96); |
| | | } |
| | | 100% { |
| | | opacity: 1; |
| | | transform: translateY(0) scale(1); |
| | | } |
| | | } |
| | | |
| | | .notice-content { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 100%; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .notice-left { |
| | | margin-right: 1rem; |
| | | } |
| | | |
| | | .notice-status { |
| | | font-weight: 600; |
| | | font-size: 1rem; |
| | | color: #1976d2; |
| | | } |
| | | |
| | | .notice-separator { |
| | | width: 0.0625rem; |
| | | height: 1.5rem; |
| | | background: #e0e0e0; |
| | | margin-right: 1rem; |
| | | } |
| | | |
| | | .notice-right { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | flex: 1; |
| | | } |
| | | |
| | | .notice-label { |
| | | color: #333; |
| | | font-size: 0.875rem; |
| | | font-weight: 500; |
| | | margin-right: 0.75rem; |
| | | } |
| | | |
| | | .notice-text { |
| | | font-weight: 400; |
| | | font-size: 0.875rem; |
| | | color: #666666; |
| | | } |
| | | |
| | | .notice-number { |
| | | font-weight: 600; |
| | | font-size: 1rem; |
| | | color: #1976d2; |
| | | margin-left: 0.25rem; |
| | | } |
| | | |
| | | .notice-unit { |
| | | font-weight: 600; |
| | | font-size: 1rem; |
| | | color: #1976d2; |
| | | margin-left: 0.25rem; |
| | | } |
| | | |
| | | /* åè½æ¨¡åæ ·å¼ */ |
| | | .common-module { |
| | | margin-bottom: 1.5rem; |
| | | background: linear-gradient(135deg, #ffffff 0%, #fafbfc 100%); |
| | | border-radius: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.25rem 1.25rem rgba(0, 0, 0, 0.06); |
| | | border: none; |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | width: 3.75rem; |
| | | height: 3.75rem; |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(0, 0, 0, 0.02) 0%, |
| | | transparent 70% |
| | | ); |
| | | border-radius: 50%; |
| | | transform: translate(1.875rem, -1.875rem); |
| | | } |
| | | } |
| | | |
| | | .marketing-module { |
| | | --module-color: #2979ff; |
| | | } |
| | | |
| | | .purchase-module { |
| | | --module-color: #1976d2; |
| | | } |
| | | |
| | | .collaboration-module { |
| | | --module-color: #4caf50; |
| | | } |
| | | |
| | | .production-module { |
| | | --module-color: #ff9800; |
| | | } |
| | | |
| | | .equipment-module { |
| | | --module-color: #9c27b0; |
| | | } |
| | | |
| | | .module-header { |
| | | margin-bottom: 1.5rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .module-title-container { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .module-title { |
| | | color: #333333; |
| | | font-size: 1.125rem; |
| | | font-weight: 600; |
| | | position: relative; |
| | | } |
| | | |
| | | .module-subtitle { |
| | | color: #666666; |
| | | font-size: 0.75rem; |
| | | font-weight: 400; |
| | | margin-left: 0.5rem; |
| | | } |
| | | |
| | | .module-content { |
| | | width: 100%; |
| | | display: grid; |
| | | gap: 1rem; |
| | | } |
| | | |
| | | .icon-container { |
| | | width: 3.25rem; |
| | | height: 3.25rem; |
| | | border-radius: 0.75rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 0.375rem; |
| | | box-shadow: 0 0.1875rem 0.75rem rgba(0, 0, 0, 0.12); |
| | | transition: all 0.2s ease; |
| | | position: relative; |
| | | overflow: hidden; |
| | | animation: fadeInScale 0.5s ease both; |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(255, 255, 255, 0.1) 0%, |
| | | transparent 50%, |
| | | rgba(255, 255, 255, 0.05) 100% |
| | | ); |
| | | opacity: 0; |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | border-radius: 0.75rem; |
| | | background: linear-gradient( |
| | | 45deg, |
| | | transparent, |
| | | rgba(255, 255, 255, 0.2), |
| | | transparent |
| | | ); |
| | | opacity: 0; |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | &:hover { |
| | | transform: translateY(-0.1875rem) scale(1.02); |
| | | box-shadow: 0 0.5rem 1.5625rem rgba(0, 0, 0, 0.18); |
| | | |
| | | &::before, |
| | | &::after { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | &:active { |
| | | transform: scale(0.97); |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.18); |
| | | } |
| | | } |
| | | |
| | | .item-label { |
| | | font-size: 0.8125rem; |
| | | color: #555555; |
| | | text-align: center; |
| | | display: block; |
| | | line-height: 1.4; |
| | | font-weight: 500; |
| | | margin-top: 0.25rem; |
| | | margin-bottom: 0.625rem; |
| | | } |
| | | |
| | | .grid-text { |
| | | font-size: 0.875rem; |
| | | color: #909399; |
| | | padding: 0.625rem 0 1.25rem 0; |
| | | /* #ifndef APP-PLUS */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | |
| | | /* æè²æ¨¡å¼éé
*/ |
| | | @media (prefers-color-scheme: dark) { |
| | | .content { |
| | | background: linear-gradient(135deg, #121317 0%, #161a20 100%); |
| | | } |
| | | .content::before { |
| | | background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="rgba(255, 255, 255, 0.05)"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>'); |
| | | } |
| | | .common-module { |
| | | background: linear-gradient(135deg, #1e1f24 0%, #23252b 100%); |
| | | box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35); |
| | | } |
| | | .module-title { |
| | | color: #e9edf3; |
| | | } |
| | | .module-subtitle, |
| | | .item-label, |
| | | .notice-text, |
| | | .notice-unit, |
| | | .notice-label { |
| | | color: #c7cbd3; |
| | | } |
| | | .notice { |
| | | background: linear-gradient(135deg, #1b2330 0%, #1a2432 100%); |
| | | border-color: rgba(255, 255, 255, 0.06); |
| | | box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4); |
| | | } |
| | | .notice-status, |
| | | .notice-number { |
| | | color: #8ab4ff; |
| | | } |
| | | .bg-img { |
| | | background: linear-gradient(135deg, #1f4fb9 0%, #0e3a8a 100%); |
| | | } |
| | | } |
| | | |
| | | @keyframes rotate { |
| | | from { |
| | | transform: rotate(0deg); |
| | | } |
| | | to { |
| | | transform: rotate(360deg); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInDown { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(-1.25rem); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInUp { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(1.25rem); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInScale { |
| | | 0% { |
| | | opacity: 0; |
| | | transform: translateY(0.5rem) scale(0.96); |
| | | } |
| | | 100% { |
| | | opacity: 1; |
| | | transform: translateY(0) scale(1); |
| | | } |
| | | } |
| | | |
| | | .notice-left { |
| | | margin-right: 1rem; |
| | | } |
| | | .notice-status { |
| | | font-size: 1rem; |
| | | } |
| | | .notice-separator { |
| | | width: 0.0625rem; |
| | | height: 1.5rem; |
| | | margin-right: 1rem; |
| | | } |
| | | .notice-label { |
| | | font-size: 0.875rem; |
| | | margin-right: 0.75rem; |
| | | } |
| | | .notice-text { |
| | | font-size: 0.875rem; |
| | | } |
| | | .notice-number { |
| | | font-size: 1rem; |
| | | margin-left: 0.25rem; |
| | | } |
| | | .notice-unit { |
| | | font-size: 0.875rem; |
| | | margin-left: 0.125rem; |
| | | } |
| | | |
| | | .common-module { |
| | | margin-bottom: 1.5rem; |
| | | background: linear-gradient(135deg, #ffffff 0%, #fafbfc 100%); |
| | | border-radius: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.25rem 1.25rem rgba(0, 0, 0, 0.06); |
| | | border: none; |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: all 0.3s ease; |
| | | |
| | | &::after { |
| | | content: ""; |
| | | position: absolute; |
| | | top: 0; |
| | | right: 0; |
| | | width: 3.75rem; |
| | | height: 3.75rem; |
| | | background: radial-gradient( |
| | | circle, |
| | | rgba(0, 0, 0, 0.02) 0%, |
| | | transparent 70% |
| | | ); |
| | | border-radius: 50%; |
| | | transform: translate(1.875rem, -1.875rem); |
| | | } |
| | | } |
| | | |
| | | .marketing-module { |
| | | --module-color: #2979ff; |
| | | } |
| | | |
| | | .purchase-module { |
| | | --module-color: #1976d2; |
| | | } |
| | | |
| | | .collaboration-module { |
| | | --module-color: #4caf50; |
| | | } |
| | | |
| | | .production-module { |
| | | --module-color: #ff9800; |
| | | } |
| | | |
| | | .equipment-module { |
| | | --module-color: #9c27b0; |
| | | } |
| | | |
| | | .module-header { |
| | | margin-bottom: 1.5rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .module-title-container { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .module-title { |
| | | color: #333333; |
| | | font-size: 1.125rem; |
| | | font-weight: 600; |
| | | position: relative; |
| | | } |
| | | |
| | | .module-subtitle { |
| | | color: #666666; |
| | | font-size: 0.75rem; |
| | | font-weight: 400; |
| | | margin-left: 0.5rem; |
| | | } |
| | | |
| | | .module-content { |
| | | width: 100%; |
| | | display: grid; |
| | | gap: 1rem; |
| | | } |
| | | |
| | | .icon-container { |
| | | width: 3.25rem; |
| | | height: 3.25rem; |
| | | border-radius: 0.75rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 0.375rem; |
| | | box-shadow: 0 0.1875rem 0.75rem rgba(0, 0, 0, 0.12); |
| | | transition: all 0.2s ease; |
| | | position: relative; |
| | | overflow: hidden; |
| | | animation: fadeInScale 0.5s ease both; |
| | | |
| | | &:hover { |
| | | transform: translateY(-0.1875rem) scale(1.02); |
| | | box-shadow: 0 0.5rem 1.5625rem rgba(0, 0, 0, 0.18); |
| | | } |
| | | |
| | | &:active { |
| | | transform: scale(0.97); |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.18); |
| | | } |
| | | } |
| | | |
| | | .item-label { |
| | | font-size: 0.8125rem; |
| | | margin-top: 0.25rem; |
| | | margin-bottom: 0.625rem; |
| | | } |
| | | .grid-text { |
| | | font-size: 0.875rem; |
| | | } |
| | | |
| | | @media (prefers-color-scheme: dark) { |
| | | .common-module { |
| | | box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35); |
| | | } |
| | | .notice { |
| | | box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4); |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader :title="detailType === 1 ? 'æ°å¢ç¥è¯åº' : 'ç¥è¯åºè¯¦æ
'" |
| | | @back="goBack" /> |
| | | <u-form ref="formRef" |
| | | label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <!-- <u-cell-group title="ç¥è¯ä¿¡æ¯"> --> |
| | | <u-form-item label="ç¥è¯æ é¢" |
| | | prop="title" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.title" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥ç¥è¯æ é¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¥è¯ç±»å" |
| | | prop="type" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="equipmentname" |
| | | readonly |
| | | placeholder="è¯·éæ©ç¥è¯ç±»å" |
| | | @click="showEquipmentSheet = true" /> |
| | | <template v-if="!readonly" |
| | | #right> |
| | | <up-icon name="arrow-right" |
| | | @click="openEquipmentSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="éç¨åºæ¯" |
| | | prop="scenario" |
| | | border-bottom> |
| | | <u-input v-model="form.scenario" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥éç¨åºæ¯" /> |
| | | </u-form-item> |
| | | <u-form-item label="è§£å³æç" |
| | | prop="status" |
| | | border-bottom> |
| | | <u-input v-model="statusname" |
| | | readonly |
| | | placeholder="è¯·éæ©è§£å³æç" |
| | | @click="showStatusSheet = true" /> |
| | | <template v-if="!readonly" |
| | | #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showStatusSheet = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="é®é¢æè¿°" |
| | | required |
| | | prop="remark" |
| | | border-bottom> |
| | | <u-textarea v-model="form.problem" |
| | | type="textarea" |
| | | rows="4" |
| | | :disabled="readonly" |
| | | placeholder="请è¾å
¥é®é¢æè¿°" /> |
| | | </u-form-item> |
| | | <u-form-item label="è§£å³æ¹æ¡" |
| | | prop="solution" |
| | | required |
| | | border-bottom> |
| | | <u-textarea v-model="form.solution" |
| | | type="textarea" |
| | | rows="4" |
| | | :disabled="readonly" |
| | | placeholder="请è¾å
¥è§£å³æ¹æ¡" /> |
| | | </u-form-item> |
| | | <u-form-item label="å
³é®è¦ç¹" |
| | | prop="keyPoints" |
| | | border-bottom> |
| | | <u-textarea v-model="form.keyPoints" |
| | | type="textarea" |
| | | rows="4" |
| | | :disabled="readonly" |
| | | placeholder="请è¾å
¥å
³é®è¦ç¹ï¼ç¨éå·åé" /> |
| | | </u-form-item> |
| | | <u-form-item label="å建人" |
| | | prop="creator" |
| | | border-bottom> |
| | | <u-input v-model="form.creator" |
| | | readonly |
| | | placeholder="è¯·éæ©å建人" |
| | | @click="openCreatorSheet" /> |
| | | <template v-if="!readonly" |
| | | #right> |
| | | <up-icon name="arrow-right" |
| | | @click="openCreatorSheet"></up-icon> |
| | | </template> |
| | | <!-- <u-input v-model="form.creator" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥å建人" /> --> |
| | | </u-form-item> |
| | | <u-form-item label="ä½¿ç¨æ¬¡æ°" |
| | | prop="usageCount" |
| | | border-bottom> |
| | | <uni-number-box v-model="form.usageCount" |
| | | :min="0" |
| | | :disabled="readonly" |
| | | placeholder="请è¾å
¥ä½¿ç¨æ¬¡æ°" /> |
| | | </u-form-item> |
| | | <!-- </u-cell-group> --> |
| | | <!-- æäº¤æé® --> |
| | | <view v-if="!readonly" |
| | | class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="sign-btn" |
| | | type="primary" |
| | | @click="handleSubmit" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- 设å¤é
ç½®éæ©å¨ --> |
| | | <up-action-sheet :show="showEquipmentSheet" |
| | | :actions="equipmentOptions" |
| | | @select="handleEquipmentChange" |
| | | @close="showEquipmentSheet = false" /> |
| | | <up-action-sheet :show="showCreatorSheet" |
| | | :actions="creatorOptions" |
| | | @select="handleCreatorChange" |
| | | @close="showCreatorSheet = false" /> |
| | | <!-- <u-popup :show="showEquipmentSheet" |
| | | mode="bottom" |
| | | @close="showEquipmentSheet = false" |
| | | height="200px"> |
| | | <view class="popup-content"> |
| | | <view class="popup-body"> |
| | | <u-checkbox-group v-model="form.equipment" |
| | | @change="handleEquipmentChange" |
| | | icon-placement="right" |
| | | placement="row"> |
| | | <view style="width:100%;padding:10px;margin-top:20px;"> |
| | | <u-checkbox v-for="option in equipmentOptions" |
| | | :key="option.value" |
| | | :name="option.value" |
| | | :label="option.name" |
| | | class="checkbox-item"></u-checkbox> |
| | | </view> |
| | | </u-checkbox-group> |
| | | </view> |
| | | </view> |
| | | </u-popup> --> |
| | | <!-- ç¶æéæ©å¨ --> |
| | | <up-action-sheet :show="showStatusSheet" |
| | | :actions="statusOptions" |
| | | @select="onStatusSelect" |
| | | @close="showStatusSheet = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "meeting-settings-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { |
| | | addKnowledgeBase, |
| | | updateKnowledgeBase, |
| | | } from "@/api/managementMeetings/knowledgeBase"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0, |
| | | }); |
| | | const { knowledge_type } = useDict("knowledge_type"); |
| | | const knowledgeTypeOptions = computed(() => knowledge_type?.value || []); |
| | | const equipmentOptions = ref([]); |
| | | const statusOptions = ref([ |
| | | { value: "high", name: "æ¾èæå" }, |
| | | { value: "medium", name: "ä¸è¬æå" }, |
| | | { value: "low", name: "轻微æå" }, |
| | | ]); |
| | | //// 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const showEquipmentSheet = ref(false); |
| | | const showStatusSheet = ref(false); |
| | | const openEquipmentSheet = () => { |
| | | showEquipmentSheet.value = true; |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const statusname = ref(""); |
| | | // ç¶æéæ© |
| | | const onStatusSelect = action => { |
| | | form.value.efficiency = action.value; |
| | | statusname.value = action.name; |
| | | showStatusSheet.value = false; |
| | | }; |
| | | const showCreatorSheet = ref(false); |
| | | const creatorOptions = ref([]); |
| | | const openCreatorSheet = () => { |
| | | showCreatorSheet.value = true; |
| | | }; |
| | | const getCreatorOptions = async () => { |
| | | try { |
| | | const res = await userListNoPageByTenantId(); |
| | | if (res.code === 200) { |
| | | creatorOptions.value = res.data || []; |
| | | creatorOptions.value.forEach(item => { |
| | | item.name = item.nickName; |
| | | item.value = item.userId; |
| | | }); |
| | | } else { |
| | | showToast("è·åå建人å表失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è·åå建人å表失败:", e); |
| | | showToast("è·åå建人å表失败"); |
| | | } |
| | | }; |
| | | // åå»ºäººéæ© |
| | | const handleCreatorChange = val => { |
| | | form.value.creator = val.name; |
| | | }; |
| | | const equipmentname = ref(""); |
| | | // 设å¤é
ç½®éæ© |
| | | const handleEquipmentChange = val => { |
| | | form.value.type = val.value; |
| | | equipmentname.value = val.name; |
| | | showEquipmentSheet.value = false; |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | if (!form.value.title) { |
| | | showToast("请è¾å
¥æ é¢"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.scenario) { |
| | | showToast("请è¾å
¥éç¨åºæ¯"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.problem) { |
| | | showToast("请è¾å
¥é®é¢æè¿°"); |
| | | return; |
| | | } |
| | | if (!form.value.solution) { |
| | | showToast("请è¾å
¥è§£å³æ¹æ¡"); |
| | | return; |
| | | } |
| | | try { |
| | | loading.value = true; |
| | | if (detailType.value === 1) { |
| | | addKnowledgeBase(form.value).then(res => { |
| | | if (res.code !== 200) { |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | return; |
| | | } |
| | | loading.value = false; |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | }); |
| | | } else if (detailType.value === 2) { |
| | | updateKnowledgeBase(form.value).then(res => { |
| | | if (res.code !== 200) { |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | return; |
| | | } |
| | | loading.value = false; |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | }); |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("ä¿å失败:", e); |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨ä¸è·åä¼è®® room æ°æ® |
| | | const meetingRoom = uni.getStorageSync("meetingRoom"); |
| | | if (meetingRoom) { |
| | | form.value = JSON.parse(JSON.stringify(meetingRoom)); |
| | | if (meetingRoom.equipment) { |
| | | if (Array.isArray(meetingRoom.equipment)) { |
| | | form.value.equipment = meetingRoom.equipment; |
| | | } else { |
| | | form.value.equipment = meetingRoom.equipment.split(","); |
| | | } |
| | | } |
| | | statusname.value = meetingRoom.status === 1 ? "å¯ç¨" : "ç¦ç¨"; |
| | | |
| | | // æ¸
餿¬å°åå¨ä¸çæ°æ®ï¼é¿å
䏿¬¡æå¼æ¶ä»ç¶æ¾ç¤º |
| | | uni.removeStorageSync("meetingRoom"); |
| | | } |
| | | }; |
| | | const readonly = ref(false); |
| | | const detailType = ref(1); |
| | | const knowledgeId = ref(""); |
| | | |
| | | onLoad(options => { |
| | | detailType.value = Number(options.detailType); |
| | | knowledgeId.value = options.id || ""; |
| | | |
| | | // 妿æ¯ç¼è¾ææ¥ç模å¼ï¼è·åç¥è¯è¯¦æ
|
| | | if (knowledgeId.value && (detailType.value === 2 || detailType.value === 3)) { |
| | | // getKnowledgeDetail(knowledgeId.value); |
| | | equipmentname.value = |
| | | equipmentOptions.value.find(item => item.value === form.value.type) |
| | | ?.name || ""; |
| | | statusname.value = |
| | | statusOptions.value.find(item => item.value === form.value.efficiency) |
| | | ?.name || ""; |
| | | } |
| | | |
| | | // æ¥ç模å¼è®¾ç½®åªè¯» |
| | | if (detailType.value === 3) { |
| | | readonly.value = true; |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getCreatorOptions(); |
| | | // 仿¬å°åå¨ä¸è·åç¥è¯æ°æ® |
| | | const knowledgeBase = uni.getStorageSync("knowledgeBase"); |
| | | if (knowledgeBase) { |
| | | form.value = JSON.parse(JSON.stringify(knowledgeBase)); |
| | | } |
| | | |
| | | initPageData(); |
| | | equipmentOptions.value = knowledgeTypeOptions.value.map(item => ({ |
| | | value: item.value, |
| | | name: item.label, |
| | | })); |
| | | if (detailType.value === 1) { |
| | | form.value = { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0, |
| | | }; |
| | | equipmentname.value = ""; |
| | | statusname.value = ""; |
| | | } |
| | | |
| | | if (detailType.value != 1) { |
| | | equipmentname.value = |
| | | equipmentOptions.value.find(item => item.value === form.value.type) |
| | | ?.name || ""; |
| | | statusname.value = |
| | | statusOptions.value.find(item => item.value === form.value.efficiency) |
| | | ?.name || ""; |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | .client-visit { |
| | | 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; |
| | | } |
| | | |
| | | .location-icon { |
| | | color: #1989fa; |
| | | font-size: 1.2rem; |
| | | } |
| | | |
| | | .selector-container { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .selector-text { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | |
| | | .popup-content { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .popup-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .close-icon { |
| | | font-size: 20px; |
| | | color: #999; |
| | | } |
| | | |
| | | .popup-body { |
| | | max-height: 60vh; |
| | | overflow-y: auto; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .checkbox-item { |
| | | margin-bottom: 15rpx; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .popup-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | gap: 15rpx; |
| | | } |
| | | |
| | | .cancel-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | |
| | | .confirm-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | .checkbox-item { |
| | | margin-top: 40rpx; |
| | | } |
| | | </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="name" |
| | | @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="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" |
| | | :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.title || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç¥è¯ç±»å</text> |
| | | <text class="detail-value">{{ formatReceiptType(item.type) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éç¨åºæ¯</text> |
| | | <text class="detail-value">{{ item.scenario || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§£å³æç</text> |
| | | <u-tag size="mini" |
| | | :type="getTagClass(item.efficiency)">{{ formatReceiptType1(item.efficiency) }}</u-tag> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä½¿ç¨æ¬¡æ°</text> |
| | | <text class="detail-value">{{ item.usageCount }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å建人</text> |
| | | <text class="detail-value">{{ item.creator }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å建æ¶é´</text> |
| | | <text class="detail-value">{{ item.createTime }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item,3)"> |
| | | æ¥ç |
| | | </u-button> |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="confirmDelete(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item,2)"> |
| | | ç¼è¾ |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ ç¥è¯è®°å½</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | listKnowledgeBase, |
| | | delKnowledgeBase, |
| | | } from "@/api/managementMeetings/knowledgeBase"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "client-visit-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const name = ref(""); |
| | | |
| | | // æè®¿è®°å½æ°æ® |
| | | const visitList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const { knowledge_type } = useDict("knowledge_type"); |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | return getKnowledgeTypeLabel(params); |
| | | }; |
| | | const formatReceiptType1 = params => { |
| | | if (params == "high") { |
| | | return "æ¾èæå"; |
| | | } else if (params == "medium") { |
| | | return "ä¸è¬æå"; |
| | | } else if (params == "low") { |
| | | return "轻微æå"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | const getTagClass = type => { |
| | | if (type == "high") { |
| | | return "success"; |
| | | } else if (type == "medium") { |
| | | return "warning"; |
| | | } else if (type == "low") { |
| | | return "info"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | const knowledgeTypeOptions = computed(() => knowledge_type?.value || []); |
| | | // è·åç¥è¯ç±»åæ ç¾ |
| | | const getKnowledgeTypeLabel = val => { |
| | | console.log(knowledgeTypeOptions, "knowledgeTypeOptions"); |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | title: name.value, |
| | | }; |
| | | listKnowledgeBase(params) |
| | | .then(res => { |
| | | visitList.value = res.data.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const addVisit = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/knowledgeBase/detail?detailType=1", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const viewDetail = (item, detailType) => { |
| | | uni.setStorageSync("knowledgeBase", item); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/knowledgeBase/detail?detailType=" + |
| | | detailType + |
| | | "&id=" + |
| | | item.id, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ç¡®è®¤ |
| | | const confirmDelete = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤ç¥è¯ "${item.title}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteKnowledge(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æ§è¡å é¤ |
| | | const deleteKnowledge = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | delKnowledgeBase([id]) |
| | | .then(res => { |
| | | closeToast(); |
| | | if (res.code === 200) { |
| | | showToast("å 餿å"); |
| | | getList(); // éæ°è·åå表 |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .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; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | color: #333; // ä¿æé¡µé¢ç¹æçææ¬é¢è² |
| | | } |
| | | |
| | | // ç¶ææ ·å¼ |
| | | .status-enabled { |
| | | color: #28a745; // ä¿æé¡µé¢ç¹æçæåé¢è² |
| | | } |
| | | |
| | | .status-disabled { |
| | | color: #dc3545; // ä¿æé¡µé¢ç¹æçé误é¢è² |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | </style> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view style="background-color: #fff;" |
| | | class="client-visit-detail"> |
| | | <PageHeader title="ä¼è®®ç³è¯·" |
| | | @back="goBack" /> |
| | | <view> |
| | | <view v-for="item in applicationTypes" |
| | | :key="item.value" |
| | | class="application-type-item" |
| | | :class="{ active: meetingForm.applicationType === item.value }" |
| | | @click="selectApplicationType(item)"> |
| | | <view class="application-type-info"> |
| | | <view class="application-type-name">{{ item.name }}</view> |
| | | <view class="application-type-desc">{{ item.desc }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <u-form ref="formRef" |
| | | label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <u-cell-group title="ä¼è®®ç³è¯·"> |
| | | <u-form-item label="ä¼è®®ä¸»é¢" |
| | | prop="title" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¼è®®å®¤" |
| | | prop="roomId" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.roomName" |
| | | placeholder="è¯·éæ©ä¼è®®å®¤" |
| | | readonly |
| | | @click="showRoomPicker = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showRoomPicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="主æäºº" |
| | | prop="host" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.host" |
| | | placeholder="请è¾å
¥ä¸»æäººå§å" /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¼è®®æ¥æ" |
| | | prop="meetingDate" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.meetingDate" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" /> |
| | | <template #right> |
| | | <up-icon name="calendar" |
| | | @click="showDatePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="å¼å§æ¶é´" |
| | | prop="startTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.startTime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | readonly |
| | | @click="showStartTimePicker = true" /> |
| | | <template #right> |
| | | <up-icon name="clock" |
| | | @click="showStartTimePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»ææ¶é´" |
| | | prop="endTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.endTime" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | readonly |
| | | @click="showEndTimePicker = true" /> |
| | | <template #right> |
| | | <up-icon name="clock" |
| | | @click="showEndTimePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="åä¼äººå" |
| | | prop="participants" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.participantsNames" |
| | | placeholder="è¯·éæ©åä¼äººå" |
| | | readonly |
| | | @click="showEquipmentSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="openParticipantPicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ä¼è®®è¯´æ" |
| | | prop="description" |
| | | border-bottom> |
| | | <u-input v-model="meetingForm.description" |
| | | placeholder="请è¾å
¥ä¼è®®è¯´æ" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | </u-form> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="resetForm">éç½®</u-button> |
| | | <u-button class="save-btn" |
| | | @click="handleSubmit">ä¿å</u-button> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker v-model="meetingForm.meetingDate" |
| | | mode="date" |
| | | :show="showDatePicker" |
| | | @confirm="onDateSelect" |
| | | @cancel="showDatePicker = false" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | :min-date="minDate" /> |
| | | <!-- å¼å§æ¶é´éæ©å¨ --> |
| | | <up-action-sheet :show="showStartTimePicker" |
| | | :actions="timeOptions" |
| | | @select="onStartTimeSelect" |
| | | @close="showStartTimePicker = false" /> |
| | | <!-- ç»ææ¶é´éæ©å¨ --> |
| | | <up-action-sheet :show="showEndTimePicker" |
| | | :actions="timeOptions" |
| | | @select="onEndTimeSelect" |
| | | @close="showEndTimePicker = false" /> |
| | | <!-- ä¼è®®å®¤éæ©å¨ --> |
| | | <up-action-sheet :show="showRoomPicker" |
| | | :actions="meetingRooms" |
| | | @select="onRoomSelect" |
| | | @close="showRoomPicker = false" /> |
| | | <u-popup :show="showEquipmentSheet" |
| | | mode="bottom" |
| | | @close="showEquipmentSheet = false" |
| | | height="200px"> |
| | | <view class="popup-content"> |
| | | <view class="popup-body"> |
| | | <u-checkbox-group v-model="meetingForm.participants" |
| | | @change="handleParticipantChange" |
| | | icon-placement="right" |
| | | placement="row"> |
| | | <view style="width:100%;padding:10px;margin-top:20px;"> |
| | | <u-checkbox v-for="option in employees" |
| | | :key="option.id" |
| | | :name="option.id" |
| | | :label="`${option.staffName} (${option.postName})`" |
| | | class="checkbox-item"></u-checkbox> |
| | | </view> |
| | | </u-checkbox-group> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "meeting-settings-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | saveMeetingApplication, |
| | | getRoomEnum, |
| | | } from "@/api/managementMeetings/meeting"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/onboarding"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const meetingForm = reactive({ |
| | | title: "", |
| | | type: "", |
| | | roomId: "", |
| | | roomName: "", |
| | | host: "", |
| | | meetingDate: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | participants: [], |
| | | description: "", |
| | | participantsNames: [], |
| | | applicationType: "department", |
| | | }); |
| | | // ç³è¯·ç±»åé项 |
| | | const applicationTypes = ref([ |
| | | { |
| | | value: "approval", |
| | | name: "å®¡æ¹æµç¨ä¼è®®", |
| | | desc: "éè¦ç»è¿å¤çº§å®¡æ¹çä¼è®®ç³è¯·", |
| | | // icon: Document, |
| | | }, |
| | | { |
| | | value: "department", |
| | | name: "é¨é¨çº§ä¼è®®", |
| | | desc: "é¨é¨å
é¨ä¼è®®ç³è¯·æµç¨", |
| | | // icon: Promotion, |
| | | }, |
| | | { |
| | | value: "notification", |
| | | name: "ä¼è®®éç¥", |
| | | desc: "æ é审æ¹ç´æ¥åå¸çä¼è®®éç¥", |
| | | // icon: Bell, |
| | | }, |
| | | ]); |
| | | // 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const showDatePicker = ref(false); |
| | | const showStartTimePicker = ref(false); |
| | | const showEndTimePicker = ref(false); |
| | | const showRoomPicker = ref(false); |
| | | |
| | | // æå°æ¥æï¼ä»å¤©ï¼ |
| | | const minDate = computed(() => { |
| | | return dayjs().format("YYYY-MM-DD"); |
| | | }); |
| | | |
| | | // éæ©ç³è¯·ç±»å |
| | | const selectApplicationType = item => { |
| | | meetingForm.applicationType = item.value; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const showEquipmentSheet = ref(false); |
| | | const openParticipantPicker = () => { |
| | | showEquipmentSheet.value = true; |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | meetingForm.title = ""; |
| | | meetingForm.type = ""; |
| | | meetingForm.roomId = ""; |
| | | meetingForm.roomName = ""; |
| | | meetingForm.host = ""; |
| | | meetingForm.meetingDate = ""; |
| | | meetingForm.startTime = ""; |
| | | meetingForm.endTime = ""; |
| | | meetingForm.participants = []; |
| | | meetingForm.participantsNames = []; |
| | | meetingForm.description = ""; |
| | | meetingForm.applicationType = "department"; |
| | | }; |
| | | const handleParticipantChange = val => { |
| | | console.log("val", val); |
| | | |
| | | meetingForm.participants = val; |
| | | meetingForm.participantsNames = employees.value |
| | | .filter(employee => val.includes(employee.id)) |
| | | .map(employee => employee.staffName); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | console.log("meetingForm", meetingForm); |
| | | if (!meetingForm.title) { |
| | | showToast("请è¾å
¥ä¼è®®ä¸»é¢"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.roomId) { |
| | | showToast("è¯·éæ©ä¼è®®å®¤"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.host) { |
| | | showToast("请è¾å
¥ä¸»æäºº"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.meetingDate) { |
| | | showToast("è¯·éæ©ä¼è®®æ¥æ"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.startTime) { |
| | | showToast("è¯·éæ©å¼å§æ¶é´"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.endTime) { |
| | | showToast("è¯·éæ©ç»ææ¶é´"); |
| | | return; |
| | | } |
| | | |
| | | if (!meetingForm.participants) { |
| | | showToast("è¯·éæ©åä¼äººå"); |
| | | return; |
| | | } |
| | | |
| | | // éªè¯å¼å§æ¶é´å¿
é¡»å°äºç»ææ¶é´ |
| | | if (meetingForm.startTime >= meetingForm.endTime) { |
| | | showToast("å¼å§æ¶é´å¿
é¡»å°äºç»ææ¶é´"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | loading.value = true; |
| | | |
| | | let formData = { ...meetingForm }; |
| | | formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00`; |
| | | formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00`; |
| | | formData.participants = JSON.stringify(meetingForm.participants); |
| | | |
| | | console.log(formData); |
| | | |
| | | // è°ç¨å®é
çAPI |
| | | const res = await saveMeetingApplication(formData); |
| | | |
| | | if (res.code === 200) { |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | showToast(res.message || "ä¿å失败ï¼è¯·éè¯"); |
| | | } |
| | | } catch (e) { |
| | | console.error("ä¿å失败:", e); |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | // æ¥æéæ©å¨ç¡®è®¤åè° |
| | | const onDateSelect = action => { |
| | | console.log(action.value); |
| | | |
| | | if (action.value) { |
| | | meetingForm.meetingDate = dayjs(action.value).format("YYYY-MM-DD"); |
| | | } else { |
| | | meetingForm.meetingDate = dayjs().format("YYYY-MM-DD"); |
| | | } |
| | | |
| | | showDatePicker.value = false; |
| | | }; |
| | | const onStartTimeSelect = action => { |
| | | meetingForm.startTime = action.value; |
| | | showStartTimePicker.value = false; |
| | | }; |
| | | const onEndTimeSelect = action => { |
| | | meetingForm.endTime = action.value; |
| | | showEndTimePicker.value = false; |
| | | }; |
| | | |
| | | // ä¼è®®å®¤éæ©åè° |
| | | const onRoomSelect = action => { |
| | | meetingForm.roomId = action.id; |
| | | meetingForm.roomName = action.name; |
| | | showRoomPicker.value = false; |
| | | }; |
| | | // æ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼ |
| | | const timeOptions = ref([]); |
| | | |
| | | // åå§åæ¶é´é项 |
| | | const initTimeOptions = () => { |
| | | const options = []; |
| | | for (let hour = 8; hour <= 18; hour++) { |
| | | // æ¯ä¸ªå°æ¶æ·»å 两个éé¡¹ï¼æ´ç¹ååç¹ |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, "0")}:00`, |
| | | name: `${hour.toString().padStart(2, "0")}:00`, |
| | | }); |
| | | |
| | | if (hour < 18) { |
| | | // 18:00ä¹å没æåç¹é项 |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, "0")}:30`, |
| | | name: `${hour.toString().padStart(2, "0")}:30`, |
| | | }); |
| | | } |
| | | } |
| | | timeOptions.value = options; |
| | | }; |
| | | // ä¼è®®å®¤å表 |
| | | const employees = ref([]); |
| | | const meetingRooms = ref([]); |
| | | const getMeetingRooms = async () => { |
| | | try { |
| | | const res = await getRoomEnum(); |
| | | if (res.code === 200) { |
| | | meetingRooms.value = res.data || []; |
| | | } else { |
| | | showToast(res.message || "è·åä¼è®®å®¤å表失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è·åä¼è®®å®¤å表失败:", e); |
| | | showToast("è·åä¼è®®å®¤å表失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initPageData(); |
| | | initTimeOptions(); |
| | | getMeetingRooms(); |
| | | staffOnJobListPage().then(res => { |
| | | console.log(res.data.records, "res.data.records"); |
| | | employees.value = res.data.records.sort((a, b) => |
| | | a.postName.localeCompare(b.postName) |
| | | ); |
| | | console.log(employees.value, "employees.value"); |
| | | }); |
| | | }); |
| | | |
| | | const initPageData = () => { |
| | | // åå§åæ°æ® |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .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: #ffffff; |
| | | width: 6.375rem; |
| | | background: #c7c9cc; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #ffffff; |
| | | width: 14rem; |
| | | background: linear-gradient(140deg, #00baff 0%, #006cfb 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .application-type-item { |
| | | width: 94%; |
| | | margin-left: 3%; |
| | | // height: 120rpx; |
| | | background-color: #f1f1f1; |
| | | border-radius: 10rpx; |
| | | margin-top: 20rpx; |
| | | padding: 20rpx; |
| | | box-shadow: 0 2rpx 12rpx 0 rgba(246, 244, 244, 0.1); |
| | | transition: box-shadow 0.3s ease; |
| | | } |
| | | .application-type-item.active { |
| | | box-shadow: 0 4rpx 16rpx 0 rgba(0, 0, 0, 0.15); |
| | | background-color: #fff; |
| | | border: 1rpx solid #0078a3; |
| | | } |
| | | |
| | | .application-type-name { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #000000; |
| | | } |
| | | .application-type-item.active .application-type-name { |
| | | color: #0078a3; |
| | | } |
| | | .application-type-desc { |
| | | font-weight: 400; |
| | | font-size: 0.875rem; |
| | | margin-top: 0.5rem; |
| | | color: #757575; |
| | | } |
| | | .application-type-item.active .application-type-desc { |
| | | color: #0078a3; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="approve-page"> |
| | | <PageHeader title="审æ¹" |
| | | @back="goBack" /> |
| | | <!-- ç³è¯·ä¿¡æ¯ --> |
| | | <view class="application-info"> |
| | | <view class="info-header"> |
| | | <text class="info-title">ä¼è®®ä¿¡æ¯</text> |
| | | </view> |
| | | <view class="info-content"> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®ä¸»é¢</text> |
| | | <text class="info-value">{{ approvalData.title }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ç³è¯·äºº</text> |
| | | <text class="info-value">{{ approvalData.applicant }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">主ç人</text> |
| | | <text class="info-value">{{ approvalData.host }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®æ¶é´</text> |
| | | <text class="info-value">{{ formatDateTime(approvalData.meetingTime) }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®å°ç¹</text> |
| | | <text class="info-value">{{ approvalData.location }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">审æ¹ç¶æ</text> |
| | | <text class="info-value tag" |
| | | :class="getTagClass(approvalData.approveNodeStatus)"> |
| | | {{ formatReceiptType(approvalData.approveNodeStatus) }} |
| | | </text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººæ°</text> |
| | | <text class="info-value">{{ approvalData.participants.length }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººå</text> |
| | | <text class="info-value">{{ approvalData.participants.map(it => it.name).join("ã") }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- åºé¨æä½æé® --> |
| | | <view v-if="isEdit" |
| | | class="footer-actions"> |
| | | <u-button class="reject-btn" |
| | | @click="handleReject">ä¸éè¿</u-button> |
| | | <u-button class="approve-btn" |
| | | @click="handleApprove">éè¿</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { saveMeetingApplication } from "@/api/managementMeetings/meetExamine"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | |
| | | const approvalData = ref({}); |
| | | const approvalSteps = ref([]); |
| | | const isEdit = ref(false); |
| | | |
| | | onLoad(options => { |
| | | console.log(options, "options"); |
| | | if (options.item) { |
| | | approvalData.value = JSON.parse(options.item); |
| | | } |
| | | if (options.edit) { |
| | | isEdit.value = options.edit === "true" ? true : false; |
| | | } |
| | | }); |
| | | |
| | | const goBack = () => { |
| | | uni.removeStorageSync("approveId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params == 1) { |
| | | return "å·²éè¿"; |
| | | } else if (params == 2) { |
| | | return "æªéè¿"; |
| | | } else if (params == 3) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "warning"; |
| | | } else if (type == 3) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | const submitForm = status => { |
| | | // è°ç¨å端 |
| | | saveMeetingApplication({ id: approvalData.value.id, status: status }) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | showToast("å®¡æ¹æäº¤æå"); |
| | | // æç¤ºåè¿åä¸ä¸ä¸ªé¡µé¢ |
| | | setTimeout(() => { |
| | | goBack(); // å
鍿¯ uni.navigateBack() |
| | | }, 800); |
| | | } else { |
| | | showToast(res.message || "å®¡æ¹æä½å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("å®¡æ¹æä½å¤±è´¥:", error); |
| | | showToast("å®¡æ¹æä½å¤±è´¥ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | |
| | | const handleApprove = () => { |
| | | uni.showModal({ |
| | | title: "确认æä½", |
| | | content: "ç¡®å®è¦éè¿è¯¥ä¼è®®ç³è¯·åï¼", |
| | | success: res => { |
| | | if (res.confirm) submitForm(1); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | const handleReject = () => { |
| | | uni.showModal({ |
| | | title: "确认æä½", |
| | | content: "ç¡®å®ä¸éè¿è¯¥ä¼è®®ç³è¯·åï¼", |
| | | success: res => { |
| | | if (res.confirm) submitForm(2); |
| | | }, |
| | | }); |
| | | }; |
| | | // åå§èç¹æ°æ®ï¼ç¨äºæäº¤é»è¾ï¼ |
| | | const activities = ref([]); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .approve-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | } |
| | | |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .application-info { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .info-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .info-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .info-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | width: 80px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .process-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .process-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .process-steps { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .process-step { |
| | | display: flex; |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | |
| | | .step-line { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .step-indicator { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .step-dot { |
| | | width: 32px; |
| | | height: 32px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | position: relative; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .process-step.completed .step-dot { |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | .process-step.current .step-dot { |
| | | background: #1890ff; |
| | | color: #fff; |
| | | animation: pulse 2s infinite; |
| | | } |
| | | |
| | | .process-step.pending .step-dot { |
| | | background: #d9d9d9; |
| | | color: #999; |
| | | } |
| | | |
| | | .step-line { |
| | | width: 2px; |
| | | height: 40px; |
| | | background: #d9d9d9; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .process-step.completed .step-line { |
| | | background: #52c41a; |
| | | } |
| | | |
| | | .process-step.rejected .step-dot { |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | .process-step.rejected .step-line { |
| | | background: #ff4d4f; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | padding-top: 4px; |
| | | } |
| | | |
| | | .step-info { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .step-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-approver { |
| | | font-size: 14px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-time { |
| | | font-size: 12px; |
| | | color: #999; |
| | | display: block; |
| | | } |
| | | |
| | | .step-opinion { |
| | | background: #f8f9fa; |
| | | padding: 12px; |
| | | border-radius: 8px; |
| | | border-left: 4px solid #52c41a; |
| | | } |
| | | |
| | | .opinion-label { |
| | | font-size: 12px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .opinion-content { |
| | | font-size: 14px; |
| | | color: #333; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .approval-input { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .input-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .input-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .input-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .footer-actions { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 16px; |
| | | box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .reject-btn { |
| | | width: 120px; |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | |
| | | .approve-btn { |
| | | width: 120px; |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | /* éé
u-buttonæ ·å¼ */ |
| | | :deep(.u-button) { |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0.7); |
| | | } |
| | | 70% { |
| | | box-shadow: 0 0 0 10px rgba(24, 144, 255, 0); |
| | | } |
| | | 100% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0); |
| | | } |
| | | } |
| | | .signature-section { |
| | | background: #fff; |
| | | padding: 12px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | .signature-header { |
| | | margin-bottom: 8px; |
| | | } |
| | | .signature-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .signature-box { |
| | | width: 100%; |
| | | height: 180px; |
| | | background: #fff; |
| | | border: 1px dashed #d9d9d9; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | .signature-actions { |
| | | margin-top: 8px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 审æ¹ç®¡çä¸»é¡µé¢ |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ä¼è®®å®¡æ¹" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | v-model="searchForm.title" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-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.title }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.status)">{{ formatReceiptType(item.status) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·äºº</text> |
| | | <text class="detail-value">{{ item.applicant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">主ç人</text> |
| | | <text class="detail-value">{{ item.host }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">ä¼è®®æ¶é´</text> |
| | | <text class="detail-value highlightBlue">{{ formatDateTime(item.meetingTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¼è®®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ item.participants.length }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="actions"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn view" |
| | | @click="viewDetail(item)"> |
| | | 详æ
|
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | | :disabled="item.status != 0" |
| | | @click="approve(item)"> |
| | | å®¡æ¹ |
| | | </u-button> |
| | | </view> |
| | | <!-- <view class="detail-info" |
| | | style="align-items: flex-end;"> |
| | | <view class="detail-row"> |
| | | |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, toRefs, reactive } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getExamineList, |
| | | getRoomEnum, |
| | | } from "@/api/managementMeetings/meetExamine"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/onboarding"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¿é´æä¸¾ |
| | | const roomEnum = ref([]); |
| | | // æ¿é´æä¸¾æ¥è¯¢ |
| | | const getRoomEnumList = () => { |
| | | return getRoomEnum() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | roomEnum.value = res.data; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // åå·¥å表 |
| | | const staffList = ref([]); |
| | | // åå·¥å表æ¥è¯¢ |
| | | const getStaffOnJobList = () => { |
| | | return staffOnJobListPage() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | staffList.value = res.data.records; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | getExamineList({ |
| | | ...page, |
| | | ...searchForm.value, |
| | | }) |
| | | .then(res => { |
| | | console.log(res.data.records, "res.data.records"); |
| | | ledgerList.value = res.data.records.map(it => { |
| | | console.log(it, "it1"); |
| | | let room = roomEnum.value.find(room => it.roomId === room.id); |
| | | it.location = `${room.name}(${room.location})`; |
| | | let staffs = JSON.parse(it.participants); |
| | | it.staffCount = staffs.size; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm:ss" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; |
| | | it.participants = staffList.value |
| | | .filter(staff => staffs.some(id => id == staff.id)) |
| | | .map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postName})`, |
| | | }; |
| | | }); |
| | | console.log(it, "it2"); |
| | | |
| | | return it; |
| | | }); |
| | | |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params == 1) { |
| | | return "å·²éè¿"; |
| | | } else if (params == 2) { |
| | | return "æªéè¿"; |
| | | } else if (params == 3) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "warning"; |
| | | } else if (type == 3) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = item => { |
| | | // uni.setStorageSync("approveId", item.approveId); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetExamine/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=true", |
| | | }); |
| | | }; |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetExamine/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=false", |
| | | }); |
| | | }; |
| | | |
| | | onShow(async () => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | try { |
| | | // çå¾
ä¸¤ä¸ªå¼æ¥æ¹æ³æ§è¡å®æ |
| | | await Promise.all([getRoomEnumList(), getStaffOnJobList()]); |
| | | // ä¸¤ä¸ªæ¹æ³æ§è¡å®æååæ§è¡ getList() |
| | | getList(); |
| | | } catch (error) { |
| | | console.error("åå§åæ°æ®å¤±è´¥:", error); |
| | | // å³ä½¿åºé乿§è¡ getList()ï¼ç¡®ä¿é¡µé¢è½æ£å¸¸å è½½ |
| | | getList(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | margin-top: 18rpx; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="approve-page"> |
| | | <PageHeader title="åå¸" |
| | | @back="goBack" /> |
| | | <!-- ç³è¯·ä¿¡æ¯ --> |
| | | <view class="application-info"> |
| | | <view class="info-header"> |
| | | <text class="info-title">ä¼è®®ä¿¡æ¯</text> |
| | | </view> |
| | | <view class="info-content"> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®ä¸»é¢</text> |
| | | <text class="info-value">{{ approvalData.title }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ç³è¯·äºº</text> |
| | | <text class="info-value">{{ approvalData.applicant }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">主ç人</text> |
| | | <text class="info-value">{{ approvalData.host }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®æ¶é´</text> |
| | | <text class="info-value">{{ formatDateTime(approvalData.meetingTime) }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®å°ç¹</text> |
| | | <text class="info-value">{{ approvalData.location }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">审æ¹ç¶æ</text> |
| | | <text class="info-value tag" |
| | | :class="getTagClass(approvalData.approveNodeStatus)"> |
| | | {{ formatReceiptType(approvalData.approveNodeStatus) }} |
| | | </text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®è¯´æ</text> |
| | | <text class="info-value">{{ approvalData.description }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººæ°</text> |
| | | <text class="info-value">{{ approvalData.participants.length }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººå</text> |
| | | <text class="info-value">{{ approvalData.participants.map(it => it.name).join("ã") }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- å叿è§è¾å
¥ --> |
| | | <view v-if="isEdit" |
| | | class="approval-input"> |
| | | <view class="input-header"> |
| | | <text class="input-title">å叿è§</text> |
| | | </view> |
| | | <view class="input-content"> |
| | | <u-textarea v-model="approvalOpinion" |
| | | rows="4" |
| | | placeholder="请è¾å
¥å叿è§" |
| | | maxlength="200" |
| | | count /> |
| | | </view> |
| | | </view> |
| | | <!-- åºé¨æä½æé® --> |
| | | <view v-if="isEdit" |
| | | class="footer-actions"> |
| | | <!-- <u-button class="reject-btn" |
| | | @click="handleReject">ä¸éè¿</u-button> --> |
| | | <u-button class="approve-btn" |
| | | @click="handleApprove">åå¸</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { saveMeetingApplication } from "@/api/managementMeetings/meetExamine"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | |
| | | const approvalData = ref({}); |
| | | const approvalSteps = ref([]); |
| | | const approvalOpinion = ref(""); |
| | | const isEdit = ref(false); |
| | | |
| | | onLoad(options => { |
| | | console.log(options, "options"); |
| | | if (options.item) { |
| | | approvalData.value = JSON.parse(options.item); |
| | | } |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼é»è®¤å叿è§ä¸ºå½åå®¡æ¹æè§ |
| | | if (options.edit) { |
| | | isEdit.value = options.edit === "true" ? true : false; |
| | | } |
| | | console.log(approvalData.value, "approvalData.value"); |
| | | }); |
| | | |
| | | const goBack = () => { |
| | | uni.removeStorageSync("approveId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
åå¸"; |
| | | } else if (params == 1) { |
| | | return "å·²åå¸"; |
| | | } else if (params == 2) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | const submitForm = status => { |
| | | // æ ¡éªåå¸æè§ |
| | | if (!approvalOpinion.value?.trim()) { |
| | | showToast("请è¾å
¥å叿è§"); |
| | | return; |
| | | } |
| | | |
| | | // è°ç¨å端 |
| | | saveMeetingApplication({ |
| | | id: approvalData.value.id, |
| | | publishStatus: status, |
| | | publishComment: approvalOpinion.value, // æ·»å åå¸æè§ |
| | | }) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | showToast("å叿å"); |
| | | // æç¤ºåè¿åä¸ä¸ä¸ªé¡µé¢ |
| | | setTimeout(() => { |
| | | goBack(); // å
鍿¯ uni.navigateBack() |
| | | }, 800); |
| | | } else { |
| | | showToast(res.message || "å叿ä½å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("å叿ä½å¤±è´¥:", error); |
| | | showToast("å叿ä½å¤±è´¥ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | |
| | | const handleApprove = () => { |
| | | uni.showModal({ |
| | | title: "确认æä½", |
| | | content: "ç¡®å®è¦åå¸è¯¥ä¼è®®åï¼", |
| | | success: res => { |
| | | if (res.confirm) submitForm(1); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | const handleReject = () => { |
| | | uni.showModal({ |
| | | title: "确认æä½", |
| | | content: "ç¡®å®ä¸éè¿è¯¥ä¼è®®ç³è¯·åï¼", |
| | | success: res => { |
| | | if (res.confirm) submitForm(2); |
| | | }, |
| | | }); |
| | | }; |
| | | // åå§èç¹æ°æ®ï¼ç¨äºæäº¤é»è¾ï¼ |
| | | const activities = ref([]); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .approve-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | } |
| | | |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .application-info { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .info-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .info-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .info-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | width: 80px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .process-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .process-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .process-steps { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .process-step { |
| | | display: flex; |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | |
| | | .step-line { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .step-indicator { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .step-dot { |
| | | width: 32px; |
| | | height: 32px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | position: relative; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .process-step.completed .step-dot { |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | .process-step.current .step-dot { |
| | | background: #1890ff; |
| | | color: #fff; |
| | | animation: pulse 2s infinite; |
| | | } |
| | | |
| | | .process-step.pending .step-dot { |
| | | background: #d9d9d9; |
| | | color: #999; |
| | | } |
| | | |
| | | .step-line { |
| | | width: 2px; |
| | | height: 40px; |
| | | background: #d9d9d9; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .process-step.completed .step-line { |
| | | background: #52c41a; |
| | | } |
| | | |
| | | .process-step.rejected .step-dot { |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | .process-step.rejected .step-line { |
| | | background: #ff4d4f; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | padding-top: 4px; |
| | | } |
| | | |
| | | .step-info { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .step-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-approver { |
| | | font-size: 14px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-time { |
| | | font-size: 12px; |
| | | color: #999; |
| | | display: block; |
| | | } |
| | | |
| | | .step-opinion { |
| | | background: #f8f9fa; |
| | | padding: 12px; |
| | | border-radius: 8px; |
| | | border-left: 4px solid #52c41a; |
| | | } |
| | | |
| | | .opinion-label { |
| | | font-size: 12px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .opinion-content { |
| | | font-size: 14px; |
| | | color: #333; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .approval-input { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .input-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .input-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .input-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .footer-actions { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 16px; |
| | | box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .reject-btn { |
| | | width: 120px; |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | |
| | | .approve-btn { |
| | | width: 120px; |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | /* éé
u-buttonæ ·å¼ */ |
| | | :deep(.u-button) { |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0.7); |
| | | } |
| | | 70% { |
| | | box-shadow: 0 0 0 10px rgba(24, 144, 255, 0); |
| | | } |
| | | 100% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0); |
| | | } |
| | | } |
| | | .signature-section { |
| | | background: #fff; |
| | | padding: 12px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | .signature-header { |
| | | margin-bottom: 8px; |
| | | } |
| | | .signature-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .signature-box { |
| | | width: 100%; |
| | | height: 180px; |
| | | background: #fff; |
| | | border: 1px dashed #d9d9d9; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | .signature-actions { |
| | | margin-top: 8px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 审æ¹ç®¡çä¸»é¡µé¢ |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ä¼è®®åå¸" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | v-model="searchForm.title" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-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.title }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.status)">{{ formatReceiptType(item.status) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·äºº</text> |
| | | <text class="detail-value">{{ item.applicant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">主ç人</text> |
| | | <text class="detail-value">{{ item.host }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">ä¼è®®æ¶é´</text> |
| | | <text class="detail-value highlightBlue">{{ formatDateTime(item.meetingTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¼è®®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ item.participants.length }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="actions"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn view" |
| | | @click="viewDetail(item)"> |
| | | 详æ
|
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | | :disabled="item.status != 0" |
| | | @click="approve(item)"> |
| | | åå¸ |
| | | </u-button> |
| | | </view> |
| | | <!-- <view class="detail-info" |
| | | style="align-items: flex-end;"> |
| | | <view class="detail-row"> |
| | | |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, toRefs, reactive } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getMeetingPublish, |
| | | getRoomEnum, |
| | | } from "@/api/managementMeetings/meetExamine"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/onboarding"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¿é´æä¸¾ |
| | | const roomEnum = ref([]); |
| | | // æ¿é´æä¸¾æ¥è¯¢ |
| | | const getRoomEnumList = () => { |
| | | return getRoomEnum() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | roomEnum.value = res.data; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // åå·¥å表 |
| | | const staffList = ref([]); |
| | | // åå·¥å表æ¥è¯¢ |
| | | const getStaffOnJobList = () => { |
| | | return staffOnJobListPage() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | staffList.value = res.data.records; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | getMeetingPublish({ |
| | | ...page, |
| | | ...searchForm.value, |
| | | }) |
| | | .then(res => { |
| | | console.log(res.data.records, "res.data.records"); |
| | | ledgerList.value = res.data.records.map(it => { |
| | | console.log(it, "it1"); |
| | | let room = roomEnum.value.find(room => it.roomId === room.id); |
| | | it.location = `${room.name}(${room.location})`; |
| | | let staffs = JSON.parse(it.participants); |
| | | it.staffCount = staffs.size; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm:ss" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; |
| | | it.participants = staffList.value |
| | | .filter(staff => staffs.some(id => id == staff.id)) |
| | | .map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postName})`, |
| | | }; |
| | | }); |
| | | console.log(it, "it2"); |
| | | |
| | | return it; |
| | | }); |
| | | |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
åå¸"; |
| | | } else if (params == 1) { |
| | | return "å·²åå¸"; |
| | | } else if (params == 2) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = item => { |
| | | // uni.setStorageSync("approveId", item.approveId); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetPublish/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=true", |
| | | }); |
| | | }; |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetPublish/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=false", |
| | | }); |
| | | }; |
| | | |
| | | onShow(async () => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | try { |
| | | // çå¾
ä¸¤ä¸ªå¼æ¥æ¹æ³æ§è¡å®æ |
| | | await Promise.all([getRoomEnumList(), getStaffOnJobList()]); |
| | | // ä¸¤ä¸ªæ¹æ³æ§è¡å®æååæ§è¡ getList() |
| | | getList(); |
| | | } catch (error) { |
| | | console.error("åå§åæ°æ®å¤±è´¥:", error); |
| | | // å³ä½¿åºé乿§è¡ getList()ï¼ç¡®ä¿é¡µé¢è½æ£å¸¸å è½½ |
| | | getList(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | margin-top: 18rpx; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="approve-page"> |
| | | <PageHeader title="æ»ç»" |
| | | @back="goBack" /> |
| | | <!-- ç³è¯·ä¿¡æ¯ --> |
| | | <view class="application-info"> |
| | | <view class="info-header"> |
| | | <text class="info-title">ä¼è®®ä¿¡æ¯</text> |
| | | </view> |
| | | <view class="info-content"> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®ä¸»é¢</text> |
| | | <text class="info-value">{{ approvalData.title }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ç³è¯·äºº</text> |
| | | <text class="info-value">{{ approvalData.applicant }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">主ç人</text> |
| | | <text class="info-value">{{ approvalData.host }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®æ¶é´</text> |
| | | <text class="info-value">{{ formatDateTime(approvalData.meetingTime) }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®å°ç¹</text> |
| | | <text class="info-value">{{ approvalData.location }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">审æ¹ç¶æ</text> |
| | | <text class="info-value tag" |
| | | :class="getTagClass(approvalData.approveNodeStatus)"> |
| | | {{ formatReceiptType(approvalData.approveNodeStatus) }} |
| | | </text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ä¼è®®è¯´æ</text> |
| | | <text class="info-value">{{ approvalData.description }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººæ°</text> |
| | | <text class="info-value">{{ approvalData.participants.length }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åä¼äººå</text> |
| | | <text class="info-value">{{ approvalData.participants.map(it => it.name).join("ã") }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æäº¤æè§è¾å
¥ --> |
| | | <view v-if="isEdit" |
| | | class="approval-input"> |
| | | <view class="input-header"> |
| | | <text class="input-title">ä¼è®®çºªè¦</text> |
| | | </view> |
| | | <view class="input-content"> |
| | | <Editor v-model:modelValue="minutesContent" |
| | | :height="300" /> |
| | | </view> |
| | | </view> |
| | | <!-- åºé¨æä½æé® --> |
| | | <view v-if="isEdit" |
| | | class="footer-actions"> |
| | | <u-button class="approve-btn" |
| | | @click="handleApprove">æäº¤</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <script setup> |
| | | import { ref, onMounted, nextTick } from "vue"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { |
| | | saveMeetingMinutes, |
| | | getMeetingMinutesByMeetingId, |
| | | } from "@/api/managementMeetings/meetExamine"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import Editor from "@/components/Editor/index.vue"; |
| | | |
| | | const approvalData = ref({}); |
| | | const approvalSteps = ref([]); |
| | | const isEdit = ref(false); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | onLoad(options => { |
| | | console.log(options, "options"); |
| | | if (options.item) { |
| | | approvalData.value = JSON.parse(options.item); |
| | | } |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼é»è®¤æäº¤æè§ä¸ºå½åå®¡æ¹æè§ |
| | | if (options.edit) { |
| | | isEdit.value = options.edit === "true" ? true : false; |
| | | } |
| | | getMeetingMinutes(); |
| | | console.log(approvalData.value, "approvalData.value"); |
| | | }); |
| | | const goBack = () => { |
| | | uni.removeStorageSync("approveId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
审æ¹"; |
| | | } else if (params == 1) { |
| | | return "å·²éè¿"; |
| | | } else if (params == 2) { |
| | | return "æªéè¿"; |
| | | } else if (params == 3) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "warning"; |
| | | } else if (type == 3) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | const minutesContent = ref(""); |
| | | const minutesContentId = ref(""); |
| | | const getMeetingMinutes = () => { |
| | | getMeetingMinutesByMeetingId(approvalData.value.id) |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | |
| | | if (res.data) { |
| | | minutesContent.value = res.data.content; |
| | | minutesContentId.value = res.data.id; |
| | | } else { |
| | | minutesContent.value = `<h2>${approvalData.value.title}ä¼è®®çºªè¦</h2> |
| | | <p><strong>ä¼è®®æ¶é´ï¼</strong>${ |
| | | approvalData |
| | | .value |
| | | .meetingTime |
| | | }</p> |
| | | <p><strong>ä¼è®®å°ç¹ï¼</strong>${ |
| | | approvalData |
| | | .value |
| | | .location |
| | | }</p> |
| | | <p><strong>主æäººï¼</strong>${ |
| | | approvalData |
| | | .value |
| | | .host |
| | | }</p> |
| | | <p><strong>åä¼äººåï¼</strong></p> |
| | | <ol> |
| | | ${approvalData.value.participants |
| | | .map( |
| | | p => |
| | | `<li>${p.name}</li>` |
| | | ) |
| | | .join( |
| | | "" |
| | | )} |
| | | </ol> |
| | | <p><strong>ä¼è®®å
容ï¼</strong></p> |
| | | <ol> |
| | | <li>è®®é¢ä¸ï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | <li>è®®é¢äºï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | </ol> |
| | | <p><strong>夿³¨ï¼</strong></p>`; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("è·åä¼è®®çºªè¦å¤±è´¥:", error); |
| | | showToast("è·åä¼è®®çºªè¦å¤±è´¥ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | const submitForm = status => { |
| | | console.log(minutesContent.value, "坿æ¬"); |
| | | if (!minutesContent.value) { |
| | | ElMessage.warning("请è¾å
¥ä¼è®®çºªè¦å
容"); |
| | | return; |
| | | } |
| | | |
| | | // è°ç¨å端 |
| | | saveMeetingMinutes({ |
| | | id: minutesContentId.value, |
| | | content: minutesContent.value, |
| | | meetingId: approvalData.value.id, |
| | | title: approvalData.value.title, |
| | | }) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | showToast("æäº¤æå"); |
| | | // æç¤ºåè¿åä¸ä¸ä¸ªé¡µé¢ |
| | | setTimeout(() => { |
| | | goBack(); // å
鍿¯ uni.navigateBack() |
| | | }, 800); |
| | | } else { |
| | | showToast(res.message || "æäº¤æä½å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("æäº¤æä½å¤±è´¥:", error); |
| | | showToast("æäº¤æä½å¤±è´¥ï¼è¯·éè¯"); |
| | | }); |
| | | }; |
| | | |
| | | const handleApprove = () => { |
| | | uni.showModal({ |
| | | title: "确认æä½", |
| | | content: "ç¡®å®è¦æäº¤è¯¥ä¼è®®æ»ç»åï¼", |
| | | success: res => { |
| | | if (res.confirm) submitForm(1); |
| | | }, |
| | | }); |
| | | }; |
| | | // åå§èç¹æ°æ®ï¼ç¨äºæäº¤é»è¾ï¼ |
| | | const activities = ref([]); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .approve-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | } |
| | | |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .application-info { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .info-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .info-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .info-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | width: 80px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .process-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .process-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .process-steps { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .process-step { |
| | | display: flex; |
| | | position: relative; |
| | | margin-bottom: 24px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | |
| | | .step-line { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .step-indicator { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .step-dot { |
| | | width: 32px; |
| | | height: 32px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | position: relative; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .process-step.completed .step-dot { |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | .process-step.current .step-dot { |
| | | background: #1890ff; |
| | | color: #fff; |
| | | animation: pulse 2s infinite; |
| | | } |
| | | |
| | | .process-step.pending .step-dot { |
| | | background: #d9d9d9; |
| | | color: #999; |
| | | } |
| | | |
| | | .step-line { |
| | | width: 2px; |
| | | height: 40px; |
| | | background: #d9d9d9; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .process-step.completed .step-line { |
| | | background: #52c41a; |
| | | } |
| | | |
| | | .process-step.rejected .step-dot { |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | .process-step.rejected .step-line { |
| | | background: #ff4d4f; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | padding-top: 4px; |
| | | } |
| | | |
| | | .step-info { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .step-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-approver { |
| | | font-size: 14px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .step-time { |
| | | font-size: 12px; |
| | | color: #999; |
| | | display: block; |
| | | } |
| | | |
| | | .step-opinion { |
| | | background: #f8f9fa; |
| | | padding: 12px; |
| | | border-radius: 8px; |
| | | border-left: 4px solid #52c41a; |
| | | } |
| | | |
| | | .opinion-label { |
| | | font-size: 12px; |
| | | color: #666; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .opinion-content { |
| | | font-size: 14px; |
| | | color: #333; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .approval-input { |
| | | background: #fff; |
| | | margin: 16px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .input-header { |
| | | padding: 16px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | background: #f8f9fa; |
| | | } |
| | | |
| | | .input-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .input-content { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .footer-actions { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 16px; |
| | | box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .reject-btn { |
| | | width: 120px; |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | |
| | | .approve-btn { |
| | | width: 120px; |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | /* éé
u-buttonæ ·å¼ */ |
| | | :deep(.u-button) { |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0.7); |
| | | } |
| | | 70% { |
| | | box-shadow: 0 0 0 10px rgba(24, 144, 255, 0); |
| | | } |
| | | 100% { |
| | | box-shadow: 0 0 0 0 rgba(24, 144, 255, 0); |
| | | } |
| | | } |
| | | .signature-section { |
| | | background: #fff; |
| | | padding: 12px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | .signature-header { |
| | | margin-bottom: 8px; |
| | | } |
| | | .signature-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .signature-box { |
| | | width: 100%; |
| | | height: 180px; |
| | | background: #fff; |
| | | border: 1px dashed #d9d9d9; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | .signature-actions { |
| | | margin-top: 8px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | /* å·¥å
·æ æé®æ ·å¼ */ |
| | | :deep(.ql-toolbar.ql-snow .ql-button) { |
| | | height: 28px; |
| | | width: 28px; |
| | | padding: 4px; |
| | | } |
| | | :deep(.ql-toolbar.ql-snow .ql-picker-label) { |
| | | height: 28px; |
| | | padding: 4px 8px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 审æ¹ç®¡çä¸»é¡µé¢ |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ä¼è®®æ»ç»" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | v-model="searchForm.title" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-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.title }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.status)">{{ formatReceiptType(item.status) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç³è¯·äºº</text> |
| | | <text class="detail-value">{{ item.applicant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">主ç人</text> |
| | | <text class="detail-value">{{ item.host }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">ä¼è®®æ¶é´</text> |
| | | <text class="detail-value highlightBlue">{{ formatDateTime(item.meetingTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¼è®®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ item.participants.length }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="actions"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn view" |
| | | @click="viewDetail(item)"> |
| | | 详æ
|
| | | </u-button> |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | | :disabled="item.status != 0" |
| | | @click="approve(item)"> |
| | | æ·»å çºªè¦ |
| | | </u-button> |
| | | </view> |
| | | <!-- <view class="detail-info" |
| | | style="align-items: flex-end;"> |
| | | <view class="detail-row"> |
| | | |
| | | </view> |
| | | </view> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, toRefs, reactive } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getMeetingPublish, |
| | | getRoomEnum, |
| | | } from "@/api/managementMeetings/meetExamine"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/onboarding"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¿é´æä¸¾ |
| | | const roomEnum = ref([]); |
| | | // æ¿é´æä¸¾æ¥è¯¢ |
| | | const getRoomEnumList = () => { |
| | | return getRoomEnum() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | roomEnum.value = res.data; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // åå·¥å表 |
| | | const staffList = ref([]); |
| | | // åå·¥å表æ¥è¯¢ |
| | | const getStaffOnJobList = () => { |
| | | return staffOnJobListPage() |
| | | .then(res => { |
| | | console.log(res.data, "res.data"); |
| | | staffList.value = res.data.records; |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | getMeetingPublish({ |
| | | ...page, |
| | | ...searchForm.value, |
| | | }) |
| | | .then(res => { |
| | | console.log(res.data.records, "res.data.records"); |
| | | ledgerList.value = res.data.records.map(it => { |
| | | console.log(it, "it1"); |
| | | let room = roomEnum.value.find(room => it.roomId === room.id); |
| | | it.location = `${room.name}(${room.location})`; |
| | | let staffs = JSON.parse(it.participants); |
| | | it.staffCount = staffs.size; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm:ss" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; |
| | | console.log(staffList.value, "staffList.value"); |
| | | it.participants = staffList.value |
| | | .filter(staff => staffs.some(id => id == staff.id)) |
| | | .map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postName})`, |
| | | }; |
| | | }); |
| | | console.log(it, "it2"); |
| | | |
| | | return it; |
| | | }); |
| | | |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "å¾
审æ¹"; |
| | | } else if (params == 1) { |
| | | return "å·²éè¿"; |
| | | } else if (params == 2) { |
| | | return "æªéè¿"; |
| | | } else if (params == 3) { |
| | | return "已忶"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "success"; |
| | | } else if (type == 2) { |
| | | return "warning"; |
| | | } else if (type == 3) { |
| | | return "danger"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = item => { |
| | | // uni.setStorageSync("approveId", item.approveId); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetSummary/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=true", |
| | | }); |
| | | }; |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/meetSummary/approve?item=" + |
| | | JSON.stringify(item) + |
| | | "&edit=false", |
| | | }); |
| | | }; |
| | | |
| | | onShow(async () => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | try { |
| | | // çå¾
ä¸¤ä¸ªå¼æ¥æ¹æ³æ§è¡å®æ |
| | | await Promise.all([getRoomEnumList(), getStaffOnJobList()]); |
| | | // ä¸¤ä¸ªæ¹æ³æ§è¡å®æååæ§è¡ getList() |
| | | getList(); |
| | | } catch (error) { |
| | | console.error("åå§åæ°æ®å¤±è´¥:", error); |
| | | // å³ä½¿åºé乿§è¡ getList()ï¼ç¡®ä¿é¡µé¢è½æ£å¸¸å è½½ |
| | | getList(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | margin-top: 18rpx; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 审æ¹ç®¡çä¸»é¡µé¢ |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ä¼è®®çæ¿" |
| | | @back="goBack" /> |
| | | <!-- 审æ¹å表 --> |
| | | <view class="topbox"> |
| | | <view class="boxItem"> |
| | | <view class="boxItem-num"> |
| | | {{stats.total ? stats.total : 0}} |
| | | </view> |
| | | <view class="boxItem-title"> |
| | | æ»ä¼è®®æ° |
| | | </view> |
| | | </view> |
| | | <view class="boxItem"> |
| | | <view class="boxItem-num"> |
| | | {{stats.underWay ? stats.underWay : 0}} |
| | | </view> |
| | | <view class="boxItem-title"> |
| | | è¿è¡ä¸ |
| | | </view> |
| | | </view> |
| | | <view class="boxItem"> |
| | | <view class="boxItem-num"> |
| | | {{stats.completed ? stats.completed : 0}} |
| | | </view> |
| | | <view class="boxItem-title"> |
| | | 已宿 |
| | | </view> |
| | | </view> |
| | | <view class="boxItem"> |
| | | <view class="boxItem-num"> |
| | | {{stats.toStart ? stats.toStart : 0}} |
| | | </view> |
| | | <view class="boxItem-title"> |
| | | å³å°å¼å§ |
| | | </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.title }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.status)">{{ formatReceiptType(item.status) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">主æäºº</text> |
| | | <text class="detail-value">{{ item.host }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ item.participants.length }}</text> |
| | | </view> |
| | | <view class="detail-row-approveReason"> |
| | | <text class="detail-label">ä¼è®®æ¶é´</text> |
| | | <text class="detail-value highlightBlue">{{dayjs(item.startTime).format("YYYY-MM-DD")}} |
| | | {{ formatTime(item.startTime) }} - {{ formatTime(item.endTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¼è®®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ item.participants.length }}</text> |
| | | </view> |
| | | <!-- <up-divider></up-divider> --> |
| | | <u-collapse @change="change" |
| | | @close="close" |
| | | @open="open" |
| | | accordion |
| | | border |
| | | :duration="300"> |
| | | <u-collapse-item :title="`ä¼è®®çºªè¦ ${item.content ? '' : '(æ )'}`" |
| | | :name="`meeting-${index}`"> |
| | | <view class="meeting-content"> |
| | | <view v-if="item.content" |
| | | class="content-html"><rich-text :nodes="item.content"></rich-text></view> |
| | | <view v-else |
| | | class="no-content"> |
| | | <text>ææ ä¼è®®çºªè¦å
容</text> |
| | | </view> |
| | | </view> |
| | | </u-collapse-item> |
| | | </u-collapse> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, toRefs, reactive } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getMeetSummaryItems, |
| | | getMeetSummary, |
| | | } from "@/api/managementMeetings/meetExamine"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | }, |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // ç»è®¡æ°æ® |
| | | const stats = ref({}); |
| | | const getnum = () => { |
| | | getMeetSummary().then(res => { |
| | | stats.value = res.data; |
| | | }); |
| | | }; |
| | | // æ ¼å¼åæ¶é´ |
| | | const formatTime = timeStr => { |
| | | const date = new Date(timeStr); |
| | | return date.toLocaleTimeString("zh-CN", { |
| | | hour: "2-digit", |
| | | minute: "2-digit", |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | |
| | | getMeetSummaryItems() |
| | | .then(res => { |
| | | ledgerList.value = res.data.map(item => { |
| | | return { |
| | | ...item, |
| | | participants: JSON.parse(item.participants), |
| | | }; |
| | | }); |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == 0) { |
| | | return "已宿"; |
| | | } else if (params == 1) { |
| | | return "å³å°å¼å§"; |
| | | } else if (params == 2) { |
| | | return "è¿è¡ä¸"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "info"; |
| | | } else if (type == 1) { |
| | | return "warning"; |
| | | } else if (type == 2) { |
| | | return "success"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | // u-collapse äºä»¶å¤ç彿° |
| | | const change = name => { |
| | | console.log("å±å¼ç颿¿å:", name); |
| | | }; |
| | | |
| | | const close = name => { |
| | | console.log("å
³éç颿¿å:", name); |
| | | }; |
| | | |
| | | const open = name => { |
| | | console.log("æå¼ç颿¿å:", name); |
| | | }; |
| | | |
| | | onShow(async () => { |
| | | // 页é¢å è½½å®æåçåå§åé»è¾ |
| | | try { |
| | | // ä¸¤ä¸ªæ¹æ³æ§è¡å®æååæ§è¡ getList() |
| | | getList(); |
| | | getnum(); |
| | | } catch (error) { |
| | | console.error("åå§åæ°æ®å¤±è´¥:", error); |
| | | // å³ä½¿åºé乿§è¡ getList()ï¼ç¡®ä¿é¡µé¢è½æ£å¸¸å è½½ |
| | | getList(); |
| | | getnum(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | // ææ¡£å¾æ æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .document-icon { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // æµ®å¨æé®æ ·å¼ - è¦çå
Œ
±æ ·å¼ä¸çèæ¯è² |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.highlightYellow { |
| | | color: #ed8d05; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: #f0f6ff; |
| | | color: #2b7cff; |
| | | border: 1px solid #e0efff; |
| | | border-radius: 999px; |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | margin-top: 18rpx; |
| | | } |
| | | |
| | | .action-btn { |
| | | border-radius: 16px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | .topbox { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-left: 20px; |
| | | margin-right: 20px; |
| | | margin-top: 10px; |
| | | } |
| | | .boxItem { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background-color: #fff; |
| | | width: 24%; |
| | | padding-top: 10px; |
| | | padding-bottom: 10px; |
| | | border-radius: 6px; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); |
| | | } |
| | | .boxItem-num { |
| | | margin-bottom: 5px; |
| | | font-weight: 500; |
| | | color: #2979ff; |
| | | } |
| | | |
| | | // ä¼è®®çºªè¦æ ·å¼ |
| | | .meeting-content { |
| | | padding: 15px; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .content-html { |
| | | color: #333; |
| | | word-break: break-word; |
| | | } |
| | | |
| | | .content-html :deep(p) { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .content-html :deep(ul), |
| | | .content-html :deep(ol) { |
| | | margin-bottom: 10px; |
| | | padding-left: 20px; |
| | | } |
| | | |
| | | .content-html :deep(li) { |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .no-content { |
| | | color: #999; |
| | | text-align: center; |
| | | padding: 20px 0; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | // u-collapse æ ·å¼ä¼å |
| | | :deep(.u-collapse) { |
| | | margin-top: 10px; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | :deep(.u-collapse-item__header) { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.u-collapse-item__content) { |
| | | background-color: #fafafa; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="meeting-list"> |
| | | <PageHeader title="ä¼è®®å表" |
| | | @back="goBack" /> |
| | | <!-- æ¥è¯¢è¡¨å --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="æ¥è¯¢æ¥æ" |
| | | @click.stop="showDatePicker" |
| | | v-model="queryForm.meetingDate" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="clearDate"> |
| | | <u-icon name="close-circle-fill" |
| | | size="24" |
| | | color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker v-model="datePickerValue" |
| | | mode="date" |
| | | :show="showDatePickerDialog" |
| | | @confirm="handleDateConfirm" |
| | | @cancel="showDatePickerDialog = false" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" /> |
| | | <!-- ä¼è®®å®¤ä½¿ç¨æ
åµ --> |
| | | <view class="table-container"> |
| | | <scroll-view scroll-x="true" |
| | | style="width: 100%;"> |
| | | <view class="time-table"> |
| | | <!-- 表头 --> |
| | | <view class="table-header"> |
| | | <view class="header-cell room-header">ä¼è®®å®¤</view> |
| | | <view v-for="timeSlot in timeSlots" |
| | | :key="timeSlot.value" |
| | | class="header-cell time-header"> |
| | | {{ timeSlot.label }} |
| | | </view> |
| | | </view> |
| | | <!-- è¡¨æ ¼å
容 --> |
| | | <view class="table-body"> |
| | | <view v-for="room in roomUsage" |
| | | :key="room.id" |
| | | class="table-row"> |
| | | <view class="cell room-cell">{{ room.name }}</view> |
| | | <view class="cells-container"> |
| | | <template v-for="(cell, index) in generateMeetingCells(room)" |
| | | :key="index"> |
| | | <view class="cell content-cell" |
| | | :class="[cell.type, `status-${cell.meeting?.status || '0'}`]" |
| | | :style="{ width: `${cell.span * 120}rpx` }" |
| | | @click="viewMeetingDetails(cell)"> |
| | | <view v-if="cell.type === 'meeting'" |
| | | class="meeting-content"> |
| | | <view class="meeting-title">{{ cell.meeting.title }}</view> |
| | | <view class="meeting-time">{{ cell.startTime }}-{{ cell.endTime }}</view> |
| | | </view> |
| | | <view v-else |
| | | class="free-content"> |
| | | ç©ºé² |
| | | </view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | <!-- ä¼è®®è¯¦æ
å¯¹è¯æ¡ --> |
| | | <u-popup :show="detailDialogVisible" |
| | | mode="center" |
| | | customStyle="width: 80%;" |
| | | :round="10"> |
| | | <view class="dialog-content"> |
| | | <view class="dialog-header"> |
| | | <text class="dialog-title">ä¼è®®è¯¦æ
</text> |
| | | <up-icon name="close" |
| | | @click="detailDialogVisible = false" |
| | | class="close-icon"></up-icon> |
| | | </view> |
| | | <view v-if="currentMeeting" |
| | | class="dialog-body"> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">ä¼è®®ä¸»é¢</text> |
| | | <text class="detail-value">{{ currentMeeting.title }}</text> |
| | | </view> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">ä¼è®®å®¤</text> |
| | | <text class="detail-value">{{ currentMeeting.room }}</text> |
| | | </view> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">ä¼è®®æ¶é´</text> |
| | | <text class="detail-value">{{ currentMeeting.time }}</text> |
| | | </view> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">主æäºº</text> |
| | | <text class="detail-value">{{ currentMeeting.host }}</text> |
| | | </view> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">åä¼äººæ°</text> |
| | | <text class="detail-value">{{ currentMeeting.participants }}人</text> |
| | | </view> |
| | | <view class="detail-item"> |
| | | <text class="detail-label">ä¼è®®è¯´æ</text> |
| | | <text class="detail-value">{{ currentMeeting.description }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <u-button @click="detailDialogVisible = false">å
³é</u-button> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getMeetingUseList } from "@/api/managementMeetings/meeting.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // æ¥è¯¢è¡¨å |
| | | const queryForm = reactive({ |
| | | meetingDate: dayjs().format("YYYY-MM-DD"), |
| | | }); |
| | | |
| | | const loading = ref(false); |
| | | const timeSlots = ref([]); |
| | | const roomUsage = ref([]); |
| | | const currentMeeting = ref(null); |
| | | const detailDialogVisible = ref(false); |
| | | const showDatePickerDialog = ref(false); |
| | | const datePickerValue = ref(Date.now()); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¸
ç©ºæ¥æ |
| | | const clearDate = () => { |
| | | datePickerValue.value = Date.now(); |
| | | queryForm.meetingDate = dayjs().format("YYYY-MM-DD"); |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | if (queryForm.meetingDate) { |
| | | datePickerValue.value = new Date(queryForm.meetingDate).getTime(); |
| | | } else { |
| | | datePickerValue.value = Date.now(); |
| | | } |
| | | console.log(datePickerValue.value, "datePickerValue.value"); |
| | | showDatePickerDialog.value = true; |
| | | }; |
| | | |
| | | // å¤çæ¥æéæ©ç¡®è®¤ |
| | | const handleDateConfirm = value => { |
| | | // dayjs().format("YYYY-MM-DD") |
| | | console.log(value, "value"); |
| | | |
| | | queryForm.meetingDate = dayjs(value.value).format("YYYY-MM-DD"); |
| | | showDatePickerDialog.value = false; |
| | | getList(); |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // åå§åæ¶é´æ§½ï¼ä»¥åå°æ¶ä¸ºé´éï¼ä»8:00å°17:30ï¼ |
| | | const initTimeSlots = () => { |
| | | const slots = []; |
| | | // çæ8:00å°17:00çæ¶é´æ®µ |
| | | for (let hour = 8; hour <= 17; hour++) { |
| | | // æ·»å æ´ç¹ |
| | | slots.push({ |
| | | label: `${hour.toString().padStart(2, "0")}:00`, |
| | | value: `${hour.toString().padStart(2, "0")}:00`, |
| | | }); |
| | | |
| | | // æ·»å åç¹ï¼ç´å°17:30 |
| | | if (hour <= 17) { |
| | | slots.push({ |
| | | label: `${hour.toString().padStart(2, "0")}:30`, |
| | | value: `${hour.toString().padStart(2, "0")}:30`, |
| | | }); |
| | | } |
| | | } |
| | | // ç§»é¤æåä¸ä¸ª18:00çæ¶é´æ®µ |
| | | if (slots.length > 0 && slots[slots.length - 1].value === "18:00") { |
| | | slots.pop(); |
| | | } |
| | | timeSlots.value = slots; |
| | | console.log(timeSlots.value, "timeSlots.value"); |
| | | }; |
| | | |
| | | // çæä¼è®®å®¤çæ¶é´åå
æ ¼ |
| | | const generateMeetingCells = room => { |
| | | const cells = []; |
| | | const meetings = room.meetings || []; |
| | | const occupiedSlots = new Set(); |
| | | |
| | | // å¤çæ¯ä¸ªä¼è®® |
| | | for (const meeting of meetings) { |
| | | const startIdx = timeSlots.value.findIndex( |
| | | slot => slot.value === meeting.startTime |
| | | ); |
| | | let endIdx = timeSlots.value.findIndex( |
| | | slot => slot.value === meeting.endTime |
| | | ); |
| | | if (endIdx === -1) { |
| | | endIdx = timeSlots.value.length; |
| | | } |
| | | |
| | | if (startIdx !== -1) { |
| | | // æ 记被å ç¨çæ¶é´æ®µ |
| | | for (let i = startIdx; i < endIdx; i++) { |
| | | if (timeSlots.value[i]) { |
| | | occupiedSlots.add(timeSlots.value[i].value); |
| | | } |
| | | } |
| | | |
| | | // å建ä¼è®®åå
æ ¼ |
| | | cells.push({ |
| | | type: "meeting", |
| | | meeting: meeting, |
| | | span: endIdx - startIdx, |
| | | startTime: meeting.startTime, |
| | | endTime: meeting.endTime, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // å¤çç©ºé²æ¶é´æ®µ |
| | | for (let i = 0; i < timeSlots.value.length; i++) { |
| | | const slot = timeSlots.value[i]; |
| | | if (!occupiedSlots.has(slot.value)) { |
| | | // æ¥æ¾è¿ç»çç©ºé²æ¶é´æ®µ |
| | | let span = 1; |
| | | while ( |
| | | i + span < timeSlots.value.length && |
| | | !occupiedSlots.has(timeSlots.value[i + span].value) |
| | | ) { |
| | | occupiedSlots.add(timeSlots.value[i + span].value); |
| | | span++; |
| | | } |
| | | |
| | | cells.push({ |
| | | type: "free", |
| | | span: span, |
| | | time: slot.value, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ææ¶é´æåº |
| | | cells.sort((a, b) => { |
| | | const timeA = a.startTime || a.time; |
| | | const timeB = b.startTime || b.time; |
| | | return ( |
| | | timeSlots.value.findIndex(s => s.value === timeA) - |
| | | timeSlots.value.findIndex(s => s.value === timeB) |
| | | ); |
| | | }); |
| | | console.log(cells, "cells"); |
| | | return cells; |
| | | }; |
| | | |
| | | // æ¥çä¼è®®è¯¦æ
|
| | | const viewMeetingDetails = cell => { |
| | | console.log(cell, "cell"); |
| | | |
| | | if (cell && cell.type === "meeting") { |
| | | currentMeeting.value = cell.meeting; |
| | | detailDialogVisible.value = true; |
| | | } else { |
| | | uni.showToast({ |
| | | title: "该æ¶é´æ®µä¼è®®å®¤ç©ºé²", |
| | | icon: "info", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // æ¥è¯¢æé®æä½ |
| | | const handleSearch = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const resp = await getMeetingUseList({ ...queryForm }); |
| | | roomUsage.value = resp.data; |
| | | } catch (error) { |
| | | uni.showToast({ |
| | | title: "è·åæ°æ®å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | queryForm.meetingDate = dayjs().format("YYYY-MM-DD"); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | // åå§åæ¶é´æ§½ |
| | | initTimeSlots(); |
| | | |
| | | // é»è®¤æ¥è¯¢ä»å¤©çæ°æ® |
| | | handleSearch(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | .meeting-list { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding: 16rpx; |
| | | } |
| | | |
| | | .search-section { |
| | | background: #fff; |
| | | padding: 16rpx; |
| | | border-radius: 8rpx; |
| | | margin-bottom: 16rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12rpx; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .filter-button { |
| | | padding: 12rpx 16rpx; |
| | | background: #f5f7fa; |
| | | border-radius: 4rpx; |
| | | } |
| | | |
| | | .form-buttons { |
| | | display: flex; |
| | | gap: 12rpx; |
| | | margin-top: 16rpx; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .table-container { |
| | | margin-top: 16rpx; |
| | | overflow-x: auto; |
| | | } |
| | | |
| | | .time-table { |
| | | width: 100%; |
| | | } |
| | | |
| | | .table-header { |
| | | display: flex; |
| | | border: 1rpx solid #e4e7ed; |
| | | background: #f5f7fa; |
| | | } |
| | | |
| | | .header-cell { |
| | | padding: 12rpx 8rpx; |
| | | text-align: center; |
| | | font-weight: bold; |
| | | border-right: 1rpx solid #e4e7ed; |
| | | } |
| | | |
| | | .room-header { |
| | | width: 120rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .time-header { |
| | | width: 120rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .table-body { |
| | | border: 1rpx solid #e4e7ed; |
| | | border-top: none; |
| | | } |
| | | |
| | | .table-row { |
| | | display: flex; |
| | | border-top: 1rpx solid #e4e7ed; |
| | | } |
| | | |
| | | .table-row:first-child { |
| | | border-top: none; |
| | | } |
| | | |
| | | .cell { |
| | | padding: 16rpx 8rpx; |
| | | text-align: center; |
| | | border-right: 1rpx solid #e4e7ed; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | word-break: break-word; |
| | | line-height: 1.2; |
| | | } |
| | | |
| | | .room-cell { |
| | | width: 120rpx; |
| | | font-weight: bold; |
| | | flex-shrink: 0; |
| | | background: #f9fafc; |
| | | } |
| | | |
| | | .cells-container { |
| | | display: flex; |
| | | } |
| | | |
| | | .content-cell { |
| | | min-height: 120rpx; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | padding: 16rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .content-cell:active { |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .free { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | .meeting { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .status-1 { |
| | | background-color: #fef0f0; |
| | | color: #d14646; |
| | | } |
| | | |
| | | .status-0 { |
| | | background-color: #ecf5ff; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .meeting-content { |
| | | width: 100%; |
| | | } |
| | | |
| | | .meeting-title { |
| | | font-weight: bold; |
| | | margin-bottom: 8rpx; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | .meeting-time { |
| | | font-size: 20rpx; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .free-content { |
| | | color: #909399; |
| | | } |
| | | |
| | | /* å¯¹è¯æ¡æ ·å¼ */ |
| | | .dialog-content { |
| | | padding: 24rpx; |
| | | } |
| | | |
| | | .dialog-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 24rpx; |
| | | padding-bottom: 16rpx; |
| | | border-bottom: 1rpx solid #e4e7ed; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .close-icon { |
| | | font-size: 32rpx; |
| | | color: #909399; |
| | | } |
| | | |
| | | .dialog-body { |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .detail-item { |
| | | display: flex; |
| | | margin-bottom: 16rpx; |
| | | padding: 8rpx 0; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | } |
| | | |
| | | .detail-label { |
| | | width: 140rpx; |
| | | font-weight: bold; |
| | | color: #606266; |
| | | } |
| | | |
| | | .detail-value { |
| | | flex: 1; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-top: 16rpx; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader title="ä¼è®®å®¤è¯¦æ
" |
| | | @back="goBack" /> |
| | | <u-form ref="formRef" |
| | | label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <u-cell-group title="ä¼è®®å®¤ä¿¡æ¯"> |
| | | <u-form-item label="ä¼è®®å®¤åç§°" |
| | | prop="name" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.name" |
| | | placeholder="请è¾å
¥ä¼è®®å®¤åç§°" /> |
| | | </u-form-item> |
| | | <u-form-item label="ä½ç½®" |
| | | required |
| | | prop="location" |
| | | border-bottom> |
| | | <u-input v-model="form.location" |
| | | placeholder="请è¾å
¥ä½ç½®" /> |
| | | </u-form-item> |
| | | <u-form-item label="容纳人æ°" |
| | | required |
| | | prop="capacity" |
| | | border-bottom> |
| | | <u-input v-model="form.capacity" |
| | | placeholder="请è¾å
¥å®¹çº³äººæ°" /> |
| | | </u-form-item> |
| | | <u-form-item label="设å¤é
ç½®" |
| | | prop="equipment" |
| | | border-bottom> |
| | | <u-input v-model="form.equipment" |
| | | readonly |
| | | placeholder="è¯·éæ©è®¾å¤é
ç½®" |
| | | @click="showEquipmentSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="openEquipmentSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç¶æ" |
| | | prop="status" |
| | | border-bottom> |
| | | <u-input v-model="statusname" |
| | | readonly |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | @click="showStatusSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showStatusSheet = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="夿³¨" |
| | | prop="remark" |
| | | border-bottom> |
| | | <u-input v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨" /> |
| | | </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">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- 设å¤é
ç½®éæ©å¨ --> |
| | | <u-popup :show="showEquipmentSheet" |
| | | mode="bottom" |
| | | @close="showEquipmentSheet = false" |
| | | height="200px"> |
| | | <view class="popup-content"> |
| | | <view class="popup-body"> |
| | | <u-checkbox-group v-model="form.equipment" |
| | | @change="handleEquipmentChange" |
| | | icon-placement="right" |
| | | placement="row"> |
| | | <view style="width:100%;padding:10px;margin-top:20px;"> |
| | | <u-checkbox v-for="option in equipmentOptions" |
| | | :key="option.value" |
| | | :name="option.value" |
| | | :label="option.name" |
| | | class="checkbox-item"></u-checkbox> |
| | | </view> |
| | | </u-checkbox-group> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | <!-- ç¶æéæ©å¨ --> |
| | | <up-action-sheet :show="showStatusSheet" |
| | | :actions="statusOptions" |
| | | @select="onStatusSelect" |
| | | @close="showStatusSheet = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "meeting-settings-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { saveRoom } from "@/api/managementMeetings/meetingSettings"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | name: "", |
| | | location: "", |
| | | capacity: "", |
| | | equipment: [], |
| | | status: "", |
| | | remark: "", |
| | | }); |
| | | const equipmentOptions = ref([ |
| | | { value: "æå½±ä»ª", name: "æå½±ä»ª" }, |
| | | { value: "çµè§", name: "çµè§" }, |
| | | { value: "é³å", name: "é³å" }, |
| | | { value: "çµè¯", name: "çµè¯" }, |
| | | { value: "è§é¢ä¼è®®ç³»ç»", name: "è§é¢ä¼è®®ç³»ç»" }, |
| | | { value: "ç½æ¿", name: "ç½æ¿" }, |
| | | { value: "ååæ¿", name: "ååæ¿" }, |
| | | { value: "æ 线ç½ç»", name: "æ 线ç½ç»" }, |
| | | ]); |
| | | const statusOptions = ref([ |
| | | { value: "1", name: "å¯ç¨" }, |
| | | { value: "0", name: "ç¦ç¨" }, |
| | | ]); |
| | | //// 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const showEquipmentSheet = ref(false); |
| | | const showStatusSheet = ref(false); |
| | | const openEquipmentSheet = () => { |
| | | showEquipmentSheet.value = true; |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const statusname = ref(""); |
| | | // ç¶æéæ© |
| | | const onStatusSelect = action => { |
| | | form.value.status = action.value; |
| | | statusname.value = action.name; |
| | | showStatusSheet.value = false; |
| | | }; |
| | | // 设å¤é
ç½®éæ© |
| | | const handleEquipmentChange = val => { |
| | | form.value.equipment = val; |
| | | console.log("form.value.equipment", form.value.equipment); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | if (!form.value.name) { |
| | | showToast("请è¾å
¥ä¼è®®å®¤åç§°"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.location) { |
| | | showToast("请è¾å
¥ä½ç½®"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.capacity) { |
| | | showToast("请è¾å
¥å®¹çº³äººæ°"); |
| | | return; |
| | | } |
| | | try { |
| | | loading.value = true; |
| | | form.value.equipment = form.value.equipment.join(","); |
| | | form.value.status = Number(form.value.status); |
| | | form.value.capacity = Number(form.value.capacity); |
| | | // 使ç¨å®å
¨æµ
æ·è´ï¼é¿å
对象å±å¼å¨æäºè¿è¡æ¶æé |
| | | console.log("form.value", form.value); |
| | | saveRoom(form.value).then(res => { |
| | | if (res.code !== 200) { |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | return; |
| | | } |
| | | loading.value = false; |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | }); |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("ä¿å失败:", e); |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨ä¸è·åä¼è®® room æ°æ® |
| | | const meetingRoom = uni.getStorageSync("meetingRoom"); |
| | | if (meetingRoom) { |
| | | form.value = JSON.parse(JSON.stringify(meetingRoom)); |
| | | if (meetingRoom.equipment) { |
| | | if (Array.isArray(meetingRoom.equipment)) { |
| | | form.value.equipment = meetingRoom.equipment; |
| | | } else { |
| | | form.value.equipment = meetingRoom.equipment.split(","); |
| | | } |
| | | } |
| | | statusname.value = meetingRoom.status === 1 ? "å¯ç¨" : "ç¦ç¨"; |
| | | |
| | | // æ¸
餿¬å°åå¨ä¸çæ°æ®ï¼é¿å
䏿¬¡æå¼æ¶ä»ç¶æ¾ç¤º |
| | | uni.removeStorageSync("meetingRoom"); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initPageData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | .client-visit { |
| | | 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; |
| | | } |
| | | |
| | | .location-icon { |
| | | color: #1989fa; |
| | | font-size: 1.2rem; |
| | | } |
| | | |
| | | .selector-container { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .selector-text { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | |
| | | .popup-content { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .popup-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .close-icon { |
| | | font-size: 20px; |
| | | color: #999; |
| | | } |
| | | |
| | | .popup-body { |
| | | max-height: 60vh; |
| | | overflow-y: auto; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .checkbox-item { |
| | | margin-bottom: 15rpx; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .popup-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | gap: 15rpx; |
| | | } |
| | | |
| | | .cancel-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | |
| | | .confirm-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | .checkbox-item { |
| | | margin-top: 40rpx; |
| | | } |
| | | </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="name" |
| | | @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="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" |
| | | :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.name || '-' }}</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.name || '-' }}</text> |
| | | </view> --> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä½ç½®</text> |
| | | <text class="detail-value">{{ item.location || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">容纳人æ°</text> |
| | | <text class="detail-value">{{ item.capacity || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设å¤é
ç½®</text> |
| | | <text class="detail-value">{{ item.equipment }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç¶æ</text> |
| | | <text class="detail-value" |
| | | :class="{'status-enabled': item.status == 1, 'status-disabled': item.status == 0}">{{ item.status == 1 ? 'å¯ç¨' : 'ç¦ç¨' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <!-- <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="confirmDelete(item)"> |
| | | å é¤ |
| | | </u-button> --> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ ä¼è®®å®¤è®°å½</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <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 { |
| | | getMeetingRoomList, |
| | | delRoom, |
| | | } from "@/api/managementMeetings/meetingSettings"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "client-visit-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const name = ref(""); |
| | | |
| | | // æè®¿è®°å½æ°æ® |
| | | const visitList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const confirmDelete = item => { |
| | | uni.showModal({ |
| | | title: "确认å é¤", |
| | | content: `æ¯å¦ç¡®è®¤å é¤ä¼è®®å®¤ ${item.name}ï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | delRoom(item.id) |
| | | .then(() => { |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | name: name.value, |
| | | }; |
| | | getMeetingRoomList(params) |
| | | .then(res => { |
| | | visitList.value = res.data.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const addVisit = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingSettings/detail", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const viewDetail = item => { |
| | | uni.setStorageSync("meetingRoom", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/meetingSettings/detail", |
| | | }); |
| | | }; |
| | | |
| | | 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; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | color: #333; // ä¿æé¡µé¢ç¹æçææ¬é¢è² |
| | | } |
| | | |
| | | // ç¶ææ ·å¼ |
| | | .status-enabled { |
| | | color: #28a745; // ä¿æé¡µé¢ç¹æçæåé¢è² |
| | | } |
| | | |
| | | .status-disabled { |
| | | color: #dc3545; // ä¿æé¡µé¢ç¹æçé误é¢è² |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | </style> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- å
å®¹å®¹å¨ --> |
| | | <view class="content-container"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">客æ·ä¿¡æ¯</view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·åç§°</text> |
| | | <text class="info-value">{{ form.customerName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">è系人</text> |
| | | <text class="info-value">{{ form.contact || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">èç³»çµè¯</text> |
| | | <text class="info-value">{{ form.contactPhone || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æè®¿ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">æè®¿ä¿¡æ¯</view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æè®¿ç®ç</text> |
| | | <text class="info-value">{{ form.purposeVisit || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æè®¿æ¶é´</text> |
| | | <text class="info-value">{{ form.purposeDate || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æè®¿å°ç¹</text> |
| | | <text class="info-value multi-line">{{ form.visitAddress || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æè®¿äºº</text> |
| | | <text class="info-value">{{ form.visitingPeople || '-' }}</text> |
| | | </view> |
| | | <view class="info-item" v-if="form.latitude && form.longitude"> |
| | | <text class="info-label">ç»çº¬åº¦</text> |
| | | <text class="info-value">{{ form.latitude }}, {{ form.longitude }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 夿³¨ä¿¡æ¯ --> |
| | | <view class="section"> |
| | | <view class="section-title">夿³¨ä¿¡æ¯</view> |
| | | <view class="info-item remark-item"> |
| | | <text class="info-label">夿³¨</text> |
| | | <text class="info-value multi-line">{{ form.remark }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | import { ref, onMounted } from 'vue' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import useUserStore from "@/store/modules/user" |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | customerName: '', |
| | | contact: '', |
| | | contactPhone: '', |
| | | visitingPeople: '', |
| | | purposeVisit: '', |
| | | purposeDate: '', |
| | | visitAddress: '', |
| | | latitude: '', |
| | | longitude: '', |
| | | locationAddress: '', |
| | | remark: '' |
| | | }) |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // è¿åæ¶æ¸
餿¬å°åå¨çID |
| | | uni.removeStorageSync('clientVisit') |
| | | uni.navigateBack() |
| | | } |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨è·åæè®¿è®°å½è¯¦æ
|
| | | const row = uni.getStorageSync('clientVisit') |
| | | if (row) { |
| | | form.value = { ...row } |
| | | } else { |
| | | showToast('ææ æè®¿è®°å½æ°æ®') |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | initPageData() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | |
| | | .client-visit-detail { |
| | | min-height: 100vh; |
| | | background-color: #f8f9fa; |
| | | } |
| | | |
| | | .content-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .section { |
| | | background-color: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333333; |
| | | padding: 16px 16px 12px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | padding: 14px 16px; |
| | | border-bottom: 1px solid #f8f8f8; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .info-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #666666; |
| | | min-width: 80px; |
| | | flex-shrink: 0; |
| | | line-height: 22px; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333333; |
| | | flex: 1; |
| | | line-height: 22px; |
| | | text-align: right; |
| | | } |
| | | |
| | | .multi-line { |
| | | text-align: left; |
| | | word-break: break-all; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .remark-item { |
| | | padding-bottom: 16px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="client-visit-detail"> |
| | | <PageHeader :title="detailType === 1 ? 'åå¸å¶åº¦' : 'å¶åº¦è¯¦æ
'" |
| | | @back="goBack" /> |
| | | <u-form ref="formRef" |
| | | label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <!-- <u-cell-group title="ç¥è¯ä¿¡æ¯"> --> |
| | | <u-form-item label="å¶åº¦ç¼å·" |
| | | prop="regulationNum" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.regulationNum" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥å¶åº¦ç¼å·" /> |
| | | </u-form-item> |
| | | <u-form-item label="å¶åº¦æ é¢" |
| | | prop="title" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.title" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥å¶åº¦æ é¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="å¶åº¦åç±»" |
| | | prop="type" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="equipmentname" |
| | | readonly |
| | | placeholder="è¯·éæ©å¶åº¦åç±»" |
| | | @click="showEquipmentSheet = true" /> |
| | | <template v-if="!readonly" |
| | | #right> |
| | | <up-icon name="arrow-right" |
| | | @click="openEquipmentSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="å¶åº¦å
容" |
| | | prop="scenario" |
| | | required |
| | | border-bottom> |
| | | <u-textarea v-model="form.content" |
| | | type="textarea" |
| | | rows="4" |
| | | :disabled="readonly" |
| | | placeholder="请è¾å
¥å¶åº¦å
容" /> |
| | | </u-form-item> |
| | | <u-form-item label="å¶åº¦çæ¬" |
| | | prop="title" |
| | | border-bottom> |
| | | <u-input v-model="form.version" |
| | | :readonly="readonly" |
| | | placeholder="请è¾å
¥å¶åº¦çæ¬" /> |
| | | </u-form-item> |
| | | <u-form-item label="çææ¶é´" |
| | | prop="status" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.effectiveTime" |
| | | readonly |
| | | placeholder="è¯·éæ©çææ¶é´" |
| | | @click="showEffectiveTimeSheet = true" /> |
| | | <template v-if="!readonly" |
| | | #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showEffectiveTimeSheet = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="éç¨èå´" |
| | | required |
| | | prop="remark" |
| | | border-bottom> |
| | | <up-checkbox-group v-model="form.scope" |
| | | :disabled="readonly" |
| | | placement="column" |
| | | @change="checkboxChange"> |
| | | <up-checkbox :customStyle="{marginBottom: '8px'}" |
| | | v-for="(item, index) in checkboxList1" |
| | | :key="index" |
| | | :label="item.name" |
| | | :name="item.value"> |
| | | </up-checkbox> |
| | | </up-checkbox-group> |
| | | </u-form-item> |
| | | <u-form-item label="éè¦ç¡®è®¤" |
| | | prop="solution" |
| | | border-bottom> |
| | | <up-switch :disabled="readonly" |
| | | v-model="form.requireConfirm"></up-switch> |
| | | </u-form-item> |
| | | <!-- </u-cell-group> --> |
| | | <!-- æäº¤æé® --> |
| | | <view v-if="!readonly" |
| | | class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="sign-btn" |
| | | type="primary" |
| | | @click="handleSubmit" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- 设å¤é
ç½®éæ©å¨ --> |
| | | <up-action-sheet :show="showEquipmentSheet" |
| | | :actions="equipmentOptions" |
| | | @select="handleEquipmentChange" |
| | | @close="showEquipmentSheet = false" /> |
| | | <!-- ç¶æéæ©å¨ --> |
| | | <up-action-sheet :show="showStatusSheet" |
| | | :actions="statusOptions" |
| | | @select="onStatusSelect" |
| | | @close="showStatusSheet = false" /> |
| | | <up-datetime-picker :show="showEffectiveTimeSheet" |
| | | @confirm="handleEffectiveTimeConfirm" |
| | | @cancel="showEffectiveTimeSheet = false" |
| | | v-model="effectiveTime" |
| | | mode="datetime"></up-datetime-picker> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "meeting-settings-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { |
| | | addRuleManagement, |
| | | updateRuleManagement, |
| | | } from "@/api/managementMeetings/rulesRegulationsManagement"; |
| | | import dayjs from "dayjs"; |
| | | const userStore = useUserStore(); |
| | | const showEffectiveTimeSheet = ref(false); |
| | | const effectiveTime = ref(new Date()); |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | const checkboxList1 = ref([ |
| | | { name: "å
¨ä½åå·¥", value: "all" }, |
| | | { name: "管çå±", value: "manager" }, |
| | | { name: "人äºé¨é¨", value: "hr" }, |
| | | { name: "è´¢å¡é¨é¨", value: "finance" }, |
| | | { name: "ææ¯é¨é¨", value: "tech" }, |
| | | ]); |
| | | const equipmentOptions = ref([ |
| | | { value: "hr", name: "人äºå¶åº¦" }, |
| | | { value: "finance", name: "è´¢å¡å¶åº¦" }, |
| | | { value: "safety", name: "å®å
¨å¶åº¦" }, |
| | | { value: "tech", name: "ææ¯å¶åº¦" }, |
| | | ]); |
| | | const statusOptions = ref([ |
| | | { value: "high", name: "æ¾èæå" }, |
| | | { value: "medium", name: "ä¸è¬æå" }, |
| | | { value: "low", name: "轻微æå" }, |
| | | ]); |
| | | //// 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const showEquipmentSheet = ref(false); |
| | | const showStatusSheet = ref(false); |
| | | const openEquipmentSheet = () => { |
| | | showEquipmentSheet.value = true; |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const statusname = ref(""); |
| | | // ç¶æéæ© |
| | | const onStatusSelect = action => { |
| | | form.value.efficiency = action.value; |
| | | statusname.value = action.name; |
| | | showStatusSheet.value = false; |
| | | }; |
| | | const equipmentname = ref(""); |
| | | const handleEffectiveTimeConfirm = () => { |
| | | form.value.effectiveTime = dayjs(effectiveTime.value).format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ); |
| | | showEffectiveTimeSheet.value = false; |
| | | }; |
| | | // å¶åº¦åç±»éæ© |
| | | const handleEquipmentChange = val => { |
| | | form.value.category = val.value; |
| | | equipmentname.value = val.name; |
| | | showEquipmentSheet.value = false; |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | if (!form.value.regulationNum) { |
| | | showToast("请è¾å
¥å¶åº¦ç¼å·"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.title) { |
| | | showToast("请è¾å
¥å¶åº¦æ é¢"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.category) { |
| | | showToast("è¯·éæ©å¶åº¦åç±»"); |
| | | return; |
| | | } |
| | | if (!form.value.content) { |
| | | showToast("请è¾å
¥å¶åº¦å
容"); |
| | | return; |
| | | } |
| | | if (!form.value.effectiveTime) { |
| | | showToast("è¯·éæ©çææ¶é´"); |
| | | return; |
| | | } |
| | | if (!form.value.scope.length) { |
| | | showToast("è¯·éæ©çæèå´"); |
| | | return; |
| | | } |
| | | try { |
| | | loading.value = true; |
| | | if (detailType.value === 1) { |
| | | addRuleManagement(form.value).then(res => { |
| | | if (res.code !== 200) { |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | return; |
| | | } |
| | | loading.value = false; |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | }); |
| | | } else if (detailType.value === 2) { |
| | | updateRuleManagement(form.value).then(res => { |
| | | if (res.code !== 200) { |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | return; |
| | | } |
| | | loading.value = false; |
| | | showToast("ä¿åæå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | }); |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("ä¿å失败:", e); |
| | | showToast("ä¿å失败ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // åå§å页颿°æ® |
| | | const initPageData = () => { |
| | | // 仿¬å°åå¨ä¸è·åä¼è®® room æ°æ® |
| | | const meetingRoom = uni.getStorageSync("meetingRoom"); |
| | | if (meetingRoom) { |
| | | form.value = JSON.parse(JSON.stringify(meetingRoom)); |
| | | if (meetingRoom.equipment) { |
| | | if (Array.isArray(meetingRoom.equipment)) { |
| | | form.value.equipment = meetingRoom.equipment; |
| | | } else { |
| | | form.value.equipment = meetingRoom.equipment.split(","); |
| | | } |
| | | } |
| | | statusname.value = meetingRoom.status === 1 ? "å¯ç¨" : "ç¦ç¨"; |
| | | |
| | | // æ¸
餿¬å°åå¨ä¸çæ°æ®ï¼é¿å
䏿¬¡æå¼æ¶ä»ç¶æ¾ç¤º |
| | | uni.removeStorageSync("meetingRoom"); |
| | | } |
| | | }; |
| | | const readonly = ref(false); |
| | | const detailType = ref(1); |
| | | const knowledgeId = ref(""); |
| | | |
| | | onLoad(options => { |
| | | detailType.value = Number(options.detailType); |
| | | knowledgeId.value = options.id || ""; |
| | | |
| | | // æ¥ç模å¼è®¾ç½®åªè¯» |
| | | if (detailType.value === 3) { |
| | | readonly.value = true; |
| | | } |
| | | }); |
| | | // é置表å |
| | | const resetForm = () => { |
| | | form.value = { |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }; |
| | | equipmentname.value = ""; |
| | | statusname.value = ""; |
| | | }; |
| | | onMounted(() => { |
| | | console.log(effectiveTime.value, "çææ¶é´"); |
| | | |
| | | // 仿¬å°åå¨ä¸è·åç¥è¯æ°æ® |
| | | const rulesRegulations = uni.getStorageSync("rulesRegulations"); |
| | | initPageData(); |
| | | if (rulesRegulations) { |
| | | form.value = JSON.parse(JSON.stringify(rulesRegulations)); |
| | | } |
| | | |
| | | if (detailType.value === 1) { |
| | | resetForm(); |
| | | } |
| | | |
| | | if (detailType.value != 1) { |
| | | equipmentname.value = |
| | | equipmentOptions.value.find(item => item.value == form.value.category) |
| | | ?.name || ""; |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | .client-visit { |
| | | 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; |
| | | } |
| | | |
| | | .location-icon { |
| | | color: #1989fa; |
| | | font-size: 1.2rem; |
| | | } |
| | | |
| | | .selector-container { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .selector-text { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | |
| | | .popup-content { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .popup-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .close-icon { |
| | | font-size: 20px; |
| | | color: #999; |
| | | } |
| | | |
| | | .popup-body { |
| | | max-height: 60vh; |
| | | overflow-y: auto; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .checkbox-item { |
| | | margin-bottom: 15rpx; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .popup-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | gap: 15rpx; |
| | | } |
| | | |
| | | .cancel-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | |
| | | .confirm-btn-popup { |
| | | flex: 1; |
| | | border-radius: 8rpx; |
| | | } |
| | | .checkbox-item { |
| | | margin-top: 40rpx; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="file-list-page"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="é件管ç" |
| | | @back="goBack" /> |
| | | <!-- éä»¶å表 --> |
| | | <view class="file-list-container"> |
| | | <view v-if="fileList.length > 0" |
| | | class="file-list"> |
| | | <view v-for="(file, index) in fileList" |
| | | :key="file.id || index" |
| | | class="file-item"> |
| | | <!-- æä»¶å¾æ --> |
| | | <!-- <view class="file-icon" |
| | | :class="getFileIconClass(file.fileType)"> |
| | | <up-icon :name="getFileIcon(file.fileType)" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | </view> --> |
| | | <!-- æä»¶ä¿¡æ¯ --> |
| | | <view class="file-info"> |
| | | <text class="file-name">{{ file.name }}</text> |
| | | <!-- <text class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ file.uploadTime || file.createTime }}</text> --> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="file-actions"> |
| | | <!-- <u-button size="small" |
| | | type="primary" |
| | | plain |
| | | @click="previewFile(file)">é¢è§</u-button> --> |
| | | <u-button size="small" |
| | | type="info" |
| | | plain |
| | | @click="downloadFile(file)">ä¸è½½å¹¶é¢è§</u-button> |
| | | <u-button size="small" |
| | | type="error" |
| | | plain |
| | | @click="confirmDelete(file, index)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-else |
| | | class="empty-state"> |
| | | <up-icon name="document" |
| | | size="64" |
| | | color="#c0c4cc" /> |
| | | <text class="empty-text">ææ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | <!-- <a rel="nofollow" |
| | | id="downloadLink" |
| | | href="#" |
| | | style="display:none;">ä¸è½½ææ¬æä»¶</a> --> |
| | | <!-- ä¸ä¼ æé® --> |
| | | <view class="upload-button" |
| | | @click="chooseFile"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff" /> |
| | | <text class="upload-text">ä¸ä¼ éä»¶</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import config from "@/config"; |
| | | import { getToken } from "@/utils/auth"; |
| | | // import { saveAs } from "file-saver"; |
| | | import { |
| | | listRuleFiles, |
| | | addRuleFile, |
| | | delRuleFile, |
| | | upload, |
| | | } from "@/api/managementMeetings/rulesRegulationsManagement"; |
| | | import { blobValidate } from "@/utils/ruoyi"; |
| | | |
| | | // éä»¶å表 |
| | | const fileList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // const request = axios.create({ |
| | | // baseURL: "URL.com", |
| | | // adapter: axiosAdapterUniapp, |
| | | // }); |
| | | // è·åæä»¶å¾æ |
| | | const getFileIcon = fileType => { |
| | | const iconMap = { |
| | | doc: "document", |
| | | docx: "document", |
| | | xls: "grid", |
| | | xlsx: "grid", |
| | | pdf: "document", |
| | | ppt: "copy", |
| | | pptx: "copy", |
| | | txt: "document", |
| | | jpg: "image", |
| | | jpeg: "image", |
| | | png: "image", |
| | | gif: "image", |
| | | zip: "folder", |
| | | rar: "folder", |
| | | }; |
| | | return iconMap[fileType.toLowerCase()] || "document"; |
| | | }; |
| | | |
| | | // è·åæä»¶å¾æ æ ·å¼ç±» |
| | | const getFileIconClass = fileType => { |
| | | const colorMap = { |
| | | doc: "blue", |
| | | docx: "blue", |
| | | xls: "green", |
| | | xlsx: "green", |
| | | pdf: "red", |
| | | ppt: "orange", |
| | | pptx: "orange", |
| | | txt: "gray", |
| | | jpg: "purple", |
| | | jpeg: "purple", |
| | | png: "purple", |
| | | gif: "purple", |
| | | zip: "yellow", |
| | | rar: "yellow", |
| | | }; |
| | | return colorMap[fileType.toLowerCase()] || "gray"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæä»¶å¤§å° |
| | | const formatFileSize = bytes => { |
| | | if (bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }; |
| | | |
| | | // éæ©æä»¶ |
| | | const chooseFile = () => { |
| | | uni.chooseImage({ |
| | | count: 9, |
| | | sizeType: ["original", "compressed"], |
| | | sourceType: ["album", "camera"], |
| | | success: res => { |
| | | console.log(res, "éæ©å¾çæå"); |
| | | uploadFiles(res.tempFiles); |
| | | }, |
| | | fail: err => { |
| | | console.error("éæ©å¾ç失败:", err); |
| | | showToast("éæ©æä»¶å¤±è´¥"); |
| | | }, |
| | | }); |
| | | // uni.chooseFile({ |
| | | // count: 9, |
| | | // extension: [ |
| | | // ".doc", |
| | | // ".docx", |
| | | // ".xls", |
| | | // ".xlsx", |
| | | // ".pdf", |
| | | // ".ppt", |
| | | // ".pptx", |
| | | // ".txt", |
| | | // ".jpg", |
| | | // ".jpeg", |
| | | // ".png", |
| | | // ".gif", |
| | | // ".zip", |
| | | // ".rar", |
| | | // ], |
| | | // success: res => { |
| | | // console.log(res, "éæ©æä»¶æå"); |
| | | // uploadFiles(res.tempFiles); |
| | | // }, |
| | | // fail: err => { |
| | | // showToast("éæ©æä»¶å¤±è´¥"); |
| | | // }, |
| | | // }); |
| | | }; |
| | | |
| | | // ä¸ä¼ æä»¶ |
| | | const uploadFiles = tempFiles => { |
| | | console.log(tempFiles, "ä¸ä¼ æä»¶1"); |
| | | tempFiles.forEach((tempFile, index) => { |
| | | // æ¾ç¤ºä¸ä¼ ä¸æç¤º |
| | | uni.showLoading({ |
| | | title: "ä¸ä¼ ä¸...", |
| | | mask: true, |
| | | }); |
| | | console.log(tempFile, "ä¸ä¼ æä»¶2"); |
| | | // 1. ç´æ¥ä½¿ç¨ uni.uploadFile ä¸ä¼ æä»¶ |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + "/file/upload", |
| | | filePath: tempFile.path, |
| | | name: "file", |
| | | header: { |
| | | Authorization: "Bearer " + getToken(), |
| | | }, |
| | | success: uploadRes => { |
| | | uni.hideLoading(); |
| | | console.log(uploadRes, "ä¸ä¼ æä»¶3"); |
| | | |
| | | try { |
| | | const res = JSON.parse(uploadRes.data); |
| | | console.log(res, "ä¸ä¼ æä»¶4"); |
| | | if (res.code === 200) { |
| | | // 2. æåæä»¶ä¿¡æ¯ |
| | | const fileName = tempFile.name |
| | | ? tempFile.name |
| | | : tempFile.path.split("/").pop(); |
| | | // const fileType = fileName.split(".").pop(); |
| | | // 3. æé ä¿åæä»¶ä¿¡æ¯çåæ° |
| | | const saveData = { |
| | | name: fileName, |
| | | rulesRegulationsManagementId: rulesRegulationsManagementId.value, |
| | | url: res.data.tempPath || "", |
| | | }; |
| | | console.log(saveData, "ä¿åæä»¶ä¿¡æ¯åæ°"); |
| | | // 4. è°ç¨ addRuleFile æ¥å£ä¿åæä»¶ä¿¡æ¯ |
| | | addRuleFile(saveData) |
| | | .then(addRes => { |
| | | if (addRes.code === 200) { |
| | | // 5. æ·»å å°æä»¶å表 |
| | | const newFile = { |
| | | ...addRes.data, |
| | | uploadTime: new Date().toLocaleString(), |
| | | }; |
| | | // fileList.value.push(newFile); |
| | | getFileList(); |
| | | showToast("ä¸ä¼ æå"); |
| | | } else { |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¿åæä»¶ä¿¡æ¯å¤±è´¥:", err); |
| | | showToast("ä¿åæä»¶ä¿¡æ¯å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | showToast("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | } catch (e) { |
| | | console.error("è§£æä¸ä¼ ç»æå¤±è´¥:", e); |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | uni.hideLoading(); |
| | | console.error("ä¸ä¼ 失败:", err); |
| | | showToast("ä¸ä¼ 失败"); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | // ä¸è½½æä»¶ |
| | | const downloadFile = file => { |
| | | var url = |
| | | config.baseUrl + |
| | | "/common/download?fileName=" + |
| | | encodeURIComponent(file.url) + |
| | | "&delete=true"; |
| | | console.log(url, "url"); |
| | | |
| | | uni |
| | | .downloadFile({ |
| | | url: url, |
| | | responseType: "blob", |
| | | header: { Authorization: "Bearer " + getToken() }, |
| | | }) |
| | | .then(res => { |
| | | let osType = uni.getStorageSync("deviceInfo").osName; |
| | | let filePath = res.tempFilePath; |
| | | if (osType === "ios") { |
| | | uni.openDocument({ |
| | | filePath: filePath, |
| | | showMenu: true, |
| | | success: res => { |
| | | resolve(res); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.openDocument--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } else { |
| | | uni.saveFile({ |
| | | tempFilePath: filePath, |
| | | success: fileRes => { |
| | | uni.showToast({ |
| | | icon: "none", |
| | | mask: true, |
| | | title: |
| | | "æä»¶å·²ä¿åï¼Android/data/uni.UNI720216F/apps/__UNI__720216F/" + |
| | | fileRes.savedFilePath, //ä¿åè·¯å¾ |
| | | duration: 3000, |
| | | }); |
| | | setTimeout(() => { |
| | | //æå¼ææ¡£æ¥ç |
| | | uni.openDocument({ |
| | | filePath: fileRes.savedFilePath, |
| | | success: function (res) { |
| | | resolve(fileRes); |
| | | }, |
| | | }); |
| | | }, 3000); |
| | | }, |
| | | fail: err => { |
| | | console.log("uni.save--fail"); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | } |
| | | // const isBlob = blobValidate(res.data); |
| | | // if (isBlob) { |
| | | // const blob = new Blob([res.data], { type: "text/plain" }); |
| | | // const url = URL.createObjectURL(blob); |
| | | // const downloadLink = document.getElementById("downloadLink"); |
| | | // downloadLink.href = url; |
| | | // downloadLink.download = file.name; |
| | | // downloadLink.click(); |
| | | // showToast("ä¸è½½æå"); |
| | | // } else { |
| | | // showToast("ä¸è½½å¤±è´¥"); |
| | | // } |
| | | }) |
| | | .catch(err => { |
| | | console.error("ä¸è½½å¤±è´¥:", err); |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // 确认å é¤ |
| | | const confirmDelete = (file, index) => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤éä»¶ "${file.name}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteFile(file.id, index); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å 餿件 |
| | | const deleteFile = (fileId, index) => { |
| | | uni.showLoading({ |
| | | title: "å é¤ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | delRuleFile([fileId]) |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | // fileList.value.splice(index, 1); |
| | | getFileList(); |
| | | showToast("å 餿å"); |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæç¤º |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | const rulesRegulationsManagementId = ref(""); |
| | | // 页é¢å è½½æ¶ |
| | | onMounted(() => { |
| | | // ä» API è·åéä»¶å表 |
| | | getFileList(); |
| | | // 仿¬å°åå¨è·å rulesRegulationsManagementId |
| | | rulesRegulationsManagementId.value = uni.getStorageSync( |
| | | "rulesRegulationsManagement" |
| | | ); |
| | | }); |
| | | |
| | | // è·åéä»¶å表 |
| | | const getFileList = () => { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | mask: true, |
| | | }); |
| | | |
| | | listRuleFiles() |
| | | .then(res => { |
| | | uni.hideLoading(); |
| | | if (res.code === 200) { |
| | | fileList.value = res.data.records || []; |
| | | } else { |
| | | showToast("è·åéä»¶å表失败"); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | uni.hideLoading(); |
| | | showToast("è·åéä»¶å表失败"); |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .file-list-page { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100rpx; |
| | | } |
| | | |
| | | .file-list-container { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .file-list { |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .file-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | |
| | | .file-icon { |
| | | width: 56rpx; |
| | | height: 56rpx; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 20rpx; |
| | | |
| | | &.blue { |
| | | background: #409eff; |
| | | } |
| | | |
| | | &.green { |
| | | background: #67c23a; |
| | | } |
| | | |
| | | &.red { |
| | | background: #f56c6c; |
| | | } |
| | | |
| | | &.orange { |
| | | background: #e6a23c; |
| | | } |
| | | |
| | | &.gray { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.purple { |
| | | background: #909399; |
| | | } |
| | | |
| | | &.yellow { |
| | | background: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | display: block; |
| | | font-size: 16px; |
| | | color: #303133; |
| | | margin-bottom: 8rpx; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | display: flex; |
| | | gap: 12rpx; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 100rpx 0; |
| | | background: #ffffff; |
| | | border-radius: 8rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .upload-button { |
| | | position: fixed; |
| | | bottom: 40rpx; |
| | | right: 40rpx; |
| | | width: 130rpx; |
| | | height: 130rpx; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.4); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .upload-text { |
| | | font-size: 10px; |
| | | color: #ffffff; |
| | | margin-top: 4rpx; |
| | | } |
| | | |
| | | .upload-progress { |
| | | padding: 40rpx 0; |
| | | } |
| | | |
| | | .upload-progress-text { |
| | | display: block; |
| | | text-align: center; |
| | | margin-top: 20rpx; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </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="name" |
| | | @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="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" |
| | | :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.title || '-' }}</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.regulationNum || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åç±»</text> |
| | | <u-tag size="mini">{{ formatReceiptType(item.category) }}</u-tag> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">çæ¬</text> |
| | | <text class="detail-value">{{ item.version || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åå¸äºº</text> |
| | | <text class="detail-value">{{ item.createUserName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å叿¶é´</text> |
| | | <text class="detail-value">{{ item.createTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç¶æ</text> |
| | | <u-tag size="mini" |
| | | :type="item.status === 'active' ? 'success' : 'info'"> |
| | | {{ item.status === "active" ? 'çæä¸' : 'å·²åºæ¢' }} |
| | | </u-tag> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">已读人æ°</text> |
| | | <text class="detail-value">{{ item.readCount || '-' }}</text> |
| | | </view> |
| | | <u-collapse border="false" |
| | | accordion |
| | | @open="(value) => handleOpen(value, index)"> |
| | | <u-collapse-item title="çæ¬åå²" |
| | | border="false" |
| | | :name="item.category"> |
| | | <view class="table-container"> |
| | | <u-table2 :data="item.tableData1" |
| | | :columns="columns" |
| | | stripe |
| | | border /> |
| | | </view> |
| | | </u-collapse-item> |
| | | <!-- <u-collapse-item title="é
è¯»ç¶æ" |
| | | border="false" |
| | | :name="item.id"> |
| | | <view class="table-container"> |
| | | <u-table2 :data="item.tableData2" |
| | | :columns="columns2" |
| | | stripe |
| | | border /> |
| | | </view> |
| | | </u-collapse-item> --> |
| | | </u-collapse> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item,3)"> |
| | | æ¥ç |
| | | </u-button> |
| | | <!-- <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="handleAbrogate(item)"> |
| | | åºå¼ |
| | | </u-button> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item,2)"> |
| | | ç¼è¾ |
| | | </u-button> --> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="fileList(item,2)"> |
| | | éä»¶ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ è§ç« å¶åº¦</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <!-- <view class="fab-button" |
| | | @click="addVisit"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | listRuleManagement, |
| | | getReadingStatusList, |
| | | getReadingStatusByRuleId, |
| | | updateRuleManagement, |
| | | // delKnowledgeBase, |
| | | } from "@/api/managementMeetings/rulesRegulationsManagement"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "client-visit-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | // åºå¼è§ç« å¶åº¦ |
| | | const handleAbrogate = item => { |
| | | uni.showModal({ |
| | | title: "åºå¼ç¡®è®¤", |
| | | content: `ç¡®å®è¦åºå¼è¯¥è§ç« å¶åº¦åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | item.status = "repealed"; |
| | | updateRuleManagement(item).then(() => { |
| | | showToast("åºå¼æå"); |
| | | getList(); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | // éä»¶å表 |
| | | const fileList = item => { |
| | | console.log(item.id, "item"); |
| | | uni.setStorageSync("rulesRegulationsManagement", item.id); |
| | | // // éä»¶å表跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/rulesRegulationsManagement/fileList", |
| | | }); |
| | | }; |
| | | const columns = ref([ |
| | | { title: "çæ¬å·", key: "version", width: 100 }, |
| | | { title: "æ´æ°æ¶é´", key: "updateTime", width: 200 }, |
| | | { title: "æ´æ°äºº", key: "createUserName", width: 150 }, |
| | | { title: "åæ´è¯´æ", key: "status", width: 100 }, |
| | | ]); |
| | | const columns2 = ref([ |
| | | { title: "åå·¥å§å", key: "employee", width: 150 }, |
| | | { title: "æå±é¨é¨", key: "department", width: 150 }, |
| | | { title: "é
读æ¶é´", key: "createTime", width: 200 }, |
| | | { title: "确认æ¶é´", key: "confirmTime", width: 200 }, |
| | | { title: "ç¶æ", key: "status", width: 100 }, |
| | | ]); |
| | | // æç´¢å
³é®è¯ |
| | | const name = ref(""); |
| | | |
| | | // æè®¿è®°å½æ°æ® |
| | | const visitList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const { knowledge_type } = useDict("knowledge_type"); |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = params => { |
| | | if (params == "hr") { |
| | | return "人äºå¶åº¦"; |
| | | } else if (params == "finance") { |
| | | return "è´¢å¡å¶åº¦"; |
| | | } else if (params == "safety") { |
| | | return "å®å
¨å¶åº¦"; |
| | | } else if (params == "tech") { |
| | | return "ææ¯å¶åº¦"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | const getTagClass = type => { |
| | | if (type == "high") { |
| | | return "success"; |
| | | } else if (type == "medium") { |
| | | return "warning"; |
| | | } else if (type == "low") { |
| | | return "info"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | const knowledgeTypeOptions = computed(() => knowledge_type?.value || []); |
| | | // è·åç¥è¯ç±»åæ ç¾ |
| | | const getKnowledgeTypeLabel = val => { |
| | | console.log(knowledgeTypeOptions, "knowledgeTypeOptions"); |
| | | const item = knowledgeTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | const handleOpen = (value, index) => { |
| | | if ( |
| | | value == "hr" || |
| | | value == "finance" || |
| | | value == "safety" || |
| | | value == "tech" |
| | | ) { |
| | | // åå²çæ¬ |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | category: value, |
| | | }; |
| | | listRuleManagement(params) |
| | | .then(res => { |
| | | visitList.value[index].tableData1 = res.data.records; |
| | | visitList.value[index].tableData1.forEach(item => { |
| | | item.status = item.status == "active" ? "çæä¸" : "å·²åºæ¢"; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // é
è¯»ç¶æ |
| | | getReadingStatusByRuleId(value) |
| | | .then(res => { |
| | | visitList.value[index].tableData2 = res.data; |
| | | visitList.value[index].tableData2.forEach(item => { |
| | | item.status = item.status == "confirmed" ? "已确认" : "æªç¡®è®¤"; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | } |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | title: name.value, |
| | | }; |
| | | listRuleManagement(params) |
| | | .then(res => { |
| | | visitList.value = res.data.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢æè®¿ - 跳转å°ç»è®°é¡µé¢ |
| | | const addVisit = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/managementMeetings/rulesRegulationsManagement/detail?detailType=1", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const viewDetail = (item, detailType) => { |
| | | uni.setStorageSync("rulesRegulations", item); |
| | | uni.navigateTo({ |
| | | url: |
| | | "/pages/managementMeetings/rulesRegulationsManagement/detail?detailType=" + |
| | | detailType + |
| | | "&id=" + |
| | | item.id, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ç¡®è®¤ |
| | | const confirmDelete = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤ç¥è¯ "${item.title}" åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteKnowledge(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æ§è¡å é¤ |
| | | const deleteKnowledge = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | delKnowledgeBase([id]) |
| | | .then(res => { |
| | | closeToast(); |
| | | if (res.code === 200) { |
| | | showToast("å 餿å"); |
| | | getList(); // éæ°è·åå表 |
| | | } else { |
| | | showToast("å é¤å¤±è´¥"); |
| | | } |
| | | }) |
| | | .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; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | color: #333; // ä¿æé¡µé¢ç¹æçææ¬é¢è² |
| | | } |
| | | |
| | | // ç¶ææ ·å¼ |
| | | .status-enabled { |
| | | color: #28a745; // ä¿æé¡µé¢ç¹æçæåé¢è² |
| | | } |
| | | |
| | | .status-disabled { |
| | | color: #dc3545; // ä¿æé¡µé¢ç¹æçé误é¢è² |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | |
| | | // è¡¨æ ¼å®¹å¨ï¼å®ç°æ¨ªåæ»å¨ |
| | | .table-container { |
| | | overflow-x: auto; |
| | | margin: 0 -20rpx; |
| | | padding: 0 20rpx; |
| | | } |
| | | |
| | | .table-container::-webkit-scrollbar { |
| | | height: 6rpx; |
| | | } |
| | | |
| | | .table-container::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3rpx; |
| | | } |
| | | |
| | | .table-container::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3rpx; |
| | | } |
| | | |
| | | .table-container::-webkit-scrollbar-thumb:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | // .u-table2 { |
| | | // width: 500px; |
| | | // } |
| | | </style> |
| | | |
| src/pages/managementMeetings/sealManagement/detail.vue
src/pages/managementMeetings/sealManagement/index.vue
src/pages/procurementManagement/invoiceEntry/add.vue
src/pages/procurementManagement/invoiceEntry/index.vue
src/pages/procurementManagement/paymentEntry/add.vue
src/pages/procurementManagement/paymentEntry/index.vue
src/pages/procurementManagement/paymentLedger/detail.vue
src/pages/procurementManagement/paymentLedger/index.vue
src/pages/procurementManagement/procurementInvoiceLedger/detail.vue
src/pages/procurementManagement/procurementInvoiceLedger/index.vue
src/pages/procurementManagement/procurementLedger/detail.vue
src/pages/procurementManagement/procurementLedger/index.vue
src/pages/procurementManagement/receiptPaymentHistory/index.vue
src/pages/sales/deliveryLedger/index.vue
src/pages/sales/invoiceLedger/detail.vue
src/pages/sales/invoiceLedger/index.vue
src/pages/sales/invoicingRegistration/add.vue
src/pages/sales/invoicingRegistration/index.vue
src/pages/sales/invoicingRegistration/view.vue
src/pages/sales/receiptPayment/add.vue
src/pages/sales/receiptPayment/index.vue
src/pages/sales/receiptPaymentHistory/index.vue
src/pages/sales/receiptPaymentLedger/detail.vue
src/pages/sales/receiptPaymentLedger/index.vue
src/pages/sales/salesAccount/detail.vue
src/pages/sales/salesAccount/goOut.vue
src/pages/sales/salesAccount/index.vue
src/pages/sales/salesAccount/out.vue
src/pages/sales/salesAccount/view.vue
src/static/images/icon/baojiaguanli.png
src/static/images/icon/baoxiaoguanli.png
src/static/images/icon/caigouguanli.png
src/static/images/icon/chuchaiguanli@2x.png
src/static/images/icon/chukuguanli@2x.png
src/static/images/icon/gongchuguanli@2x.png
src/static/images/icon/guizhangzhidu@2x.png
src/static/images/icon/huiyifabu@2x.png
src/static/images/icon/huiyikanban@2x.png
src/static/images/icon/huiyiliebiao@2x.png
src/static/images/icon/huiyishenpi@2x.png
src/static/images/icon/huiyishenqing@2x.png
src/static/images/icon/huiyishezhi@2x.png
src/static/images/icon/huiyizongjie@2x.png
src/static/images/icon/qingjiaguanli@2x.png
src/static/images/icon/rukuguanli@2x.png
src/static/images/icon/tongzhigonggao@2x.png
src/static/images/icon/yongyinguanli@2x.png
src/static/images/icon/zhishiku@2x.png
src/static/images/icon/zidingyichuku.png
src/static/images/index/caigoushuju.png
src/static/images/index/kucunshuju.png
src/static/images/index/num1.png
src/static/images/index/num2.png
src/static/images/index/num3.png
src/static/images/index/xiaoshoushuju.png
src/static/images/tabbar/home.png
src/static/images/tabbar/homeBlue.png
src/static/images/tabbar/home_.png (已删除)
src/static/images/tabbar/mine.png (已删除)
src/static/images/tabbar/mine_.png (已删除)
src/static/images/tabbar/my.png
src/static/images/tabbar/myBlue.png
src/static/images/tabbar/new.png
src/static/images/tabbar/newBlue.png
src/static/images/tabbar/work.png
src/static/images/tabbar/workBlue.png
src/static/images/tabbar/work_.png (已删除) |