feat: 🚀 订阅功能

This commit is contained in:
2025-09-16 16:38:30 +08:00
parent eb1b66a066
commit d3a3ef2911
456 changed files with 40544 additions and 124 deletions

View File

@@ -0,0 +1,313 @@
<template>
<div v-if="formData.length" class="table-search" style="display: flex">
<div style="flex: 2">
<el-form ref="formRef" :model="_searchParams" :inline="true">
<template v-for="item in formData" :key="item.prop">
<el-form-item
:prop="item.prop"
:label-width="item.labelWidth ? item.labelWidth : '120px'"
class="form-item"
:label="item.label"
>
<!-- 输入框 -->
<template v-if="item.type === 'input'">
<el-input
:placeholder="item.placeholder"
:maxlength="item.maxlength || 255"
v-model.trim="_searchParams[`${item.prop}`]"
style="width: 224px"
@input="handleInput(item)"
@keyup.enter="handleFormSearch"
clearable
@clear="handleEmitClear(item)"
/>
</template>
<!-- 下拉框 -->
<template v-if="item.type === 'select'">
<el-select
v-model="_searchParams[`${item.prop}`]"
:placeholder="item.placeholder"
clearable
ref="selectRef"
style="width: 224px"
>
<el-option
v-for="option in item.options"
:label="option.label"
:value="option.value"
:key="option.label"
/>
</el-select>
</template>
<!-- 开始-结束-日期选择器 -->
<template v-if="item.type === 'daterange'">
<el-date-picker
v-model="_searchParams[`${item.prop}`]"
:type="item.type"
:start-placeholder="item.startPlaceholder"
:end-placeholder="item.endPlaceholder"
:defaultTime="item.value"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 205px"
@change="handlePicker(item)"
/>
</template>
<!-- 远程搜索供應商-->
<template
v-if="item.type === 'selectRemote' || item.type === 'selectRemote1' || item.type === 'selectRemote2'"
>
<el-select
v-model="_searchParams[`${item.prop}`]"
:placeholder="item.placeholder"
clearable
remote
filterable
@clear="handleClear(item)"
:loading="loading"
class="m-2 select"
remote-show-suffix
:remote-method="
(query:any) => {
remoteMethod(
query,
item
);
}
"
:disabled="item.disabled"
style="width: 224px"
>
<el-option
:label="option.label"
:value="option.value"
v-for="option in item.options"
:key="option.label"
/>
</el-select>
</template>
<!-- getProductLinesApi -->
<template v-if="item.type === 'selectMultipleRemote' || item.type === 'selectProductLinesRemote'">
<el-select
v-model="_searchParams[`${item.prop}`]"
:placeholder="item.placeholder"
remote
multiple
filterable
@clear="handleClear(item)"
:loading="loading"
class="m-2 select"
remote-show-suffix
:remote-method="
(query:any) => {
handleSelectMultipleRemote(
query,
item
);
}
"
:disabled="item.disabled"
style="width: 224px"
>
<el-option
:label="option.label"
:value="option.value"
v-for="option in item.options"
:key="option.label"
/>
</el-select>
</template>
<!--本地多选带模糊搜索 -->
<template v-if="item.type === 'selectMultiple'">
<!-- multiple -->
<el-select
v-model="_searchParams[`${item.prop}`]"
filterable
multiple
:disabled="item.disabled"
:placeholder="item.placeholder"
class="m-2 select"
style="width: 224px"
>
<!-- 循环渲染选项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 === 'selectMultipleD'">
<!-- multiple -->
<el-select
v-model="_searchParams[`${item.prop}`]"
filterable
clearable
:disabled="item.disabled"
:placeholder="item.placeholder"
class="m-2 select"
style="width: 224px"
>
<!-- 循环渲染选项label 为显示文本value 为实际提交值 -->
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
></el-option>
</el-select>
</template>
</el-form-item>
</template>
</el-form>
</div>
<div style="display: flex">
<el-button type="primary" @click="handleFormSearch" style="margin-bottom: 0"> 搜索 </el-button>
<el-button @click="handleFormReset" style="margin-bottom: 0">重置</el-button>
</div>
</div>
</template>
<script setup lang="ts" name="SearchForm">
import { verificationInput } from "./components/utils/verificationInput";
import { getSupplierApi, getCustomersApi, getProductLinesApi } from "@/api/modules/global";
const props = defineProps<{
formData: any[];
searchParams: Record<string, any>;
}>();
const emits = defineEmits<{
(e: "search", result: Record<string, any>): void;
(e: "reset", result: Record<string, any>): void;
}>();
let loading = ref(false);
const _searchParams = computed(() => {
return props.searchParams;
});
//日期选择后重选赋值
const handlePicker = (item: any) => {
const { prop } = item;
if (prop === "Time" || prop === "Time1") {
if (Array.isArray(_searchParams.value[prop]) && _searchParams.value[prop].length > 0) {
_searchParams.value[item.startDate] = _searchParams.value[prop].join(",");
} else {
_searchParams.value[item.startDate] = "";
}
}
};
//供应商
const getSupplier = async (keywords: any, item: any) => {
let org_number = _searchParams.value.org_number.join(",");
const result: any = await getSupplierApi({ keywords, org_number });
if (result?.code === 0) {
const { data } = result;
item.options = data;
}
};
//客戶
const getCustomers = async (keywords: any, item: any) => {
let org_number = _searchParams.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,
label: item.customer_name
});
});
item.options = 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;
}
}
};
//多选远程搜索
const handleSelectMultipleRemote = async (query: any, item: any) => {
loading.value = true;
if (!query) {
loading.value = false;
return;
}
//去除字符串首尾的所有空白字符。
let valClone = query.replace(/^\s*|\s*$/g, "");
if (!valClone.length) {
loading.value = false;
return;
}
if (item.type === "selectMultipleRemote") {
//客戶編碼
getCustomers(valClone, item);
} else if (item.type === "selectProductLinesRemote") {
//品线
getProductLines(valClone, item);
}
loading.value = false;
};
//单选远程搜索(供应商)
const remoteMethod = async (query: any, item: any) => {
loading.value = true;
if (!query) {
loading.value = false;
return;
}
//去除字符串首尾的所有空白字符。
let valClone = query.replace(/^\s*|\s*$/g, "");
if (!valClone.length) {
loading.value = false;
return;
}
//供应商
if (item.type === "selectRemote") {
getSupplier(valClone, item);
}
loading.value = false;
};
const handleClear = (item: any) => {
item.options = [];
};
//input输入监听
const handleInput = (item: any) => {
//验证
verificationInput(item, _searchParams);
};
const handleEmitClear = (item: any) => {
console.log(item);
};
const handleFormSearch = () => {
emits("search", _searchParams.value);
};
const handleFormReset = () => {
emits("reset", _searchParams.value);
};
</script>
<style lang="scss" scope>
@import "./index.scss";
</style>