Files
new_wms_admin/src/components/DetailsSearch/index.vue
2025-10-17 16:59:21 +08:00

400 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="search-box1" ref="searchRef">
<el-form
ref="ruleFormRef"
:model="_searchResult"
:inline="props.inline ? false : true"
class="form-box"
:show-message="false"
style="height: 100%; font-size: 14px"
>
<template v-for="item in formData" :key="item.prop">
<el-form-item
:label="item.label"
:prop="item.prop"
:label-width="labelWidth || '81px'"
:error="item.error"
:required="item.required"
:show-message="item.showMessage ? item.showMessage : false"
:inline-message="item.inlineMessage"
:style="item.style ? item.style : 'margin-right:8px;position: relative;'"
:class="item.class ? item.class : 'form-item'"
>
<!-- :required="item.required" -->
<template v-if="item.type === 'input'">
<el-input
v-model.trim="_searchResult[`${item.prop}`]"
:placeholder="item.placeholder"
:disabled="item.disabled"
:maxlength="item.maxLength ? item.maxLength : 255"
@input="valueVerify(item)"
>
</el-input>
</template>
<template v-if="item.type === 'textarea'">
<el-input
v-model.trim="_searchResult[`${item.prop}`]"
:placeholder="item.placeholder"
:disabled="item.disabled"
type="textarea"
>
</el-input>
</template>
<template v-if="item.type === 'inputs'">
<el-input
v-model.trim="_searchResult[`${item.startProp}`]"
:placeholder="item.startPlaceholder"
:disabled="item.startDisabled"
maxlength="255"
style="width: 144px !important"
@input="valueVerifyInputs(item)"
/>
<span style="margin: 0 3px">-</span>
<el-input
v-model.trim="_searchResult[`${item.endProp}`]"
:placeholder="item.endPlaceholder"
:disabled="item.endDisabled"
maxlength="255"
style="width: 144px !important"
@input="valueVerifyInputs(item)"
/>
</template>
<template v-if="item.type === 'select'">
<el-select
v-model="_searchResult[`${item.prop}`]"
:placeholder="item.placeholder"
clearable
:disabled="item.disabled"
>
<el-option
v-for="options in item.options"
:label="options.label"
:value="options.value"
:key="options.label"
/>
</el-select>
</template>
<template v-if="item.type === 'date'">
<el-date-picker
:disabled="item.disabled"
v-model="_searchResult[`${item.prop}`]"
:type="item.type"
:placeholder="item.placeholder"
format="YYYY-MM-DD"
:style="item.style"
value-format="YYYY-MM-DD"
/>
</template>
<template v-if="item.type === 'selectRemote' || item.type === 'selectRemoteUser'">
<el-select
v-model="_searchResult[`${item.prop}`]"
:placeholder="item.placeholder"
clearable
remote
reserve-keyword
filterable
ref="slectRef1"
class="m-2 select"
remote-show-suffix
:remote-method="
(query:any) => {
remoteMethod(
query,
item
);
}
"
:disabled="item.disabled"
>
<el-option
:label="option.label"
:value="option.value"
v-for="option in item.options"
:key="option.value"
/>
</el-select>
</template>
<!-- 多选带模糊搜索 -->
<template v-if="item.type === 'selectMultiple'">
<el-select
v-model="_searchResult[`${item.prop}`]"
multiple
filterable
:reserve-keyword="false"
@remove-tag="handleRomoveTag(item)"
:disabled="item.disabled"
:placeholder="item.placeholder"
>
<!-- 循环渲染选项label 为显示文本value 为实际提交值 -->
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
></el-option>
</el-select>
</template>
<template
v-if="item.type === 'selectMultipleRemoteCustomersNames' || item.type === 'selectProductLinesRemote'"
>
<!-- // filterable -->
<el-select
v-model="_searchResult[`${item.prop}`]"
:placeholder="item.placeholder"
remote
filterable
multiple
:reserve-keyword="false"
@remove-tag="handleTagRemove1(item)"
class="m-2 select"
:remote-method="(query:any)=> handleSelectMultipleRemote(query, item)"
:disabled="item.disabled"
style="max-height: 300px; overflow-y: auto"
>
<el-option
:label="option.label"
:value="option.value"
v-for="option in item.options"
:key="option.label"
/>
</el-select>
</template>
</el-form-item>
</template>
</el-form>
</div>
</template>
<script lang="ts" setup name="Search">
import { ref } from "vue";
import { FormInstance } from "element-plus";
import { getCustomersApi, getUsersApi, getProductLinesApi } from "@/api/modules/global";
import { integerRexg, numberDecimalSeparatorRexg } from "@/utils/regexp/index";
const ruleFormRef = ref<FormInstance>();
const props = defineProps<{
formData: any[];
labelWidth?: string;
ruleForm: Record<string, any>;
style?: string;
inline?: Boolean;
getSearchValue?: () => void;
selectMultipleRemoveTag?: () => void;
selectMultipleRemoteTag1?: () => void;
setRuleFormValue?: () => void;
}>();
let _searchResult = computed(() => {
return props.ruleForm;
});
const emits = defineEmits<{
(e: "getSearchValue", result: Record<string, any>): void;
(e: "setMaterialList", result: Record<string, any>): void;
(e: "setRuleFormValue", result: Record<string, any>): void;
(e: "selectMultipleRemoveTag", result: Record<string, any>): void;
(e: "selectMultipleRemoteTag1", result: Record<string, any>): void;
}>();
const handleRomoveTag = (item: any) => {
emits("selectMultipleRemoveTag", { item, org_number: _searchResult.value.org_number });
};
const handleTagRemove1 = (item: any) => {
if (!_searchResult.value[item.prop].length) {
item.options = [];
}
};
//客戶
const getCustomers = async (keywords: any, item: any) => {
let org_number = _searchResult.value.org_number.join(",");
const result: any = await getCustomersApi({ keywords, org_number });
if (result?.code === 0) {
const { data } = result;
if (Array.isArray(data) && data.length) {
let options: any = [];
data.forEach((item: any) => {
options.push({
value: item.customer_number + "_" + item.use_org_number,
label: item.customer_name + " " + `(${item.use_org_name})`,
id: item.use_org_number,
useOrgName: item.use_org_name
});
});
item.options = options;
} else {
item.options = [];
}
}
};
//品线
const getProductLines = async (keywords: any, item: any) => {
const result: any = await getProductLinesApi({ keywords });
if (result?.code === 0) {
const { data } = result;
if (Array.isArray(data) && data.length) {
let options: any = [];
data.forEach((item: any) => {
options.push({
value: item,
label: item
});
});
item.options = options;
} else {
item.options = [];
}
}
};
//订阅账号
const getUsers = async (keywords: any, item: any) => {
const result: any = await getUsersApi({ keywords });
if (result?.code === 0) {
const { data } = result;
if (Array.isArray(data) && data.length) {
let options: any = [];
data.forEach((item: any) => {
options.push({
value: item.dduid,
label: item.realname + " " + item.mobile
});
});
item.options = options;
} else {
item.options = [];
}
}
};
//远程搜索多选
const handleSelectMultipleRemote = (query: any, item: any) => {
if (!query) {
return;
}
item.options = [];
let valClone = query.replace(/^\s*|\s*$/g, "");
if (!valClone) {
return;
}
//客户
if (item.type === "selectMultipleRemoteCustomersNames") {
getCustomers(valClone, item);
}
if (item.type === "selectProductLinesRemote") {
getProductLines(valClone, item);
}
};
const remoteMethod = async (query: any, item: any) => {
if (!query) {
return;
}
let valClone = query.replace(/^\s*|\s*$/g, "");
if (!valClone) {
return;
}
if (item.type === "selectRemoteUser") {
getUsers(valClone, item);
}
};
//input输入验证
const valueVerify = (item: any) => {
//只能输入整数
if (item.reg === "integerRexg") {
let value = integerRexg(_searchResult.value[item.prop]);
_searchResult.value[item.prop] = value;
}
if (item.reg === "numberDecimalSeparatorRexg") {
let value = numberDecimalSeparatorRexg(_searchResult.value[item.prop]);
_searchResult.value[item.prop] = value;
}
emits("getSearchValue", {
val: _searchResult.value,
prop: item.prop
});
};
const valueVerifyInputs = (item: any) => {
//只能输入整数
if (item.reg === "integerRexg") {
let value = integerRexg(_searchResult.value[item.startProp]);
_searchResult.value[item.startProp] = value;
}
emits("getSearchValue", {
val: _searchResult.value,
prop: item.prop
});
};
defineExpose({
formElement: ruleFormRef
});
</script>
<style lang="scss" scope>
.search-box1 {
position: relative;
display: flex;
min-width: 1280px;
padding: 16px;
background: #ffffff;
border-radius: 6px;
// 单据头用的样式
.form-box {
// width: 85%;
.form-item {
width: 392px !important;
// height: 32px;
// 原代码有 height: 32px !important; 这会导致子元素高度超出后被遮盖
height: auto !important; // 改为自动高度
min-height: 32px; // 保留最小高度,未选择时对齐
margin-bottom: 8px !important;
.el-form-item__label {
font-size: 12px !important;
}
.el-select {
width: 392px;
}
.el-form-item--default {
width: 392px;
}
}
.form-item1 {
width: 594px !important;
// height: 32px;
// 原代码有 height: 32px !important; 这会导致子元素高度超出后被遮盖
height: auto !important; // 改为自动高度
min-height: 32px; // 保留最小高度,未选择时对齐
margin-bottom: 8px !important;
.el-form-item__label {
font-size: 12px !important;
}
.el-select {
width: 594px;
}
.el-form-item--default {
width: 594px;
}
}
.form-item2 {
width: 494px !important;
}
margin-bottom: 8px !important;
}
}
.el-form-item--default .el-form-item__label {
height: 32px;
margin-bottom: 8px;
// font-size: 12px;
line-height: 32px;
color: rgb(92 92 92 / 100%);
}
</style>