🎈 perf: 处理一些细节问题

This commit is contained in:
砂糖
2025-08-27 16:25:52 +08:00
parent cd822d4296
commit 278b0c8258
12 changed files with 484 additions and 271 deletions

View File

@@ -362,4 +362,8 @@ div.pagination-container {
.el-input--large .el-input__icon {
height: var(--btn-height);
line-height: var(--btn-height);
}
.el-tabs__content {
overflow: visible !important;
}

View File

@@ -0,0 +1,278 @@
<template>
<div class="klp-list-container">
<!-- 列表加载状态 -->
<div v-loading="loading" class="list-loading-wrapper">
<!-- 列表项渲染 -->
<div
v-for="(item, index) in listData"
:key="item[listKey] || index"
class="klp-list-item"
:class="{ 'active': isSelected(item) }"
@click.stop="handleItemClick(item)"
>
<!-- 列表标题区域 - 文字溢出省略+Tooltip -->
<div class="klp-list-title">
<span class="title-label">{{ titleLabel }}</span>
<el-tooltip
:content="item[titleField]"
placement="top"
:disabled="!isContentOverflow(item)"
effect="light"
>
<span class="title-value">{{ item[titleField] }}</span>
</el-tooltip>
</div>
<!-- 右侧操作按钮组 -->
<div class="klp-list-actions">
<slot name="actions" :item="item" :isSelected="isSelected(item)"></slot>
</div>
</div>
<!-- 空状态提示 -->
<div v-if="listData.length === 0 && !loading" class="klp-list-empty">
<el-empty description="暂无数据" />
</div>
</div>
</div>
</template>
<script>
export default {
name: "klp-list",
components: {},
props: {
/** 列表数据源(必传) */
listData: {
type: Array,
required: true,
default: () => []
},
/** 列表项唯一标识字段必传如orderId、id */
listKey: {
type: String,
required: true
},
/** 列表标题前置标签(如"订单编号:" */
titleLabel: {
type: String,
required: true,
default: "标题"
},
/** 列表项标题对应的字段名如orderCode、name */
titleField: {
type: String,
required: true,
default: "title"
},
/** 列表加载状态 */
loading: {
type: Boolean,
required: false,
default: false
},
/** 标题最大宽度(像素),控制文字溢出 */
titleMaxWidth: {
type: Number,
required: false,
default: 200
}
},
data() {
return {
// 内部管理选中状态:存储当前选中项的唯一键值(单选中)
selectedKey: null,
// 文字溢出检测临时元素(避免重复创建)
overflowCheckElements: {}
};
},
methods: {
/**
* 判断当前列表项是否被选中
* @param {Object} item - 列表项数据
* @returns {Boolean} 选中状态
*/
isSelected(item) {
const itemKey = item[this.listKey];
return this.selectedKey === itemKey;
},
/**
* 列表项点击事件:切换选中状态(单选中逻辑)
* @param {Object} item - 点击的列表项数据
*/
handleItemClick(item) {
const itemKey = item[this.listKey];
// 单选中逻辑:点击已选中项取消选中,点击未选中项切换选中(取消其他项)
this.selectedKey = this.selectedKey === itemKey ? null : itemKey;
// 向父组件触发事件传递当前选中项null表示无选中
const selectedItem = this.selectedKey ? item : null;
this.$emit("item-click", selectedItem, item);
},
/**
* 清空选中状态支持父组件通过ref调用
*/
clearSelection() {
this.selectedKey = null;
// 触发清空选中事件
this.$emit("selection-cleared");
},
/**
* 主动设置选中项支持父组件通过ref调用
* @param {String/Number} targetKey - 要选中项的唯一键值
*/
setSelection(targetKey) {
const isExist = this.listData.some(item => item[this.listKey] === targetKey);
if (isExist) {
this.selectedKey = targetKey;
// 触发选中事件
const selectedItem = this.listData.find(item => item[this.listKey] === targetKey);
this.$emit("item-click", selectedItem);
} else {
this.selectedKey = null;
console.warn(`列表中不存在key为${targetKey}的项`);
}
},
/**
* 判断文字是否溢出控制Tooltip显示/隐藏)
* @param {Object} item - 列表项数据
* @returns {Boolean} 是否溢出
*/
isContentOverflow(item) {
const itemKey = item[this.listKey];
const content = item[this.titleField] || "";
// 内容为空时不显示Tooltip
if (!content) return false;
// 创建临时元素测量文字实际宽度(复用元素避免性能问题)
if (!this.overflowCheckElements[itemKey]) {
const tempEl = document.createElement("span");
// 复制title-value的样式确保测量准确
tempEl.style.cssText = `
visibility: hidden;
position: absolute;
white-space: nowrap;
font-size: 14px;
font-weight: 500;
color: #303133;
`;
tempEl.textContent = content;
document.body.appendChild(tempEl);
this.overflowCheckElements[itemKey] = tempEl;
}
// 比较文字实际宽度与设定的最大宽度
const tempEl = this.overflowCheckElements[itemKey];
return tempEl.offsetWidth > this.titleMaxWidth;
}
},
watch: {
/** 列表数据变化时,重置选中状态和溢出检测元素 */
listData: {
deep: true,
handler() {
this.clearSelection();
// 清理临时测量元素
Object.values(this.overflowCheckElements).forEach(el => {
document.body.removeChild(el);
});
this.overflowCheckElements = {};
}
},
/** 标题最大宽度变化时,强制重绘以重新计算溢出 */
titleMaxWidth() {
this.$forceUpdate();
}
},
/** 组件销毁时清理临时元素,避免内存泄漏 */
beforeDestroy() {
Object.values(this.overflowCheckElements).forEach(el => {
document.body.removeChild(el);
});
}
};
</script>
<style scoped>
/* 列表容器基础样式 */
.klp-list-container {
max-height: calc(100vh - 220px);
overflow-y: auto;
padding-right: 8px;
margin-top: 10px;
}
/* 加载状态容器(避免加载时容器塌陷) */
.list-loading-wrapper {
min-height: 100px;
}
/* 列表项样式 */
.klp-list-item {
padding: 6px 8px;
margin-bottom: 6px;
border-bottom: 1px solid #e6e6e6;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
}
/* 列表项选中状态(左侧高亮边框+背景色) */
.klp-list-item.active {
border-left: 3px solid #409eff;
background-color: #f5f7fa;
}
/* 列表标题区域(占满中间空间,让操作按钮靠右) */
.klp-list-title {
display: flex;
align-items: center;
flex: 1;
}
/* 标题前置标签样式 */
.klp-list-title .title-label {
color: #606266;
margin-right: 6px;
font-size: 13px;
white-space: nowrap; /* 标签不换行 */
}
/* 标题内容样式(溢出省略) */
.klp-list-title .title-value {
color: #303133;
font-weight: 500;
font-size: 14px;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号 */
max-width: v-bind(titleMaxWidth + "px"); /* 绑定父组件传入的最大宽度 */
}
/* 操作按钮组(按钮间距控制) */
.klp-list-actions {
display: flex;
align-items: center;
gap: 4px;
}
/* 空状态样式(居中显示) */
.klp-list-empty {
padding: 40px 0;
text-align: center;
}
</style>

View File

@@ -4,10 +4,36 @@
<el-col :span="6">
<div>
<el-row>
<el-input v-model="queryParams.orderCode" placeholder="请输入单据编号" clearable
@keyup.enter.native="handleQuery" />
<el-input
v-model="queryParams.orderCode"
placeholder="请输入单据编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-row>
<el-tree v-loading="orderListLoading" :data="treeData" :props="defaultProps" @node-click="handleNodeClick" />
<!-- 使用klp-list组件替换el-tree -->
<klp-list
v-loading="orderListLoading"
:list-data="orderList"
list-key="orderId"
title-label="订单编号"
title-field="orderCode"
:title-max-width="180"
@item-click="handleItemClick"
>
<!-- 操作按钮插槽 -->
<!-- <template #actions="{ item, isSelected }">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click.stop="handleViewDetail(item)"
title="查看详情"
></el-button>
</template> -->
</klp-list>
<pagination
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@@ -47,14 +73,15 @@
</el-tab-pane>
<el-tab-pane label="应收明细" name="receivable">
<el-table v-loading="rightLoading" :data="currentOrder.receivables" empty-text="暂无数据">
<el-table-column label="应收ID" align="center" prop="receivableId" v-if="false" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column label="订单ID" align="center" prop="orderId" />
<el-table-column label="到期日" align="center" prop="dueDate" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.dueDate, '{y}-{m}-{d}') }}</span>
<el-tag v-if="new Date(scope.row.dueDate) < new Date()" type="danger">过期</el-tag>
<el-tag v-else-if="new Date(scope.row.dueDate) > new Date()" type="success">还剩{{ parseInt((new Date(scope.row.dueDate) - new Date()) / (1000 * 60 * 60 * 24)) }}</el-tag>
<el-tag v-else-if="new Date(scope.row.dueDate) > new Date()" type="success">
还剩{{ parseInt((new Date(scope.row.dueDate) - new Date()) / (1000 * 60 * 60 * 24)) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="应收金额" align="center" prop="amount" />
@@ -66,14 +93,15 @@
</el-tab-pane>
<el-tab-pane label="应付明细" name="payable">
<el-table v-loading="rightLoading" :data="currentOrder.payables" empty-text="暂无数据">
<el-table-column label="应付ID" align="center" prop="payableId" v-if="false" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="订单ID" align="center" prop="orderId" />
<el-table-column label="到期日" align="center" prop="dueDate" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.dueDate, '{y}-{m}-{d}') }}</span>
<el-tag v-if="new Date(scope.row.dueDate) < new Date()" type="danger">过期</el-tag>
<el-tag v-else-if="new Date(scope.row.dueDate) > new Date()" type="success">还剩{{ parseInt((new Date(scope.row.dueDate) - new Date()) / (1000 * 60 * 60 * 24)) }}</el-tag>
<el-tag v-else-if="new Date(scope.row.dueDate) > new Date()" type="success">
还剩{{ parseInt((new Date(scope.row.dueDate) - new Date()) / (1000 * 60 * 60 * 24)) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="应付金额" align="center" prop="amount" />
@@ -97,7 +125,6 @@
</el-col>
</el-row>
</div>
</template>
<script>
@@ -108,11 +135,13 @@ import { listPayable } from "@/api/finance/payable";
import { listFinancialDocument } from "@/api/finance/financialDocument";
import OrderDetailList from '@/views/wms/order/panels/detail.vue'
import klpList from "@/components/KLPUI/KLPList/index.vue"; // 引入klp-list组件
export default {
name: "Order",
components: {
OrderDetailList
OrderDetailList,
klpList // 注册klp-list组件
},
data() {
return {
@@ -124,12 +153,8 @@ export default {
orderCode: undefined
},
orderListLoading: false,
treeData: [],
orderList: [], // 用于klp-list的列表数据
total: 0,
defaultProps: {
children: 'children',
label: 'label'
},
rightLoading: false,
}
},
@@ -144,39 +169,62 @@ export default {
getList() {
this.orderListLoading = true;
listOrder(this.queryParams).then(response => {
this.treeData = response.rows.map(item => ({
label: item.orderCode,
value: item
}));
this.orderList = response.rows; // 直接使用原始数据
this.total = response.total;
}).finally(() => {
this.orderListLoading = false;
});
},
handleNodeClick(data) {
// 处理列表项点击事件
handleItemClick(selectedItem) {
if (!selectedItem) {
this.currentOrder = null;
return;
}
if (this.rightLoading) {
this.$message.warning('请等待当前订单加载完成');
return;
}
this.currentOrder = data.value;
this.fetchData(data.value.orderId);
this.currentOrder = selectedItem;
this.fetchData(selectedItem.orderId);
},
// 查看详情按钮点击事件
handleViewDetail(item) {
this.currentOrder = item;
this.fetchData(item.orderId);
},
async fetchData(orderId) {
this.rightLoading = true;
// 需要逐个获取订单明细、应收明细、应付明细、凭证管理
const orderDetail = (await listOrderDetail({ orderId, pageSize: 1000 })).rows;
const receivableDetail = (await listReceivable({ orderId, pageSize: 1000 })).rows;
const payableDetail = (await listPayable({ orderId, pageSize: 1000 })).rows;
const documentDetail = (await listFinancialDocument({ orderId, pageSize: 1000 })).rows;
this.rightLoading = false;
this.currentOrder = {
...this.currentOrder,
details: orderDetail,
receivables: receivableDetail,
payables: payableDetail,
documents: documentDetail
try {
// 并行请求提高性能
const [
orderDetailRes,
receivableRes,
payableRes,
documentRes
] = await Promise.all([
listOrderDetail({ orderId, pageSize: 1000 }),
listReceivable({ orderId, pageSize: 1000 }),
listPayable({ orderId, pageSize: 1000 }),
listFinancialDocument({ orderId, pageSize: 1000 })
]);
this.currentOrder = {
...this.currentOrder,
details: orderDetailRes.rows,
receivables: receivableRes.rows,
payables: payableRes.rows,
documents: documentRes.rows
};
} catch (error) {
this.$message.error('数据加载失败,请重试');
console.error(error);
} finally {
this.rightLoading = false;
}
}
}
}
</script>
</script>

View File

@@ -39,14 +39,22 @@
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="bomItemList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="属性名称" align="center" prop="attrKey" />
<el-table-column label="属性名称" align="center" prop="attrKey">
<template slot-scope="scope">
<span>{{ scope.row.attrKey }}</span>
<span v-if="scope.row.remark">
<el-tooltip :content="scope.row.remark" placement="top">
<i class="el-icon-info"></i>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column label="属性值" align="center" prop="attrValue" />
<el-table-column label="备注" align="center" prop="remark" />
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button

View File

@@ -65,8 +65,8 @@
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" /> -->
<!-- 添加或修改订单明细对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@@ -106,7 +106,7 @@
<el-select placeholder="请选择产品规范" @change="handleChangeSpec" style="width: 100%;">
<el-option v-for="item in productSpecList" :key="item.groupId" :label="item.groupName" :value="item.groupId" />
<template #empty>
<el-button type="primary" @click="handleAddSpec">新增产品规范</el-button>
<el-button @click="handleAddSpec" style="width: 100%;">新增产品规范</el-button>
</template>
</el-select>
</div>
@@ -158,7 +158,7 @@ export default {
EOrderStatus,
queryParams: {
pageNum: 1,
pageSize: 20,
pageSize: 100,
orderId: this.orderId,
productId: undefined,
quantity: undefined,

View File

@@ -2,7 +2,7 @@
<div class="app-container">
<!-- 左右布局容器 -->
<el-row :gutter="20">
<!-- 左侧自定义简洁订单列表区8 -->
<!-- 左侧使用klp-list组件6 -->
<el-col :span="6" style="display: table-cell;">
<!-- 搜索表单 - 精简搜索项 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"
@@ -19,54 +19,33 @@
</el-row>
</el-form>
<!-- 功能按钮区 -->
<!-- <el-row :gutter="10" class="mb-4">
<el-col :span="6">
</el-col>
<el-col :span="6">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
class="w-full">批量删除</el-button>
</el-col>
</el-row> -->
<!-- klp-list组件 -->
<klp-list
:list-data="orderList"
:model-value="selectedIds"
title-field="orderCode"
list-key="orderId"
title-label="订单编号"
:loading="loading"
@item-click="handleRowClick"
>
<!-- 自定义操作按钮 -->
<template #actions="{ item }">
<!-- 预订单确认按钮 -->
<el-button size="mini" plain title="预订单确认" type="success" icon="el-icon-check" v-if="isPre"
@click.stop="handleStartProduction(item)"></el-button>
<!-- 自定义简洁列表 -->
<div class="custom-list-container" v-loading="loading">
<!-- 列表项 -->
<div v-for="(item, index) in orderList" :key="item.orderId" class="order-item"
:class="{ 'active': selectedOrderId === item.orderId }" @click="handleRowClick(item)">
<!-- 复选框 -->
<!-- <el-checkbox v-model="selectedIds[item.orderId]" @change.stop="handleCheckboxChange(item, $event)"
class="checkbox"></el-checkbox> -->
<!-- 订单编号 -->
<div class="order-code">
<span class="label">订单编号</span>
<span class="value">{{ item.orderCode }}</span>
</div>
<!-- 操作按钮组 -->
<div class="order-actions">
<!-- 预订单确认按钮 -->
<el-button size="mini" plain title="预订单确认" type="success" icon="el-icon-check" v-if="isPre"
@click.stop="handleStartProduction(item)"></el-button>
<!-- 删除按钮 -->
<el-button size="mini" type="text" style="color: red" icon="el-icon-delete" @click.stop="handleDelete(item)"></el-button>
</div>
</div>
<!-- 空状态 -->
<div v-if="orderList.length === 0 && !loading" class="empty-state">
<el-empty description="暂无订单数据" />
</div>
</div>
<!-- 删除按钮 -->
<el-button size="mini" type="text" style="color: red" icon="el-icon-delete" @click.stop="handleDelete(item)"></el-button>
</template>
</klp-list>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" class="mt-4" />
</el-col>
<!-- 右侧详情区占16 -->
<!-- 右侧详情区占18 -->
<el-col :span="18">
<div>
<!-- 未选中行时显示提示 -->
@@ -81,56 +60,45 @@
<!-- 订单信息Tab -->
<el-tab-pane label="订单信息" name="orderInfo">
<el-form ref="detailForm" :model="form" :rules="rules" label-width="80px" size="small" class="mt-4">
<!-- <el-row :gutter="20"> -->
<!-- <el-col :span="12"> -->
<el-form-item label="订单ID" prop="orderId">
<el-input style="width: 60%;" v-model="form.orderId" placeholder="无" disabled>
<el-button style="padding: -1;" slot="append" size="mini" type="text" icon="el-icon-document-copy"
@click.stop="copyOrderId(form.orderId)"></el-button>
</el-input>
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<el-form-item label="订单编号" prop="orderCode">
<el-input style="width: 60%;" v-model="form.orderCode" placeholder="无" disabled />
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<el-form-item label="客户名称" prop="customerId">
<customer-select style="width: 60%;" v-model="form.customerId" />
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<el-form-item label="销售经理" prop="salesManager">
<el-input style="width: 60%;" v-model="form.salesManager" placeholder="无" />
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<el-form-item label="含税金额" prop="taxAmount">
<el-input-number style="width: 60%;" :controls="false" v-model="form.taxAmount" placeholder="0.00" precision="2"
:min="0" />
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12"> -->
<el-form-item label="无税金额" prop="noTaxAmount">
<el-input-number style="width: 60%;" :controls="false" v-model="form.noTaxAmount" placeholder="0.00" precision="2"
:min="0" />
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="12" v-if="!isPre"> -->
<el-form-item label="订单状态" prop="orderStatus">
<el-select style="width: 60%;" v-model="form.orderStatus" @change="handleOrderStatusChange" size="mini">
<el-option v-for="item in dict.type.order_status" :key="item.value" :label="item.label"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
<!-- </el-col> -->
<!-- <el-col :span="24"> -->
<el-form-item label="备注" prop="remark">
<el-input style="width: 60%;" v-model="form.remark" placeholder="无" type="textarea" rows="4" />
</el-form-item>
<!-- </el-col> -->
<!-- </el-row> -->
<el-form-item label="订单ID" prop="orderId">
<el-input style="width: 60%;" v-model="form.orderId" placeholder="无" disabled>
<el-button style="padding: -1;" slot="append" size="mini" type="text" icon="el-icon-document-copy"
@click.stop="copyOrderId(form.orderId)"></el-button>
</el-input>
</el-form-item>
<el-form-item label="订单编号" prop="orderCode">
<el-input style="width: 60%;" v-model="form.orderCode" placeholder="无" disabled />
</el-form-item>
<el-form-item label="客户名称" prop="customerId">
<customer-select style="width: 60%;" v-model="form.customerId" />
</el-form-item>
<el-form-item label="销售经理" prop="salesManager">
<el-input style="width: 60%;" v-model="form.salesManager" placeholder="无" />
</el-form-item>
<el-form-item label="含税金额" prop="taxAmount">
<el-input-number style="width: 60%;" :controls="false" v-model="form.taxAmount" placeholder="0.00" precision="2"
:min="0" />
</el-form-item>
<el-form-item label="无税金额" prop="noTaxAmount">
<el-input-number style="width: 60%;" :controls="false" v-model="form.noTaxAmount" placeholder="0.00" precision="2"
:min="0" />
</el-form-item>
<el-form-item label="订单状态" prop="orderStatus" v-if="!isPre">
<el-select style="width: 60%;" v-model="form.orderStatus" @change="handleOrderStatusChange" size="mini">
<el-option v-for="item in dict.type.order_status" :key="item.value" :label="item.label"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input style="width: 60%;" v-model="form.remark" placeholder="无" type="textarea" rows="4" />
</el-form-item>
<!-- 更新按钮 -->
<el-form-item class="text-right">
@@ -203,10 +171,11 @@ import { getOrder, delOrder, addOrder, updateOrder, listByStatus } from "@/api/w
import OrderDetailPanel from './detail.vue';
import { EOrderStatus } from "@/utils/enums";
import CustomerSelect from '@/components/KLPService/CustomerSelect/index.vue';
import klpList from "@/components/KLPUI/KLPList/index.vue";
export default {
name: "Order",
components: { OrderDetailPanel, CustomerSelect },
components: { OrderDetailPanel, CustomerSelect, klpList },
dicts: ['order_status'],
props: {
isPre: {
@@ -227,10 +196,8 @@ export default {
buttonLoading: false,
// 列表加载遮罩
loading: true,
// 选中的订单ID集合(用于批量操作)
// 选中的订单ID集合
selectedIds: {},
// 非多个禁用(批量删除用)
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
@@ -304,7 +271,6 @@ export default {
// 重置选中状态
this.selectedIds = {};
this.checkMultipleStatus();
// 如果之前选中的订单不在列表中了,清空选中状态
if (this.selectedOrderId && !this.orderList.some(item => item.orderId === this.selectedOrderId)) {
@@ -337,18 +303,6 @@ export default {
});
},
/** 处理复选框变化 */
handleCheckboxChange(item, checked) {
this.selectedIds[item.orderId] = checked;
this.checkMultipleStatus();
},
/** 检查批量操作状态 */
checkMultipleStatus() {
const selectedCount = Object.values(this.selectedIds).filter(checked => checked).length;
this.multiple = selectedCount === 0;
},
/** 订单状态变更 */
handleOrderStatusChange() {
updateOrder(this.form).then(response => {
@@ -463,30 +417,13 @@ export default {
/** 删除订单 */
handleDelete(row) {
// 获取要删除订单ID
let orderIds;
if (row) {
// 单条删除
orderIds = [row.orderId];
} else {
// 批量删除
orderIds = Object.entries(this.selectedIds)
.filter(([id, checked]) => checked)
.map(([id]) => id);
}
if (!orderIds.length) {
this.$modal.msgWarning("请选择要删除的订单");
return;
}
this.$modal.confirm(`是否确认删除选中的 ${orderIds.length} 个订单?`).then(() => {
this.$modal.confirm(`是否确认删除订单"${row.orderCode}"`).then(() => {
this.loading = true;
return delOrder(orderIds);
return delOrder([row.orderId]);
}).then(() => {
this.$modal.msgSuccess("删除成功");
// 如果删除的是当前选中的订单,清空详情
if (row && this.selectedOrderId === row.orderId) {
if (this.selectedOrderId === row.orderId) {
this.selectedOrderId = null;
}
this.getList();
@@ -525,78 +462,6 @@ export default {
padding: 16px;
}
/* 自定义列表容器 */
.custom-list-container {
max-height: calc(100vh - 220px);
overflow-y: auto;
padding-right: 8px;
margin-top: 10px;
}
/* 列表项样式 */
.order-item {
padding: 12px 16px;
margin-bottom: 10px;
border-bottom: 1px solid #e6e6e6;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
justify-content: space-between;
align-items: center;
}
/* 选中状态 */
.order-item.active {
border-left: 3px solid #409eff;
background-color: #f5f7fa;
}
/* 订单编号样式 */
.order-code {
display: flex;
align-items: center;
}
.order-code .label {
color: #606266;
margin-right: 6px;
font-size: 13px;
}
.order-code .value {
color: #303133;
font-weight: 500;
font-size: 14px;
}
/* 操作按钮组 */
.order-actions {
display: flex;
align-items: center;
gap: 4px;
}
/* 复选框样式调整 */
.checkbox {
margin-left: 8px;
}
/* 空状态样式 */
.empty-state {
padding: 40px 0;
text-align: center;
}
/* 右侧详情容器 */
.detail-container {
height: 100%;
background: #fff;
border-radius: 4px;
padding: 16px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
min-height: calc(100vh - 32px);
}
/* 空提示样式 */
.empty-tip {
height: 400px;
@@ -617,4 +482,4 @@ export default {
padding: 0 10px !important;
text-align: center !important;
}
</style>
</style>

View File

@@ -1,10 +1,6 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="采购订单编号" prop="detailCode">
<el-input v-model="queryParams.detailCode" placeholder="请输入采购订单编号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="原材料" prop="rawMaterialId">
<RawMaterialSelect v-model="queryParams.rawMaterialId" placeholder="请选择原材料" can-add />
</el-form-item>
@@ -40,10 +36,10 @@
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
</el-col>
<el-col :span="1.5">
<!-- <el-col :span="1.5">
<el-button type="info" plain icon="el-icon-plus" size="mini" :disabled="!hasArrivalItems"
@click="handleCreateStockIn">创建入库单</el-button>
</el-col>
</el-col> -->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>

View File

@@ -12,15 +12,15 @@
>
<!-- 下拉选项循环制造规范列表 -->
<el-option
v-for="item in mSpecList"
:key="item.specId"
:label="item.specName"
:value="item.specId"
v-for="item in pSpecList"
:key="item.groupId"
:label="item.groupName"
:value="item.groupId"
/>
<!-- 无数据提示 -->
<el-option
v-if="mSpecList.length === 0 && !loading"
v-if="pSpecList.length === 0 && !loading"
value=""
disabled
>
@@ -30,7 +30,7 @@
</template>
<script>
import { listManufacturingSpec } from '@/api/work/manufacturingSpec'
import { listProductSpecGroup } from '@/api/work/productSpecGroup'
import { debounce } from '@/utils' // 防抖:避免频繁触发接口请求
export default {
@@ -44,7 +44,7 @@ export default {
// 可选:允许外部自定义搜索参数的字段名(增强组件复用性)
searchKey: {
type: String,
default: 'specName' // 默认为“规范名称”搜索对应接口的mSpecName参数
default: 'groupName' // 默认为“规范名称”搜索对应接口的mSpecName参数
},
// 可选:每页加载数量(外部可配置)
pageSize: {
@@ -54,7 +54,7 @@ export default {
},
data() {
return {
mSpecList: [], // 制造规范列表数据
pSpecList: [], // 制造规范列表数据
loading: false, // 远程请求加载状态
queryParams: {
// 搜索参数默认用specName可通过searchKey自定义
@@ -109,14 +109,14 @@ export default {
// 5. 获取制造规范列表(远程接口请求)
getList() {
this.loading = true // 开始加载:显示加载动画
listManufacturingSpec(this.queryParams)
listProductSpecGroup(this.queryParams)
.then(res => {
// 接口成功赋值列表数据兼容res.rows或res.data.rows避免接口返回格式差异
this.mSpecList = res.rows || res.data?.rows || []
this.pSpecList = res.rows || res.data?.rows || []
})
.catch(() => {
// 接口失败:清空列表,避免旧数据残留
this.mSpecList = []
this.pSpecList = []
this.$message.error('获取制造规范列表失败,请重试') // 错误提示(优化用户体验)
})
.finally(() => {
@@ -125,9 +125,9 @@ export default {
},
// 6. 选择变化时触发(返回完整订单项,方便父组件使用)
handleSelectChange(mSpecId) {
handleSelectChange(pSpecId) {
// 根据选中的ID找到对应的完整制造规范对象
const selectedItem = this.mSpecList.find(item => item.specId === mSpecId)
const selectedItem = this.pSpecList.find(item => item.groupId === pSpecId)
// 触发change事件返回完整项父组件可通过@change接收
this.$emit('change', selectedItem)
// 可选触发input事件后额外触发change事件符合常规组件使用习惯

View File

@@ -53,7 +53,9 @@ export default {
return;
}
// 处理数据,兼容多种字段名,保证任务名唯一
const taskData = this.tasks.map((item, idx) => {
const taskData = this.tasks
.map((item, idx) => {
const name = (item.taskName || item.planName || item.remark || item.productName || item.name || `任务${idx+1}`) + (item.productName ? `-${item.productName}` : '');
const start = item.startDate || item.start_time || item.start || item.start_date;
const end = item.endDate || item.end_time || item.end || item.end_date;
@@ -72,7 +74,10 @@ export default {
startDate: start,
endDate: end
};
});
})
// 确保三个字段都存在startDate,endDate,name
.filter(item => item.startDate && item.endDate && item.name);
// 先全部用 getColor 分配基础色
taskData.forEach((item, idx) => {
item._color = getColor(item.lineId, item.orderId, idx);

View File

@@ -44,11 +44,18 @@
<el-table v-loading="loading" :data="productSpecList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键" align="center" prop="specId" v-if="false"/>
<el-table-column label="所属产品规范组ID" align="center" prop="groupId" />
<el-table-column label="规范名称" align="center" prop="specKey" />
<el-table-column label="规范名称" align="center" prop="specKey">
<template slot-scope="scope">
<span>{{ scope.row.specKey }}</span>
<span v-if="scope.row.remark">
<el-tooltip :content="scope.row.remark" placement="top">
<i class="el-icon-info"></i>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column label="规范值" align="center" prop="specValue" />
<el-table-column label="备注" align="center" prop="remark" />
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
<el-table-column label="操作" v-if="!readonly" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button

View File

@@ -135,8 +135,10 @@ export default {
this.$refs.detailForm.validate(valid => {
if (!valid) return;
if (this.detailForm.dateRange && this.detailForm.dateRange.length === 2) {
this.detailForm.startDate = this.detailForm.dateRange[0].replace(' ', "T") + '.000Z';
this.detailForm.endDate = this.detailForm.dateRange[1].replace(' ', "T") + '.000Z';
// const startDate = this.parseTime(this.detailForm.dateRange[0], '{y}-{m}-{d}T{h}:{i}:{s}') + '.000Z';
// const endDate = this.parseTime(this.detailForm.dateRange[1], '{y}-{m}-{d}T{h}:{i}:{s}') + '.000Z';
this.detailForm.startDate = this.detailForm.dateRange[0];
this.detailForm.endDate = this.detailForm.dateRange[1];
} else {
this.detailForm.startDate = '';
this.detailForm.endDate = '';

View File

@@ -35,7 +35,7 @@
<el-select placeholder="请选择产品规范" @change="handleChangeSpec" style="width: 100%;">
<el-option v-for="item in productSpecList.filter(item => item.productId != this.form.productId)" :key="item.groupId" :label="item.groupName" :value="item.groupId" />
<template #empty>
<el-button type="primary" @click="handleAddSpec">新增产品规范</el-button>
<el-button @click="handleAddSpec" style="width: 100%;">新增产品规范</el-button>
</template>
</el-select>
</div>