refactor(KLPService): 重构组件目录结构并新增多个表单选择组件
重构KLPService组件目录结构,将原有组件迁移至formItems子目录并新增多个表单选择组件。主要变更包括: 1. 移除CategorySelect组件及相关引用 2. 新增CraftSelect、AmountSelect、VendorSelect等表单组件 3. 优化WarehouseSelect组件支持禁用状态 4. 重构ProductSelect和RawMaterialSelect为卡片式选择器 5. 新增统一导出机制支持按需导入 同时更新相关视图文件以适配新的组件结构,改进代码可维护性和复用性。
This commit is contained in:
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-model="innerValue"
|
||||
:placeholder="placeholder"
|
||||
:clearable="clearable"
|
||||
:disabled="disabled"
|
||||
:filterable="filterable"
|
||||
@change="onChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in categoryOptions"
|
||||
:key="item.categoryId"
|
||||
:label="item.categoryName"
|
||||
:value="item.categoryId"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'CategorySelect',
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String, null],
|
||||
default: null
|
||||
},
|
||||
categoryType: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: v => [
|
||||
'base_material',
|
||||
'surface_treatment',
|
||||
'customer_req',
|
||||
'spec_packaging'
|
||||
].includes(v)
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择分类'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
innerValue: this.value
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState('category', ['categoryList']),
|
||||
categoryOptions() {
|
||||
return this.categoryList.filter(
|
||||
item => item.categoryType === this.categoryType && item.isEnabled === 1
|
||||
);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.innerValue = val;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!this.categoryList || this.categoryList.length === 0) {
|
||||
this.getCategoryList();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('category', ['getCategoryList']),
|
||||
onChange(val) {
|
||||
this.$emit('input', val);
|
||||
this.$emit('change', val);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -13,7 +13,8 @@
|
||||
v-for="item in warehouseOptions"
|
||||
:key="item.warehouseId"
|
||||
:label="item.warehouseName"
|
||||
:value="item.warehouseId"
|
||||
:value="item.warehouseId"
|
||||
:disabled="item.isEnabled == 0"
|
||||
>
|
||||
<span :style="{ paddingLeft: item.level * 20 + 'px' }">
|
||||
{{ item.warehouseName }}
|
||||
@@ -88,7 +89,8 @@ export default {
|
||||
const option = {
|
||||
warehouseId: item.warehouseId,
|
||||
warehouseName: item.warehouseName,
|
||||
level: level
|
||||
level: level,
|
||||
isEnabled: item.isEnabled,
|
||||
};
|
||||
|
||||
// 递归构建子节点
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
<template>
|
||||
<div
|
||||
:class="['actual-warehouse-select', { 'is-block': block }]"
|
||||
:style="wrapperStyle"
|
||||
>
|
||||
<el-cascader
|
||||
filterable
|
||||
ref="cascader"
|
||||
v-model="innerPath"
|
||||
:props="cascaderProps"
|
||||
:placeholder="placeholder"
|
||||
:clearable="clearable"
|
||||
:show-all-levels="true"
|
||||
:emit-path="true"
|
||||
style="width: 100%;"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listActualWarehouse } from '@/api/wms/actualWarehouse';
|
||||
|
||||
export default {
|
||||
name: 'ActualWarehouseSelect',
|
||||
props: {
|
||||
// 对外仍然是「单个 ID」,即第三级 actualWarehouseId
|
||||
value: {
|
||||
type: [Number, String, null],
|
||||
default: null
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择实际库位'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 已经不再显示“最高级”
|
||||
showTop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
block: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 240
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'small'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 级联组件内部使用的「路径值」,例如 [一级ID, 二级ID, 三级ID]
|
||||
innerPath: [],
|
||||
// 记录所有已加载节点(如果后面要根据 ID 反查路径,可复用)
|
||||
allLoadedNodes: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
wrapperStyle() {
|
||||
const widthValue = this.block
|
||||
? '100%'
|
||||
: (typeof this.width === 'number' ? `${this.width}px` : this.width);
|
||||
return { width: widthValue };
|
||||
},
|
||||
// el-cascader 的 props 配置
|
||||
cascaderProps() {
|
||||
return {
|
||||
lazy: true,
|
||||
lazyLoad: this.loadNode, // 懒加载方法
|
||||
checkStrictly: false, // 只允许选叶子节点
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
children: 'children'
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 外部把 value 置空时,同步清空面板
|
||||
value(val) {
|
||||
if (val == null || val === '') {
|
||||
this.innerPath = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 级联懒加载
|
||||
* node.level:
|
||||
* 0:根(还没选任何东西,parentId = 0 -> 加载一级)
|
||||
* 1:一级节点,加载二级
|
||||
* 2:二级节点,加载三级(三级设为叶子,不再展开)
|
||||
*/
|
||||
loadNode(node, resolve) {
|
||||
const { level, value } = node;
|
||||
|
||||
// 超过第三级就不再加载
|
||||
if (level >= 3) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const parentId = level === 0 ? 0 : value;
|
||||
|
||||
listActualWarehouse({ parentId }).then(res => {
|
||||
const list = (res.data || []).map(item => {
|
||||
const nextLevel = level + 1;
|
||||
const isLeafLevel = nextLevel >= 3; // 第三级为叶子,不能再展开
|
||||
|
||||
const nodeData = {
|
||||
value: item.actualWarehouseId,
|
||||
label: item.actualWarehouseName,
|
||||
leaf: isLeafLevel,
|
||||
// 只有第三级可选;一、二级全部 disabled
|
||||
disabled: nextLevel == 3 && !item.isEnabled,
|
||||
// 保留原始数据和层级
|
||||
raw: item,
|
||||
level: nextLevel
|
||||
};
|
||||
|
||||
this.registerNode(nodeData);
|
||||
return nodeData;
|
||||
});
|
||||
|
||||
resolve(list);
|
||||
}).catch(err => {
|
||||
console.error('加载仓库树失败:', err);
|
||||
resolve([]);
|
||||
});
|
||||
},
|
||||
|
||||
/** 把节点放进缓存数组里,后面如需扩展可用 */
|
||||
registerNode(node) {
|
||||
const id = node.value;
|
||||
const idx = this.allLoadedNodes.findIndex(
|
||||
n => String(n.value) === String(id)
|
||||
);
|
||||
if (idx === -1) {
|
||||
this.allLoadedNodes.push(node);
|
||||
} else {
|
||||
this.$set(this.allLoadedNodes, idx, {
|
||||
...this.allLoadedNodes[idx],
|
||||
...node
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 选中变化:
|
||||
* value 是路径数组,如 [一级ID, 二级ID, 三级ID]
|
||||
* 我们对外只抛最后一个(第三级)ID
|
||||
*/
|
||||
handleChange(value) {
|
||||
if (!Array.isArray(value) || value.length === 0) {
|
||||
this.$emit('input', null);
|
||||
this.$emit('select', null);
|
||||
return;
|
||||
}
|
||||
|
||||
const leafId = value[value.length - 1];
|
||||
|
||||
// 拿到当前选中节点,获取完整路径信息
|
||||
const nodes = this.$refs.cascader.getCheckedNodes();
|
||||
let payload = null;
|
||||
if (nodes && nodes.length > 0) {
|
||||
const node = nodes[0];
|
||||
const pathNodes = node.path || [];
|
||||
|
||||
payload = {
|
||||
id: leafId,
|
||||
pathIds: pathNodes.map(n => n.value),
|
||||
pathLabels: pathNodes.map(n => n.label),
|
||||
// 原始 data(如果需要后台做别的处理可以用)
|
||||
rawPath: pathNodes.map(n => n.data || n.raw || {})
|
||||
};
|
||||
}
|
||||
|
||||
this.$emit('input', leafId);
|
||||
this.$emit('select', payload);
|
||||
},
|
||||
|
||||
/** 外部刷新:如果以后需要强制重载,可以扩展这里(目前不需要缓存) */
|
||||
refresh() {
|
||||
this.innerPath = [];
|
||||
this.allLoadedNodes = [];
|
||||
// el-cascader 的懒加载不需要预载,这里清空即可
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.actual-warehouse-select {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.actual-warehouse-select.is-block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 让级联宽度占满容器,其他高度、边框等跟 el-select 共用全局 .el-input__inner 样式 */
|
||||
.actual-warehouse-select .el-cascader {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<el-select v-model="_value" placeholder="请选择">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'AmountSelect',
|
||||
computed: {
|
||||
...mapGetters(['financialAccounts']),
|
||||
_value: {
|
||||
get() {
|
||||
return this.value;
|
||||
},
|
||||
set(value) {
|
||||
console.log(value, 'value');
|
||||
this.$emit('change', value);
|
||||
this.$emit('input', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFinancialAccounts();
|
||||
},
|
||||
methods: {
|
||||
getFinancialAccounts() {
|
||||
console.log(this.financialAccounts, 'financialAccounts');
|
||||
this.options = this.financialAccounts.map(item => ({
|
||||
label: item.accountName,
|
||||
value: item.accountId
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div class="check-item-transfer">
|
||||
<!-- Element-UI穿梭框核心组件 -->
|
||||
<el-transfer v-model="internalValue" :data="transferData" :titles="['待选检查项', '已选检查项']" :props="transferProps"
|
||||
@change="handleTransferChange" filterable filter-placeholder="请输入检查项名称搜索" v-loading="loading" :disabled="loading">
|
||||
<!-- 自定义选项内容(单根节点包裹,解决Vue2警告) -->
|
||||
<template slot-scope="{ option }">
|
||||
<span class="transfer-option-content">
|
||||
<span>{{ option.itemName }}</span>
|
||||
<span style="margin-left: 8px; color: #999; font-size: 12px">
|
||||
({{ option.qualitativeQuantitative === 0 ? '定性' : '定量' }})
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<div class="transfer-footer" style="display: flex; justify-content: center; align-items: center; height: 40px;"
|
||||
slot="right-footer">
|
||||
<el-button size="small" @click="loadInspectionItemTemplateList">选择预设检验方案</el-button>
|
||||
</div>
|
||||
|
||||
</el-transfer>
|
||||
|
||||
<el-dialog title="选择待检项方案" :visible.sync="open" width="400px" append-to-body>
|
||||
|
||||
<el-input v-model="queryParams.templateName" placeholder="请输入任务名称" @change="loadInspectionItemTemplateList" />
|
||||
|
||||
<el-table highlight-current-row border @row-click="handleRowClick" v-loading="loading"
|
||||
:data="inspectionItemTemplateList" @selection-change="handleSelectionChange">
|
||||
<el-table-column label="方案名称" align="center" prop="templateName" />
|
||||
<el-table-column label="方案描述" align="center" prop="templateDesc" />
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > queryParams.pageSize" :total="total" :page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize" @pagination="loadInspectionItemTemplateList" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCheckItem } from "@/api/mes/qc/checkItem";
|
||||
import { listInspectionItemTemplate } from "@/api/mes/qc/inspectionItemTemplate";
|
||||
|
||||
export default {
|
||||
name: "CheckItemTransfer",
|
||||
// 接收外部v-model绑定的itemIds字符串(逗号分隔)
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 穿梭框数据源(去重后的检查项列表)
|
||||
transferData: [],
|
||||
// 内部选中值(数组,与v-model的字符串双向同步)
|
||||
internalValue: [],
|
||||
// 穿梭框字段映射(key必须唯一)
|
||||
transferProps: {
|
||||
key: "itemId", // 唯一标识字段
|
||||
label: "itemName" // 显示文本字段
|
||||
},
|
||||
total: 0,
|
||||
// 数据加载状态
|
||||
loading: false,
|
||||
templateList: [],
|
||||
open: false,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
templateName: undefined,
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听外部传入的value变化,同步到内部选中值
|
||||
value: {
|
||||
immediate: true, // 初始化时立即执行
|
||||
handler(newVal) {
|
||||
if (newVal && typeof newVal === "string") {
|
||||
// 字符串转数字数组(过滤空值,统一类型)
|
||||
this.internalValue = newVal
|
||||
.split(",")
|
||||
.filter(Boolean) // 过滤空字符串
|
||||
.map(id => id.toString()); // 统一转为字符串类型
|
||||
} else {
|
||||
this.internalValue = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 组件创建时加载检查项列表
|
||||
this.loadCheckItemList();
|
||||
},
|
||||
methods: {
|
||||
/** 加载检查项列表(核心修复:去重+类型统一) */
|
||||
async loadCheckItemList() {
|
||||
try {
|
||||
this.loading = true;
|
||||
// 查询全部检查项(不分页)
|
||||
const queryParams = { pageNum: 1, pageSize: 9999 };
|
||||
const response = await listCheckItem(queryParams);
|
||||
let rawList = response.rows || [];
|
||||
|
||||
// 修复1:统一itemId为字符串类型(避免字符串/数字不匹配)
|
||||
rawList = rawList.map(item => ({
|
||||
...item,
|
||||
itemId: item.itemId.toString() // 强制转为字符串类型
|
||||
}));
|
||||
|
||||
// 修复2:按itemId去重(解决重复key导致穿梭无效的核心问题)
|
||||
this.transferData = [...new Map(
|
||||
rawList.map(item => [item.itemId, item]) // Map的key唯一,自动去重
|
||||
).values()];
|
||||
|
||||
} catch (error) {
|
||||
// 兼容不同的提示方式
|
||||
if (this.$modal) {
|
||||
this.$modal.msgError("加载检查项列表失败");
|
||||
} else if (this.$message) {
|
||||
this.$message.error("加载检查项列表失败");
|
||||
}
|
||||
console.error("检查项列表加载异常:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
handleRowClick(row) {
|
||||
this.$emit("input", row.inspectionItem);
|
||||
this.open = false;
|
||||
},
|
||||
|
||||
/** 加载待检项方案列表 */
|
||||
async loadInspectionItemTemplateList() {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.open = true;
|
||||
const response = await listInspectionItemTemplate(this.queryParams);
|
||||
this.inspectionItemTemplateList = response.rows || [];
|
||||
this.total = response.total || 0;
|
||||
} catch (error) {
|
||||
if (this.$modal) {
|
||||
this.$modal.msgError("加载待检项方案列表失败");
|
||||
} else if (this.$message) {
|
||||
this.$message.error("加载待检项方案列表失败");
|
||||
}
|
||||
console.error("待检项方案列表加载异常:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/** 穿梭框选中状态变化处理(双向绑定核心逻辑) */
|
||||
handleTransferChange(newVal) {
|
||||
// 过滤空值后转逗号分隔的字符串
|
||||
const itemIdsStr = newVal
|
||||
.filter(Boolean)
|
||||
.join(",");
|
||||
|
||||
// 触发input事件实现v-model双向绑定
|
||||
this.$emit("input", itemIdsStr);
|
||||
// 向外暴露change事件,返回数组和字符串两种格式
|
||||
this.$emit("change", newVal, itemIdsStr);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.check-item-transfer {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 自定义选项样式,确保显示完整 */
|
||||
.transfer-option-content {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 2px 0;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<el-select v-model="processId" placeholder="请选择工艺">
|
||||
<el-option v-for="item in craftList" :key="item.processId" :label="item.processName" :value="item.processId" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'CraftSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number, undefined],
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
craftList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCraftList();
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['processList']),
|
||||
processId: {
|
||||
get() {
|
||||
return this.$props.value;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value);
|
||||
this.$emit('change', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCraftList() {
|
||||
console.log(this.processList)
|
||||
this.craftList = this.processList;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<el-select filterable v-model="_customerId" remote :remote-method="remoteSearchCustomer" :loading="customerLoading" placeholder="请选择客户">
|
||||
<el-option v-for="item in customerList" :key="item.customerId" :label="item.name" :value="item.customerId" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCustomer } from '@/api/wms/customer';
|
||||
|
||||
export default {
|
||||
name: 'CustomerSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_customerId: {
|
||||
get() {
|
||||
return this.value;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
customerList: [],
|
||||
customerLoading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.remoteSearchCustomer('');
|
||||
},
|
||||
methods: {
|
||||
remoteSearchCustomer(query) {
|
||||
this.customerLoading = true;
|
||||
listCustomer({ name: query, pageNum: 1, pageSize: 10 }).then(response => {
|
||||
this.customerList = response.rows;
|
||||
}).finally(() => {
|
||||
this.customerLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<span>
|
||||
<el-form-item label="物料类型" v-show="!hideType">
|
||||
<el-select v-model="_itemType" placeholder="请选择物料类型" clearable>
|
||||
<el-option v-for="dict in dict.type.stock_item_type" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品类型">
|
||||
<ProductSelect v-if="_itemType === 'product'" v-model="_itemId" placeholder="请选择产品" @change="onItemChange" :multiple="multiple" />
|
||||
<SemiSelect v-else-if="_itemType === 'semi'" v-model="_itemId" placeholder="请选择半成品" @change="onItemChange" :multiple="multiple" />
|
||||
<RawMaterialSelect v-else-if="_itemType === 'raw_material'" v-model="_itemId" placeholder="请选择原材料" @change="onItemChange" :multiple="multiple" />
|
||||
<el-input v-else disabled v-model="_itemId" placeholder="请先选择物料类型" :disabled="true" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProductSelect from '@/components/KLPService/ProductSelect/index.vue';
|
||||
import SemiSelect from '@/components/KLPService/SemiSelect/index.vue';
|
||||
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect/index.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ProductSelect,
|
||||
SemiSelect,
|
||||
RawMaterialSelect
|
||||
},
|
||||
dicts: ['stock_item_type'],
|
||||
props: {
|
||||
itemType: {
|
||||
type: String,
|
||||
require: true
|
||||
},
|
||||
itemId: {
|
||||
type: [String, Array],
|
||||
require: true
|
||||
},
|
||||
hideType: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
},
|
||||
// 计算属性劫持双向绑定的数据
|
||||
computed: {
|
||||
_itemType: {
|
||||
get() {
|
||||
return this.itemType;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:itemType', val);
|
||||
}
|
||||
},
|
||||
_itemId: {
|
||||
get() {
|
||||
if (!this.itemId) {
|
||||
return this.itemId;
|
||||
}
|
||||
return this.itemId.toString();
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:itemId', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onItemChange(val) {
|
||||
this.$emit('change', this._itemType, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-select v-model="innerValue" placeholder="请选择" v-if="orderId" clearable>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.itemId"
|
||||
:label="item.materialTypeCode + '[' + item.specification + ']'"
|
||||
:value="item.itemId"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- <div v-else-if="loading" style="border: 1px solid #828991; padding: 1px;">
|
||||
加载中...
|
||||
</div> -->
|
||||
<div v-else v-loading="loading" style="border: 1px solid #828991; padding: 1px;">请先选择订单后再选择明细</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listPurchaseOrderItem } from '@/api/erp/purchase'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
orderId: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
innerValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadItems() {
|
||||
if (!this.orderId) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
listPurchaseOrderItem({
|
||||
orderId: this.orderId,
|
||||
pageSize: 9999,
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
if (res.code === 200) {
|
||||
this.options = res.rows || []
|
||||
}
|
||||
}).catch(error => {
|
||||
this.loading = false
|
||||
console.error('订单明细搜索失败:', error)
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
orderId: {
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.loadItems()
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-model="innerValue"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="输入订单号搜索"
|
||||
:remote-method="remoteMethod"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listPurchaseOrder } from '@/api/erp/purchase'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// innerValue: this.value, // 内部维护的选中值
|
||||
options: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算属性,将内部值同步到父组件
|
||||
innerValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
// watch: {
|
||||
// // 监听父组件传入的value变化,同步到内部值
|
||||
// value(newVal) {
|
||||
// this.innerValue = newVal
|
||||
// },
|
||||
// // 监听内部值变化,同步到父组件
|
||||
// innerValue(newVal) {
|
||||
// this.$emit('input', newVal)
|
||||
// }
|
||||
// },
|
||||
methods: {
|
||||
remoteMethod(query) {
|
||||
if (query !== '') {
|
||||
this.loading = true
|
||||
listPurchaseOrder({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
orderCode: query
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.options = res.rows.map(item => ({
|
||||
value: item.orderId,
|
||||
label: item.orderCode
|
||||
}))
|
||||
}).catch(error => {
|
||||
this.loading = false
|
||||
console.error('订单搜索失败:', error)
|
||||
})
|
||||
} else {
|
||||
this.options = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,395 @@
|
||||
<template>
|
||||
<div class="product-selector">
|
||||
<!-- 触发器按钮 -->
|
||||
<div class="el-input" v-if="!readonly" type="text" @click="dialogVisible = true">
|
||||
<div class="el-input__inner">
|
||||
<el-icon class="el-icon-search"></el-icon>
|
||||
{{ buttonText }}
|
||||
</div>
|
||||
</div>
|
||||
<span v-else class="readonly-text">{{ displayText }}</span>
|
||||
|
||||
<!-- 选择对话框 -->
|
||||
<el-dialog append-to-body title="选择产品" :visible.sync="dialogVisible" width="1200px" :close-on-click-modal="false"
|
||||
@close="handleClose">
|
||||
<!-- 搜索区域(保持不变) -->
|
||||
<el-form :inline="true" :model="queryParams" class="search-form" size="small">
|
||||
<el-form-item label="产品编号">
|
||||
<el-input v-model="queryParams.productCode" placeholder="请输入产品编号" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品名称">
|
||||
<MemoInput storageKey="productName" v-model="queryParams.productName" placeholder="请输入产品名称" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格">
|
||||
<el-input v-model="queryParams.specification" placeholder="请输入规格" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="材质">
|
||||
<MemoInput storageKey="material" v-model="queryParams.material" placeholder="请输入材质" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="厂家">
|
||||
<MemoInput storageKey="manufacturer" v-model="queryParams.manufacturer" placeholder="请输入厂家" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="表面处理">
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 卡片布局(替换原表格) -->
|
||||
<div v-loading="loading" class="card-container">
|
||||
<div v-for="(item, index) in productList" :key="index + item.productId" class="product-card"
|
||||
:class="{ 'selected-card': isSelected(item.productId) }" @click="handleRowClick(item)">
|
||||
<!-- 多选勾选框 -->
|
||||
<el-checkbox v-if="multiple" :checked="isSelected(item.productId)"
|
||||
@change="(val) => handleCardSelection(val, item)" class="card-checkbox" />
|
||||
|
||||
<!-- 卡片内容(包含所有原表格字段) -->
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<span class="name">{{ item.productName }}</span>
|
||||
<span class="code">[{{ item.productCode }}]</span>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="info-item">规格:<span>{{ item.specification || '-' }}</span></div>
|
||||
<div class="info-item">材质:<span>{{ item.material || '-' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<div class="empty-tip" v-if="productList.length === 0 && !loading">
|
||||
暂无匹配的产品数据
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页(保持不变) -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmSelection" v-if="multiple">
|
||||
确认选择
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProduct } from '@/api/wms/product';
|
||||
import MemoInput from '@/components/MemoInput/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'ProductSelector',
|
||||
components: {
|
||||
MemoInput
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
filters: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
loading: false,
|
||||
productList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
productCode: undefined,
|
||||
productName: undefined,
|
||||
owner: undefined,
|
||||
specification: undefined,
|
||||
material: undefined,
|
||||
manufacturer: undefined,
|
||||
surfaceTreatmentDesc: undefined,
|
||||
zincLayer: undefined
|
||||
},
|
||||
selectedIds: [],
|
||||
selectedRows: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
// 如果为选中任何产品,显示选择产品
|
||||
// 如果为选中多个产品,显示已选 X 项
|
||||
// 如果为选中单个产品,显示产品名称
|
||||
if (this.selectedIds.length === 0) {
|
||||
return '请选择产品';
|
||||
}
|
||||
if (this.multiple) {
|
||||
return `已选 ${this.selectedIds.length} 项`;
|
||||
} else {
|
||||
return `${this.selectedRows[0]?.productName}[${this.selectedRows[0]?.specification || '-'}] (${this.selectedRows[0]?.material || '-'})`;
|
||||
}
|
||||
},
|
||||
displayText() {
|
||||
if (this.multiple) {
|
||||
return this.selectedIds.length > 0
|
||||
? `已选 ${this.selectedIds.length} 项`
|
||||
: '未选择';
|
||||
} else {
|
||||
return this.selectedRows[0]?.productName || '未选择';
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.selectedIds = val ? val.split(',').filter(id => id) : [];
|
||||
// this.syncSelectedRows();
|
||||
this.$forceUpdate(); // 新增:强制刷新视图
|
||||
}
|
||||
},
|
||||
dialogVisible(val) {
|
||||
if (val) {
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 判断卡片是否选中
|
||||
isSelected(productId) {
|
||||
return this.selectedIds.includes(productId);
|
||||
},
|
||||
|
||||
// 同步选中行数据
|
||||
// syncSelectedRows() {
|
||||
// if (this.productList.length === 0) return;
|
||||
// // this.selectedRows = this.productList.filter(item =>
|
||||
// // this.selectedIds.includes(item.productId)
|
||||
// // );
|
||||
// },
|
||||
|
||||
// 卡片选择事件(多选)
|
||||
handleCardSelection(checked, item) {
|
||||
if (checked) {
|
||||
!this.selectedIds.includes(item.productId) && this.selectedIds.push(item.productId);
|
||||
} else {
|
||||
this.selectedIds = this.selectedIds.filter(id => id !== item.productId);
|
||||
}
|
||||
// this.syncSelectedRows();
|
||||
},
|
||||
|
||||
// 原有方法保持不变(仅修改同步选中状态逻辑)
|
||||
async getList() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const params = { ...this.queryParams, ...this.filters };
|
||||
const response = await listProduct(params);
|
||||
if (response.code === 200) {
|
||||
this.productList = response.rows || [];
|
||||
this.total = response.total || 0;
|
||||
// this.syncSelectedRows(); // 加载数据后同步选中状态
|
||||
}
|
||||
return this.productList;
|
||||
} catch (error) {
|
||||
console.error('获取产品列表失败', error);
|
||||
this.$message.error('获取产品列表失败');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
productCode: undefined,
|
||||
productName: undefined,
|
||||
owner: undefined,
|
||||
specification: undefined,
|
||||
material: undefined,
|
||||
manufacturer: undefined,
|
||||
surfaceTreatmentDesc: undefined,
|
||||
zincLayer: undefined
|
||||
};
|
||||
this.getList();
|
||||
},
|
||||
|
||||
handleRowClick(row) {
|
||||
if (!this.multiple) {
|
||||
this.selectedIds = [row.productId];
|
||||
this.selectedRows = [row];
|
||||
this.confirmSelection();
|
||||
}
|
||||
},
|
||||
|
||||
handleSelect(row) {
|
||||
if (this.multiple) {
|
||||
const index = this.selectedIds.indexOf(row.productId);
|
||||
index > -1
|
||||
? (this.selectedIds.splice(index, 1), this.selectedRows.splice(index, 1))
|
||||
: (this.selectedIds.push(row.productId), this.selectedRows.push(row));
|
||||
} else {
|
||||
this.selectedIds = [row.productId];
|
||||
this.selectedRows = [row];
|
||||
this.confirmSelection();
|
||||
}
|
||||
},
|
||||
|
||||
confirmSelection() {
|
||||
const emitValue = this.selectedIds.join(',');
|
||||
this.$emit('input', emitValue);
|
||||
this.$emit('change', emitValue, this.selectedRows);
|
||||
this.dialogVisible = false;
|
||||
this.$forceUpdate(); // 新增:强制刷新视图
|
||||
},
|
||||
|
||||
handleClose() {
|
||||
this.selectedIds = this.value ? this.value.split(',').filter(id => id) : [];
|
||||
// this.syncSelectedRows();
|
||||
this.dialogVisible = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.product-selector {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.readonly-text {
|
||||
color: #606266;
|
||||
line-height: 1;
|
||||
padding: 8px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 20px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
/* 卡片容器样式 */
|
||||
.card-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
min-height: 400px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* 卡片样式 */
|
||||
.product-card {
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 0px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
/* 选中卡片样式 */
|
||||
.selected-card {
|
||||
border-color: #409eff;
|
||||
background-color: #f0f7ff;
|
||||
}
|
||||
|
||||
/* 多选勾选框位置 */
|
||||
.card-checkbox {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
/* 卡片内容样式 */
|
||||
.card-content {
|
||||
margin-right: 24px;
|
||||
/* 给多选框留空间 */
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 16px;
|
||||
color: #1989fa;
|
||||
margin-right: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.card-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.info-item span {
|
||||
color: #303133;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* 空数据提示 */
|
||||
.empty-tip {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400px;
|
||||
color: #909399;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,398 @@
|
||||
<template>
|
||||
<div class="raw-material-selector">
|
||||
<!-- 触发器按钮 -->
|
||||
<div class="el-input" v-if="!readonly" type="text" @click="dialogVisible = true">
|
||||
<div class="el-input__inner">
|
||||
<el-icon class="el-icon-search"></el-icon>
|
||||
{{ buttonText }}
|
||||
</div>
|
||||
</div>
|
||||
<span v-else class="readonly-text">{{ displayText }}</span>
|
||||
|
||||
<!-- 选择对话框 -->
|
||||
<el-dialog title="选择原材料" :visible.sync="dialogVisible" width="1200px" :close-on-click-modal="false"
|
||||
@close="handleClose" append-to-body>
|
||||
<!-- 搜索区域(保持不变) -->
|
||||
<el-form :inline="true" :model="queryParams" class="search-form" size="small">
|
||||
<el-form-item label="编号">
|
||||
<el-input v-model="queryParams.rawMaterialCode" placeholder="请输入原材料编号" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<MemoInput storageKey="productName" v-model="queryParams.rawMaterialName" placeholder="请输入原材料名称" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格">
|
||||
<el-input v-model="queryParams.specification" placeholder="请输入规格" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="材质">
|
||||
<MemoInput storageKey="material" v-model="queryParams.material" placeholder="请输入材质" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="厂家">
|
||||
<MemoInput storageKey="manufacturer" v-model="queryParams.manufacturer" placeholder="请输入厂家" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="表面处理">
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 卡片布局(替换原表格) -->
|
||||
<div v-loading="loading" class="card-container">
|
||||
<div v-for="(item, index) in rawMaterialList" :key="index + item.rawMaterialId" class="material-card"
|
||||
:class="{ 'selected-card': isSelected(item.rawMaterialId) }" @click="handleRowClick(item)">
|
||||
<!-- 多选勾选框 -->
|
||||
<el-checkbox v-if="multiple" :checked="isSelected(item.rawMaterialId)"
|
||||
@change="(val) => handleCardSelection(val, item)" class="card-checkbox" />
|
||||
|
||||
<!-- 卡片内容(包含所有原表格字段) -->
|
||||
<div class="card-content">
|
||||
<div class="card-title">
|
||||
<span class="name">{{ item.rawMaterialName }}</span>
|
||||
<span class="code">[{{ item.rawMaterialCode }}]</span>
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="info-item">规格:<span>{{ item.specification || '-' }}</span></div>
|
||||
<div class="info-item">单位:<span>{{ item.unit || '-' }}</span></div>
|
||||
<div class="info-item">材质:<span>{{ item.material || '-' }}</span></div>
|
||||
<div class="info-item">厂家:<span>{{ item.manufacturer || '-' }}</span></div>
|
||||
<div class="info-item">表面处理:<span>{{ item.surfaceTreatmentDesc || '-' }}</span></div>
|
||||
<div class="info-item">锌层:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<div class="empty-tip" v-if="rawMaterialList.length === 0 && !loading">
|
||||
暂无匹配的原材料数据
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页(保持不变) -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmSelection" v-if="multiple">
|
||||
确认选择
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRawMaterial } from '@/api/wms/rawMaterial';
|
||||
import MemoInput from '@/components/MemoInput/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'RawMaterialSelector',
|
||||
components: {
|
||||
MemoInput
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
filters: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
loading: false,
|
||||
rawMaterialList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
rawMaterialCode: undefined,
|
||||
rawMaterialName: undefined,
|
||||
specification: undefined,
|
||||
material: undefined,
|
||||
manufacturer: undefined,
|
||||
surfaceTreatmentDesc: undefined,
|
||||
zincLayer: undefined
|
||||
},
|
||||
selectedIds: [],
|
||||
selectedRows: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
// 如果为选中任何原材料,显示选择原材料
|
||||
// 如果为选中多个原材料,显示已选 X 项
|
||||
// 如果为选中单个原材料,显示原材料名称
|
||||
console.log(this.selectedIds);
|
||||
if (this.selectedIds.length === 0) {
|
||||
return '请选择原材料';
|
||||
}
|
||||
if (this.multiple) {
|
||||
return `已选 ${this.selectedIds.length} 项`;
|
||||
} else {
|
||||
return `${this.selectedRows[0]?.rawMaterialName}[${this.selectedRows[0]?.specification || '-'}] (${this.selectedRows[0]?.material || '-'})`;
|
||||
}
|
||||
},
|
||||
displayText() {
|
||||
if (this.multiple) {
|
||||
return this.selectedIds.length > 0
|
||||
? `已选 ${this.selectedIds.length} 项`
|
||||
: '未选择';
|
||||
} else {
|
||||
return this.selectedRows[0]?.rawMaterialName || '未选择';
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
console.log('watch触发val', val);
|
||||
this.selectedIds = val ? val.split(',').filter(id => id) : [];
|
||||
// this.syncSelectedRows();
|
||||
this.$forceUpdate(); // 新增:强制刷新视图
|
||||
}
|
||||
},
|
||||
dialogVisible(val) {
|
||||
if (val) {
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 判断卡片是否选中
|
||||
isSelected(rawMaterialId) {
|
||||
return this.selectedIds.includes(rawMaterialId);
|
||||
},
|
||||
|
||||
// 卡片选择事件(多选)
|
||||
handleCardSelection(checked, item) {
|
||||
if (checked) {
|
||||
!this.selectedIds.includes(item.rawMaterialId) && this.selectedIds.push(item.rawMaterialId);
|
||||
} else {
|
||||
this.selectedIds = this.selectedIds.filter(id => id != item.rawMaterialId);
|
||||
}
|
||||
},
|
||||
|
||||
// 原有方法保持不变(仅修改同步选中状态逻辑)
|
||||
async getList() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const params = { ...this.queryParams, ...this.filters };
|
||||
console.log('params', params);
|
||||
const response = await listRawMaterial(params);
|
||||
if (response.code === 200) {
|
||||
this.rawMaterialList = response.rows.map(item => ({
|
||||
...item,
|
||||
rawMaterialId: item.rawMaterialId.toString()
|
||||
})) || [];
|
||||
this.total = response.total || 0;
|
||||
}
|
||||
return this.rawMaterialList;
|
||||
} catch (error) {
|
||||
console.error('获取原材料列表失败', error);
|
||||
this.$message.error('获取原材料列表失败');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
rawMaterialCode: undefined,
|
||||
rawMaterialName: undefined,
|
||||
specification: undefined,
|
||||
material: undefined,
|
||||
manufacturer: undefined,
|
||||
surfaceTreatmentDesc: undefined,
|
||||
zincLayer: undefined
|
||||
};
|
||||
this.getList();
|
||||
},
|
||||
|
||||
handleRowClick(row) {
|
||||
if (!this.multiple) {
|
||||
this.selectedIds = [row.rawMaterialId];
|
||||
this.selectedRows = [row];
|
||||
this.confirmSelection();
|
||||
}
|
||||
},
|
||||
|
||||
handleSelect(row) {
|
||||
if (this.multiple) {
|
||||
const index = this.selectedIds.indexOf(row.rawMaterialId);
|
||||
index > -1
|
||||
? (this.selectedIds.splice(index, 1), this.selectedRows.splice(index, 1))
|
||||
: (this.selectedIds.push(row.rawMaterialId), this.selectedRows.push(row));
|
||||
} else {
|
||||
this.selectedIds = [row.rawMaterialId];
|
||||
this.selectedRows = [row];
|
||||
this.confirmSelection();
|
||||
}
|
||||
},
|
||||
|
||||
confirmSelection() {
|
||||
const emitValue = this.selectedIds.join(',');
|
||||
this.$emit('input', emitValue);
|
||||
this.$emit('change', emitValue, this.selectedRows);
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
handleClose() {
|
||||
this.selectedIds = this.value ? this.value.split(',').filter(id => id) : [];
|
||||
// this.syncSelectedRows();
|
||||
this.dialogVisible = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.raw-material-selector {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.readonly-text {
|
||||
color: #606266;
|
||||
line-height: 1;
|
||||
padding: 8px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 20px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
/* 卡片容器样式 */
|
||||
.card-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
min-height: 400px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* 卡片样式 */
|
||||
.material-card {
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 0px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
/* 选中卡片样式 */
|
||||
.selected-card {
|
||||
border-color: #409eff;
|
||||
background-color: #f0f7ff;
|
||||
}
|
||||
|
||||
/* 多选勾选框位置 */
|
||||
.card-checkbox {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
/* 卡片内容样式 */
|
||||
.card-content {
|
||||
margin-right: 24px;
|
||||
/* 给多选框留空间 */
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 16px;
|
||||
color: #1989fa;
|
||||
margin-right: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.card-info {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.info-item span {
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 空数据提示 */
|
||||
.empty-tip {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400px;
|
||||
color: #909399;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
112
klp-ui/src/components/KLPService/formItems/UserSelect/index.vue
Normal file
112
klp-ui/src/components/KLPService/formItems/UserSelect/index.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-model="selectedValue"
|
||||
:multiple="multiple"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="handleSearch"
|
||||
:loading="loading"
|
||||
:placeholder="placeholder"
|
||||
style="width: 100%"
|
||||
@change="handleChange"
|
||||
:clearable="clearable"
|
||||
>
|
||||
<el-option
|
||||
v-for="user in filteredUsers"
|
||||
:key="user.userId"
|
||||
:label="`${user.nickName}(${user.dept && user.dept.deptName ? user.dept.deptName : '无部门'})`"
|
||||
:value="user.userId"
|
||||
>
|
||||
<span>{{ user.nickName }}</span>
|
||||
<span style="color: #999; font-size: 12px; margin-left: 8px;">{{ user.dept && user.dept.deptName ? user.dept.deptName : '无部门' }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { selectUser } from '@/api/system/user'
|
||||
|
||||
export default {
|
||||
name: 'UserSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number, Array],
|
||||
default: null
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择用户'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userList: [],
|
||||
loading: false,
|
||||
searchKeyword: '',
|
||||
filteredUsers: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
this.$emit('change', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
searchKeyword(val) {
|
||||
this.filterUsers(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchUsers()
|
||||
},
|
||||
methods: {
|
||||
fetchUsers() {
|
||||
this.loading = true
|
||||
selectUser({}).then(res => {
|
||||
this.userList = res.data || res.rows || []
|
||||
this.filteredUsers = this.userList
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSearch(query) {
|
||||
this.searchKeyword = query
|
||||
},
|
||||
filterUsers(keyword) {
|
||||
if (!keyword) {
|
||||
this.filteredUsers = this.userList
|
||||
} else {
|
||||
const lower = keyword.toLowerCase()
|
||||
this.filteredUsers = this.userList.filter(user => {
|
||||
return (
|
||||
(user.nickName && user.nickName.toLowerCase().includes(lower)) ||
|
||||
(user.dept && user.dept.deptName && user.dept.deptName.toLowerCase().includes(lower))
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
handleChange(val) {
|
||||
this.$emit('input', val)
|
||||
this.$emit('change', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<el-select
|
||||
remote
|
||||
clearable
|
||||
filterable
|
||||
v-model="_value"
|
||||
:remote-method="remoteSearchVendor"
|
||||
:loading="vendorLoading"
|
||||
placeholder="请选择供应商"
|
||||
>
|
||||
<el-option v-for="item in vendorList" :key="item.supplierId" :label="item.name" :value="item.supplierId" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listSupplier } from "@/api/wms/supplier";
|
||||
|
||||
export default {
|
||||
name: "VendorSelect",
|
||||
data() {
|
||||
return {
|
||||
vendorList: [],
|
||||
vendorLoading: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_value: {
|
||||
get() {
|
||||
return this.value;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit("input", val);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.remoteSearchVendor("");
|
||||
},
|
||||
methods: {
|
||||
remoteSearchVendor(query) {
|
||||
this.vendorLoading = true;
|
||||
listSupplier({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
name: query
|
||||
}).then(response => {
|
||||
this.vendorList = response.rows;
|
||||
this.vendorLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-model="selected"
|
||||
:placeholder="placeholder"
|
||||
:clearable="clearable"
|
||||
:disabled="disabled"
|
||||
:size="size"
|
||||
filterable
|
||||
@change="onChange"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in warehouseOptions"
|
||||
:key="item.warehouseId"
|
||||
:label="item.warehouseName"
|
||||
:value="item.warehouseId"
|
||||
:disabled="item.isEnabled == 0"
|
||||
>
|
||||
<span :style="{ paddingLeft: item.level * 20 + 'px' }">
|
||||
{{ item.warehouseName }}
|
||||
</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listWarehouse } from '@/api/wms/warehouse';
|
||||
|
||||
export default {
|
||||
name: 'WarehouseSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String, null],
|
||||
default: null
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择仓库'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'mini'
|
||||
},
|
||||
showTop: {
|
||||
type: Boolean,
|
||||
default: false // 是否显示顶级节点
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
warehouseOptions: [],
|
||||
selected: this.value
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.selected = val;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions();
|
||||
},
|
||||
methods: {
|
||||
loadOptions() {
|
||||
listWarehouse().then(response => {
|
||||
console.log('仓库API返回数据:', response);
|
||||
const data = response.data || [];
|
||||
console.log('处理后的数据:', data);
|
||||
this.warehouseOptions = this.buildTreeOptions(data);
|
||||
console.log('构建的树形选项:', this.warehouseOptions);
|
||||
}).catch(error => {
|
||||
console.error("加载仓库选项失败:", error);
|
||||
this.warehouseOptions = [];
|
||||
});
|
||||
},
|
||||
buildTreeOptions(data, parentId = null, level = 0) {
|
||||
const options = [];
|
||||
|
||||
data.forEach(item => {
|
||||
if (item.parentId === parentId) {
|
||||
const option = {
|
||||
warehouseId: item.warehouseId,
|
||||
warehouseName: item.warehouseName,
|
||||
level: level,
|
||||
isEnabled: item.isEnabled,
|
||||
};
|
||||
|
||||
// 递归构建子节点
|
||||
const children = this.buildTreeOptions(data, item.warehouseId, level + 1);
|
||||
if (children.length > 0) {
|
||||
options.push(option);
|
||||
options.push(...children);
|
||||
} else {
|
||||
options.push(option);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return options;
|
||||
},
|
||||
onChange(val) {
|
||||
this.$emit('input', val);
|
||||
this.$emit('change', val);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
15
klp-ui/src/components/KLPService/formItems/index.js
Normal file
15
klp-ui/src/components/KLPService/formItems/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// 所有表单组件,查找该目录下的所有文件夹下的index.vue文件,并设置统一导出
|
||||
const req = require.context('./', true, /\/index\.vue$/) // 注意:第一个参数是当前目录,第二个参数改为true(递归查找子文件夹)
|
||||
|
||||
const modules = {}
|
||||
req.keys().forEach(key => {
|
||||
// 提取文件夹名称作为组件名(比如 ./Input/index.vue → Input)
|
||||
const componentName = key.replace(/^\.\/(.*)\/index\.vue$/, '$1')
|
||||
modules[componentName] = req(key).default
|
||||
|
||||
// 关键:为每个组件添加命名导出(支持按需导入)
|
||||
module.exports[componentName] = req(key).default
|
||||
})
|
||||
|
||||
// 保持默认导出(支持全部导入)
|
||||
module.exports.default = modules
|
||||
@@ -1,4 +1,3 @@
|
||||
export { default as CategorySelect } from './CategorySelect/index.vue';
|
||||
export { default as CheckItemSelect } from './CheckItemSelect/index.vue';
|
||||
export { default as ProductSelect } from './ProductSelect/index.vue';
|
||||
export { default as RawMaterialSelect } from './RawMaterialSelect/index.vue';
|
||||
|
||||
@@ -164,11 +164,11 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="逻辑库区" required>
|
||||
<el-select v-model="item.warehouseId" placeholder="请选择逻辑库区" style="width: 100%" filterable
|
||||
:disabled="readonly">
|
||||
<el-option v-for="warehouse in warehouseList" :key="warehouse.warehouseId"
|
||||
:label="warehouse.warehouseName" :value="warehouse.warehouseId" />
|
||||
</el-select>
|
||||
<WarehouseSelect
|
||||
v-model="item.warehouseId"
|
||||
placeholder="请选择逻辑库区"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="真实库区" required>
|
||||
<ActualWarehouseSelect
|
||||
@@ -208,6 +208,7 @@ import CoilSelector from '@/components/CoilSelector';
|
||||
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
|
||||
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
|
||||
import ProductSelect from "@/components/KLPService/ProductSelect";
|
||||
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
|
||||
|
||||
export default {
|
||||
name: 'SplitCoil',
|
||||
@@ -216,6 +217,7 @@ export default {
|
||||
ActualWarehouseSelect,
|
||||
RawMaterialSelect,
|
||||
ProductSelect,
|
||||
WarehouseSelect,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -159,11 +159,11 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="逻辑库区" prop="warehouseId">
|
||||
<el-select v-model="updateForm.warehouseId" placeholder="请选择逻辑库区" style="width: 100%" filterable
|
||||
:disabled="readonly">
|
||||
<el-option v-for="warehouse in warehouseList" :key="warehouse.warehouseId"
|
||||
:label="warehouse.warehouseName" :value="warehouse.warehouseId" />
|
||||
</el-select>
|
||||
<WarehouseSelect
|
||||
v-model="updateForm.warehouseId"
|
||||
placeholder="请选择逻辑库区"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="真实库区" prop="actualWarehouseId">
|
||||
@@ -234,6 +234,7 @@ import { listProductWithBom } from '@/api/wms/product';
|
||||
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
|
||||
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
|
||||
import ProductSelect from "@/components/KLPService/ProductSelect";
|
||||
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
|
||||
|
||||
export default {
|
||||
name: 'TypingCoil',
|
||||
@@ -241,6 +242,7 @@ export default {
|
||||
ActualWarehouseSelect,
|
||||
RawMaterialSelect,
|
||||
ProductSelect,
|
||||
WarehouseSelect,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -136,8 +136,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProduct, getProduct, delProduct, addProduct, updateProduct, addProductWithBom } from "@/api/wms/product";
|
||||
import CategorySelect from '@/components/KLPService/CategorySelect';
|
||||
import { listProduct, getProduct, delProduct, updateProduct, addProductWithBom } from "@/api/wms/product";
|
||||
import CategoryRenderer from '@/components/KLPService/Renderer/CategoryRenderer.vue';
|
||||
import UserSelect from '@/components/KLPService/UserSelect';
|
||||
// import BomPanel from '../bom/components/BomPanel.vue';
|
||||
@@ -146,7 +145,6 @@ import UserSelect from '@/components/KLPService/UserSelect';
|
||||
export default {
|
||||
name: "Product",
|
||||
components: {
|
||||
CategorySelect,
|
||||
CategoryRenderer,
|
||||
UserSelect,
|
||||
// BomPanel,
|
||||
|
||||
@@ -20,28 +20,6 @@
|
||||
<el-form-item label="负责人" prop="salesManager">
|
||||
<el-input v-model="queryParams.owner" :multiple="false" placeholder="请填写负责人" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="基础材质" prop="baseMaterialId">
|
||||
<CategorySelect v-model="queryParams.baseMaterialId" categoryType="base_material" placeholder="请选择基础材质分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="表面处理" prop="surfaceTreatmentId">
|
||||
<CategorySelect v-model="queryParams.surfaceTreatmentId" categoryType="surface_treatment" placeholder="请选择表面处理分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户需求" prop="customerReqId">
|
||||
<CategorySelect v-model="queryParams.customerReqId" categoryType="customer_req" placeholder="请选择客户需求分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="包装方式" prop="packagingId">
|
||||
<CategorySelect v-model="queryParams.packagingId" categoryType="spec_packaging" placeholder="请选择包装分类" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-select v-model="queryParams.isEnabled" placeholder="请选择是否启用" clearable>
|
||||
<el-option
|
||||
v-for="dict in dict.type.common_swicth"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
@@ -197,61 +175,6 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- <el-divider>分类信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="基础材质" prop="baseMaterialId">
|
||||
<CategorySelect v-model="form.baseMaterialId" categoryType="base_material" placeholder="请选择基础材质分类" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表面处理" prop="surfaceTreatmentId">
|
||||
<CategorySelect v-model="form.surfaceTreatmentId" categoryType="surface_treatment" placeholder="请选择表面处理分类" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户需求" prop="customerReqId">
|
||||
<CategorySelect v-model="form.customerReqId" categoryType="customer_req" placeholder="请选择客户需求分类" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="包装方式" prop="packagingId">
|
||||
<CategorySelect v-model="form.packagingId" categoryType="spec_packaging" placeholder="请选择包装分类" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider>参数信息</el-divider>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="厚度" prop="thickness">
|
||||
<el-input v-model="form.thickness" placeholder="请输入厚度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="宽度" prop="width">
|
||||
<el-input v-model="form.width" placeholder="请输入宽度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="内径" prop="innerDiameter">
|
||||
<el-input v-model="form.innerDiameter" placeholder="请输入内径" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-select v-model="form.isEnabled" placeholder="请选择是否启用" clearable>
|
||||
<el-option
|
||||
v-for="dict in dict.type.common_swicth"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row> -->
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
@@ -267,7 +190,6 @@
|
||||
|
||||
<script>
|
||||
import { listProduct, getProduct, delProduct, addProduct, updateProduct } from "@/api/wms/product";
|
||||
import CategorySelect from '@/components/KLPService/CategorySelect';
|
||||
import CategoryRenderer from '@/components/KLPService/Renderer/CategoryRenderer.vue';
|
||||
import UserSelect from '@/components/KLPService/UserSelect';
|
||||
// import BomPanel from '../bom/components/BomPanel.vue';
|
||||
@@ -276,7 +198,6 @@ import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
|
||||
export default {
|
||||
name: "Product",
|
||||
components: {
|
||||
CategorySelect,
|
||||
CategoryRenderer,
|
||||
UserSelect,
|
||||
// BomPanel,
|
||||
|
||||
@@ -161,27 +161,17 @@
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- <el-dialog title="参数" @close="bomDialogVisible = false" :visible.sync="bomDialogVisible" width="600px" append-to-body>
|
||||
<BomPanel :id="bomId" type="raw_material" @addBom="handleAddBom" :itemId="itemId" />
|
||||
</el-dialog> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRawMaterial, getRawMaterial, delRawMaterial, addRawMaterial, updateRawMaterial, addRawMaterialWithBom } from "@/api/wms/rawMaterial";
|
||||
import CategorySelect from "@/components/KLPService/CategorySelect/index.vue";
|
||||
import { listRawMaterial, getRawMaterial, delRawMaterial, updateRawMaterial, addRawMaterialWithBom } from "@/api/wms/rawMaterial";
|
||||
import CategoryRenderer from '@/components/KLPService/Renderer/CategoryRenderer.vue';
|
||||
// import BomPanel from '@/views/wms/bom/components/BomPanel.vue';
|
||||
// import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
|
||||
|
||||
export default {
|
||||
name: "RawMaterial",
|
||||
components: {
|
||||
CategorySelect,
|
||||
CategoryRenderer,
|
||||
// BomPanel,
|
||||
// BomInfoMini
|
||||
},
|
||||
dicts: ['common_swicth'],
|
||||
data() {
|
||||
|
||||
Reference in New Issue
Block a user