| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 设å¤ç®¡ç |
| | | import request from '@/utils/request' |
| | | |
| | | // /equipmentManagement/list |
| | | // æ¥è¯¢è®¾å¤ç®¡çå表 |
| | | export function getManagementList(query) { |
| | | return request({ |
| | | url: '/equipmentManagement/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // /equipmentManagement/addOrEditEquipment |
| | | // æ·»å æç¼è¾è®¾å¤ |
| | | export function addOrEditEquipment(data) { |
| | | return request({ |
| | | url: '/equipmentManagement/addOrEditEquipment', |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // /equipmentManagement/delEquipment |
| | | // å é¤è®¾å¤ |
| | | export function delEquipment(data) { |
| | | return request({ |
| | | url: '/equipmentManagement/delEquipment', |
| | | method: 'delete', |
| | | data |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 设å¤ç®¡ç |
| | | import request from '@/utils/request' |
| | | |
| | | |
| | | // /equipmentUsageRecord/list |
| | | // æ¥è¯¢è®¾å¤ä½¿ç¨è®°å½ |
| | | export function getUsageRecordList(query) { |
| | | return request({ |
| | | url: '/equipmentUsageRecord/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // /equipmentUsageRecord/addOrEditUsageRecord |
| | | // æ·»å æç¼è¾è®¾å¤ä½¿ç¨è®°å½ |
| | | export function addOrEditUsageRecord(data) { |
| | | return request({ |
| | | url: '/equipmentUsageRecord/addOrEditUsageRecord', |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // /equipmentUsageDetail/list?usageId=3 |
| | | // 设å¤é¢ç¨å½è¿è®°å½æ¥è¯¢ |
| | | export function getUsageDetailList(usageId) { |
| | | return request({ |
| | | url: `/equipmentUsageDetail/list?usageId=${usageId}`, |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // ç»å½æ¹æ³ |
| | | export function loginCheckFactory(username, password, factoryId) { |
| | | export function login(username, password, code, uuid) { |
| | | const data = { |
| | | username, |
| | | password, |
| | | factoryId |
| | | code, |
| | | uuid |
| | | } |
| | | return request({ |
| | | url: '/loginCheckFactory', |
| | | url: '/login', |
| | | headers: { |
| | | isToken: false, |
| | | repeatSubmit: false |
| | | }, |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // æ³¨åæ¹æ³ |
| | | export function register(data) { |
| | | return request({ |
| | | url: '/register', |
| | | headers: { |
| | | isToken: false |
| | | }, |
| | |
| | | }) |
| | | } |
| | | |
| | | // è·åå
¬å¸å表 |
| | | export function userLoginFacotryList(params) { |
| | | // è·åéªè¯ç |
| | | export function getCodeImg() { |
| | | return request({ |
| | | url: '/userLoginFacotryList', |
| | | url: '/captchaImage', |
| | | headers: { |
| | | isToken: false |
| | | }, |
| | | method: 'get', |
| | | params: params |
| | | timeout: 20000 |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ææ¡£ç®¡ç |
| | | import request from '@/utils/request' |
| | | |
| | | |
| | | // /system/user/listAll |
| | | // æ¥è¯¢ææç¨æ·å表 |
| | | export function userListAll() { |
| | | return request({ |
| | | url: '/system/user/listAll', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // /equipmentManagement/equipmentList |
| | | // æ¥è¯¢è®¾å¤å表 |
| | | export function getEquipmentList(query) { |
| | | return request({ |
| | | url: '/equipmentManagement/equipmentList', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // /coalInfo/coalInfoList |
| | | // æ¥è¯¢ç
¤ç§å表 |
| | | export function getCoalInfoList(query) { |
| | | return request({ |
| | | url: '/coalInfo/coalInfoList', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // /coalField/coalFieldList |
| | | // æ¥è¯¢ç
¤è´¨å段å表 |
| | | export function getCoalFieldList(query) { |
| | | return request({ |
| | | url: '/coalField/coalFieldList', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | |
| | | const config = { |
| | | // baseUrl: 'https://vue.ruoyi.vip/prod-api', |
| | | // baseUrl: 'http://localhost/prod-api', |
| | | baseUrl: 'http://114.132.189.42:9066', // å®å¤æ¶¦æ³° |
| | | // baseUrl: 'http://114.132.189.42:9068', // æ°çæµ·å·å¼å¿ |
| | | // baseUrl: 'http://192.168.1.147:9036', |
| | | baseUrl: 'http://192.168.1.147:7016', // |
| | | //cloudåå°ç½å
³å°å |
| | | // baseUrl: 'http://192.168.10.3:8080', |
| | | // åºç¨ä¿¡æ¯ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * éç¨å é¤åè½ç»åå¼å½æ°ï¼APPçæ¬ï¼ |
| | | * æä¾ç»ä¸çå é¤ç¡®è®¤ãAPIè°ç¨ãæ°æ®æ´æ°é»è¾ï¼éé
uni-appåuviewplus |
| | | */ |
| | | import { useToast } from "@/utils/uviewplus"; |
| | | |
| | | /** |
| | | * å建å é¤åè½ |
| | | * @param {Object} options é
ç½®é项 |
| | | * @param {Function|Function} options.deleteApi å é¤API彿°æè¿åAPI彿°ç彿° |
| | | * @param {Function|Function} options.getList éæ°è·ååè¡¨æ°æ®ç彿°æè¿å彿°ç彿° |
| | | * @param {Ref} options.selectedRows éä¸è¡çååºå¼å¼ç¨ |
| | | * @param {Ref} options.tableData è¡¨æ ¼æ°æ®çååºå¼å¼ç¨ |
| | | * @param {Ref} options.total æ»æ°çååºå¼å¼ç¨ |
| | | * @param {String} options.confirmText 确认å é¤çæç¤ºææ¬ |
| | | * @param {String} options.successText å 餿åçæç¤ºææ¬ |
| | | * @param {Boolean} options.useLocalUpdate æ¯å¦ä½¿ç¨æ¬å°æ´æ°ï¼ä¸éæ°è¯·æ±æ¥å£ï¼ |
| | | * @returns {Object} è¿åå é¤ç¸å
³çæ¹æ³ |
| | | */ |
| | | export function useDelete(options = {}) { |
| | | const { |
| | | deleteApi, |
| | | getList, |
| | | selectedRows, |
| | | tableData, |
| | | total, |
| | | confirmText = "ç¡®å®å é¤éä¸çæ°æ®åï¼", |
| | | successText = "å 餿å", |
| | | useLocalUpdate = false |
| | | } = options; |
| | | |
| | | /** |
| | | * è·åå®é
çå é¤API彿° |
| | | * æ¯æç´æ¥ä¼ å
¥å½æ°æè¿å彿°ç彿° |
| | | */ |
| | | const getDeleteApi = () => { |
| | | if (typeof deleteApi === 'function') { |
| | | // å°è¯è°ç¨çæ¯å¦è¿å彿° |
| | | try { |
| | | const result = deleteApi(); |
| | | return typeof result === 'function' ? result : deleteApi; |
| | | } catch (error) { |
| | | // 妿è°ç¨åºéï¼è¯´æè¿æ¬èº«å°±æ¯API彿° |
| | | return deleteApi; |
| | | } |
| | | } |
| | | return deleteApi; |
| | | }; |
| | | |
| | | /** |
| | | * è·åå®é
çè·ååè¡¨å½æ° |
| | | * æ¯æç´æ¥ä¼ å
¥å½æ°æè¿å彿°ç彿° |
| | | */ |
| | | const getListFunction = () => { |
| | | if (typeof getList === 'function') { |
| | | try { |
| | | const result = getList(); |
| | | return typeof result === 'function' ? result : getList; |
| | | } catch (error) { |
| | | // 妿è°ç¨åºéï¼è¯´æè¿æ¬èº«å°±æ¯åè¡¨å½æ° |
| | | return getList; |
| | | } |
| | | } |
| | | return getList; |
| | | }; |
| | | |
| | | /** |
| | | * æ¹éå 餿¹æ³ |
| | | * @param {Array} customIds èªå®ä¹è¦å é¤çIDæ°ç»ï¼å¦æä¸ä¼ å使ç¨selectedRows |
| | | */ |
| | | const handleDelete = async (customIds = null) => { |
| | | // ç¡®å®è¦å é¤çè¡ |
| | | const rowsToDelete = customIds ? |
| | | tableData.value.filter(item => customIds.includes(item.id)) : |
| | | selectedRows.value; |
| | | |
| | | // æ£æ¥æ¯å¦æé䏿°æ® |
| | | if (rowsToDelete.length === 0) { |
| | | useToast().warning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | // 确认å é¤ - 使ç¨uni-appçshowModalæ¿ä»£Element PlusçMessageBox |
| | | const result = await uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: confirmText, |
| | | confirmText: 'ç¡®å®', |
| | | cancelText: 'åæ¶', |
| | | confirmColor: '#2979ff' |
| | | }); |
| | | |
| | | // ç¨æ·ç¹å»åæ¶ |
| | | if (!result.confirm) { |
| | | useToast().info("已忶å é¤"); |
| | | return false; |
| | | } |
| | | |
| | | // æåID |
| | | const ids = rowsToDelete.map(item => item.id); |
| | | |
| | | // è·åå½åçå é¤API彿° |
| | | const currentDeleteApi = getDeleteApi(); |
| | | if (!currentDeleteApi) { |
| | | useToast().error("å é¤APIæªé
ç½®"); |
| | | return false; |
| | | } |
| | | |
| | | // è°ç¨å é¤API |
| | | const res = await currentDeleteApi(ids); |
| | | |
| | | if (res.code === 200) { |
| | | // æ ¹æ®é
ç½®éæ©æ´æ°æ¹å¼ |
| | | if (useLocalUpdate) { |
| | | // æ¬å°æ´æ°ï¼ä»è¡¨æ ¼æ°æ®ä¸ç§»é¤å·²å é¤ç项 |
| | | tableData.value = tableData.value.filter(item => !ids.includes(item.id)); |
| | | if (total && total.value !== undefined) { |
| | | total.value = tableData.value.length; |
| | | } |
| | | } else { |
| | | // éæ°è·åæ°æ® |
| | | const currentGetList = getListFunction(); |
| | | if (currentGetList) { |
| | | await currentGetList(); |
| | | } |
| | | } |
| | | |
| | | // æ¸
空éä¸ç¶æ |
| | | if (selectedRows && selectedRows.value) { |
| | | selectedRows.value = []; |
| | | } |
| | | |
| | | useToast().success(successText); |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | // å
¶ä»é误å¤ç |
| | | console.error("å 餿ä½å¤±è´¥:", error); |
| | | } |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * å é¤åä¸ªé¡¹ç® |
| | | * @param {Object} row è¦å é¤çè¡æ°æ® |
| | | */ |
| | | const handleDeleteSingle = async (row) => { |
| | | return await handleDelete([row.id]); |
| | | }; |
| | | |
| | | /** |
| | | * å é¤å¤ä¸ªé¡¹ç®ï¼æ¹éå é¤ï¼ |
| | | */ |
| | | const handleDeleteBatch = async () => { |
| | | return await handleDelete(); |
| | | }; |
| | | |
| | | return { |
| | | handleDelete, |
| | | handleDeleteSingle, |
| | | handleDeleteBatch |
| | | }; |
| | | } |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/ledger/index", |
| | | "path": "pages/management/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦", |
| | | "navigationStyle": "custom" |
| | |
| | | <template> |
| | | <view class="content"> |
| | | <view class="header-section"> |
| | | <view class="currentFactory"> |
| | | <up-text type="primary" :text="userStore.currentFactoryName" @click="show = true" size="18" |
| | | class="factoryName" suffixIcon="arrow-right" :iconStyle="iconStyle"></up-text> |
| | | </view> |
| | | <up-picker :show="show" :columns="factoryList" @confirm="changeFactory" @cancel="show = false"></up-picker> |
| | | </view> |
| | | |
| | | <view class="hero-section"> |
| | | <view class="bg-img"> |
| | | <view class="hero-content"> |
| | | <text class="hero-title">润泰çç©ç§æ</text> |
| | | <text class="hero-title">é西æå¾·ç¯ä¿</text> |
| | | </view> |
| | | <view class="hero-wave"></view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- <view class="notice-section">--> |
| | | <!-- <view class="notice">--> |
| | | <!-- <view class="notice-content">--> |
| | | <!-- <view class="notice-left">--> |
| | | <!-- <text class="notice-status">éç¥</text>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="notice-separator"></view>--> |
| | | <!-- <view class="notice-right">--> |
| | | <!-- <text class="notice-label">{{currentStatus}}</text>--> |
| | | <!-- <text class="notice-text">彿¥éå®è®¾å¤æ°:<text class="notice-number">{{number}}<text class="notice-unit">个</text></text></text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | |
| | | <!-- è¥éç®¡çæ¨¡å --> |
| | | <view class="common-module marketing-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 marketingItems" |
| | | :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 purchase-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 purchaseItems" |
| | | :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">--> |
| | | <!-- <view class="module-title-container">--> |
| | | <!-- <text class="module-title">ç产管æ§</text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="module-content">--> |
| | | <!-- <up-grid--> |
| | | <!-- :border="false"--> |
| | | <!-- col="4"--> |
| | | <!-- >--> |
| | | <!-- <up-grid-item--> |
| | | <!-- v-for="(item, index) in productionItems"--> |
| | | <!-- :key="index"--> |
| | | <!-- @click="handleCommonItemClick(item)"--> |
| | | <!-- >--> |
| | | <!-- <view class="icon-container" :style="{ background: item.bgColor }">--> |
| | | <!-- <up-icon--> |
| | | <!-- :name="item.icon"--> |
| | | <!-- :size="58"--> |
| | | <!-- color="#ffffff"--> |
| | | <!-- ></up-icon>--> |
| | | <!-- </view>--> |
| | | <!-- <text class="item-label">{{item.label}}</text>--> |
| | | <!-- </up-grid-item>--> |
| | | <!-- </up-grid>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | |
| | | <!-- 设å¤ç®¡ç模å --> |
| | | <view class="common-module equipment-module"> |
| | |
| | | |
| | | <script setup> |
| | | import {ref, onMounted, nextTick, reactive} from 'vue'; |
| | | import {userLoginFacotryList} from "@/api/login"; |
| | | import modal from "@/plugins/modal"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | |
| | | }, 3000) |
| | | } |
| | | |
| | | // è¥é管çåè½æ°æ® |
| | | const marketingItems = reactive([ |
| | | { |
| | | icon: '/static/images/icon/xiaoshoutaizhang@2x.png', |
| | | label: 'éå®å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/kaipiaodengji@2x.png', |
| | | label: 'å¼ç¥¨ç»è®°', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/kaipiaotaizhang@2x.png', |
| | | label: 'å¼ç¥¨å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/huikuandengji@2x.png', |
| | | label: '忬¾ç»è®°', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/huikuanliushui@2x.png', |
| | | label: '忬¾æµæ°´', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/kehuwanglai@2x.png', |
| | | label: '客æ·å¾æ¥', |
| | | } |
| | | ]); |
| | | |
| | | // éè´ç®¡çåè½æ°æ® |
| | | const purchaseItems = reactive([ |
| | | { |
| | | icon: '/static/images/icon/caigoutaizhang@2x.png', |
| | | label: 'éè´å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/laipiaodengji@2x.png', |
| | | label: 'æ¥ç¥¨ç»è®°', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/laipiaotaizhang@2x.png', |
| | | label: 'æ¥ç¥¨å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/fukuanjingji@2x.png', |
| | | label: '仿¬¾ç»è®°', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/fukuanliushui@2x.png', |
| | | label: '仿¬¾æµæ°´', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/gongyingshangwanglai@2x.png', |
| | | label: 'ä¾åºå徿¥', |
| | | }, |
| | | ]); |
| | | |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | | { |
| | | icon: '/static/images/icon/xietongshenpi@2x.png', |
| | | label: 'åå审æ¹', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/kehubaifang@2x.png', |
| | | label: 'å®¢æ·æè®¿', |
| | | } |
| | | ]); |
| | | |
| | | // ç产管æ§åè½æ°æ® |
| | | const productionItems = reactive([ |
| | | { |
| | | icon: '/static/images/icon/shengchandingdan@2x.png', |
| | | label: 'ç产订å', |
| | | bgColor: '#FF9800' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shengchanpaigong@2x.png', |
| | | label: 'ç产派工', |
| | | bgColor: '#FF6B35' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shengchanpaichan@2x.png', |
| | | label: 'å·¥åºæäº§', |
| | | bgColor: '#E91E63' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shengchanbaogong@2x.png', |
| | | label: 'ç产æ¥å·¥', |
| | | bgColor: '#673AB7' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shengchanhesuan@2x.png', |
| | | label: 'çäº§æ ¸ç®', |
| | | bgColor: '#3F51B5' |
| | | } |
| | | ]); |
| | | |
| | | // 设å¤ç®¡çåè½æ°æ® |
| | | const equipmentItems = reactive([ |
| | | // { |
| | | // icon: '/static/images/icon/shebeitaizhang@2x.png', |
| | | // label: '设å¤å°è´¦', |
| | | // }, |
| | | { |
| | | icon: '/static/images/icon/shbeibaoxiu@2x.png', |
| | | label: 'è®¾å¤æ¥ä¿®', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shbeibaoyang@2x.png', |
| | | label: '设å¤ä¿å
»', |
| | | icon: '/static/images/icon/shebeitaizhang@2x.png', |
| | | label: '设å¤å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/xunjianshangchuan@2x.png', |
| | | label: 'å·¡æ£ä¸ä¼ ', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/guzhangfenxi@2x.png', |
| | | label: 'åæè¿½æº¯', |
| | | bgColor: '#ff9800' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/zhinengpaidan@2x.png', |
| | | label: 'æºè½æ´¾å', |
| | | bgColor: '#ff6b35' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/zuoyezhidao@2x.png', |
| | | label: 'ä½ä¸æå¯¼', |
| | | bgColor: '#4caf50' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/jieguoyanzheng@2x.png', |
| | | label: 'ç»æéªè¯', |
| | | bgColor: '#9c27b0' |
| | | } |
| | | ]); |
| | | |
| | | // å¤ç常ç¨åè½ç¹å» |
| | | 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/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/productionReport/index' |
| | | }); |
| | | break; |
| | | case 'çäº§æ ¸ç®': |
| | | uni.navigateTo({ |
| | | url: '/pages/productionManagement/productionAccounting/index' |
| | | }); |
| | | break; |
| | | case '设å¤å°è´¦': |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/ledger/index' |
| | | url: '/pages/management/index' |
| | | }); |
| | | break; |
| | | case 'è®¾å¤æ¥ä¿®': |
| | |
| | | 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}`, |
| | |
| | | // å建对åç»ä»¶çå¼ç¨ |
| | | const uToastRef = ref(null); |
| | | |
| | | function getUserLoginFacotryList() { |
| | | userLoginFacotryList({userName: userStore.nickName}).then(res => { |
| | | // æ£æ¥res.dataæ¯å¦ä¸ºæ°ç» |
| | | factoryList.value[0] = [] |
| | | if (res.data && Array.isArray(res.data)) { |
| | | factoryListTem.value = res.data |
| | | res.data.forEach(item => { |
| | | factoryList.value[0].push(item.deptName) |
| | | }) |
| | | factoryId.value = userStore.currentDeptId |
| | | } else { |
| | | // 妿res.data䏿¯æ°ç»ï¼è®¾ç½®ä¸ºç©ºæ°ç» |
| | | factoryList.value = [] |
| | | } |
| | | }).catch(error => { |
| | | modal.msgError('è·åå
¬å¸å表失败:', error) |
| | | factoryList.value = [] |
| | | }) |
| | | } |
| | | const changeFactory = async (arr) => { |
| | | show.value = false; |
| | | const factoryId = factoryListTem.value[arr.indexs[0]].deptId |
| | | const loginForm = { |
| | | username: userStore.name, |
| | | password: uni.getStorageSync('remembered_password'), |
| | | factoryId: factoryId, |
| | | } |
| | | modal.loading("å·æ°ä¸ï¼è¯·èå¿çå¾
...") |
| | | userStore.loginCheckFactory(loginForm).then(() => { |
| | | modal.closeLoading() |
| | | nextTick(() => { |
| | | loginSuccess() |
| | | }); |
| | | }).catch(() => { |
| | | modal.closeLoading() |
| | | }) |
| | | } |
| | | function loginSuccess(result) { |
| | | uni.reLaunch({ |
| | | url: '/pages/index' |
| | |
| | | onMounted(() => { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo() |
| | | getUserLoginFacotryList() |
| | | // å¯å¨éç¥ç¶æå®æ¶å¨ |
| | | startStatusTimer() |
| | | }); |
| | |
| | | <view class="login-form-content"> |
| | | <view class="input-item flex align-center"> |
| | | <up-input prefixIcon="account" placeholder="请è¾å
¥è´¦å·" border="bottom" |
| | | @blur="getUserLoginFacotryList" |
| | | maxlength="30" v-model="loginForm.userName" clearable></up-input> |
| | | </view> |
| | | <view class="input-item flex align-center"> |
| | | <up-input prefixIcon="lock" placeholder="请è¾å
¥å¯ç " border="bottom" maxlength="20" v-model="loginForm.password" clearable type="password"></up-input> |
| | | </view> |
| | | <view class="input-item flex align-center select-container"> |
| | | <up-icon name="tags" size="18"></up-icon> |
| | | <up-picker-data |
| | | v-model="loginForm.factoryId" |
| | | title="è¯·éæ©å
¬å¸" |
| | | :options="factoryList" |
| | | valueKey="id" |
| | | style="width: 100%;" |
| | | labelKey="name"> |
| | | </up-picker-data> |
| | | </view> |
| | | <view> |
| | | <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">ç»å½</button> |
| | |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import { userLoginFacotryList} from '@/api/login' |
| | | import { ref, onMounted } from "vue"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getWxCode } from '@/utils/geek'; |
| | |
| | | const loginForm = ref({ |
| | | userName: "", |
| | | password: "", |
| | | factoryId: "", |
| | | currentFatoryName: "", |
| | | }); |
| | | const factoryList = ref([]) // å
¬å¸å表 |
| | |
| | | }) |
| | | } |
| | | |
| | | function getUserLoginFacotryList() { |
| | | if(loginForm.value.userName){ |
| | | userLoginFacotryList({userName:loginForm.value.userName}).then(res => { |
| | | console.log('res',res) |
| | | // æ£æ¥res.dataæ¯å¦ä¸ºæ°ç» |
| | | if (res.data && Array.isArray(res.data)) { |
| | | // éæ°ç»è£
æ°æ®æ ¼å¼ï¼deptIdåæidï¼deptNameåæname |
| | | factoryList.value = res.data.map(item => ({ |
| | | id: item.deptId, |
| | | name: item.deptName |
| | | })) |
| | | } else { |
| | | // 妿res.data䏿¯æ°ç»ï¼è®¾ç½®ä¸ºç©ºæ°ç» |
| | | factoryList.value = [] |
| | | } |
| | | }).catch(error => { |
| | | showToast('è·åå
¬å¸å表失败:', error) |
| | | factoryList.value = [] |
| | | }) |
| | | }else { |
| | | factoryList.value = [] |
| | | } |
| | | } |
| | | |
| | | async function handleLogin() { |
| | | if (loginForm.value.userName === "") { |
| | | showToast("请è¾å
¥æ¨çè´¦å·") |
| | | } else if (loginForm.value.password === "") { |
| | | showToast("请è¾å
¥æ¨çå¯ç ") |
| | | } else if (loginForm.value.factoryId === "") { |
| | | showToast("è¯·éæ©å
¬å¸") |
| | | } else { |
| | | showToast("ç»å½ä¸ï¼è¯·èå¿çå¾
...") |
| | | pwdLogin() |
| | |
| | | }; |
| | | // å¯ç ç»å½ |
| | | async function pwdLogin() { |
| | | userStore.loginCheckFactory(loginForm.value).then(() => { |
| | | userStore.login(loginForm.value).then(() => { |
| | | modal.closeLoading() |
| | | // ç»å½æååä¿åå¯ç |
| | | savePassword(); |
| | |
| | | // 页é¢å è½½æ¶æ£æ¥æ¯å¦æä¿åçå¯ç |
| | | onMounted(() => { |
| | | loadPassword(); |
| | | getUserLoginFacotryList() |
| | | }); |
| | | </script> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="equipment-management"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <PageHeader title="设å¤ç®¡ç" @back="goBack"/> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section" v-if="shouldShowSearch"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | :placeholder="searchPlaceholder" |
| | | v-model="queryParams.searchAll" |
| | | @change="search" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="search"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ ç¾é¡µ --> |
| | | <view class="tabs-section"> |
| | | <u-tabs |
| | | :list="tabs" |
| | | :current="activeTabIndex" |
| | | @change="handleTabChange" |
| | | :scrollable="false" |
| | | lineWidth="30" |
| | | lineColor="#2979ff" |
| | | :activeStyle="{ |
| | | color: '#2979ff', |
| | | fontWeight: 'bold' |
| | | }" |
| | | /> |
| | | </view> |
| | | |
| | | <!-- å表åºå --> |
| | | <scroll-view |
| | | class="list-container" |
| | | scroll-y |
| | | refresher-enabled |
| | | :refresher-triggered="refreshing" |
| | | @refresherrefresh="onRefresh" |
| | | > |
| | | <!-- å è½½ç¶æ --> |
| | | <view v-if="loading" class="loading-container"> |
| | | <u-loading-icon text="å è½½ä¸..." /> |
| | | </view> |
| | | |
| | | <!-- 设å¤å表 --> |
| | | <view v-else-if="!loading && tableData.length > 0" class="ledger-list"> |
| | | <view v-for="(item, index) in tableData" :key="item.id || 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.equipmentNo || 'æªç¼å·' }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <!-- 设å¤åè¡¨é¡µé¢ --> |
| | | <template v-if="activeTab === 'management'"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设å¤åç§°</text> |
| | | <text class="detail-value">{{ item.equipmentName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">èæ</text> |
| | | <text class="detail-value">{{ (item.consumables !== undefined ? item.consumables : item.isConsumables) ? 'æ¯' : 'å¦' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ»æ°é</text> |
| | | <text class="detail-value highlight">{{ item.quantity || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·²ä½¿ç¨æ°é</text> |
| | | <text class="detail-value">{{ item.usedNo || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.specification || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éè´æ¥æ</text> |
| | | <text class="detail-value">{{ item.purchaseDate || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éè´ä»·æ ¼</text> |
| | | <text class="detail-value">{{ item.purchasePrice ? `Â¥${item.purchasePrice}` : '-' }}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <!-- 设å¤é¢ç¨é¡µé¢ --> |
| | | <template v-else-if="activeTab === 'equipmentRequisition'"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">é¢ç¨äºº</text> |
| | | <text class="detail-value">{{ item.userName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设å¤åç§°</text> |
| | | <text class="detail-value">{{ item.equipmentName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">é¢ç¨æ°é</text> |
| | | <text class="detail-value highlight">{{ item.usageQuantity || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å½è¿æ°é</text> |
| | | <text class="detail-value">{{ item.returnQuantity || 0 }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">使ç¨ç¶æ</text> |
| | | <text class="detail-value" :style="{ color: getStatusColor(item.equipmentStatus) }"> |
| | | {{ getStatusText(item.equipmentStatus) }} |
| | | </text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">使ç¨å¼å§æ¶é´</text> |
| | | <text class="detail-value">{{ item.usageStartTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">使ç¨ç»ææ¶é´</text> |
| | | <text class="detail-value">{{ item.usageEndTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" v-if="item.remarks"> |
| | | <text class="detail-label">夿³¨</text> |
| | | <text class="detail-value">{{ item.remarks }}</text> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- æä½æé® - åªå¨è®¾å¤é¢ç¨é¡µé¢æ¾ç¤º --> |
| | | <template v-if="activeTab === 'equipmentRequisition'"> |
| | | <up-divider></up-divider> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="handleView(item)" |
| | | > |
| | | æ¥ç |
| | | </u-button> |
| | | <u-button |
| | | v-if="shouldShowReturnButton(item)" |
| | | type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.equipmentStatus === EQUIPMENT_STATUS.RETURNED" |
| | | @click.stop="handleReturn(item)" |
| | | > |
| | | å½è¿ |
| | | </u-button> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- ç©ºç¶æ --> |
| | | <view v-else-if="!loading && tableData.length === 0" class="no-data"> |
| | | <text>ææ {{ currentTabConfig?.label || '' }}æ°æ®</text> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <!-- æµ®å¨æä½æé® - 设å¤é¢ç¨é¡µé¢æ¾ç¤ºé¢ç¨æé® --> |
| | | <view |
| | | v-if="activeTab === 'equipmentRequisition'" |
| | | class="fab-button" |
| | | @tap="handleAdd" |
| | | > |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | |
| | | <!-- å¼¹çªç»ä»¶ --> |
| | | <managementDialog |
| | | v-if="activeTab == 'management'" |
| | | v-model:copyForm="copyForm" |
| | | v-model:managementFormDialog="manaDialog" |
| | | :addOrEdit="addOrEdit" |
| | | :form="form" |
| | | @submit="getList" |
| | | /> |
| | | <EquipmentRequisition |
| | | v-model="equipmentRequisitionDialog" |
| | | :formData="form" |
| | | :maxQuantity="getMaxQuantity()" |
| | | :addOrEdit="addOrEdit" |
| | | :equipmentStatus="form.equipmentStatus" |
| | | @submit="onEquipmentRequisitionSubmit" |
| | | /> |
| | | |
| | | <!-- æ¥ç详æ
å¼¹çª --> |
| | | <u-popup |
| | | v-model="dialogTableVisible" |
| | | :title="dialogTableTitle" |
| | | mode="center" |
| | | :closeable="true" |
| | | > |
| | | <view class="dialog-content"> |
| | | <u-table |
| | | :data="dialogTableData" |
| | | :columns="dialogTableColumns" |
| | | height="400px" |
| | | /> |
| | | </view> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, onMounted, reactive, ref, nextTick, toRefs } from "vue"; |
| | | |
| | | // uviewplusç»ä»¶å¯¼å
¥ |
| | | import { useToast } from '@/utils/uviewplus' |
| | | const { showToast } = useToast() |
| | | |
| | | // ç»ä»¶å¯¼å
¥ |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import managementDialog from "./mould/managementDialog.vue"; |
| | | import EquipmentRequisition from "./mould/equipmentRequisitionDialog.vue"; |
| | | |
| | | // API æå¡å¯¼å
¥ |
| | | import { |
| | | getManagementList, |
| | | } from "@/api/equipment/management/index.js"; |
| | | import { getUsageRecordList, getUsageDetailList } from "@/api/equipment/requisition/index.js"; |
| | | |
| | | // 设å¤ç¶ææä¸¾ |
| | | const EQUIPMENT_STATUS = { |
| | | USING: 1, // 使ç¨ä¸ |
| | | PARTIAL_RETURN: 2, // é¨åå½è¿ |
| | | RETURNED: 3 // å·²å½è¿ |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | switch(status) { |
| | | case EQUIPMENT_STATUS.USING: return "使ç¨ä¸"; |
| | | case EQUIPMENT_STATUS.PARTIAL_RETURN: return "é¨åå½è¿"; |
| | | case EQUIPMENT_STATUS.RETURNED: return "å·²å½è¿"; |
| | | default: return "æªç¥ç¶æ"; |
| | | } |
| | | }; |
| | | |
| | | // è·åç¶æé¢è² |
| | | const getStatusColor = (status) => { |
| | | switch(status) { |
| | | case EQUIPMENT_STATUS.USING: return '#409eff'; // èè² |
| | | case EQUIPMENT_STATUS.PARTIAL_RETURN: return '#e6a23c'; // æ©è² |
| | | case EQUIPMENT_STATUS.RETURNED: return '#67c23a'; // ç»¿è² |
| | | default: return '#909399'; // ç°è² |
| | | } |
| | | }; |
| | | |
| | | // ååºå¼ç¶æç®¡ç - 使ç¨è§£æåé»è®¤å¼ |
| | | const initFormState = () => ({ consumables: false }); |
| | | |
| | | const state = reactive({ |
| | | form: initFormState(), |
| | | title: "", |
| | | copyForm: {}, |
| | | addOrEdit: "add", |
| | | loading: false, |
| | | activeTab: "management", |
| | | tableData: [], |
| | | // åé¡µç¶æï¼ä¿çç¨äºAPIè°ç¨ï¼ä½ä¸æ¾ç¤ºå页ç»ä»¶ï¼ |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | total: 0, |
| | | // 䏿巿°ç¶æ |
| | | refreshing: false, |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | searchAll: "", |
| | | }, |
| | | }); |
| | | |
| | | // 使ç¨è§£æç®åè®¿é® |
| | | const { |
| | | form, |
| | | title, |
| | | copyForm, |
| | | addOrEdit, |
| | | loading, |
| | | activeTab, |
| | | tableData, |
| | | pageNum, |
| | | pageSize, |
| | | total, |
| | | queryParams, |
| | | refreshing, |
| | | } = toRefs(state); |
| | | |
| | | // æ·»å 缺失çååºå¼åé |
| | | const manaDialog = ref(false); |
| | | const equipmentRequisitionDialog = ref(false); |
| | | const usageRecordDialog = ref(false); |
| | | const dialogTableVisible = ref(false); |
| | | const dialogTableTitle = ref(''); |
| | | const dialogTableData = ref([]); |
| | | const dialogTableColumns = ref([]); |
| | | |
| | | // æ ç¾é¡µé
ç½® - 便äºåç»æ©å± |
| | | const tabsConfig = { |
| | | management: { |
| | | label: "设å¤å表", |
| | | searchPlaceholder: "设å¤ç¼å·/设å¤åç§°/è§æ ¼åå·", |
| | | showSearch: true, |
| | | api: getManagementList, |
| | | columns: [ |
| | | { prop: "equipmentNo", label: "设å¤ç¼å·", minWidth: 100 }, |
| | | { prop: "equipmentName", label: "设å¤åç§°", minWidth: 100 }, |
| | | { prop: "consumables", label: "èæ", |
| | | formatter: (row) => { |
| | | const value = row.consumables !== undefined ? row.consumables : row.isConsumables; |
| | | return value ? "æ¯" : "å¦"; |
| | | }, minWidth: 100 }, |
| | | { prop: "quantity", label: "æ»æ°é", minWidth: 100 }, |
| | | { prop: "usedNo", label: "å·²ä½¿ç¨æ°é", minWidth: 100 }, |
| | | { prop: "specification", label: "è§æ ¼åå·", minWidth: 100 }, |
| | | { prop: "purchaseDate", label: "éè´æ¥æ", minWidth: 100 }, |
| | | { prop: "purchasePrice", label: "éè´ä»·æ ¼", minWidth: 100 }, |
| | | ], |
| | | }, |
| | | equipmentRequisition: { |
| | | label: "设å¤é¢ç¨", |
| | | searchPlaceholder: "设å¤ç¼å·/设å¤åç§°/è§æ ¼åå·", |
| | | showSearch: true, |
| | | api: getUsageRecordList, |
| | | columns: [ |
| | | { prop: "userName", label: "é¢ç¨äºº", minWidth: 100 }, |
| | | { prop: "equipmentNo", label: "设å¤ç¼å·", minWidth: 100 }, |
| | | { prop: "equipmentName", label: "设å¤åç§°", minWidth: 100 }, |
| | | { prop: "usageQuantity", label: "é¢ç¨æ°é", minWidth: 100 }, |
| | | {prop: "returnQuantity" , label: "å½è¿æ°é", minWidth: 100, |
| | | formatter: (row) => row.returnQuantity || 0 |
| | | }, |
| | | { |
| | | prop: "equipmentStatus", |
| | | label: "使ç¨ç¶æ", |
| | | minWidth: 100, |
| | | formatter: (row) => getStatusText(row.equipmentStatus), |
| | | cellStyle: (row) => ({ color: getStatusColor(row.equipmentStatus) }), |
| | | }, |
| | | { prop: "usageStartTime", label: "使ç¨å¼å§æ¶é´", minWidth: 100 }, |
| | | { prop: "usageEndTime", label: "使ç¨ç»ææ¶é´", minWidth: 100 }, |
| | | { prop: "remarks", label: "夿³¨", minWidth: 100 }, |
| | | ], |
| | | }, |
| | | }; |
| | | |
| | | // æ ç¾é¡µæ°æ® - u-tabséè¦nameä½ä¸ºæ¾ç¤ºææ¬ |
| | | const tabs = computed(() => |
| | | Object.entries(tabsConfig).map(([name, config]) => ({ |
| | | name: config.label, // 使ç¨labelä½ä¸ºæ¾ç¤ºææ¬ |
| | | value: name, // ä¿ååå§nameå¼ |
| | | })) |
| | | ); |
| | | |
| | | // å½åæ ç¾é¡µç´¢å¼ - 使ç¨refè䏿¯computedï¼ç¡®ä¿ååºå¼æ´æ° |
| | | const activeTabIndex = ref(0); |
| | | |
| | | // å½åæ ç¾é¡µé
ç½® |
| | | const currentTabConfig = computed(() => tabsConfig[activeTab.value]); |
| | | |
| | | // 计ç®å±æ§ |
| | | const searchPlaceholder = computed( |
| | | () => currentTabConfig.value?.searchPlaceholder || "请è¾å
¥æç´¢ä¿¡æ¯" |
| | | ); |
| | | const shouldShowSearch = computed( |
| | | () => currentTabConfig.value?.showSearch || false |
| | | ); |
| | | |
| | | // 夿æ¯å¦æ¾ç¤ºå½è¿æé® |
| | | const shouldShowReturnButton = (item) => { |
| | | if (activeTab.value !== 'equipmentRequisition') { |
| | | return false; |
| | | } |
| | | // å¦æè®¾å¤ç¶ææ¯å·²å½è¿ï¼ä¸æ¾ç¤ºå½è¿æé® |
| | | if (item.equipmentStatus === EQUIPMENT_STATUS.RETURNED) { |
| | | return false; |
| | | } |
| | | // å
¶ä»ç¶æé½æ¾ç¤ºå½è¿æé®ï¼ä½¿ç¨ä¸ãé¨åå½è¿ãæè
没æç¶æï¼ |
| | | return true; |
| | | }; |
| | | |
| | | // 卿è·åèªå®ä¹æé®é
ç½®ï¼ä¿çç¨äºå
¶ä»ç¨éï¼ |
| | | const getCustomButtons = () => { |
| | | const buttons = []; |
| | | |
| | | // å¨è®¾å¤é¢ç¨é¡µé¢æ·»å å½è¿æé® |
| | | if (activeTab.value === 'equipmentRequisition') { |
| | | buttons.push({ |
| | | name: 'return', |
| | | label: 'å½è¿', |
| | | type: 'success', |
| | | size: 'small', |
| | | link: true, |
| | | show: (row) => shouldShowReturnButton(row), |
| | | disabled: (row) => row.equipmentStatus === EQUIPMENT_STATUS.RETURNED, |
| | | }); |
| | | } |
| | | |
| | | return buttons; |
| | | }; |
| | | |
| | | // å¤çèªå®ä¹æé®ç¹å»äºä»¶ |
| | | const handleCustomButtonClick = ({ buttonName, row }) => { |
| | | switch (buttonName) { |
| | | case 'return': |
| | | handleReturn(row); |
| | | break; |
| | | // å¯ä»¥å¨è¿éæ·»å æ´å¤èªå®ä¹æé®çå¤çé»è¾ |
| | | default: |
| | | console.warn(`æªå¤ççèªå®ä¹æé®: ${buttonName}`); |
| | | } |
| | | }; |
| | | const handleReturn = (row) => { |
| | | // æ£æ¥è®¾å¤ç¶æ |
| | | if (row.equipmentStatus === EQUIPMENT_STATUS.RETURNED) { |
| | | showToast('该设å¤å·²å½è¿å®æï¼æ é忬¡å½è¿', 'warning'); |
| | | return; |
| | | } |
| | | |
| | | if (row.equipmentStatus !== EQUIPMENT_STATUS.USING && row.equipmentStatus !== EQUIPMENT_STATUS.PARTIAL_RETURN) { |
| | | showToast('该设å¤å½åç¶æä¸æ¯æå½è¿æä½', 'warning'); |
| | | return; |
| | | } |
| | | |
| | | form.value = { ...row }; |
| | | addOrEdit.value = "return"; // 设置为å½è¿æ¨¡å¼ |
| | | title.value = `å½è¿è®¾å¤ - ${row.equipmentName || ''}`; |
| | | copyForm.value = { ...row }; |
| | | equipmentRequisitionDialog.value = true; |
| | | console.log("å½è¿è®¾å¤ï¼", row); |
| | | }; |
| | | // æ ç¾é¡µåæ¢å¤ç - u-tabsç@changeäºä»¶ä¼ éçæ¯å¯¹è±¡ { index: number } |
| | | const handleTabChange = (e) => { |
| | | const index = typeof e === 'object' && e.index !== undefined ? e.index : e; |
| | | console.log('handleTabChange:', e, 'index:', index, 'tabs:', tabs.value); |
| | | const selectedTab = tabs.value[index]; |
| | | if (selectedTab && selectedTab.value !== activeTab.value) { |
| | | activeTab.value = selectedTab.value; |
| | | activeTabIndex.value = index; |
| | | resetState(); |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | |
| | | const resetState = () => { |
| | | form.value = { |
| | | consumables: false, |
| | | }; |
| | | addOrEdit.value = "add"; |
| | | loading.value = true; |
| | | tableData.value = []; |
| | | pageNum.value = 1; |
| | | pageSize.value = 20; |
| | | total.value = 0; |
| | | queryParams.value.searchAll = ""; |
| | | refreshing.value = false; |
| | | }; |
| | | |
| | | const resetQuery = () => { |
| | | queryParams.value.searchAll = ""; |
| | | pageNum.value = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const search = () => { |
| | | pageNum.value = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // å¤çæ°å¢é¢ç¨ |
| | | const handleAdd = () => { |
| | | console.log('handleAdd 被è°ç¨', 'activeTab:', activeTab.value, 'activeTabIndex:', activeTabIndex.value); |
| | | addOrEdit.value = "add"; |
| | | form.value = {}; |
| | | title.value = `æ°å¢${currentTabConfig.value?.label || '设å¤é¢ç¨'}`; |
| | | copyForm.value = {}; |
| | | console.log('å夿å¼å¼¹çªï¼equipmentRequisitionDialogå½åå¼:', equipmentRequisitionDialog.value); |
| | | equipmentRequisitionDialog.value = true; |
| | | console.log('å¼¹çªå·²æå¼ï¼equipmentRequisitionDialogæ°å¼:', equipmentRequisitionDialog.value); |
| | | }; |
| | | |
| | | const handleView = async (row) => { |
| | | // åªå¤ç设å¤é¢ç¨é¡µé¢çæ¥çåè½ |
| | | if (activeTab.value === 'equipmentRequisition') { |
| | | try { |
| | | dialogTableTitle.value = `${row.equipmentName || '设å¤'} - æä½è®°å½è¯¦æ
`; |
| | | |
| | | // æ¾ç¤ºå è½½ç¶æ |
| | | dialogTableVisible.value = true; |
| | | dialogTableData.value = []; |
| | | |
| | | // è°ç¨è¯¦æ
æ¥å£è·åæ°æ® |
| | | const { data, code } = await getUsageDetailList(row.id); |
| | | if (code === 200 && data) { |
| | | // å¤çæ°ç»æ°æ®ï¼ç´æ¥æ¾ç¤ºæä½è®°å½å表 |
| | | if (Array.isArray(data)) { |
| | | dialogTableData.value = data; |
| | | dialogTableColumns.value = [ |
| | | { prop: 'equipmentNo', label: '设å¤ç¼å·', minWidth: 100 }, |
| | | { prop: 'equipmentName', label: '设å¤åç§°', minWidth: 120 }, |
| | | { prop: 'specification', label: 'è§æ ¼åå·', minWidth: 100 }, |
| | | { |
| | | prop: 'operationType', |
| | | label: 'æä½ç±»å', |
| | | minWidth: 80, |
| | | formatter: (row) => row.operationType === 1 ? 'é¢ç¨' : 'å½è¿' |
| | | }, |
| | | { prop: 'quantity', label: 'æä½æ°é', minWidth: 80 }, |
| | | { prop: 'operator', label: 'æä½äºº', minWidth: 80 }, |
| | | { prop: 'remark', label: '夿³¨', minWidth: 150, showOverflowTooltip: true }, |
| | | { prop: 'createTime', label: 'æä½æ¶é´', minWidth: 150 } |
| | | ]; |
| | | } else { |
| | | showToast('ææ æä½è®°å½', 'warning'); |
| | | } |
| | | } else { |
| | | showToast('è·å详æ
æ°æ®å¤±è´¥', 'error'); |
| | | dialogTableVisible.value = false; |
| | | } |
| | | |
| | | } catch (error) { |
| | | console.error('è·å详æ
失败:', error); |
| | | showToast('è·å详æ
æ°æ®å¤±è´¥', 'error'); |
| | | dialogTableVisible.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 䏿巿° |
| | | const onRefresh = async () => { |
| | | refreshing.value = true; |
| | | pageNum.value = 1; |
| | | await getList(); |
| | | refreshing.value = false; |
| | | }; |
| | | |
| | | // è·åè®¾å¤æå¤§å¯é¢ç¨æ°é |
| | | const getMaxQuantity = () => { |
| | | if (form.value.equipmentId) { |
| | | const equipment = tableData.value.find( |
| | | (item) => item.equipmentId === form.value.equipmentId |
| | | ); |
| | | return equipment ? equipment.quantity : null; |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | // 设å¤é¢ç¨å¼¹çªæäº¤å¤ç |
| | | const onEquipmentRequisitionSubmit = (formData) => { |
| | | if (formData.equipmentStatus === EQUIPMENT_STATUS.RETURNED) { |
| | | showToast("设å¤å·²å®å
¨å½è¿", 'success'); |
| | | } else if (formData.equipmentStatus === EQUIPMENT_STATUS.PARTIAL_RETURN) { |
| | | } else if (formData.equipmentStatus === EQUIPMENT_STATUS.USING) { |
| | | showToast("设å¤é¢ç¨æå", 'success'); |
| | | } else { |
| | | showToast("æä½æå", 'success'); |
| | | } |
| | | equipmentRequisitionDialog.value = false; |
| | | nextTick(() => { |
| | | form.value = {}; |
| | | getList(); |
| | | }); |
| | | }; |
| | | |
| | | // æ°æ®è·å |
| | | const getList = async () => { |
| | | try { |
| | | if (!refreshing.value) { |
| | | loading.value = true; |
| | | } |
| | | const apiParams = { |
| | | current: pageNum.value, |
| | | pageSize: pageSize.value, |
| | | searchAll: queryParams.value.searchAll, |
| | | }; |
| | | |
| | | const response = await currentTabConfig.value.api(apiParams); |
| | | console.log('APIååº:', response); |
| | | |
| | | // requestå·¥å
·è¿åçæ¯ { code, data, msg } ç»æ |
| | | const { data, code } = response; |
| | | |
| | | if (code !== 200) { |
| | | showToast("è·åæ°æ®å¤±è´¥ï¼" + (response?.msg || "æªç¥é误"), 'error'); |
| | | return; |
| | | } |
| | | |
| | | // data æ¯ { records: [...], total: 3, ... } ç»æ |
| | | const records = data?.records || data?.rows || []; |
| | | console.log('è§£æåçæ°æ®:', records); |
| | | |
| | | // æ°æ®å段æ å°ï¼å° isConsumables æ å°ä¸º consumables |
| | | const mappedRecords = records.map(item => ({ |
| | | ...item, |
| | | consumables: item.isConsumables !== undefined ? item.isConsumables : item.consumables |
| | | })); |
| | | |
| | | // 妿æ¯ä¸æå·æ°ï¼éç½®æ°æ®ï¼å¦åè¿½å æ°æ®ï¼ç¨äºä¸æå è½½æ´å¤ï¼ä½å½åä¸å®ç°ï¼ |
| | | if (pageNum.value === 1) { |
| | | tableData.value = mappedRecords; |
| | | } else { |
| | | tableData.value = [...tableData.value, ...mappedRecords]; |
| | | } |
| | | total.value = data?.total || 0; |
| | | console.log('æç»è¡¨æ ¼æ°æ®:', tableData.value); |
| | | } catch (error) { |
| | | console.error('è·åæ°æ®å¤±è´¥:', error); |
| | | showToast("è·åæ°æ®å¤±è´¥ï¼è¯·ç¨ååè¯", 'error'); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½ |
| | | onMounted(() => { |
| | | activeTab.value = "management"; |
| | | activeTabIndex.value = 0; |
| | | // ä¸éç½®æç´¢æ¡ä»¶ï¼ç´æ¥å è½½æ°æ® |
| | | loading.value = true; |
| | | getList(); |
| | | }); |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | |
| | | .equipment-management { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | |
| | | .tabs-section { |
| | | background: #ffffff; |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .list-container { |
| | | flex: 1; |
| | | height: calc(100vh - 200px); |
| | | } |
| | | |
| | | .loading-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 40px; |
| | | color: #999; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <u-popup |
| | | :show="visible" |
| | | mode="center" |
| | | :closeable="true" |
| | | @close="handleClose" |
| | | :round="10" |
| | | width="90%" |
| | | :safe-area-inset-bottom="true" |
| | | > |
| | | <view class="popup-content"> |
| | | <view class="popup-header"> |
| | | <text class="popup-title">{{ isReturnMode ? '设å¤å½è¿' : isEdit ? 'ç¼è¾è®¾å¤é¢ç¨' : 'æ°å¢è®¾å¤é¢ç¨' }}</text> |
| | | </view> |
| | | |
| | | <scroll-view class="form-scroll" scroll-y> |
| | | <u-form :model="form" :rules="rules" ref="formRef" label-width="110" input-align="right"> |
| | | <u-form-item label="é¢ç¨äºº" prop="userId" border-bottom required> |
| | | <u-input |
| | | v-model="displayUserName" |
| | | placeholder="è¯·éæ©é¢ç¨äºº" |
| | | readonly |
| | | @click="showUserPicker = true" |
| | | :disabled="isViewMode || isReturnMode" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showUserPicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="设å¤åç§°" prop="equipmentId" border-bottom required> |
| | | <u-input |
| | | v-model="displayEquipmentName" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | readonly |
| | | @click="showEquipmentPicker = true" |
| | | :disabled="isViewMode || isReturnMode" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showEquipmentPicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="æ¯å¦ä¸ºæ¶èå" prop="consumables" border-bottom required> |
| | | <u-input |
| | | v-model="displayConsumables" |
| | | placeholder="è¯·éæ©æ¯å¦ä¸ºæ¶èå" |
| | | readonly |
| | | @click="showConsumablesPicker = true" |
| | | :disabled="isViewMode || isReturnMode" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showConsumablesPicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="isReturnMode" label="å·²ä½¿ç¨æ°é" border-bottom> |
| | | <u-input |
| | | :value="formData.usageQuantity" |
| | | disabled |
| | | placeholder="å·²ä½¿ç¨æ°é" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="isReturnMode" label="å·²å½è¿æ°é" border-bottom> |
| | | <u-input |
| | | :value="formData.totalReturnNo || 0" |
| | | disabled |
| | | placeholder="å·²å½è¿æ°é" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="!isReturnMode && formData.status !== 2" label="é¢ç¨æ°é" prop="usageQuantity" border-bottom required> |
| | | <view class="number-box-wrapper"> |
| | | <u-number-box |
| | | v-model="form.usageQuantity" |
| | | :min="1" |
| | | :max="maxQuantity || 999" |
| | | :disabled="isViewMode" |
| | | integer |
| | | @change="onUsageQuantityChange" |
| | | /> |
| | | <text v-if="maxQuantity !== null" class="info-text">(æå¤{{ maxQuantity }}å°)</text> |
| | | </view> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="isReturnMode" label="æ¬æ¬¡å½è¿æ°é" prop="returnQuantity" border-bottom required> |
| | | <view class="number-box-wrapper"> |
| | | <u-number-box |
| | | v-model="form.returnQuantity" |
| | | :min="1" |
| | | :max="Math.max(1, remainingReturnQuantity)" |
| | | :disabled="remainingReturnQuantity <= 0" |
| | | integer |
| | | /> |
| | | <text class="info-text" v-if="remainingReturnQuantity > 0">(æå¤{{ remainingReturnQuantity }}å°)</text> |
| | | <text class="info-text" v-else>(å·²å
¨é¨å½è¿)</text> |
| | | </view> |
| | | <view |
| | | v-if="remainingReturnQuantity > 0 && form.returnQuantity === remainingReturnQuantity" |
| | | class="tip-text" |
| | | > |
| | | ð¡ æç¤ºï¼æ¬æ¬¡å½è¿åå°å®æå
¨é¨å½è¿ |
| | | </view> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="!isReturnMode" label="使ç¨å¼å§æ¶é´" prop="usageStartTime" border-bottom required> |
| | | <u-input |
| | | v-model="form.usageStartTime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | readonly |
| | | @click="showDatePicker('usageStartTime')" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker('usageStartTime')"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item v-if="isReturnMode" label="å½è¿æ¶é´" prop="returnTime" border-bottom required> |
| | | <u-input |
| | | v-model="form.returnTime" |
| | | placeholder="è¯·éæ©å½è¿æ¶é´" |
| | | readonly |
| | | @click="showDatePicker('returnTime')" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker('returnTime')"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="夿³¨" border-bottom> |
| | | <u-textarea |
| | | v-model="form.remarks" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | :disabled="isViewMode" |
| | | :autoHeight="true" |
| | | count |
| | | /> |
| | | </u-form-item> |
| | | </u-form> |
| | | </scroll-view> |
| | | |
| | | <view class="popup-footer"> |
| | | <u-button @click="handleClose" :customStyle="{ marginRight: '10px', flex: 1 }">åæ¶</u-button> |
| | | <u-button type="primary" @click="debouncedSubmit" v-if="!isViewMode" :customStyle="{ flex: 1 }">ç¡®å®</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-datetime-picker |
| | | :show="showDatePickerVisible" |
| | | v-model="datePickerValue" |
| | | mode="date" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePickerVisible = false" |
| | | /> |
| | | |
| | | <!-- ç¨æ·éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showUserPicker" |
| | | :actions="userActionList" |
| | | title="éæ©é¢ç¨äºº" |
| | | @select="onUserSelect" |
| | | @close="showUserPicker = false" |
| | | /> |
| | | |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showEquipmentPicker" |
| | | :actions="equipmentActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onEquipmentSelect" |
| | | @close="showEquipmentPicker = false" |
| | | /> |
| | | |
| | | <!-- æ¶èåéæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showConsumablesPicker" |
| | | :actions="consumablesActionList" |
| | | title="éæ©æ¯å¦ä¸ºæ¶èå" |
| | | @select="onConsumablesSelect" |
| | | @close="showConsumablesPicker = false" |
| | | /> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, watch, computed, onMounted, nextTick } from "vue"; |
| | | import { useToast, useModal } from "@/utils/uviewplus"; |
| | | import { getEquipmentList, userListAll } from "@/api/publicApi/index.js"; |
| | | import { addOrEditUsageRecord } from "@/api/equipment/requisition/index.js"; |
| | | |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const { showToast } = useToast(); |
| | | const { showModal } = useModal(); |
| | | |
| | | const userStore = useUserStore(); |
| | | let userList = ref([]); |
| | | |
| | | // è·åç¨æ·å表 |
| | | const fetchUserList = async () => { |
| | | try { |
| | | const res = await userListAll(); |
| | | if (res.code === 200) { |
| | | userList.value = res.data || res.rows || []; |
| | | console.log('ç¨æ·å表è·åæå:', userList.value); |
| | | } else { |
| | | showToast('è·åç¨æ·å表失败', 'error'); |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åç¨æ·å表失败:', error); |
| | | showToast('è·åç¨æ·å表失败', 'error'); |
| | | } |
| | | }; |
| | | |
| | | // 鿩卿¾ç¤ºç¶æ |
| | | const showUserPicker = ref(false); |
| | | const showEquipmentPicker = ref(false); |
| | | const showConsumablesPicker = ref(false); |
| | | |
| | | // ç¨æ·éæ©å表ï¼ç¨äº action-sheetï¼ |
| | | const userActionList = computed(() => { |
| | | return userList.value.map(item => ({ |
| | | name: item.nickName || item.nickname || item.userName || item.name || 'æªç¥', |
| | | value: item.userId || item.id |
| | | })); |
| | | }); |
| | | |
| | | // 设å¤éæ©å表ï¼ç¨äº action-sheetï¼ |
| | | const equipmentActionList = computed(() => { |
| | | return equipmentList.value.map(item => ({ |
| | | name: item.equipmentName || item.name || 'æªç¥è®¾å¤', |
| | | value: item.id || item.equipmentId |
| | | })); |
| | | }); |
| | | |
| | | // æ¾ç¤ºç¨çææ¬ï¼ä½¿ç¨ ref ç¡®ä¿ååºå¼ï¼ |
| | | const displayUserName = ref(''); |
| | | const displayEquipmentName = ref(''); |
| | | const displayConsumables = ref(''); |
| | | |
| | | // æ¶èåéæ©å表 |
| | | const consumablesActionList = computed(() => [ |
| | | { name: 'æ¯', value: true }, |
| | | { name: 'å¦', value: false } |
| | | ]); |
| | | |
| | | // çå¬ form ååï¼æ´æ°æ¾ç¤ºææ¬ |
| | | watch( |
| | | () => form.value.userId, |
| | | (userId) => { |
| | | if (userId) { |
| | | const user = userList.value.find(u => { |
| | | const uId = u.userId || u.id; |
| | | return uId == userId || String(uId) === String(userId); |
| | | }); |
| | | displayUserName.value = user ? (user.nickName || user.nickname || user.userName || user.name) : ''; |
| | | } else { |
| | | displayUserName.value = ''; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | watch( |
| | | () => form.value.equipmentId, |
| | | (equipmentId) => { |
| | | if (equipmentId) { |
| | | const equipment = equipmentList.value.find(e => { |
| | | const eId = e.id || e.equipmentId; |
| | | return eId == equipmentId || String(eId) === String(equipmentId); |
| | | }); |
| | | displayEquipmentName.value = equipment ? (equipment.equipmentName || equipment.name) : ''; |
| | | } else { |
| | | displayEquipmentName.value = ''; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | watch( |
| | | () => form.value.consumables, |
| | | (consumables) => { |
| | | if (consumables === true || consumables === 'true' || consumables === 1) { |
| | | displayConsumables.value = 'æ¯'; |
| | | } else if (consumables === false || consumables === 'false' || consumables === 0) { |
| | | displayConsumables.value = 'å¦'; |
| | | } else { |
| | | displayConsumables.value = ''; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // ç¨æ·éæ© |
| | | const onUserSelect = (item) => { |
| | | const userId = item.value || item.userId || item.id; |
| | | form.value.userId = userId; |
| | | // ç«å³æ´æ°æ¾ç¤ºææ¬ |
| | | const user = userList.value.find(u => { |
| | | const uId = u.userId || u.id; |
| | | return uId == userId || String(uId) === String(userId); |
| | | }); |
| | | displayUserName.value = user ? (user.nickName || user.nickname || user.userName || user.name) : ''; |
| | | showUserPicker.value = false; |
| | | // éæ©ç¨æ·åè·å设å¤å表 |
| | | getEquipment(); |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.validateField('userId'); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 设å¤éæ© |
| | | const onEquipmentSelect = (item) => { |
| | | const equipmentId = item.value || item.id || item.equipmentId; |
| | | form.value.equipmentId = equipmentId; |
| | | // ç«å³æ´æ°æ¾ç¤ºææ¬ |
| | | const equipment = equipmentList.value.find(e => { |
| | | const eId = e.id || e.equipmentId; |
| | | return eId == equipmentId || String(eId) === String(equipmentId); |
| | | }); |
| | | displayEquipmentName.value = equipment ? (equipment.equipmentName || equipment.name) : ''; |
| | | showEquipmentPicker.value = false; |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.validateField('equipmentId'); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¶èåéæ© |
| | | const onConsumablesSelect = (item) => { |
| | | const consumables = item.value !== undefined ? item.value : (item.name === 'æ¯' ? true : false); |
| | | form.value.consumables = consumables; |
| | | // ç«å³æ´æ°æ¾ç¤ºææ¬ |
| | | displayConsumables.value = consumables ? 'æ¯' : 'å¦'; |
| | | showConsumablesPicker.value = false; |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.validateField('consumables'); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // é¢ç¨æ°éåå |
| | | const onUsageQuantityChange = (value) => { |
| | | // ç¡®ä¿å¼æ¯æ°åç±»å |
| | | form.value.usageQuantity = Number(value) || 1; |
| | | // 触åéªè¯ |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.validateField('usageQuantity'); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // è·å设å¤å表 |
| | | const equipmentList = ref([]); |
| | | // è·åææ°æ°æ® |
| | | const getEquipment = async () => { |
| | | try { |
| | | const res = await getEquipmentList(); |
| | | if (res.code === 200) { |
| | | equipmentList.value = res.data || res.rows || []; |
| | | console.log('设å¤å表è·åæå:', equipmentList.value); |
| | | } else { |
| | | showToast("è·å设å¤å表失败", 'error'); |
| | | } |
| | | } catch (error) { |
| | | console.error("è·å设å¤å表失败:", error); |
| | | showToast("è·å设å¤å表失败", 'error'); |
| | | } |
| | | }; |
| | | const props = defineProps({ |
| | | modelValue: Boolean, |
| | | formData: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | addOrEdit: { |
| | | type: String, |
| | | default: "add", |
| | | }, |
| | | }); |
| | | |
| | | // é»è®¤è¡¨ååå§å¼ |
| | | const defaultForm = { |
| | | userId: "", |
| | | equipmentId: "", |
| | | consumables: false, |
| | | usageQuantity: 1, |
| | | usageStartTime: "", |
| | | returnQuantity: 1, |
| | | returnTime: "", |
| | | remarks: "", |
| | | }; |
| | | const form = ref({ ...defaultForm }); |
| | | |
| | | const maxQuantity = computed(() => { |
| | | if (!form.value.equipmentId) return 0; |
| | | const eq = equipmentList.value.find( |
| | | (item) => item.id == form.value.equipmentId |
| | | ); |
| | | // 鲿¢ä¸º0æè´æ°ï¼æå°ä¸º1 |
| | | return eq && eq.quantity > 0 ? eq.quantity : 999; |
| | | }); |
| | | const emit = defineEmits(["update:modelValue", "submit"]); |
| | | |
| | | const visible = computed({ |
| | | get: () => { |
| | | console.log('å¼¹çª visible get:', props.modelValue); |
| | | return props.modelValue; |
| | | }, |
| | | set: (v) => { |
| | | console.log('å¼¹çª visible set:', v); |
| | | emit("update:modelValue", v); |
| | | }, |
| | | }); |
| | | |
| | | // çå¬ modelValue åå |
| | | watch( |
| | | () => props.modelValue, |
| | | (newVal) => { |
| | | console.log('å¼¹çª modelValue åå:', newVal); |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // çå¬è®¾å¤éæ©åå |
| | | watch( |
| | | () => form.value.equipmentId, |
| | | (newId) => { |
| | | if (newId) { |
| | | const eq = equipmentList.value.find(item => item.id == newId); |
| | | } |
| | | } |
| | | ); |
| | | const isViewMode = computed( |
| | | () => props.addOrEdit === "view" || props.addOrEdit === "viewRow" |
| | | ); |
| | | |
| | | // 夿æ¯å¦ä¸ºå½è¿æ¨¡å¼ |
| | | const isReturnMode = computed(() => props.addOrEdit === "return"); |
| | | |
| | | // 计ç®å©ä½å¯å½è¿æ°é |
| | | const remainingReturnQuantity = computed(() => { |
| | | if (!isReturnMode.value || !props.formData.usageQuantity) return 0; |
| | | |
| | | const totalUsageQuantity = props.formData.usageQuantity || 0; // æ»ä½¿ç¨æ°é |
| | | const alreadyReturnedQuantity = props.formData.totalReturnNo || 0; // å·²å½è¿æ°é |
| | | const remaining = totalUsageQuantity - alreadyReturnedQuantity; // å©ä½å¯å½è¿æ°é |
| | | |
| | | return Math.max(0, remaining); // ç¡®ä¿ä¸ä¸ºè´æ° |
| | | }); |
| | | |
| | | const isEdit = computed(() => !!props.formData?.id); |
| | | const formRef = ref(); |
| | | |
| | | // æ¥æéæ©å¨ |
| | | const showDatePickerVisible = ref(false); |
| | | const datePickerValue = ref(Date.now()); |
| | | const currentDateField = ref(''); |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = (field) => { |
| | | if (isViewMode.value) return; |
| | | currentDateField.value = field; |
| | | if (form.value[field]) { |
| | | datePickerValue.value = new Date(form.value[field]).getTime(); |
| | | } else { |
| | | datePickerValue.value = Date.now(); |
| | | } |
| | | showDatePickerVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥æç¡®è®¤ |
| | | const onDateConfirm = (e) => { |
| | | const date = new Date(e.value); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | form.value[currentDateField.value] = `${year}-${month}-${day}`; |
| | | showDatePickerVisible.value = false; |
| | | }; |
| | | |
| | | // è·åå½åæ¥æï¼YYYY-MM-DDæ ¼å¼ï¼ |
| | | const getCurrentDate = () => { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); |
| | | const month = String(now.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(now.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | }; |
| | | |
| | | // ç¡®ä¿åå§åæ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | fetchUserList(); |
| | | getEquipment(); |
| | | }); |
| | | |
| | | |
| | | // æ è®°æ¯å¦å·²ç»åå§åï¼é¿å
watch è¦çç¨æ·éæ© |
| | | const isInitialized = ref(false); |
| | | |
| | | watch( |
| | | () => props.formData, |
| | | (val) => { |
| | | // åªå¨åå§åæ¶æè
formData æå®é
ååæ¶ææ´æ° |
| | | if (!isInitialized.value) { |
| | | if (val && Object.keys(val).length > 0) { |
| | | // åå¹¶ç°æå¼ï¼é¿å
è¦çç¨æ·å·²éæ©çå¼ |
| | | form.value = { ...defaultForm, ...val }; |
| | | |
| | | // å½è¿æ¨¡å¼åå§å |
| | | if (isReturnMode.value) { |
| | | form.value.returnTime = getCurrentDate(); |
| | | const maxReturnQuantity = remainingReturnQuantity.value; |
| | | form.value.returnQuantity = |
| | | maxReturnQuantity > 0 ? Math.min(1, maxReturnQuantity) : 0; |
| | | } |
| | | } else { |
| | | form.value = { ...defaultForm }; |
| | | } |
| | | isInitialized.value = true; |
| | | console.log('formData watch åå§åï¼form.value:', form.value); |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // çå¬å¼¹çªæå¼ï¼éç½®åå§åæ è®°å¹¶è·åæ°æ® |
| | | watch( |
| | | () => props.modelValue, |
| | | (newVal) => { |
| | | if (newVal) { |
| | | // å¼¹çªæå¼æ¶éç½®åå§åæ è®°ï¼å
许 formData watch éæ°åå§å |
| | | isInitialized.value = false; |
| | | // å¼¹çªæå¼æ¶éæ°è·åæ°æ® |
| | | if (userList.value.length === 0) { |
| | | fetchUserList(); |
| | | } |
| | | if (equipmentList.value.length === 0) { |
| | | getEquipment(); |
| | | } |
| | | } else { |
| | | // å¼¹çªå
³éæ¶éç½® |
| | | isInitialized.value = false; |
| | | } |
| | | } |
| | | ); |
| | | |
| | | const rules = computed(() => { |
| | | const baseRules = { |
| | | userId: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©é¢ç¨äºº", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!form.value.userId) { |
| | | callback(new Error("è¯·éæ©é¢ç¨äºº")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | equipmentId: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©è®¾å¤åç§°", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!form.value.equipmentId) { |
| | | callback(new Error("è¯·éæ©è®¾å¤åç§°")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | consumables: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©æ¯å¦ä¸ºæ¶èå", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (form.value.consumables === undefined || form.value.consumables === null || form.value.consumables === '') { |
| | | callback(new Error("è¯·éæ©æ¯å¦ä¸ºæ¶èå")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | }; |
| | | |
| | | if (isReturnMode.value) { |
| | | // å½è¿æ¨¡å¼çéªè¯è§å |
| | | return { |
| | | ...baseRules, |
| | | returnQuantity: [ |
| | | { required: true, message: "请è¾å
¥å½è¿æ°é", trigger: "blur" }, |
| | | { type: "number", min: 1, message: "è³å°å½è¿1å°", trigger: "blur" }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | const remaining = remainingReturnQuantity.value; |
| | | if (remaining <= 0) { |
| | | callback(new Error("å·²å
¨é¨å½è¿ï¼æ æ³ç»§ç»å½è¿")); |
| | | } else if (value > remaining) { |
| | | callback( |
| | | new Error(`å½è¿æ°éä¸è½å¤§äºå©ä½å¯å½è¿æ°é(${remaining}å°)`) |
| | | ); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | returnTime: [ |
| | | { required: true, message: "è¯·éæ©å½è¿æ¶é´", trigger: "change" }, |
| | | ], |
| | | }; |
| | | } else { |
| | | // æ°å¢/ç¼è¾æ¨¡å¼çéªè¯è§å |
| | | return { |
| | | ...baseRules, |
| | | usageQuantity: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥é¢ç¨æ°é", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | const numValue = Number(value) || 0; |
| | | if (!value && value !== 0) { |
| | | callback(new Error("请è¾å
¥é¢ç¨æ°é")); |
| | | } else if (numValue < 1) { |
| | | callback(new Error("è³å°é¢ç¨1å°")); |
| | | } else if (maxQuantity.value !== null && numValue > maxQuantity.value) { |
| | | callback(new Error("é¢ç¨æ°éä¸è½å¤§äºè®¾å¤æ°é")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | }, |
| | | ], |
| | | usageStartTime: [ |
| | | { required: true, message: "è¯·éæ©å¼å§æ¶é´", trigger: "change" }, |
| | | ], |
| | | }; |
| | | } |
| | | }); |
| | | |
| | | function handleClose() { |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // éç¨é²æå½æ° |
| | | function debounce(fn, delay = 800) { |
| | | let timer = null; |
| | | return function (...args) { |
| | | if (timer) clearTimeout(timer); |
| | | timer = setTimeout(() => { |
| | | fn.apply(this, args); |
| | | timer = null; |
| | | }, delay); |
| | | }; |
| | | } |
| | | |
| | | // 鲿åçæäº¤æ¹æ³ |
| | | const debouncedSubmit = debounce(handleSubmit, 800); |
| | | |
| | | function handleSubmit() { |
| | | formRef.value.validate(async (valid) => { |
| | | if (!valid) return; |
| | | |
| | | let submitData = { ...form.value }; |
| | | |
| | | // å½è¿æ¨¡å¼å¤ç |
| | | if (isReturnMode.value) { |
| | | const currentReturnQuantity = form.value.returnQuantity; |
| | | const totalUsageQuantity = props.formData.usageQuantity; |
| | | const alreadyReturnedQuantity = props.formData.totalReturnNo || 0; |
| | | const newTotalReturnedQuantity = |
| | | alreadyReturnedQuantity + currentReturnQuantity; |
| | | |
| | | // 夿æ¯å¦å
¨é¨å½è¿å®æ |
| | | let equipmentStatus = 2; // é»è®¤ä¸ºé¨åå½è¿ |
| | | let isFullyReturned = newTotalReturnedQuantity >= totalUsageQuantity; |
| | | |
| | | if (isFullyReturned) { |
| | | equipmentStatus = 3; // å
¨é¨å½è¿å®æ |
| | | |
| | | // å
¨é¨å½è¿æ¶ç确认æç¤º |
| | | try { |
| | | const result = await showModal({ |
| | | title: '确认å
¨é¨å½è¿', |
| | | content: `确认å°è®¾å¤"${props.formData.equipmentName || 'æªç¥è®¾å¤'}"å
¨é¨å½è¿åï¼å½è¿å设å¤ç¶æå°å为"å·²å½è¿"ã`, |
| | | confirmText: '确认å½è¿', |
| | | cancelText: 'åæ¶', |
| | | type: 'success' |
| | | }); |
| | | |
| | | if (!result) { |
| | | showToast('已忶å½è¿æä½', 'info'); |
| | | return; |
| | | } |
| | | } catch (error) { |
| | | showToast('已忶å½è¿æä½', 'info'); |
| | | return; |
| | | } |
| | | |
| | | console.log("设å¤å½è¿å®æ:", { |
| | | 设å¤åç§°: props.formData.equipmentName, |
| | | æ»ä½¿ç¨æ°é: totalUsageQuantity, |
| | | æ°çå½è¿æ»æ°: newTotalReturnedQuantity, |
| | | ç¶æ: "å·²å
¨é¨å½è¿", |
| | | }); |
| | | } else { |
| | | console.log("设å¤é¨åå½è¿:", { |
| | | 设å¤åç§°: props.formData.equipmentName, |
| | | æ»ä½¿ç¨æ°é: totalUsageQuantity, |
| | | å·²å½è¿æ°é: newTotalReturnedQuantity, |
| | | å©ä½æªå½è¿: totalUsageQuantity - newTotalReturnedQuantity, |
| | | ç¶æ: "é¨åå½è¿", |
| | | }); |
| | | } |
| | | |
| | | submitData = { |
| | | ...props.formData, |
| | | totalReturnNo: newTotalReturnedQuantity, |
| | | returnQuantity: currentReturnQuantity, |
| | | returnTime: form.value.returnTime, |
| | | equipmentStatus: equipmentStatus, |
| | | remarks: form.value.remarks, |
| | | usageQuantity: totalUsageQuantity, |
| | | }; |
| | | } |
| | | |
| | | try { |
| | | let { code, data } = await addOrEditUsageRecord(submitData); |
| | | if (code !== 200) { |
| | | showToast(data.msg || "æä½å¤±è´¥", 'error'); |
| | | return; |
| | | } |
| | | if (code == 200 && data == 1) { |
| | | emit("submit", submitData); |
| | | } |
| | | handleClose(); |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast("æä½å¤±è´¥ï¼è¯·ç¨ååè¯", 'error'); |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | |
| | | .popup-content { |
| | | width: 90vw; |
| | | max-width: 500px; |
| | | background-color: #fff; |
| | | border-radius: 10px; |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | max-height: 80vh; |
| | | } |
| | | |
| | | .popup-header { |
| | | padding: 20px; |
| | | text-align: center; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .popup-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .form-scroll { |
| | | flex: 1; |
| | | max-height: calc(80vh - 140px); |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .popup-footer { |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 15px 20px; |
| | | border-top: 1px solid #f0f0f0; |
| | | background-color: #fafafa; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .number-box-wrapper { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | width: 100%; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .info-text { |
| | | font-size: 12px; |
| | | color: #999; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .tip-text { |
| | | font-size: 12px; |
| | | color: #2979ff; |
| | | margin-top: 8px; |
| | | padding: 8px 12px; |
| | | background: #f0f7ff; |
| | | border-radius: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <u-popup |
| | | v-model="dialogVisible" |
| | | :title="addOrEdit === 'edit' ? 'ç¼è¾' : 'æ°å¢' + '设å¤'" |
| | | mode="center" |
| | | :close-on-click-overlay="false" |
| | | :before-close="handleClose" |
| | | :border-radius="20" |
| | | width="90%" |
| | | > |
| | | <u-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | label-width="auto" |
| | | > |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="设å¤ç¼å·" prop="equipmentNo"> |
| | | <u-input |
| | | v-model="formData.equipmentNo" |
| | | placeholder="请è¾å
¥è®¾å¤ç¼å·" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="设å¤åç§°" prop="equipmentName"> |
| | | <u-input |
| | | v-model="formData.equipmentName" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="æ¯å¦ä¸ºèæ" prop="consumables"> |
| | | <u-select |
| | | v-model="formData.consumables" |
| | | :list="consumablesOptions" |
| | | placeholder="è¯·éæ©æ¯å¦ä¸ºèæ" |
| | | :disabled="isViewMode" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="è§æ ¼åå·" prop="specification"> |
| | | <u-input |
| | | v-model="formData.specification" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="åæ¾ä½ç½®" prop="storageLocation"> |
| | | <u-input |
| | | v-model="formData.storageLocation" |
| | | placeholder="请è¾å
¥åæ¾ä½ç½®" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="éè´ä»·æ ¼" prop="purchasePrice"> |
| | | <u-input |
| | | v-model="formData.purchasePrice" |
| | | placeholder="请è¾å
¥éè´ä»·æ ¼" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | type="number" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="éè´æ¥æ" prop="purchaseDate"> |
| | | <u-datetime-picker |
| | | v-model="formData.purchaseDate" |
| | | mode="date" |
| | | placeholder="è¯·éæ©éè´æ¥æ" |
| | | :disabled="isViewMode" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <u-button @click="cancelForm" type="default" size="normal">åæ¶</u-button> |
| | | <u-button v-if="!isViewMode" @click="submitForm" type="primary" size="normal">ç¡®å®</u-button> |
| | | </view> |
| | | </u-form> |
| | | </u-popup> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, watch, computed, reactive } from "vue"; |
| | | import { addOrEditEquipment } from "@/api/equipment/management/index.js"; |
| | | import { useToast } from "@/utils/uviewplus"; |
| | | |
| | | const { showToast } = useToast(); |
| | | |
| | | const props = defineProps({ |
| | | beforeClose: { |
| | | type: Function, |
| | | default: () => {}, |
| | | }, |
| | | form: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | addOrEdit: { |
| | | type: String, |
| | | default: "add", |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: "", |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["submit", "handleBeforeClose"]); |
| | | |
| | | // 计ç®å±æ§ï¼ç»ä¸æ§å¶æ¯å¦ç¦ç¨ |
| | | const isViewMode = computed(() => props.addOrEdit === "viewRow"); |
| | | |
| | | // 表åå¼ç¨åæ°æ® |
| | | const formRef = ref(null); |
| | | const formData = ref({}); |
| | | const copyForm = defineModel("copyForm", { |
| | | required: true, |
| | | type: Object, |
| | | default: () => ({}), |
| | | }); |
| | | |
| | | // å¼¹çªå¯è§æ§ |
| | | const dialogVisible = defineModel("managementFormDialog", { |
| | | required: true, |
| | | type: Boolean, |
| | | }); |
| | | |
| | | // èæé项 |
| | | const consumablesOptions = reactive([ |
| | | { label: "æ¯", value: "1" }, |
| | | { label: "å¦", value: "0" } |
| | | ]); |
| | | |
| | | // çå¬å¤é¨ä¼ å
¥çè¡¨åæ°æ®ååï¼åå¹¶çå¬é»è¾ |
| | | watch( |
| | | [() => props.form, () => props.addOrEdit], |
| | | ([newForm, newAddOrEdit]) => { |
| | | formData.value = { ...newForm }; |
| | | }, |
| | | { deep: true, immediate: true } |
| | | ); |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | |
| | | try { |
| | | const valid = await formRef.value.validate(); |
| | | if (!valid) return; |
| | | |
| | | const result = await addOrEditEquipment({ ...formData.value }); |
| | | const title = props.title.includes("æ°å¢") ? "æ°å¢" : "ç¼è¾"; |
| | | |
| | | if (result.code === 200 && result.msg) { |
| | | showToast({ title: `${title}æåï¼${result.msg}`, type: 'success' }); |
| | | emit("submit", { title, ...formData.value, result }); |
| | | closeDialog(); |
| | | } else { |
| | | showToast({ title: `${title}失败ï¼${result.msg}`, type: 'error' }); |
| | | } |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast({ title: "æäº¤å¤±è´¥ï¼è¯·éè¯", type: 'error' }); |
| | | } |
| | | }; |
| | | |
| | | // å
³éå¼¹çªçç»ä¸æ¹æ³ |
| | | const closeDialog = () => { |
| | | emit("update:managementFormDialog", false); |
| | | formData.value = {}; |
| | | }; |
| | | |
| | | // åæ¶è¡¨å |
| | | const cancelForm = () => { |
| | | closeDialog(); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | if (!formRef.value) return; |
| | | formData.value = JSON.parse(JSON.stringify(copyForm.value)); |
| | | }; |
| | | |
| | | // å
³éå¼¹çª |
| | | const handleClose = () => { |
| | | emit("handleBeforeClose"); |
| | | closeDialog(); |
| | | }; |
| | | |
| | | const rules = reactive({ |
| | | equipmentNo: [ |
| | | { required: true, message: "请è¾å
¥è®¾å¤ç¼å·", trigger: "blur" }, |
| | | ], |
| | | equipmentName: [ |
| | | { required: true, message: "请è¾å
¥è®¾å¤åç§°", trigger: "blur" }, |
| | | ], |
| | | consumables: [ |
| | | { required: true, message: "è¯·éæ©æ¯å¦ä¸ºèæ", trigger: "change" }, |
| | | ], |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .form-row { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .form-col { |
| | | flex: 1; |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | .form-col:last-child { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-top: 40rpx; |
| | | flex-direction: row; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | // å¼¹çªæ ·å¼éé
|
| | | :deep(.u-popup__content) { |
| | | padding: 30rpx; |
| | | } |
| | | |
| | | :deep(.u-form-item) { |
| | | margin-bottom: 20rpx; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <u-popup |
| | | v-model="dialogVisible" |
| | | :title="addOrEdit === 'edit' ? 'ç¼è¾' : 'æ°å¢' + '设å¤'" |
| | | mode="center" |
| | | :close-on-click-overlay="false" |
| | | :before-close="handleClose" |
| | | :border-radius="20" |
| | | width="90%" |
| | | > |
| | | <u-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | label-width="auto" |
| | | > |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="设å¤ç¼å·" prop="equipmentId"> |
| | | <u-input |
| | | v-model="formData.equipmentId" |
| | | placeholder="请è¾å
¥è®¾å¤ç¼å·" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="设å¤åç§°" prop="equipmentName"> |
| | | <u-input |
| | | v-model="formData.equipmentName" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="æ°é" prop="quantity"> |
| | | <u-input |
| | | v-model="formData.quantity" |
| | | placeholder="请è¾å
¥æ°é" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | type="number" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="è§æ ¼åå·" prop="specification"> |
| | | <u-input |
| | | v-model="formData.specification" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="使ç¨ç¶æ" prop="usageStatus"> |
| | | <u-select |
| | | v-model="formData.usageStatus" |
| | | :list="usageStatusOptions" |
| | | placeholder="è¯·éæ©ä½¿ç¨ç¶æ" |
| | | :disabled="isViewMode" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="åæ¾ä½ç½®" prop="storageLocation"> |
| | | <u-input |
| | | v-model="formData.storageLocation" |
| | | placeholder="请è¾å
¥åæ¾ä½ç½®" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="form-row"> |
| | | <view class="form-col"> |
| | | <u-form-item label="éè´ä»·æ ¼" prop="purchasePrice"> |
| | | <u-input |
| | | v-model="formData.purchasePrice" |
| | | placeholder="请è¾å
¥éè´ä»·æ ¼" |
| | | :disabled="isViewMode" |
| | | border="surround" |
| | | type="number" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | <view class="form-col"> |
| | | <u-form-item label="éè´æ¥æ" prop="purchaseDate"> |
| | | <u-datetime-picker |
| | | v-model="formData.purchaseDate" |
| | | mode="date" |
| | | placeholder="è¯·éæ©éè´æ¥æ" |
| | | :disabled="isViewMode" |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <u-button v-if="!isViewMode" @click="cancelForm" type="default" size="normal">åæ¶</u-button> |
| | | <u-button v-if="!isViewMode" @click="submitForm" type="primary" size="normal">ç¡®å®</u-button> |
| | | </view> |
| | | </u-form> |
| | | </u-popup> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, watch, computed, reactive } from "vue"; |
| | | import { addOrEditEquipment } from "@/api/equipment/management/index.js"; |
| | | import { useToast } from "@/utils/uviewplus"; |
| | | |
| | | const { showToast } = useToast(); |
| | | |
| | | const props = defineProps({ |
| | | beforeClose: { |
| | | type: Function, |
| | | default: () => {}, |
| | | }, |
| | | form: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | addOrEdit: { |
| | | type: String, |
| | | default: "add", |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: "", |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["submit", "handleBeforeClose"]); |
| | | |
| | | // 计ç®å±æ§ï¼ç»ä¸æ§å¶æ¯å¦ç¦ç¨ |
| | | const isViewMode = computed(() => props.addOrEdit === "viewRow"); |
| | | |
| | | // 表åå¼ç¨åæ°æ® |
| | | const formRef = ref(null); |
| | | const formData = ref({}); |
| | | const copyForm = defineModel("copyForm", { |
| | | required: true, |
| | | type: Object, |
| | | default: () => ({}), |
| | | }); |
| | | |
| | | // å¼¹çªå¯è§æ§ |
| | | const dialogVisible = defineModel("managementFormDialog", { |
| | | required: true, |
| | | type: Boolean, |
| | | }); |
| | | |
| | | // 使ç¨ç¶æé项 |
| | | const usageStatusOptions = reactive([ |
| | | { label: "å¯ç¨", value: "1" }, |
| | | { label: "ç¦ç¨", value: "0" } |
| | | ]); |
| | | |
| | | // çå¬å¤é¨ä¼ å
¥çè¡¨åæ°æ®ååï¼åå¹¶çå¬é»è¾ |
| | | watch( |
| | | [() => props.form, () => props.addOrEdit], |
| | | ([newForm, newAddOrEdit]) => { |
| | | formData.value = { ...newForm }; |
| | | }, |
| | | { deep: true, immediate: true } |
| | | ); |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | |
| | | try { |
| | | const valid = await formRef.value.validate(); |
| | | if (!valid) return; |
| | | |
| | | const result = await addOrEditEquipment({ ...formData.value }); |
| | | const title = props.title.includes("æ°å¢") ? "æ°å¢" : "ç¼è¾"; |
| | | |
| | | if (result.code === 200 && result.msg) { |
| | | showToast({ title: `${title}æåï¼${result.msg}`, type: 'success' }); |
| | | emit("submit", { title, ...formData.value, result }); |
| | | closeDialog(); |
| | | } else { |
| | | showToast({ title: `${title}失败ï¼${result.msg}`, type: 'error' }); |
| | | } |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast({ title: "æäº¤å¤±è´¥ï¼è¯·éè¯", type: 'error' }); |
| | | } |
| | | }; |
| | | |
| | | // å
³éå¼¹çªçç»ä¸æ¹æ³ |
| | | const closeDialog = () => { |
| | | emit("update:managementFormDialog", false); |
| | | formData.value = {}; |
| | | }; |
| | | |
| | | // åæ¶è¡¨å |
| | | const cancelForm = () => { |
| | | closeDialog(); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | if (!formRef.value) return; |
| | | formData.value = JSON.parse(JSON.stringify(copyForm.value)); |
| | | }; |
| | | |
| | | // å
³éå¼¹çª |
| | | const handleClose = () => { |
| | | emit("handleBeforeClose"); |
| | | closeDialog(); |
| | | }; |
| | | |
| | | const rules = reactive({ |
| | | equipmentId: [ |
| | | { required: true, message: "请è¾å
¥è®¾å¤ç¼å·", trigger: "blur" }, |
| | | ], |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .form-row { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .form-col { |
| | | flex: 1; |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | .form-col:last-child { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-top: 40rpx; |
| | | flex-direction: row; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | // å¼¹çªæ ·å¼éé
|
| | | :deep(.u-popup__content) { |
| | | padding: 30rpx; |
| | | } |
| | | |
| | | :deep(.u-form-item) { |
| | | margin-bottom: 20rpx; |
| | | } |
| | | </style> |
| | |
| | | import {logout, getInfo, loginCheckFactory} from "@/api/login"; |
| | | import {logout, getInfo, login} from "@/api/login"; |
| | | import { getToken, setToken, removeToken } from "@/utils/auth"; |
| | | import defAva from "@/static/images/profile.jpg"; |
| | | import { defineStore } from "pinia"; |
| | |
| | | }), |
| | | actions: { |
| | | // é¨é¨ç»å½ |
| | | loginCheckFactory(userInfo: any) { |
| | | login(userInfo: any) { |
| | | const userName = userInfo.userName |
| | | const password = userInfo.password |
| | | const factoryId = userInfo.factoryId |
| | | return new Promise((resolve, reject) => { |
| | | loginCheckFactory(userName, password, factoryId).then((res: any) => { |
| | | login(userName, password, factoryId).then((res: any) => { |
| | | setToken(res.token) |
| | | this.token = res.token |
| | | resolve(null) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * uview-plus å·¥å
·å½æ°å°è£
|
| | | * æä¾ç»ä¸çæç¤ºåæ¨¡ææ¡å·¥å
· |
| | | */ |
| | | |
| | | /** |
| | | * ä½¿ç¨ Toast æç¤ºå·¥å
· |
| | | * @returns {{showToast: function}} |
| | | */ |
| | | export const useToast = () => { |
| | | /** |
| | | * æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | * @param {string} message æç¤ºæ¶æ¯ |
| | | * @param {string} [type='info'] æç¤ºç±»åï¼'success' | 'error' | 'warning' | 'info' |
| | | * @param {number} [duration=2000] æ¾ç¤ºæ¶é¿ï¼æ¯«ç§ï¼ |
| | | */ |
| | | const showToast = (message, type = 'info', duration = 2000) => { |
| | | // æ å° uview-plus ç徿 ç±»å |
| | | const iconMap = { |
| | | success: 'success', |
| | | error: 'error', |
| | | warning: 'warning', |
| | | info: 'info' |
| | | }; |
| | | |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: iconMap[type] || 'none', |
| | | duration: duration |
| | | }); |
| | | }; |
| | | |
| | | return { |
| | | showToast |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * ä½¿ç¨ Modal æ¨¡ææ¡å·¥å
· |
| | | * @returns {{showModal: function}} |
| | | */ |
| | | export const useModal = () => { |
| | | /** |
| | | * æ¾ç¤ºç¡®è®¤æ¨¡ææ¡ |
| | | * @param {Object} options é
ç½®é项 |
| | | * @param {string} options.title æ é¢ |
| | | * @param {string} options.content å
容 |
| | | * @param {boolean} [options.showCancel=true] æ¯å¦æ¾ç¤ºåæ¶æé® |
| | | * @param {string} [options.confirmText='确认'] 确认æé®ææ¬ |
| | | * @param {string} [options.cancelText='åæ¶'] åæ¶æé®ææ¬ |
| | | * @returns {Promise<boolean>} ç¨æ·ç¡®è®¤ç»æ |
| | | */ |
| | | const showModal = (options) => { |
| | | return new Promise((resolve) => { |
| | | uni.showModal({ |
| | | title: options.title || 'æç¤º', |
| | | content: options.content || '', |
| | | showCancel: options.showCancel !== false, |
| | | confirmText: options.confirmText || '确认', |
| | | cancelText: options.cancelText || 'åæ¶', |
| | | success: (res) => { |
| | | resolve(res.confirm); |
| | | }, |
| | | fail: () => { |
| | | resolve(false); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | return { |
| | | showModal |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * é»è®¤å¯¼åº |
| | | */ |
| | | export default { |
| | | useToast, |
| | | useModal |
| | | }; |