From ac00bb7b8eae1bf6aabb7f1ae67c2e5aa5b8ae90 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 12 六月 2026 10:21:12 +0800
Subject: [PATCH] 宝东 1.样式问题
---
src/views/productionManagement/workOrderEdit/index.vue | 649 +++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 459 insertions(+), 190 deletions(-)
diff --git a/src/views/productionManagement/workOrderEdit/index.vue b/src/views/productionManagement/workOrderEdit/index.vue
index b919973..ead2c1f 100644
--- a/src/views/productionManagement/workOrderEdit/index.vue
+++ b/src/views/productionManagement/workOrderEdit/index.vue
@@ -1,20 +1,29 @@
<template>
<div class="app-container">
- <div class="search_form">
+ <div class="search_form mb20">
<div class="search-row">
<div class="search-item">
- <span class="search_title">宸ュ崟缂栧彿锛�</span>
- <el-input v-model="searchForm.workOrderNo"
- style="width: 240px"
+ <span class="search_title">鐢熶骇璁㈠崟鍙凤細</span>
+ <el-input v-model="searchForm.npsNo"
+ style="width: 200px"
placeholder="璇疯緭鍏�"
@change="handleQuery"
clearable
prefix-icon="Search" />
</div>
<div class="search-item">
- <span class="search_title">鐢熶骇璁㈠崟鍙凤細</span>
- <el-input v-model="searchForm.productOrderNpsNo"
- style="width: 240px"
+ <span class="search_title">浜у搧鍚嶇О锛�</span>
+ <el-input v-model="searchForm.productName"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ prefix-icon="Search" />
+ </div>
+ <div class="search-item">
+ <span class="search_title">瑙勬牸锛�</span>
+ <el-input v-model="searchForm.model"
+ style="width: 200px"
placeholder="璇疯緭鍏�"
@change="handleQuery"
clearable
@@ -27,18 +36,124 @@
</div>
</div>
<div class="table_list">
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :tableLoading="tableLoading"
- @pagination="pagination">
- <template #completionStatus="{ row }">
- <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
- :color="progressColor(toProgressPercentage(row?.completionStatus))"
- :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
- </template>
- </PIMTable>
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.productionOrderId"
+ @expand-change="expandChange"
+ style="width: 100%"
+ height="calc(100vh - 18.5em)">
+ <el-table-column type="expand"
+ width="60"
+ fixed="left">
+ <template #default="props">
+ <el-table :data="props.row.children"
+ border
+ v-loading="props.row.childrenLoading">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="宸ュ崟绫诲瀷"
+ prop="workOrderType"
+ width="80" />
+ <el-table-column label="宸ュ崟缂栧彿"
+ prop="workOrderNo"
+ width="140"
+ show-overflow-tooltip />
+ <el-table-column label="宸ュ簭鍚嶇О"
+ prop="operationName"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="闇�姹傛暟閲�"
+ prop="planQuantity"
+ width="100" />
+ <el-table-column label="瀹屾垚鏁伴噺"
+ prop="completeQuantity"
+ width="100" />
+ <el-table-column label="瀹屾垚杩涘害"
+ width="140"
+ align="center">
+ <template #default="{ row }">
+ <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
+ :color="progressColor(toProgressPercentage(row?.completionStatus))"
+ :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
+ </template>
+ </el-table-column>
+ <el-table-column label="璁″垝寮�濮嬫椂闂�"
+ prop="planStartTime"
+ width="120" />
+ <el-table-column label="璁″垝缁撴潫鏃堕棿"
+ prop="planEndTime"
+ width="120" />
+ <el-table-column label="瀹為檯寮�濮嬫椂闂�"
+ prop="actualStartTime"
+ width="120" />
+ <el-table-column label="瀹為檯缁撴潫鏃堕棿"
+ prop="actualEndTime"
+ width="120" />
+ <el-table-column label="鎸囧畾鎶ュ伐浜�"
+ prop="userNames"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="鎿嶄綔"
+ width="210"
+ align="center"
+ fixed="right">
+ <template #default="{ row }">
+ <el-button link
+ type="primary"
+ @click="handleEdit(row)">璁″垝鏃堕棿</el-button>
+ <el-button link
+ type="primary"
+ @click="handleAssignReporter(row)">鎸囧畾鎶ュ伐浜�</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </template>
+ </el-table-column>
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="鐢熶骇璁㈠崟鍙�"
+ prop="npsNo"
+ width="160"
+ show-overflow-tooltip />
+ <el-table-column label="浜у搧鍚嶇О"
+ prop="productName"
+ width="140"
+ show-overflow-tooltip />
+ <el-table-column label="瑙勬牸"
+ prop="model"
+ show-overflow-tooltip />
+ <el-table-column label="宸ュ簭鍚嶇О"
+ prop="operationName"
+ minWidth="160"
+ show-overflow-tooltip />
+ <el-table-column label="璁″垝鏁伴噺"
+ prop="planQuantity"
+ width="100" />
+ <el-table-column label="瀹屾垚鏁伴噺"
+ prop="completeQuantity"
+ width="100" />
+ <el-table-column label="瀹屾垚杩涘害"
+ width="140"
+ align="center">
+ <template #default="{ row }">
+ <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
+ :color="progressColor(toProgressPercentage(row?.completionStatus))"
+ :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="page.total > 0"
+ :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
</div>
<el-dialog v-model="editDialogVisible"
title="缂栬緫璁″垝鏃堕棿"
@@ -68,205 +183,359 @@
</span>
</template>
</el-dialog>
+ <!-- 鎸囧畾鎶ュ伐浜哄脊绐� -->
+ <el-dialog v-model="assignReporterDialogVisible"
+ title="鎸囧畾鎶ュ伐浜�"
+ width="800px">
+ <div class="assign-reporter-content">
+ <div class="selected-tags-box"
+ v-if="selectedEmployeeIds.length > 0">
+ <div class="tags-label">宸查�夋嫨锛�</div>
+ <div class="tags-list">
+ <el-tag v-for="id in selectedEmployeeIds"
+ :key="id"
+ closable
+ @close="removeEmployeeTag(id)"
+ class="employee-tag">
+ {{ getEmployeeNameById(id) }}
+ </el-tag>
+ </div>
+ </div>
+ <div class="employee-list-container"
+ v-loading="employeeTableLoading">
+ <el-checkbox-group v-model="selectedEmployeeIds">
+ <div class="employee-grid">
+ <div v-for="item in employeeTableData"
+ :key="item.userId"
+ class="employee-item">
+ <el-checkbox :label="item.userId"
+ border>
+ <div class="employee-info">
+ <span class="name">{{ item.nickName }}</span>
+ <span class="dept">{{ item.dept?.deptName }}</span>
+ </div>
+ </el-checkbox>
+ </div>
+ </div>
+ </el-checkbox-group>
+ <div v-if="employeeTableData.length === 0"
+ class="empty-text">
+ 鏆傛棤鍖归厤浜哄憳
+ </div>
+ </div>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button type="primary"
+ @click="handleSaveReporters">纭畾</el-button>
+ <el-button @click="assignReporterDialogVisible = false">鍙栨秷</el-button>
+ </span>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
- import { getCurrentInstance, onMounted, reactive, ref, toRefs } from "vue";
- import { ElMessageBox } from "element-plus";
- import {
- productWorkOrderPage,
- updateProductWorkOrder,
- } from "@/api/productionManagement/workOrder.js";
+import { getCurrentInstance, onMounted, reactive, ref, toRefs } from "vue";
+import { ElMessageBox } from "element-plus";
+import {
+ productWorkOrderPage,
+ updateProductWorkOrder,
+ assignProductWorkOrder,
+ getWorkOrdersByOrderId,
+} from "@/api/productionManagement/workOrder.js";
+import { listUser } from "@/api/system/user.js";
+import pagination from "@/components/PIMTable/Pagination.vue";
- const { proxy } = getCurrentInstance();
+const { proxy } = getCurrentInstance();
- const tableColumn = ref([
- {
- label: "宸ュ崟绫诲瀷",
- prop: "workOrderType",
- width: "80",
- },
- {
- label: "宸ュ崟缂栧彿",
- prop: "workOrderNo",
- width: "140",
- },
- {
- label: "鐢熶骇璁㈠崟鍙�",
- prop: "npsNo",
- width: "140",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- width: "140",
- },
- {
- label: "瑙勬牸",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "宸ュ簭鍚嶇О",
- prop: "operationName",
- width: "100",
- },
- {
- label: "闇�姹傛暟閲�",
- prop: "planQuantity",
- width: "140",
- },
- {
- label: "瀹屾垚鏁伴噺",
- prop: "completeQuantity",
- width: "140",
- },
- {
- label: "瀹屾垚杩涘害",
- prop: "completionStatus",
- dataType: "slot",
- slot: "completionStatus",
- width: "140",
- },
- {
- label: "璁″垝寮�濮嬫椂闂�",
- prop: "planStartTime",
- width: "140",
- },
- {
- label: "璁″垝缁撴潫鏃堕棿",
- prop: "planEndTime",
- width: "140",
- },
- {
- label: "瀹為檯寮�濮嬫椂闂�",
- prop: "actualStartTime",
- width: "140",
- },
- {
- label: "瀹為檯缁撴潫鏃堕棿",
- prop: "actualEndTime",
- width: "140",
- },
- {
- label: "鎿嶄綔",
- width: "100",
- align: "center",
- dataType: "action",
- fixed: "right",
- operation: [
- {
- name: "璁″垝鏃堕棿",
- clickFun: row => {
- handleEdit(row);
- },
- },
- ],
- },
- ]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const expandedRowKeys = ref([]);
+const editDialogVisible = ref(false);
+const editrow = ref(null);
+const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+});
- const tableData = ref([]);
- const tableLoading = ref(false);
- const editDialogVisible = ref(false);
- const editrow = ref(null);
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
+// 鎸囧畾鎶ュ伐浜虹浉鍏�
+const assignReporterDialogVisible = ref(false);
+const employeeTableLoading = ref(false);
+const employeeTableData = ref([]);
+const employeePage = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const employeeSearchForm = reactive({
+ staffName: "",
+});
+const selectedEmployeeIds = ref([]);
+const currentWorkOrder = ref(null);
- const data = reactive({
- searchForm: {
- workOrderNo: "",
- productOrderNpsNo: "",
- },
- });
- const { searchForm } = toRefs(data);
+const data = reactive({
+ searchForm: {
+ npsNo: "",
+ productName: "",
+ model: "",
+ },
+});
+const { searchForm } = toRefs(data);
- const toProgressPercentage = val => {
- const n = Number(val);
- if (!Number.isFinite(n)) return 0;
- if (n <= 0) return 0;
- if (n >= 100) return 100;
- return Math.round(n);
- };
+const toProgressPercentage = val => {
+ const n = Number(val);
+ if (!Number.isFinite(n)) return 0;
+ if (n <= 0) return 0;
+ if (n >= 100) return 100;
+ return parseFloat(n.toFixed(2));
+};
- const progressColor = percentage => {
- const p = toProgressPercentage(percentage);
- if (p < 30) return "#f56c6c";
- if (p < 50) return "#e6a23c";
- if (p < 80) return "#409eff";
- return "#67c23a";
- };
+const progressColor = percentage => {
+ const p = toProgressPercentage(percentage);
+ if (p < 30) return "#f56c6c";
+ if (p < 50) return "#e6a23c";
+ if (p < 80) return "#409eff";
+ return "#67c23a";
+};
- const handleQuery = () => {
- page.current = 1;
- getList();
- };
+const handleQuery = () => {
+ page.current = 1;
+ expandedRowKeys.value = [];
+ getList();
+};
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
+const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ expandedRowKeys.value = [];
+ getList();
+};
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- productWorkOrderPage(params)
+const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, current: page.current, size: page.size };
+ productWorkOrderPage(params)
+ .then(res => {
+ tableLoading.value = false;
+ const records = res.data.records || [];
+ records.forEach(item => {
+ item.children = [];
+ item.childrenLoading = false;
+ });
+ tableData.value = records;
+ page.total = res.data.total;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+};
+
+const expandChange = (row, expandedRows) => {
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
+ row.childrenLoading = true;
+ getWorkOrdersByOrderId(row.productionOrderId)
.then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- page.total = res.data.total;
+ row.childrenLoading = false;
+ const idx = tableData.value.findIndex(
+ item => item.productionOrderId === row.productionOrderId
+ );
+ if (idx > -1) {
+ tableData.value[idx].children = res.data || [];
+ }
+ expandedRowKeys.value.push(row.productionOrderId);
})
.catch(() => {
- tableLoading.value = false;
+ row.childrenLoading = false;
});
- };
+ } else {
+ expandedRowKeys.value = [];
+ }
+};
- const handleEdit = row => {
- editrow.value = JSON.parse(JSON.stringify(row));
- editDialogVisible.value = true;
- };
+const handleEdit = row => {
+ editrow.value = JSON.parse(JSON.stringify(row));
+ editDialogVisible.value = true;
+};
- const handleUpdate = () => {
- updateProductWorkOrder(editrow.value)
- .then(() => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- editDialogVisible.value = false;
- getList();
- })
- .catch(() => {
- ElMessageBox.alert("淇敼澶辫触", "鎻愮ず", {
- confirmButtonText: "纭畾",
- });
+const handleUpdate = () => {
+ updateProductWorkOrder(editrow.value)
+ .then(() => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ editDialogVisible.value = false;
+ getList();
+ })
+ .catch(() => {
+ ElMessageBox.alert("淇敼澶辫触", "鎻愮ず", {
+ confirmButtonText: "纭畾",
});
+ });
+};
+
+const handleAssignReporter = row => {
+ currentWorkOrder.value = row;
+ assignReporterDialogVisible.value = true;
+ if (row.userIds) {
+ try {
+ selectedEmployeeIds.value = JSON.parse(row.userIds);
+ } catch (e) {
+ selectedEmployeeIds.value = [];
+ }
+ } else {
+ selectedEmployeeIds.value = [];
+ }
+ employeeSearchForm.staffName = "";
+ getEmployeeList();
+};
+
+const getEmployeeList = () => {
+ employeeTableLoading.value = true;
+ const params = {
+ pageNum: 1,
+ pageSize: 100,
+ };
+ listUser(params)
+ .then(res => {
+ employeeTableLoading.value = false;
+ employeeTableData.value = res.rows;
+ employeePage.total = res.total;
+ })
+ .catch(() => {
+ employeeTableLoading.value = false;
+ });
+};
+
+const getEmployeeNameById = id => {
+ const employee = employeeTableData.value.find(item => item.userId === id);
+ return employee ? employee.nickName : id;
+};
+
+const removeEmployeeTag = id => {
+ selectedEmployeeIds.value = selectedEmployeeIds.value.filter(
+ item => item !== id
+ );
+};
+
+const handleSaveReporters = () => {
+ if (selectedEmployeeIds.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鎶ュ伐浜�");
+ return;
+ }
+
+ const updateData = {
+ id: currentWorkOrder.value.id,
+ userIds: JSON.stringify(selectedEmployeeIds.value),
};
- onMounted(() => {
- getList();
- });
+ assignProductWorkOrder(updateData)
+ .then(() => {
+ proxy.$modal.msgSuccess("鎸囧畾鎴愬姛");
+ assignReporterDialogVisible.value = false;
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鎸囧畾澶辫触");
+ });
+};
+
+onMounted(() => {
+ getList();
+});
</script>
<style scoped lang="scss">
- .search-row {
+.search-row {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+.search-item {
+ display: flex;
+ align-items: center;
+}
+.search_title {
+ margin-right: 8px;
+ font-size: 14px;
+ color: #606266;
+}
+.assign-reporter-content {
+ .selected-tags-box {
+ margin-bottom: 16px;
+ padding: 12px;
+ background-color: #f5f7fa;
+ border-radius: 4px;
display: flex;
- align-items: center;
- gap: 12px;
+ align-items: flex-start;
+
+ .tags-label {
+ font-size: 14px;
+ color: #606266;
+ margin-right: 8px;
+ white-space: nowrap;
+ margin-top: 4px;
+ }
+
+ .tags-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+
+ .employee-tag {
+ margin-bottom: 4px;
+ }
+ }
}
- .search-item {
- display: flex;
- align-items: center;
- }
+ .employee-list-container {
+ max-height: 400px;
+ overflow-y: auto;
+ padding: 10px;
+ border: 1px solid #f0f0f0;
+ border-radius: 4px;
- .search_title {
- margin-right: 8px;
- font-size: 14px;
- color: #606266;
+ .employee-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
+ gap: 12px;
+ }
+
+ .employee-item {
+ :deep(.el-checkbox) {
+ width: 100%;
+ margin-right: 0;
+ height: auto;
+ padding: 8px;
+
+ .el-checkbox__label {
+ width: 100%;
+ }
+ }
+
+ .employee-info {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ .name {
+ font-weight: bold;
+ font-size: 14px;
+ color: #303133;
+ }
+
+ .dept {
+ font-size: 12px;
+ color: #909399;
+ }
+ }
+ }
+
+ .empty-text {
+ text-align: center;
+ color: #909399;
+ padding: 20px;
+ }
}
+}
</style>
--
Gitblit v1.9.3