fix: 🧩 树状结构支持多选

This commit is contained in:
2025-06-06 14:05:40 +08:00
parent f2ee833412
commit 6f8a3e72a5
25 changed files with 96 additions and 85 deletions

21
src/components.d.ts vendored
View File

@@ -7,11 +7,6 @@ export {}
declare module "vue" {
export interface GlobalComponents {
403: typeof import("./components/ErrorMessage/403.vue")["default"];
404: typeof import("./components/ErrorMessage/404.vue")["default"];
500: typeof import("./components/ErrorMessage/500.vue")["default"];
ColSetting: typeof import("./components/ProTable/components/ColSetting.vue")["default"];
Editor: typeof import("./components/Editor/index.vue")["default"];
ElAside: typeof import("element-plus/es")["ElAside"];
ElAutocomplete: typeof import("element-plus/es")["ElAutocomplete"];
ElBreadcrumb: typeof import("element-plus/es")["ElBreadcrumb"];
@@ -58,10 +53,6 @@ declare module "vue" {
ElTree: typeof import("element-plus/es")["ElTree"];
ElTreeSelect: typeof import("element-plus/es")["ElTreeSelect"];
ElUpload: typeof import("element-plus/es")["ElUpload"];
Empty: typeof import("./components/ProTable/components/Empty.vue")["default"];
FormTable: typeof import("./components/FormTable/index.vue")["default"];
Grid: typeof import("./components/Grid/index.vue")["default"];
GridItem: typeof import("./components/Grid/components/GridItem.vue")["default"];
IEpArrowDown: typeof import("~icons/ep/arrow-down")["default"];
IEpCircleClose: typeof import("~icons/ep/circle-close")["default"];
IEpFolderDelete: typeof import("~icons/ep/folder-delete")["default"];
@@ -69,19 +60,7 @@ declare module "vue" {
IEpRemove: typeof import("~icons/ep/remove")["default"];
IEpSearch: typeof import("~icons/ep/search")["default"];
IEpSwitchButton: typeof import("~icons/ep/switch-button")["default"];
ImportExcel: typeof import("./components/ImportExcel/index.vue")["default"];
Loading: typeof import("./components/Loading/index.vue")["default"];
Pagination: typeof import("./components/ProTable/components/Pagination.vue")["default"];
ProTable: typeof import("./components/ProTable/index.vue")["default"];
RouterLink: typeof import("vue-router")["RouterLink"];
RouterView: typeof import("vue-router")["RouterView"];
RulesForm: typeof import("./components/rulesForm/index.vue")["default"];
SearchForm: typeof import("./components/SearchForm/index.vue")["default"];
SearchFormItem: typeof import("./components/SearchForm/components/SearchFormItem.vue")["default"];
TableColumn: typeof import("./components/ProTable/components/TableColumn.vue")["default"];
UploadImg: typeof import("./components/Upload/UploadImg.vue")["default"];
UploadImgs: typeof import("./components/Upload/UploadImgs.vue")["default"];
UploadVideo: typeof import("./components/Upload/UploadVideo.vue")["default"];
WangEditor: typeof import("./components/WangEditor/index.vue")["default"];
}
}

View File

@@ -72,10 +72,14 @@
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"
@change="handleTreeSelectChange(item)"
/>
</template>
<!-- 双 -->
@@ -178,7 +182,7 @@ const options = [
label: "数字序列号"
}
];
// const treeSelectValue = ref(null);
const props = defineProps<SearchFormItem>();
const _searchParam = computed(() => props.searchParam);
@@ -216,7 +220,14 @@ const remoteMethod = async (query: any, item: any) => {
}
loading.value = false;
};
const handleTreeSelectChange = (item: any) => {
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 = [];
};

View File

