| src/api/productionManagement/processManagement.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/productionDesign/processManagement/edit.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/productionDesign/processManagement/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/productionDesign/processManagement/params.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/works.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/productionManagement/processManagement.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,80 @@ import request from "@/utils/request"; export function getProcessList(query) { return request({ url: "/technologyOperation/listPage", method: "get", params: query, }); } export function add(data) { return request({ url: "/technologyOperation/add", method: "post", data: data, }); } export function update(data) { return request({ url: "/technologyOperation/update", method: "put", data: data, }); } export function del(ids) { return request({ url: "/technologyOperation/batchDelete", method: "delete", data: ids, }); } export function getProcessParamList(params) { return request({ url: "/technologyOperationParam/list", method: "get", params, }); } export function addProcessParam(data) { return request({ url: "/technologyOperationParam/", method: "post", data: data, }); } export function editProcessParam(data) { return request({ url: "/technologyOperationParam/", method: "post", data: data, }); } export function deleteProcessParam(id) { return request({ url: `/technologyOperationParam/batchDelete/${id}`, method: "delete", }); } export function getDeviceLedger(query) { return request({ url: "/device/ledger/getDeviceLedger", method: "get", params: query, }); } export function getBaseParamList(query) { return request({ url: "/technologyParam/list", method: "get", params: query, }); } src/pages.json
@@ -381,6 +381,27 @@ } }, { "path": "pages/productionDesign/processManagement/index", "style": { "navigationBarTitleText": "å·¥åºç®¡ç", "navigationStyle": "custom" } }, { "path": "pages/productionDesign/processManagement/edit", "style": { "navigationBarTitleText": "å·¥åºè¯¦æ ", "navigationStyle": "custom" } }, { "path": "pages/productionDesign/processManagement/params", "style": { "navigationBarTitleText": "å·¥åºåæ°é ç½®", "navigationStyle": "custom" } }, { "path": "pages/cooperativeOffice/collaborativeApproval/index1", "style": { "navigationBarTitleText": "å ¬åºç®¡ç", src/pages/productionDesign/processManagement/edit.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,236 @@ <template> <view class="process-edit"> <PageHeader :title="pageTitle" @back="goBack" /> <up-form ref="formRef" :model="form" :rules="rules" :errorType="['none']" label-width="110"> <up-form-item label="å·¥åºç¼ç " prop="no"> <up-input v-model="form.no" placeholder="请è¾å ¥å·¥åºç¼ç " clearable /> </up-form-item> <up-form-item label="å·¥åºåç§°" prop="name" required> <up-input v-model="form.name" placeholder="请è¾å ¥å·¥åºåç§°" clearable /> </up-form-item> <up-form-item label="å·¥èµå®é¢" prop="salaryQuota"> <up-input v-model="form.salaryQuota" type="number" placeholder="请è¾å ¥å·¥èµå®é¢" clearable /> </up-form-item> <up-form-item label="计费类å" prop="type"> <up-input v-model="typeText" placeholder="è¯·éæ©è®¡è´¹ç±»å" readonly @click="showTypeSheet = true" /> <template #right> <up-icon name="arrow-right" @click="showTypeSheet = true"></up-icon> </template> </up-form-item> <up-form-item label="æ¯å¦è´¨æ£" prop="isQuality"> <view style="display: flex; justify-content: flex-end; width: 100%;"> <up-switch v-model="form.isQuality" /> </view> </up-form-item> <up-form-item label="æ¯å¦ç产" prop="isProduction"> <view style="display: flex; justify-content: flex-end; width: 100%;"> <up-switch v-model="form.isProduction" /> </view> </up-form-item> <up-form-item label="å ³è设å¤" prop="deviceLedgerId"> <up-input v-model="deviceText" placeholder="è¯·éæ©å ³è设å¤" readonly @click="showDeviceSheet = true" /> <template #right> <up-icon name="arrow-right" @click="showDeviceSheet = true"></up-icon> </template> </up-form-item> <up-form-item label="å·¥åºæè¿°" prop="remark"> <up-textarea v-model="form.remark" placeholder="请è¾å ¥å·¥åºæè¿°" autoHeight /> </up-form-item> </up-form> <FooterButtons :loading="loading" :confirmText="processId ? 'ä¿å' : 'æ°å¢'" @cancel="goBack" @confirm="handleSubmit" /> <!-- 计费类åéæ© --> <up-action-sheet :show="showTypeSheet" title="éæ©è®¡è´¹ç±»å" :actions="typeActions" @select="onSelectType" @close="showTypeSheet = false" /> <!-- 设å¤éæ© --> <up-action-sheet :show="showDeviceSheet" title="éæ©å ³è设å¤" :actions="deviceActions" @select="onSelectDevice" @close="showDeviceSheet = false" /> </view> </template> <script setup> import { reactive, ref, computed, onMounted } from "vue"; import { onLoad, onReady } from "@dcloudio/uni-app"; import FooterButtons from "@/components/FooterButtons.vue"; import { add, update, getDeviceLedger, } from "@/api/productionManagement/processManagement"; const formRef = ref(null); const loading = ref(false); const processId = ref(null); const pageTitle = computed(() => (processId.value ? "ç¼è¾å·¥åº" : "æ°å¢å·¥åº")); const form = ref({ no: "", name: "", salaryQuota: "", isQuality: false, isProduction: false, remark: "", deviceLedgerId: null, type: 0, }); const rules = { name: [{ required: true, message: "请è¾å ¥å·¥åºåç§°" }], salaryQuota: [ { validator: (rule, value, callback) => { if (value !== "" && value !== null && (isNaN(value) || value < 0)) { callback(new Error("å·¥èµå®é¢å¿ é¡»æ¯éè´æ°å")); } else { callback(); } }, }, ], }; const showTypeSheet = ref(false); const typeActions = [ { name: "计æ¶", value: 0 }, { name: "计件", value: 1 }, ]; const typeText = computed(() => { const action = typeActions.find(a => a.value === form.value.type); return action ? action.name : ""; }); const showDeviceSheet = ref(false); const deviceActions = ref([]); const deviceText = ref(""); const onSelectType = e => { form.value.type = e.value; showTypeSheet.value = false; }; const onSelectDevice = e => { form.value.deviceLedgerId = e.id; deviceText.value = e.name; showDeviceSheet.value = false; }; const loadDevices = async () => { try { const { data } = await getDeviceLedger(); deviceActions.value = (data || []).map(item => ({ name: item.deviceName, id: item.id, })); if (form.value.deviceLedgerId) { const device = deviceActions.value.find( d => d.id === Number(form.value.deviceLedgerId) ); if (device) deviceText.value = device.name; } } catch (error) { console.error("å 载设å¤å¤±è´¥", error); } }; const goBack = () => { uni.navigateBack(); }; const handleSubmit = () => { formRef.value .validate() .then(() => { loading.value = true; const promise = processId.value ? update(form.value) : add(form.value); promise .then(() => { uni.showToast({ title: processId.value ? "ä¿åæå" : "æ°å¢æå" }); setTimeout(() => { goBack(); }, 1500); }) .catch(err => { uni.showToast({ title: err.msg || "æäº¤å¤±è´¥", icon: "error" }); }) .finally(() => { loading.value = false; }); }) .catch(errors => { if (errors && errors.length > 0) { uni.showToast({ title: errors[0].message, icon: "none", }); } }); }; onLoad(option => { if (option.item) { const item = JSON.parse(decodeURIComponent(option.item)); processId.value = item.id; Object.assign(form.value, item); // å¤çç±»å转æ¢ï¼ç¡®ä¿æ¯æ°å form.value.type = Number(form.value.type); form.value.isQuality = !!form.value.isQuality; form.value.isProduction = !!form.value.isProduction; } }); onReady(() => { formRef.value.setRules(rules); }); onMounted(() => { loadDevices(); }); </script> <style scoped lang="scss"> @import "@/static/scss/form-common.scss"; .process-edit { min-height: 100vh; background: #f5f5f5; } </style> src/pages/productionDesign/processManagement/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,261 @@ <template> <view class="sales-account"> <PageHeader title="å·¥åºç®¡ç" @back="goBack" /> <view class="search-section"> <view class="search-bar"> <view class="search-input"> <up-input class="search-text" v-model="queryParams.name" placeholder="请è¾å ¥å·¥åºåç§°" clearable @change="handleSearch" /> </view> <view class="filter-button" @click="handleSearch"> <up-icon name="search" size="24" color="#999999"></up-icon> </view> </view> </view> <view v-if="list.length > 0" class="ledger-list"> <view v-for="item in list" :key="item.id" class="ledger-item"> <view class="item-header"> <view class="item-left"> <view class="document-icon"> <up-icon name="list-dot" size="16" color="#ffffff"></up-icon> </view> <text class="item-id">{{ item.name || "-" }}</text> </view> <text class="item-index">{{ item.no || "-" }}</text> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">å ³è设å¤</text> <text class="detail-value">{{ getDeviceName(item.deviceLedgerId) }}</text> </view> <view class="detail-row"> <text class="detail-label">å·¥èµå®é¢</text> <text class="detail-value highlight">Â¥{{ item.salaryQuota || 0 }}</text> </view> <view class="detail-row"> <text class="detail-label">å·¥åºç¶æ</text> <view class="detail-value"> <up-tag :text="item.isQuality ? 'è´¨æ£' : 'éè´¨æ£'" :type="item.isQuality ? 'warning' : 'info'" size="mini" style="margin-left: 8rpx" /> <up-tag :text="item.isProduction ? 'ç产' : 'ä¸ç产'" :type="item.isProduction ? 'warning' : 'info'" size="mini" style="margin-left: 8rpx" /> <up-tag v-if="item.type !== null && item.type !== undefined" :text="item.type == 0 ? '计æ¶' : '计件'" :type="item.type == 1 ? 'primary' : 'success'" size="mini" style="margin-left: 8rpx" /> </view> </view> <view class="detail-row"> <text class="detail-label">夿³¨</text> <text class="detail-value">{{ item.remark || "-" }}</text> </view> </view> <view class="action-buttons"> <up-button class="action-btn" size="small" type="primary" @click="goEdit(item)">ç¼è¾</up-button> <up-button class="action-btn" size="small" type="warning" @click="goParams(item)">åæ°é ç½®</up-button> <up-button class="action-btn" size="small" type="error" @click="handleDelete(item)">å é¤</up-button> </view> </view> <up-loadmore :status="pageStatus" /> </view> <view v-else class="no-data"> <text>ææ å·¥åºæ°æ®</text> </view> <view class="fab-button" @click="goAdd"> <up-icon name="plus" size="28" color="#ffffff"></up-icon> </view> </view> </template> <script setup> import { reactive, ref } from "vue"; import { onReachBottom, onShow } from "@dcloudio/uni-app"; import { getProcessList, del, getDeviceLedger, } from "@/api/productionManagement/processManagement"; const queryParams = reactive({ name: "", }); const list = ref([]); const deviceOptions = ref([]); const pageStatus = ref("loadmore"); const page = reactive({ current: 1, size: 10, total: 0, }); const goBack = () => { uni.navigateBack(); }; const getDeviceName = deviceId => { if (!deviceId) return "æªå ³è"; const device = deviceOptions.value.find(item => item.id === Number(deviceId)); return device?.deviceName || "æªå ³è"; }; const loadDevices = async () => { try { const { data } = await getDeviceLedger(); deviceOptions.value = data || []; } catch (error) { console.error("å 载设å¤å表失败", error); } }; const handleSearch = () => { page.current = 1; pageStatus.value = "loadmore"; list.value = []; getList(); }; const getList = () => { if (pageStatus.value === "loading" || pageStatus.value === "nomore") return; pageStatus.value = "loading"; getProcessList({ current: page.current, size: page.size, name: queryParams.name, }) .then(res => { const records = res?.data?.records || res?.records || []; const total = res?.data?.total || res?.total || 0; if (page.current === 1) { list.value = records; } else { list.value = [...list.value, ...records]; } page.total = total; if (list.value.length >= total) { pageStatus.value = "nomore"; } else { pageStatus.value = "loadmore"; page.current++; } }) .catch(() => { uni.showToast({ title: "æ¥è¯¢å¤±è´¥", icon: "error" }); pageStatus.value = "loadmore"; }); }; const goAdd = () => { uni.navigateTo({ url: "/pages/productionDesign/processManagement/edit" }); }; const goEdit = item => { uni.navigateTo({ url: `/pages/productionDesign/processManagement/edit?item=${encodeURIComponent( JSON.stringify(item) )}`, }); }; const goParams = item => { uni.navigateTo({ url: `/pages/productionDesign/processManagement/params?id=${item.id}&name=${encodeURIComponent(item.name)}`, }); }; const handleDelete = item => { uni.showModal({ title: "æç¤º", content: "ç¡®å®è¦å é¤è¯¥å·¥åºåï¼", success: res => { if (res.confirm) { del([item.id]).then(() => { uni.showToast({ title: "å 餿å" }); handleSearch(); }); } }, }); }; onReachBottom(() => { getList(); }); onShow(async () => { await loadDevices(); handleSearch(); }); </script> <style scoped lang="scss"> @import "@/styles/procurement-common.scss"; .no-data { padding-top: 100rpx; text-align: center; color: #999; font-size: 28rpx; } .action-buttons { display: flex; justify-content: flex-end; gap: 20rpx; padding-bottom: 30rpx; } .action-btn { flex: 1; margin: 0 !important; } .fab-button { position: fixed; right: 40rpx; bottom: 60rpx; width: 100rpx; height: 100rpx; background: #2979ff; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 4rpx 12rpx rgba(41, 121, 255, 0.4); z-index: 100; } </style> src/pages/productionDesign/processManagement/params.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,413 @@ <template> <view class="process-params"> <PageHeader :title="processName + ' - åæ°é ç½®'" @back="goBack" /> <view class="ledger-list"> <view v-if="paramList.length > 0"> <view v-for="item in paramList" :key="item.id" class="ledger-item"> <view class="item-header"> <view class="item-left"> <view class="document-icon"> <up-icon name="setting-fill" size="16" color="#ffffff"></up-icon> </view> <text class="item-id">{{ item.paramName || "-" }}</text> </view> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">æ åå¼</text> <text class="detail-value highlight">{{ item.standardValue || "-" }}</text> </view> <view class="detail-row"> <text class="detail-label">åä½</text> <text class="detail-value">{{ item.unit || "-" }}</text> </view> <view class="detail-row"> <text class="detail-label">åæ°ç±»å</text> <up-tag :text="getParamTypeText(item.paramType)" :type="getParamTypeTag(item.paramType)" size="mini" /> </view> <view class="detail-row"> <text class="detail-label">å弿 ¼å¼</text> <text class="detail-value">{{ item.paramFormat || "-" }}</text> </view> </view> <view class="action-buttons"> <up-button class="action-btn" size="small" type="primary" @click="handleEditParam(item)">ç¼è¾</up-button> <up-button class="action-btn" size="small" type="error" @click="handleDeleteParam(item)">å é¤</up-button> </view> </view> </view> <view v-else class="no-data"> <up-empty text="ææ åæ°é ç½®" icon="account" iconSize="60"></up-empty> </view> </view> <!-- æµ®å¨æ°å¢æé® --> <view class="fab-button" @click="openSelectModal"> <up-icon name="plus" size="28" color="#ffffff"></up-icon> </view> <!-- éæ©åæ°å¼¹çª --> <up-modal :show="selectModalVisible" title="鿩忰" width="650rpx" @confirm="handleSelectSubmit" @cancel="selectModalVisible = false" :closeOnClickOverlay="false" showCancelButton> <view class="modal-content"> <view class="search-box"> <up-input v-model="searchKeyword" placeholder="æç´¢åºç¡åæ°åç§°" clearable @confirm="handleSearch" @change="handleSearch" /> </view> <scroll-view scroll-y class="param-scroll-list" @scrolltolower="loadMoreParams"> <view v-for="param in availableParams" :key="param.id" class="param-select-item" :class="{ active: selectedBaseParam?.id === param.id }" @click="selectParam(param)"> <view class="param-main"> <text class="param-name">{{ param.paramName }}</text> <up-tag :text="getParamTypeText(param.paramType)" :type="getParamTypeTag(param.paramType)" size="mini" /> </view> <text class="param-code">{{ param.paramCode }}</text> </view> <up-loadmore :status="availablePageStatus" /> </scroll-view> <view v-if="selectedBaseParam" class="standard-input-box"> <text class="label">æ åå¼ï¼</text> <up-input v-model="selectedStandardValue" placeholder="请è¾å ¥è¯¥å·¥åºçæ åå¼" /> </view> </view> </up-modal> <!-- ç¼è¾åæ°æ åå¼å¼¹çª --> <up-modal :show="editModalVisible" title="ç¼è¾æ åå¼" width="500rpx" @confirm="handleEditSubmit" @cancel="editModalVisible = false" :closeOnClickOverlay="false" showCancelButton> <view class="modal-content"> <view class="edit-info"> <text class="edit-label">åæ°ï¼{{ currentEditParam?.paramName }}</text> <up-input v-model="currentEditValue" placeholder="请è¾å ¥æ°çæ åå¼" /> </view> </view> </up-modal> </view> </template> <script setup> import { reactive, ref, onMounted } from "vue"; import { onLoad } from "@dcloudio/uni-app"; import { getProcessParamList, addProcessParam, editProcessParam, deleteProcessParam, getBaseParamList, } from "@/api/productionManagement/processManagement"; const processId = ref(null); const processName = ref(""); const paramList = ref([]); const loading = ref(false); // 鿩忰ç¸å ³ const selectModalVisible = ref(false); const availableParams = ref([]); const searchKeyword = ref(""); const selectedBaseParam = ref(null); const selectedStandardValue = ref(""); const availablePage = reactive({ current: 1, size: 20, total: 0 }); const availablePageStatus = ref("loadmore"); // ç¼è¾åæ°ç¸å ³ const editModalVisible = ref(false); const currentEditParam = ref(null); const currentEditValue = ref(""); const goBack = () => { uni.navigateBack(); }; const getParamList = () => { loading.value = true; getProcessParamList({ technologyOperationId: processId.value }) .then(res => { paramList.value = res?.data || []; }) .catch(() => { uni.showToast({ title: "è·åå表失败", icon: "none" }); }) .finally(() => { loading.value = false; }); }; const openSelectModal = () => { searchKeyword.value = ""; selectedBaseParam.value = null; selectedStandardValue.value = ""; availableParams.value = []; availablePage.current = 1; availablePageStatus.value = "loadmore"; selectModalVisible.value = true; loadAvailableParams(true); }; const handleSearch = () => { availablePage.current = 1; availableParams.value = []; availablePageStatus.value = "loadmore"; loadAvailableParams(true); }; const loadMoreParams = () => { if ( availablePageStatus.value === "nomore" || availablePageStatus.value === "loading" ) return; loadAvailableParams(false); }; const loadAvailableParams = (isReset = false) => { if (availablePageStatus.value === "loading") return; if (isReset) { availablePage.current = 1; availableParams.value = []; availablePageStatus.value = "loading"; } else if (availablePageStatus.value === "nomore") { return; } else { availablePageStatus.value = "loading"; } getBaseParamList({ paramName: searchKeyword.value, current: availablePage.current, size: availablePage.size, }) .then(res => { const records = res?.data?.records || res?.records || []; const total = res?.data?.total || res?.total || 0; if (isReset || availablePage.current === 1) { availableParams.value = records; } else { availableParams.value = [...availableParams.value, ...records]; } availablePage.total = total; if (availableParams.value.length >= total) { availablePageStatus.value = "nomore"; } else { availablePageStatus.value = "loadmore"; availablePage.current++; } }) .catch(() => { availablePageStatus.value = "loadmore"; }); }; const selectParam = param => { selectedBaseParam.value = param; selectedStandardValue.value = param.standardValue || ""; }; const handleSelectSubmit = () => { if (!selectedBaseParam.value) { uni.showToast({ title: "è¯·éæ©ä¸ä¸ªåºç¡åæ°", icon: "none" }); return; } if (!selectedStandardValue.value) { uni.showToast({ title: "请è¾å ¥æ åå¼", icon: "none" }); return; } addProcessParam({ technologyOperationId: processId.value, technologyParamId: selectedBaseParam.value.id, standardValue: selectedStandardValue.value, }) .then(() => { uni.showToast({ title: "æ·»å æå" }); selectModalVisible.value = false; getParamList(); }) .catch(err => { uni.showToast({ title: err.msg || "æ·»å 失败", icon: "error" }); }); }; const handleEditParam = item => { currentEditParam.value = item; currentEditValue.value = item.standardValue; editModalVisible.value = true; }; const handleEditSubmit = () => { if (!currentEditValue.value) { uni.showToast({ title: "请è¾å ¥æ åå¼", icon: "none" }); return; } editProcessParam({ id: currentEditParam.value.id, technologyOperationId: processId.value, technologyParamId: currentEditParam.value.technologyParamId, standardValue: currentEditValue.value, }) .then(() => { uni.showToast({ title: "ä¿®æ¹æå" }); editModalVisible.value = false; getParamList(); }) .catch(err => { uni.showToast({ title: err.msg || "ä¿®æ¹å¤±è´¥", icon: "error" }); }); }; const handleDeleteParam = item => { uni.showModal({ title: "æç¤º", content: "ç¡®å®è¦å é¤è¯¥åæ°é ç½®åï¼", success: res => { if (res.confirm) { deleteProcessParam(item.id).then(() => { uni.showToast({ title: "å 餿å" }); getParamList(); }); } }, }); }; const getParamTypeText = type => { const typeMap = { 1: "æ°å¼", 2: "ææ¬", 3: "䏿", 4: "æ¶é´" }; return typeMap[type] || "æªç¥"; }; const getParamTypeTag = type => { const typeMap = { 1: "primary", 2: "info", 3: "warning", 4: "success" }; return typeMap[type] || "default"; }; onLoad(option => { if (option.id) { processId.value = option.id; processName.value = decodeURIComponent(option.name || ""); getParamList(); } }); </script> <style scoped lang="scss"> @import "@/styles/procurement-common.scss"; .process-params { min-height: 100vh; background: #f5f5f5; } .modal-content { padding: 20rpx 0; width: 100%; } .param-scroll-list { height: 500rpx; margin-top: 20rpx; border: 1px solid #eee; border-radius: 8rpx; } .param-select-item { padding: 20rpx; border-bottom: 1px solid #f5f5f5; width: 100%; &.active { background-color: #e3f2fd; } } .param-main { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8rpx; } .param-name { font-size: 28rpx; font-weight: bold; color: #333; } .param-code { font-size: 24rpx; color: #999; } .standard-input-box { margin-top: 30rpx; display: flex; align-items: center; .label { width: 120rpx; font-size: 28rpx; color: #333; } } .edit-info { .edit-label { display: block; margin-bottom: 20rpx; font-size: 28rpx; color: #666; } } .fab-button { position: fixed; right: 40rpx; bottom: 60rpx; width: 100rpx; height: 100rpx; background: #2979ff; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 4rpx 12rpx rgba(41, 121, 255, 0.4); z-index: 100; } </style> src/pages/works.vue
@@ -996,6 +996,11 @@ url: "/pages/productionDesign/basicParameters/index", }); break; case "å·¥åºç®¡ç": uni.navigateTo({ url: "/pages/productionDesign/processManagement/index", }); break; default: uni.showToast({ title: `ç¹å»äº${item.label}`,