From 89469f566f4ad8602def16aef6744d205a3d20a8 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 29 十二月 2025 14:32:54 +0800
Subject: [PATCH] 昭德app需求修改
---
src/pages/index.vue | 427 --------
src/pages/management/mould/equipmentRequisitionDialog.vue | 826 ++++++++++++++++
src/api/login.js | 31
src/pages.json | 2
src/api/equipment/requisition/index.js | 32
src/api/publicApi/index.js | 42
src/pages/management/index.vue | 675 +++++++++++++
src/pages/management/mould/managementDialog.vue | 260 +++++
src/api/equipment/management/index.js | 32
src/store/modules/user.ts | 6
src/pages/management/mould/usageRecord.vue | 265 +++++
src/pages/login.vue | 43
src/utils/uviewplus.js | 82 +
src/config.js | 4
src/hooks/useDelete.js | 167 +++
15 files changed, 2,415 insertions(+), 479 deletions(-)
diff --git a/src/api/equipment/management/index.js b/src/api/equipment/management/index.js
new file mode 100644
index 0000000..f64bff1
--- /dev/null
+++ b/src/api/equipment/management/index.js
@@ -0,0 +1,32 @@
+// 璁惧绠$悊
+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
+ })
+}
diff --git a/src/api/equipment/requisition/index.js b/src/api/equipment/requisition/index.js
new file mode 100644
index 0000000..3ba406d
--- /dev/null
+++ b/src/api/equipment/requisition/index.js
@@ -0,0 +1,32 @@
+// 璁惧绠$悊
+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'
+ })
+}
\ No newline at end of file
diff --git a/src/api/login.js b/src/api/login.js
index acf6978..7b7388f 100644
--- a/src/api/login.js
+++ b/src/api/login.js
@@ -1,14 +1,28 @@
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
},
@@ -33,11 +47,14 @@
})
}
-// 鑾峰彇鍏徃鍒楄〃
-export function userLoginFacotryList(params) {
+// 鑾峰彇楠岃瘉鐮�
+export function getCodeImg() {
return request({
- url: '/userLoginFacotryList',
+ url: '/captchaImage',
+ headers: {
+ isToken: false
+ },
method: 'get',
- params: params
+ timeout: 20000
})
}
\ No newline at end of file
diff --git a/src/api/publicApi/index.js b/src/api/publicApi/index.js
new file mode 100644
index 0000000..8022592
--- /dev/null
+++ b/src/api/publicApi/index.js
@@ -0,0 +1,42 @@
+// 鏂囨。绠$悊
+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
+ })
+}
\ No newline at end of file
diff --git a/src/config.js b/src/config.js
index 135cce3..aa24173 100644
--- a/src/config.js
+++ b/src/config.js
@@ -2,9 +2,7 @@
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',
// 搴旂敤淇℃伅
diff --git a/src/hooks/useDelete.js b/src/hooks/useDelete.js
new file mode 100644
index 0000000..5ab9595
--- /dev/null
+++ b/src/hooks/useDelete.js
@@ -0,0 +1,167 @@
+/**
+ * 閫氱敤鍒犻櫎鍔熻兘缁勫悎寮忓嚱鏁帮紙APP鐗堟湰锛�
+ * 鎻愪緵缁熶竴鐨勫垹闄ょ‘璁ゃ�丄PI璋冪敤銆佹暟鎹洿鏂伴�昏緫锛岄�傞厤uni-app鍜寀viewplus
+ */
+import { useToast } from "@/utils/uviewplus";
+
+/**
+ * 鍒涘缓鍒犻櫎鍔熻兘
+ * @param {Object} options 閰嶇疆閫夐」
+ * @param {Function|Function} options.deleteApi 鍒犻櫎API鍑芥暟鎴栬繑鍥濧PI鍑芥暟鐨勫嚱鏁�
+ * @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;
+
+ /**
+ * 鑾峰彇瀹為檯鐨勫垹闄PI鍑芥暟
+ * 鏀寔鐩存帴浼犲叆鍑芥暟鎴栬繑鍥炲嚱鏁扮殑鍑芥暟
+ */
+ 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 鑷畾涔夎鍒犻櫎鐨処D鏁扮粍锛屽鏋滀笉浼犲垯浣跨敤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鐨剆howModal鏇夸唬Element Plus鐨凪essageBox
+ 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);
+
+ // 鑾峰彇褰撳墠鐨勫垹闄PI鍑芥暟
+ 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
+ };
+}
\ No newline at end of file
diff --git a/src/pages.json b/src/pages.json
index 4151447..641b21e 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -296,7 +296,7 @@
}
},
{
- "path": "pages/equipmentManagement/ledger/index",
+ "path": "pages/management/index",
"style": {
"navigationBarTitleText": "璁惧鍙拌处",
"navigationStyle": "custom"
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 9bd3452..8784ee5 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -1,156 +1,16 @@
<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">
@@ -186,7 +46,6 @@
<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";
@@ -214,245 +73,25 @@
}, 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 '璁惧鎶ヤ慨':
@@ -470,26 +109,6 @@
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}`,
@@ -501,43 +120,6 @@
// 鍒涘缓瀵瑰瓙缁勪欢鐨勫紩鐢�
const uToastRef = ref(null);
-function getUserLoginFacotryList() {
- userLoginFacotryList({userName: userStore.nickName}).then(res => {
- // 妫�鏌es.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'
@@ -554,7 +136,6 @@
onMounted(() => {
// 璁剧疆鐢ㄦ埛淇℃伅
userStore.getInfo()
- getUserLoginFacotryList()
// 鍚姩閫氱煡鐘舵�佸畾鏃跺櫒
startStatusTimer()
});
diff --git a/src/pages/login.vue b/src/pages/login.vue
index 860fd09..c4eafd9 100644
--- a/src/pages/login.vue
+++ b/src/pages/login.vue
@@ -6,22 +6,10 @@
<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>
@@ -50,7 +38,6 @@
icon: 'none'
})
}
-import { userLoginFacotryList} from '@/api/login'
import { ref, onMounted } from "vue";
import useUserStore from '@/store/modules/user'
import { getWxCode } from '@/utils/geek';
@@ -63,7 +50,6 @@
const loginForm = ref({
userName: "",
password: "",
- factoryId: "",
currentFatoryName: "",
});
const factoryList = ref([]) // 鍏徃鍒楄〃
@@ -109,37 +95,11 @@
})
}
-function getUserLoginFacotryList() {
- if(loginForm.value.userName){
- userLoginFacotryList({userName:loginForm.value.userName}).then(res => {
- console.log('res',res)
- // 妫�鏌es.data鏄惁涓烘暟缁�
- if (res.data && Array.isArray(res.data)) {
- // 閲嶆柊缁勮鏁版嵁鏍煎紡锛歞eptId鍙樻垚id锛宒eptName鍙樻垚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()
@@ -147,7 +107,7 @@
};
// 瀵嗙爜鐧诲綍
async function pwdLogin() {
- userStore.loginCheckFactory(loginForm.value).then(() => {
+ userStore.login(loginForm.value).then(() => {
modal.closeLoading()
// 鐧诲綍鎴愬姛鍚庝繚瀛樺瘑鐮�
savePassword();
@@ -168,7 +128,6 @@
// 椤甸潰鍔犺浇鏃舵鏌ユ槸鍚︽湁淇濆瓨鐨勫瘑鐮�
onMounted(() => {
loadPassword();
- getUserLoginFacotryList()
});
</script>
diff --git a/src/pages/management/index.vue b/src/pages/management/index.vue
new file mode 100644
index 0000000..3adfbd2
--- /dev/null
+++ b/src/pages/management/index.vue
@@ -0,0 +1,675 @@
+<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'; // 鐏拌壊
+ }
+};
+
+// 鍝嶅簲寮忕姸鎬佺鐞� - 浣跨敤瑙f瀯鍜岄粯璁ゅ��
+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: "",
+ },
+});
+
+// 浣跨敤瑙f瀯绠�鍖栬闂�
+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闇�瑕乶ame浣滀负鏄剧ず鏂囨湰
+const tabs = computed(() =>
+ Object.entries(tabsConfig).map(([name, config]) => ({
+ name: config.label, // 浣跨敤label浣滀负鏄剧ず鏂囨湰
+ value: name, // 淇濆瓨鍘熷name鍊�
+ }))
+);
+
+// 褰撳墠鏍囩椤电储寮� - 浣跨敤ref鑰屼笉鏄痗omputed锛岀‘淇濆搷搴斿紡鏇存柊
+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('鍑嗗鎵撳紑寮圭獥锛宔quipmentRequisitionDialog褰撳墠鍊�:', equipmentRequisitionDialog.value);
+ equipmentRequisitionDialog.value = true;
+ console.log('寮圭獥宸叉墦寮�锛宔quipmentRequisitionDialog鏂板��:', 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('瑙f瀽鍚庣殑鏁版嵁:', 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>
diff --git a/src/pages/management/mould/equipmentRequisitionDialog.vue b/src/pages/management/mould/equipmentRequisitionDialog.vue
new file mode 100644
index 0000000..bae484b
--- /dev/null
+++ b/src/pages/management/mould/equipmentRequisitionDialog.vue
@@ -0,0 +1,826 @@
+<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;
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡锛圷YYY-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>
diff --git a/src/pages/management/mould/managementDialog.vue b/src/pages/management/mould/managementDialog.vue
new file mode 100644
index 0000000..178c0f2
--- /dev/null
+++ b/src/pages/management/mould/managementDialog.vue
@@ -0,0 +1,260 @@
+<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>
\ No newline at end of file
diff --git a/src/pages/management/mould/usageRecord.vue b/src/pages/management/mould/usageRecord.vue
new file mode 100644
index 0000000..8806b85
--- /dev/null
+++ b/src/pages/management/mould/usageRecord.vue
@@ -0,0 +1,265 @@
+<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>
\ No newline at end of file
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
index 969943c..009366d 100644
--- a/src/store/modules/user.ts
+++ b/src/store/modules/user.ts
@@ -1,4 +1,4 @@
-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";
@@ -26,12 +26,12 @@
}),
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)
diff --git a/src/utils/uviewplus.js b/src/utils/uviewplus.js
new file mode 100644
index 0000000..e06d472
--- /dev/null
+++ b/src/utils/uviewplus.js
@@ -0,0 +1,82 @@
+/**
+ * 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
+};
\ No newline at end of file
--
Gitblit v1.9.3