fix: 🧩 文章列表查询功能文章分类2级查询ID未传
This commit is contained in:
9
src/components.d.ts
vendored
9
src/components.d.ts
vendored
@@ -7,16 +7,12 @@ export {}
|
||||
|
||||
declare module "vue" {
|
||||
export interface GlobalComponents {
|
||||
Css: typeof import("./components/SearchForm/components/css.vue")["default"];
|
||||
ElAside: typeof import("element-plus/es")["ElAside"];
|
||||
ElAutocomplete: typeof import("element-plus/es")["ElAutocomplete"];
|
||||
ElBreadcrumb: typeof import("element-plus/es")["ElBreadcrumb"];
|
||||
ElBreadcrumbItem: typeof import("element-plus/es")["ElBreadcrumbItem"];
|
||||
ElButton: typeof import("element-plus/es")["ElButton"];
|
||||
ElCarousel: typeof import("element-plus/es")["ElCarousel"];
|
||||
ElCarouselItem: typeof import("element-plus/es")["ElCarouselItem"];
|
||||
ElCheckbox: typeof import("element-plus/es")["ElCheckbox"];
|
||||
ElCheckboxGroup: typeof import("element-plus/es")["ElCheckboxGroup"];
|
||||
ElColorPicker: typeof import("element-plus/es")["ElColorPicker"];
|
||||
ElContainer: typeof import("element-plus/es")["ElContainer"];
|
||||
ElDatePicker: typeof import("element-plus/es")["ElDatePicker"];
|
||||
ElDialog: typeof import("element-plus/es")["ElDialog"];
|
||||
@@ -38,7 +34,6 @@ declare module "vue" {
|
||||
ElOption: typeof import("element-plus/es")["ElOption"];
|
||||
ElPagination: typeof import("element-plus/es")["ElPagination"];
|
||||
ElRadio: typeof import("element-plus/es")["ElRadio"];
|
||||
ElRadioButton: typeof import("element-plus/es")["ElRadioButton"];
|
||||
ElRadioGroup: typeof import("element-plus/es")["ElRadioGroup"];
|
||||
ElScrollbar: typeof import("element-plus/es")["ElScrollbar"];
|
||||
ElSelect: typeof import("element-plus/es")["ElSelect"];
|
||||
@@ -49,8 +44,6 @@ declare module "vue" {
|
||||
ElTabPane: typeof import("element-plus/es")["ElTabPane"];
|
||||
ElTabs: typeof import("element-plus/es")["ElTabs"];
|
||||
ElTag: typeof import("element-plus/es")["ElTag"];
|
||||
ElTooltip: typeof import("element-plus/es")["ElTooltip"];
|
||||
ElTree: typeof import("element-plus/es")["ElTree"];
|
||||
ElTreeSelect: typeof import("element-plus/es")["ElTreeSelect"];
|
||||
ElUpload: typeof import("element-plus/es")["ElUpload"];
|
||||
IEpArrowDown: typeof import("~icons/ep/arrow-down")["default"];
|
||||
|
||||
@@ -77,9 +77,10 @@
|
||||
:check-strictly="false"
|
||||
show-checkbox
|
||||
style="width: 224px"
|
||||
clearable
|
||||
:collapse-tags="true"
|
||||
:collapse-tags="false"
|
||||
ref="treeSelectRef"
|
||||
@change="handleTreeSelectChange(item)"
|
||||
@remove-tag="handleRemoveTag(item, $event)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 双 -->
|
||||
@@ -158,12 +159,12 @@
|
||||
<script lang="ts" setup name="SearchFormItem">
|
||||
// import { verificationInput } from "./utils/verificationInput";
|
||||
import { getCountryListApi } from "@/api/modules/global";
|
||||
import $Bus from "@/utils/mittBus";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { ref } from "vue";
|
||||
// import { ref } from "vue";
|
||||
const $router = useRouter();
|
||||
|
||||
const routeName: any = ref($router.currentRoute.value.name);
|
||||
const treeSelectRef = ref<any>(null);
|
||||
// const userStore: any = useUserStore();
|
||||
interface SearchFormItem {
|
||||
item: { [key: string]: any };
|
||||
@@ -171,17 +172,8 @@ interface SearchFormItem {
|
||||
search: (params: any) => void; // 搜索方法
|
||||
handleEmitClear?: (item: any) => void;
|
||||
}
|
||||
let selectInputValue = ref(1);
|
||||
const options = [
|
||||
{
|
||||
value: 1,
|
||||
label: "序号"
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: "数字序列号"
|
||||
}
|
||||
];
|
||||
// let selectInputValue = ref(1);
|
||||
|
||||
// const treeSelectValue = ref(null);
|
||||
const props = defineProps<SearchFormItem>();
|
||||
const _searchParam = computed(() => props.searchParam);
|
||||
@@ -220,7 +212,119 @@ const remoteMethod = async (query: any, item: any) => {
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// 关闭标签时同步 - 修复版
|
||||
const handleRemoveTag = (item: any, removedValue: any) => {
|
||||
nextTick(() => {
|
||||
// 从item.options获取树形数据,这是我们传递给组件的数据源
|
||||
const allNodes = Array.isArray(item.options) ? item.options : [];
|
||||
console.log(allNodes, "=allNodes=");
|
||||
// 找到被删除的节点
|
||||
const removedNode = findNode(allNodes, removedValue);
|
||||
console.log(removedNode, "=removedNode=");
|
||||
let ids: any = [];
|
||||
if (removedNode) {
|
||||
// 判断被删除的是父节点还是子节点
|
||||
if (removedNode.children && Array.isArray(removedNode.children) && removedNode.children.length > 0) {
|
||||
// 是父节点,需要删除所有子节点
|
||||
const childIds = getAllChildIds(removedNode);
|
||||
// 从选中值中移除父节点和所有子节点
|
||||
ids = (_searchParam.value[item.prop] || []).filter((id: any) => !childIds.includes(id) && id !== removedNode.id);
|
||||
nextTick(() => {
|
||||
_searchParam.value[item.prop] = ids;
|
||||
_searchParam.value[item.prop1] = ids.join(",");
|
||||
});
|
||||
} else {
|
||||
// 是子节点,需要找到其父节点并删除
|
||||
const parentNode = findParentNode(allNodes, removedValue);
|
||||
if (parentNode) {
|
||||
// 从选中值中移除子节点和父节点
|
||||
ids = (_searchParam.value[item.prop] || []).filter((id: any) => id !== removedValue && id !== parentNode.id);
|
||||
nextTick(() => {
|
||||
_searchParam.value[item.prop] = ids;
|
||||
_searchParam.value[item.prop1] = ids.join(",");
|
||||
});
|
||||
} else {
|
||||
ids = (_searchParam.value[item.prop] || []).filter((id: any) => id !== removedValue && id !== parentNode.id);
|
||||
nextTick(() => {
|
||||
_searchParam.value[item.prop] = ids;
|
||||
_searchParam.value[item.prop1] = ids.join(",");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncCheckedIds(item);
|
||||
});
|
||||
};
|
||||
|
||||
// 辅助方法:查找节点
|
||||
const findNode = (nodes: any[], value: any): any => {
|
||||
if (!Array.isArray(nodes)) return null;
|
||||
|
||||
for (const node of nodes) {
|
||||
if (node?.id === value) {
|
||||
return node;
|
||||
}
|
||||
if (node?.children && Array.isArray(node.children) && node.children.length > 0) {
|
||||
const found = findNode(node.children, value);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 辅助方法:查找父节点
|
||||
const findParentNode = (nodes: any[], value: any, parent: any = null): any => {
|
||||
if (!Array.isArray(nodes)) return null;
|
||||
|
||||
for (const node of nodes) {
|
||||
if (node?.id === value) {
|
||||
return parent;
|
||||
}
|
||||
if (node?.children && Array.isArray(node.children) && node.children.length > 0) {
|
||||
const foundParent = findParentNode(node.children, value, node);
|
||||
if (foundParent) return foundParent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 辅助方法:获取所有子节点ID
|
||||
const getAllChildIds = (node: any): any[] => {
|
||||
let ids: any[] = [];
|
||||
if (node?.children && Array.isArray(node.children) && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
if (child?.id) {
|
||||
ids.push(child.id);
|
||||
ids = [...ids, ...getAllChildIds(child)];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
};
|
||||
|
||||
// 统一同步选中ID的方法
|
||||
const syncCheckedIds = (item: any) => {
|
||||
// 获取所有全选中的节点(包括父节点)
|
||||
const allCheckedNodes = treeSelectRef.value.getCheckedNodes(false, false);
|
||||
|
||||
const allCheckedIds = allCheckedNodes.map((node: any) => node.id);
|
||||
_searchParam.value[item.prop] = allCheckedIds;
|
||||
// 同步到搜索参数
|
||||
_searchParam.value[item.prop1] = allCheckedIds.length ? allCheckedIds.join(",") : null;
|
||||
};
|
||||
|
||||
const handleTreeSelectChange = (item: any) => {
|
||||
console.log(routeName.value);
|
||||
if (routeName.value === "articleListIndex") {
|
||||
// 通过ref获取组件实例
|
||||
if (treeSelectRef.value) {
|
||||
syncCheckedIds(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_searchParam.value[item.prop].length) {
|
||||
let values = cloneDeep(_searchParam.value[item.prop]);
|
||||
_searchParam.value[item.prop1] = values.join(",");
|
||||
@@ -236,7 +340,7 @@ const handleClear = (item: any) => {
|
||||
const handleInput = (item: any) => {
|
||||
console.log(item, "=====item=====");
|
||||
//验证
|
||||
// verificationInput(item, _searchParam, selectInputValue.value);
|
||||
verificationInput(item, _searchParam, selectInputValue.value);
|
||||
};
|
||||
const handleChange = (item: any) => {
|
||||
_searchParam.value[item.endProp] = "";
|
||||
@@ -249,16 +353,6 @@ const handleChange = (item: any) => {
|
||||
|
||||
const handleEmitClear = (item: any) => {
|
||||
console.log(item);
|
||||
|
||||
if (routeName.value === "barCode") {
|
||||
$Bus.emit("clearBarCodeCreateUser");
|
||||
}
|
||||
if (routeName.value === "boxCode") {
|
||||
$Bus.emit("clearBoxCodeCreateUser");
|
||||
}
|
||||
if (routeName.value === "boxMarkIndex") {
|
||||
$Bus.emit("clearBoxMarkIndexCreator");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
|
||||
299
src/components/SearchForm/components/css.vue
Normal file
299
src/components/SearchForm/components/css.vue
Normal file
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 输入框 -->
|
||||
<template v-if="item.type === 'input'">
|
||||
<el-input
|
||||
:placeholder="item.placeholder"
|
||||
:maxlength="item.maxlength || 255"
|
||||
v-model="_searchParam[`${item.prop}`]"
|
||||
style="width: 224px"
|
||||
@input="handleInput(item)"
|
||||
@keyup.enter="search"
|
||||
clearable
|
||||
@clear="handleEmitClear(item)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 下拉框 -->
|
||||
<template v-if="item.type === 'select'">
|
||||
<el-select
|
||||
v-model="_searchParam[`${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="_searchParam[`${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'">
|
||||
<el-select
|
||||
v-model="_searchParam[`${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.name" :value="option.id" v-for="option in item.options" :key="option.id" />
|
||||
</el-select>
|
||||
<!--item.prop -->
|
||||
</template>
|
||||
<!-- el-tree-select -->
|
||||
<template v-if="item.type === 'treeSelect'">
|
||||
<el-tree-select
|
||||
v-model="_searchParam[`${item.prop}`]"
|
||||
:data="item.options"
|
||||
:placeholder="item.placeholder"
|
||||
multiple
|
||||
:render-after-expand="false"
|
||||
:check-strictly="false"
|
||||
show-checkbox
|
||||
style="width: 224px"
|
||||
clearable
|
||||
:collapse-tags="true"
|
||||
ref="treeSelectRef"
|
||||
@change="handleTreeSelectChange(item)"
|
||||
@remove-tag="handleRemoveTag(item)"
|
||||
/>
|
||||
</template>
|
||||
<!-- 双 -->
|
||||
<template v-if="item.type === 'inputs'">
|
||||
<el-input
|
||||
v-model="_searchParam[`${item.startProp}`]"
|
||||
:placeholder="item.startPlaceholder"
|
||||
:disabled="item.disabled"
|
||||
maxlength="255"
|
||||
style="width: 105px !important"
|
||||
@input="handleInput(item)"
|
||||
>
|
||||
</el-input>
|
||||
<span style="margin: 0 3px">-</span>
|
||||
<el-input
|
||||
v-model="_searchParam[`${item.endProp}`]"
|
||||
:placeholder="item.endPlaceholder"
|
||||
:disabled="item.disabled"
|
||||
maxlength="255"
|
||||
style="width: 106px !important"
|
||||
@input="handleInput(item)"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="item.type === 'dateTimerange'">
|
||||
<el-date-picker
|
||||
v-model="_searchParam[`${item.prop}`]"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
:start-placeholder="item.startPlaceholder"
|
||||
:end-placeholder="item.endPlaceholder"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 205px"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-if="item.type === 'selectInputs'">
|
||||
<div></div>
|
||||
<el-select
|
||||
v-model="selectInputValue"
|
||||
placeholder="Select"
|
||||
style="width: 102px; height: 30px; margin-right: 6px"
|
||||
class="selectInputs-box"
|
||||
@change="handleChange(item)"
|
||||
>
|
||||
<el-option
|
||||
v-for="optionsItem in options"
|
||||
:key="optionsItem.value"
|
||||
:label="optionsItem.label"
|
||||
:value="optionsItem.value"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-input
|
||||
v-model="_searchParam[`${item.startProp}`]"
|
||||
:placeholder="item.startPlaceholder"
|
||||
:disabled="item.disabled"
|
||||
maxlength="255"
|
||||
style="width: 105px !important"
|
||||
@input="handleInput(item)"
|
||||
>
|
||||
</el-input>
|
||||
<span style="margin: 0 3px">-</span>
|
||||
<el-input
|
||||
v-model="_searchParam[`${item.endProp}`]"
|
||||
:placeholder="item.endPlaceholder"
|
||||
:disabled="item.disabled"
|
||||
maxlength="255"
|
||||
style="width: 106px !important"
|
||||
@input="handleInput(item)"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="SearchFormItem">
|
||||
// import { verificationInput } from "./utils/verificationInput";
|
||||
import { getCountryListApi } from "@/api/modules/global";
|
||||
import $Bus from "@/utils/mittBus";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
// import { ref } from "vue";
|
||||
const $router = useRouter();
|
||||
|
||||
const routeName: any = ref($router.currentRoute.value.name);
|
||||
const treeSelectRef = ref<any>(null);
|
||||
// const userStore: any = useUserStore();
|
||||
interface SearchFormItem {
|
||||
item: { [key: string]: any };
|
||||
searchParam: { [key: string]: any };
|
||||
search: (params: any) => void; // 搜索方法
|
||||
handleEmitClear?: (item: any) => void;
|
||||
}
|
||||
let selectInputValue = ref(1);
|
||||
const options = [
|
||||
{
|
||||
value: 1,
|
||||
label: "序号"
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: "数字序列号"
|
||||
}
|
||||
];
|
||||
// const treeSelectValue = ref(null);
|
||||
const props = defineProps<SearchFormItem>();
|
||||
const _searchParam = computed(() => props.searchParam);
|
||||
|
||||
let loading = ref(false);
|
||||
//日期选择后重选赋值
|
||||
const handlePicker = (item: any) => {
|
||||
const { prop } = item;
|
||||
if (Array.isArray(_searchParam.value[prop]) && _searchParam.value[prop].length > 0) {
|
||||
let _date: any = cloneDeep(_searchParam.value[prop]);
|
||||
_date[0] = _date[0] + " " + "00:00:00";
|
||||
_date[1] = _date[1] + " " + "23:59:59";
|
||||
_searchParam.value[item.startDate] = _date.join(",");
|
||||
} else {
|
||||
_searchParam.value[item.startDate] = "";
|
||||
}
|
||||
};
|
||||
//远程搜索(供应商)
|
||||
const remoteMethod = async (query: any, item: any) => {
|
||||
console.log(query, item);
|
||||
loading.value = true;
|
||||
if (!query) {
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
let valClone = query.replace(/^\s*|\s*$/g, "");
|
||||
if (!valClone.length) {
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
const result = await getCountryListApi({ name: valClone });
|
||||
if (result?.code === 0) {
|
||||
const { data } = result;
|
||||
console.log(data, "=======data=======");
|
||||
item.options = data;
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// 关闭标签时同步
|
||||
const handleRemoveTag = item => {
|
||||
console.log("触发了吗");
|
||||
nextTick(() => {
|
||||
syncCheckedIds(item);
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
// 统一同步选中ID的方法
|
||||
const syncCheckedIds = (item: any) => {
|
||||
// 获取所有全选中的节点(包括父节点)
|
||||
const allCheckedNodes = treeSelectRef.value.getCheckedNodes(false, false);
|
||||
const allCheckedIds = allCheckedNodes.map((node: any) => node.id);
|
||||
_searchParam.value[item.prop] = allCheckedIds;
|
||||
// 同步到搜索参数
|
||||
_searchParam.value[item.prop1] = allCheckedIds.length ? allCheckedIds.join(",") : null;
|
||||
};
|
||||
|
||||
const handleTreeSelectChange = (item: any) => {
|
||||
console.log(routeName.value);
|
||||
if (routeName.value === "articleListIndex") {
|
||||
// 通过ref获取组件实例
|
||||
if (treeSelectRef.value) {
|
||||
syncCheckedIds(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_searchParam.value[item.prop].length) {
|
||||
let values = cloneDeep(_searchParam.value[item.prop]);
|
||||
_searchParam.value[item.prop1] = values.join(",");
|
||||
} else {
|
||||
_searchParam.value[item.prop1] = "";
|
||||
}
|
||||
};
|
||||
const handleClear = (item: any) => {
|
||||
item.options = [];
|
||||
};
|
||||
|
||||
//input输入监听
|
||||
const handleInput = (item: any) => {
|
||||
console.log(item, "=====item=====");
|
||||
//验证
|
||||
// verificationInput(item, _searchParam, selectInputValue.value);
|
||||
};
|
||||
const handleChange = (item: any) => {
|
||||
_searchParam.value[item.endProp] = "";
|
||||
_searchParam.value[item.startProp] = "";
|
||||
_searchParam.value["serialNumberBegin"] = "";
|
||||
_searchParam.value["numberCodeBegin"] = "";
|
||||
_searchParam.value["serialNumberEnd"] = "";
|
||||
_searchParam.value["numberCodeEnd"] = "";
|
||||
};
|
||||
|
||||
const handleEmitClear = (item: any) => {
|
||||
console.log(item);
|
||||
|
||||
if (routeName.value === "barCode") {
|
||||
$Bus.emit("clearBarCodeCreateUser");
|
||||
}
|
||||
if (routeName.value === "boxCode") {
|
||||
$Bus.emit("clearBoxCodeCreateUser");
|
||||
}
|
||||
if (routeName.value === "boxMarkIndex") {
|
||||
$Bus.emit("clearBoxMarkIndexCreator");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
@import "../index.scss";
|
||||
</style>
|
||||
@@ -3,6 +3,8 @@
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 344px !important;
|
||||
height: 32px;
|
||||
margin-right: 12px !important;
|
||||
|
||||
372
vite.config.ts.timestamp-1758267544139-041bd9def899c.mjs
Normal file
372
vite.config.ts.timestamp-1758267544139-041bd9def899c.mjs
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user