@@ -12,19 +12,19 @@ export const verificationInput = (item: any, _searchParam: any, selectInputValue
//序列号区间值开始 限制只能输入正整数
if (startProp === "startNumber") {
_searchParam.value[startProp] = integerNumber(_searchParam.value[startProp]);
if (selectInputValue === 1) {
if (selectInputValue == 1) {
_searchParam.value["serialNumberBegin"] = _searchParam.value[startProp];
}
if (selectInputValue === 2) {
if (selectInputValue == 2) {
_searchParam.value["numberCodeBegin"] = _searchParam.value[startProp];
}
}
if (endProp === "endNumber") {
_searchParam.value[endProp] = integerNumber(_searchParam.value[endProp]);
if (selectInputValue === 1) {
if (selectInputValue == 1) {
_searchParam.value["serialNumberEnd"] = _searchParam.value[endProp];
}
if (selectInputValue === 2) {
if (selectInputValue == 2) {
_searchParam.value["numberCodeEnd"] = _searchParam.value[endProp];
}
}

View File

@@ -1,4 +1,5 @@
.el-form-item--default {
height: auto !important;
margin-bottom: 8px;
}
.form-item {
@@ -6,7 +7,7 @@
height: 32px;
margin-right: 12px !important;
.form-item-select {
width: 224px !important;
width: 254px !important;
}
}
.form-box1 {

View File

@@ -87,9 +87,10 @@ export const useTable = (
// 处理查询参数,可以给查询参数加自定义前缀操作
let nowSearchParam: Table.StateProps["searchParam"] = {};
// 防止手动清空输入框携带参数(这里可以自定义查询参数前缀)
console.log(state.searchParam, "=state.searchParam=");
for (let key in state.searchParam) {
//剔除日期参数
if (key !== "Time" && key !== "Time1") {
if (key !== "Time" && key !== "Time1" && key !== "treeIds") {
// * 某些情况下参数为 false/0 也应该携带参数
if (state.searchParam[key] || state.searchParam[key] === false || state.searchParam[key] === 0) {
nowSearchParam[key] = state.searchParam[key];

View File

@@ -97,6 +97,8 @@
// table-search 表格搜索样式
.table-search {
// height: auto;
// max-height: 80px;
margin-bottom: 10px;
.el-form {
.el-form-item__content > * {

View File

@@ -24,7 +24,7 @@
</el-table-column>
<el-table-column prop="is_show" label="是否显示">
<template #default="{ row }">
{{ row.is_show === 1 ? "✔️" : "❌" }}
{{ row.is_show == 1 ? "✔️" : "❌" }}
</template>
</el-table-column>
<el-table-column prop="icon" label="图片">

View File

@@ -1,5 +1,6 @@
interface FormItem {
prop: string;
prop1?: string;
label?: string;
placeholder?: string;
type: string;
@@ -25,7 +26,8 @@ export const FORM_DATA: FormItem[] = [
},
{
prop: "category_id",
prop: "treeIds",
prop1: "category_id",
placeholder: "请选择",
type: "treeSelect",
isArray: true,

View File

@@ -49,12 +49,12 @@ export const COLUMNS = [
width: 160
},
{
align: "center",
label: "状态",
prop: "enabled",
width: 80
},
// {
// align: "center",
// label: "状态",
// prop: "enabled",
// width: 80
// },
{ prop: "operation", label: "操作", fixed: "right", width: 200 }
];

View File

@@ -15,9 +15,9 @@
<template #image="scope">
<el-image :src="scope.row.image ? h + scope.row.image : '--'" style="width: 60px; height: 60px" />
</template>
<template #enabled="scope">
<el-tag type="success" effect="dark">{{ scope.row.enabled === 1 ? "启用" : "禁用" }}</el-tag>
</template>
<!-- <template #enabled="scope">
<el-tag type="success" effect="dark">{{ scope.row.enabled == 1 ? "启用" : "禁用" }}</el-tag>
</template> -->
<template #operation="scope">
<el-button size="small" type="primary" @click="handleBtnClick('edit', scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleBtnClick('del', scope.row)">删除</el-button>

View File

@@ -74,7 +74,7 @@ export const EDIT_FORM_DATA: FormItem[] = [
{
prop: "banner_id",
placeholder: "请选择",
type: "select",
type: "treeSelect",
label: "Banner分类: ",
options: []
},
@@ -170,7 +170,7 @@ export const EDIT_FORM_DATA1: FormItem[] = [
{
prop: "banner_id",
placeholder: "请选择",
type: "select",
type: "treeSelect",
label: "Banner分类: ",
options: []
},

View File

@@ -1,5 +1,6 @@
interface FormItem {
prop: string;
prop1?: string;
label?: string;
placeholder?: string;
type: string;
@@ -25,9 +26,10 @@ export const FORM_DATA: FormItem[] = [
},
{
prop: "banner_id",
prop: "treeIds",
prop1: "banner_id",
placeholder: "请选择",
type: "select",
type: "treeSelect",
isArray: true,
label: "Banner分类: ",
options: []

View File

@@ -18,8 +18,8 @@
<el-input v-model="scope.row.sort" @blur="handleBlur(scope.row)" @input="handleInput(scope.row)"></el-input>
</template>
<template #status="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status === 1 ? "启用" : "禁用"
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status == 1 ? "启用" : "禁用"
}}</el-tag>
</template>
<template #operation="scope">
@@ -85,6 +85,7 @@ import { useMsg } from "@/hooks/useMsg";
import { useExport } from "@/hooks/useExport";
import { integerRexg } from "@/utils/regexp/index";
import { getProductCategoryListApi } from "@/api/modules/productList";
// import { addLabelValue } from "@/utils/addLabelValue";
// 图片地址
import { h } from "@/utils/url";
// 列表接口
@@ -123,7 +124,7 @@ const dataStore = reactive<any>({
isFirstRequest: true
});
const selectedNodes = ref(null);
const selectedNodes = ref<any>(null);
const treeRef = ref(null);
@@ -203,24 +204,30 @@ const getSystemUrls = async (node: any, resolve: any) => {
}
}
};
const setImgOrVideo = () => {
if (dataStore.editRuleForm.type === "image") {
dataStore.editFormData = EDIT_FORM_DATA;
const setImgOrVideo = (result: any) => {
if (result?.data?.type === "image") {
dataStore.editFormData = cloneDeep(EDIT_FORM_DATA);
}
if (dataStore.editRuleForm.type === "video") {
dataStore.editFormData = EDIT_FORM_DATA1;
if (result?.data?.type === "video") {
dataStore.editFormData = cloneDeep(EDIT_FORM_DATA1);
}
getBannerClassEditList();
};
// 详情
const getBannerRead = async (id: any) => {
selectedNodes.value = "";
dataStore.data = [];
dataStore.title = "编辑Banner";
dataStore.visible = true;
const result = await getBannerReadApi(id);
if (result?.code === 0) {
dataStore.editRuleForm = result?.data;
setImgOrVideo();
// setImgOrVideo(result);
await setImgOrVideo(result);
dataStore.editRuleForm = await result?.data;
getProductCategoryList();
if (dataStore.editRuleForm.link && dataStore.editRuleForm.link_to) {
let { id, name, link } = dataStore.editRuleForm.link_echo_data;
if (!id || !name || !link) {
@@ -273,12 +280,12 @@ const getBannerUp = async () => {
const getBannerClassEditList = async () => {
const result = await getBannerClassListApi();
if (result?.code === 0) {
let arr: any = [];
result?.data?.forEach((item: any) => {
arr.push({ value: item.id, label: item.name });
});
dataStore.formData[1].options = arr;
dataStore.editFormData[5].options = arr;
// let arr: any = [];
// result?.data?.forEach((item: any) => {
// arr.push({ value: item.id, label: item.name });
// });
dataStore.formData[1].options = addLabelValue(result?.data);
dataStore.editFormData[5].options = addLabelValue(result?.data);
}
};
getBannerClassEditList();

View File

@@ -25,7 +25,7 @@
</el-table-column>
<el-table-column prop="is_show" label="是否显示">
<template #default="{ row }">
{{ row.is_show === 1 ? "✔️" : "❌" }}
{{ row.is_show == 1 ? "✔️" : "❌" }}
</template>
</el-table-column>
<el-table-column label="操作" :width="350">

View File

@@ -1,5 +1,6 @@
interface FormItem {
prop: string;
prop1?: string;
label?: string;
placeholder?: string;
type: string;
@@ -25,7 +26,8 @@ export const FORM_DATA: FormItem[] = [
},
{
prop: "category_id",
prop: "treeIds",
prop1: "category_id",
placeholder: "请选择",
type: "treeSelect",
isArray: true,

View File

@@ -15,8 +15,8 @@
<el-image :src="scope.row.image ? h + scope.row.image : ''" style="width: 60px; height: 60px" />
</template>
<template #status="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status === 1 ? "启用" : "禁用"
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status == 1 ? "启用" : "禁用"
}}</el-tag>
</template>
<template #sort="scope">

View File

@@ -26,7 +26,7 @@
</el-table-column>
<el-table-column prop="is_show" label="是否显示">
<template #default="{ row }">
{{ row.is_show === 1 ? "✔️" : "❌" }}
{{ row.is_show == 1 ? "✔️" : "❌" }}
</template>
</el-table-column>
<el-table-column label="操作" :width="350">
@@ -207,12 +207,12 @@ const reset = () => {
};
//重置表单配置
const resetFrom = () => {
if (dataStore.selectLevel === 1 || dataStore.selectLevel === 2) {
if (dataStore.selectLevel == 1 || dataStore.selectLevel == 2) {
dataStore.ruleForm = cloneDeep(RULE_FORM_LV1);
dataStore.formData = cloneDeep(FORM_DATA_LV1);
dataStore.rules = RULES_LV1;
}
if (dataStore.selectLevel === 3) {
if (dataStore.selectLevel == 3) {
dataStore.ruleForm = cloneDeep(RULE_FORM_LV2);
dataStore.formData = cloneDeep(FORM_DATA_LV2);
dataStore.rules = RULES_LV2;

View File

@@ -44,7 +44,7 @@
<el-table-column v-for="attrId in selectedAttrIds" :key="attrId" :label="findAttrById(attrId)?.attr_name">
<template #default="{ row }">
<el-form :model="row">
<el-form-item v-if="findAttrById(attrId)?.attr_type === 1" style="margin: 0">
<el-form-item v-if="findAttrById(attrId)?.attr_type == 1" style="margin: 0">
<el-select v-model="findAttrObjInRow(row, attrId).attr_value" placeholder="请选择">
<el-option
v-for="prop in findAttrById(attrId)?.props"

View File

@@ -1,5 +1,6 @@
interface FormItem {
prop: string;
prop1?: string;
label?: string;
placeholder?: string;
type: string;
@@ -31,7 +32,8 @@ export const FORM_DATA: FormItem[] = [
label: "型号: "
},
{
prop: "category_id",
prop: "treeIds",
prop1: "category_id",
placeholder: "请选择",
type: "treeSelect",
isArray: true,

View File

@@ -15,13 +15,13 @@
<el-image :src="scope.row.cover_image ? h + scope.row.cover_image : ''" style="width: 60px; height: 60px" />
</template>
<template #status="scope">
<el-tag effect="dark" :type="scope.row.status === 1 ? 'success' : 'danger'">{{
scope.row.status === 1 ? "启用" : "禁用"
<el-tag effect="dark" :type="scope.row.status == 1 ? 'success' : 'danger'">{{
scope.row.status == 1 ? "启用" : "禁用"
}}</el-tag>
</template>
<template #is_show="scope">
<el-tag :type="scope.row.is_show === 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.is_show === 1 ? "已上架" : "未上架"
<el-tag :type="scope.row.is_show == 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.is_show == 1 ? "已上架" : "未上架"
}}</el-tag>
</template>
<!-- sort -->
@@ -31,9 +31,9 @@
<template #operation="scope">
<el-button
size="small"
:type="scope.row.is_show === 1 ? 'danger' : 'primary'"
:type="scope.row.is_show == 1 ? 'danger' : 'primary'"
@click="handleBtnClick('上下架', scope.row)"
>{{ scope.row.is_show === 1 ? "下架" : "上架" }}</el-button
>{{ scope.row.is_show == 1 ? "下架" : "上架" }}</el-button
>
<el-button size="small" type="info" style="cursor: not-allowed" @click="handleBtnClick('添加SKU', scope.row)"
>添加SKU</el-button

View File

@@ -1,5 +1,6 @@
interface FormItem {
prop: string;
prop1?: string;
label?: string;
placeholder?: string;
type: string;
@@ -31,7 +32,8 @@ export const FORM_DATA: FormItem[] = [
label: "型号: "
},
{
prop: "category_id",
prop: "treeIds",
prop1: "category_id",
placeholder: "请选择",
type: "treeSelect",
isArray: true,

View File

@@ -8,11 +8,11 @@
:request-api="getProductTrashListApi"
:init-param="dataStore.initParam"
>
<template #image="scope">
<el-image :src="scope.row.image ? h + scope.row.image : ''" style="width: 60px; height: 60px" />
<template #cover_image="scope">
<el-image :src="scope.row.cover_image ? h + scope.row.cover_image : ''" style="width: 60px; height: 60px" />
</template>
<template #status="scope">
<el-tag type="danger" effect="dark"> {{ scope.row.status === 1 ? "删除" : "删除" }}</el-tag>
<el-tag type="danger" effect="dark"> {{ scope.row.status == 1 ? "删除" : "删除" }}</el-tag>
</template>
<template #operation="scope">

View File

@@ -12,8 +12,8 @@
:init-param="dataStore.initParam"
>
<template #status="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status === 1 ? "启用" : "禁用"
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status == 1 ? "启用" : "禁用"
}}</el-tag>
</template>
<template #operation="scope">
@@ -22,7 +22,7 @@
size="small"
type="danger"
@click="handleBtnClick('删除', scope.row)"
v-if="scope.row.delete_disable === 0"
v-if="scope.row.delete_disable == 0"
>删除</el-button
>
</template>

View File

@@ -16,8 +16,8 @@
<el-image :src="scope.row.image ? h + scope.row.image : ''" style="width: 60px; height: 60px" />
</template>
<template #status="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status === 1 ? "启用" : "禁用"
<el-tag :type="scope.row.status == 1 ? 'success' : 'danger'" effect="dark">{{
scope.row.status == 1 ? "启用" : "禁用"
}}</el-tag>
</template>
<template #operation="scope">

View File

@@ -34,12 +34,12 @@
</el-table-column>
<el-table-column prop="hidden" label="是否显示" :width="100">
<template #default="{ row }">
{{ row.hidden === 0 ? "❌" : "✔️" }}
{{ row.hidden == 0 ? "❌" : "✔️" }}
</template>
</el-table-column>
<el-table-column prop="status" label="是否启用" :width="100">
<template #default="{ row }">
{{ row.status === 1 ? "✔️" : "❌" }}
{{ row.status == 1 ? "✔️" : "❌" }}
</template>
</el-table-column>
<el-table-column label="操作" :width="160">