400 lines
14 KiB
Vue
400 lines
14 KiB
Vue
<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>
|