Files
sgxt_web/src/components/aboutTable/Search.vue

553 lines
14 KiB
Vue
Raw Normal View History

2025-04-12 14:54:02 +08:00
<template>
2025-04-23 14:23:27 +08:00
<div v-loading="loadingPage" class="pageSearch searchBox" :style="`margin-bottom: ${marginBottom}px;background-color: ${backgroundColor}`">
2025-04-12 14:54:02 +08:00
<div class="box">
<div v-for="(item, index) in getArr" :key="index" class="item">
<div class="label" v-if="item.label">{{ item.label }}</div>
<!-- select -->
<el-select
v-if="item.showType === 'select'"
v-model="searchObj[item.prop]"
:multiple="item.multiple"
:clearable="item.clearable"
:filterable="item.filterable"
:placeholder="item.placeholder"
collapse-tags
collapse-tags-tooltip
>
<el-option
v-for="obj in getOptions[item.prop]"
:key="obj.value"
:label="obj.label || obj.lable"
:value="obj.value"
/>
</el-select>
<!-- input -->
<el-input
v-else-if="item.showType === 'input'"
class="input"
v-model="searchObj[item.prop]"
:clearable="item.clearable"
:placeholder="item.placeholder"
/>
<!-- 日期段选择器 -->
<el-date-picker
v-else-if="item.showType === 'daterange'"
v-model="searchObj[item.prop]"
type="daterange"
unlink-panels
:range-separator="item.rangeSeparator"
:start-placeholder="item.startPlaceholder"
:end-placeholder="item.endPlaceholder"
:shortcuts="item.shortcuts"
:disabledDate="disabledDate"
value-format="YYYY-MM-DD"
/>
2025-07-07 15:42:18 +08:00
<el-date-picker
v-else-if="item.showType === 'datetimerange'"
v-model="searchObj[item.prop]"
type="datetimerange"
unlink-panels
:range-separator="item.rangeSeparator || '至'"
:start-placeholder="item.startPlaceholder || '开始日期'"
:end-placeholder="item.endPlaceholder || '结束日期'"
:shortcuts="item.shortcuts"
value-format="YYYY-MM-DD HH:mm:ss"
/>
2025-04-12 14:54:02 +08:00
<el-date-picker
v-else-if="item.showType === 'date'"
v-model="searchObj[item.prop]"
type="date"
:placeholder="item.placeholder"
:disabled-date="disabledDate"
:shortcuts="item.shortcuts"
value-format="YYYY-MM-DD"
>
</el-date-picker>
2025-07-19 15:49:31 +08:00
<el-date-picker
v-else-if="item.showType === 'datetime'"
v-model="searchObj[item.prop]"
type="datetime"
:placeholder="item.placeholder"
value-format="YYYY-MM-DD HH:mm:ss"
>
</el-date-picker>
2025-04-12 23:51:24 +08:00
2025-04-12 14:54:02 +08:00
<!-- checkbox -->
<template v-else-if="item.showType === 'department'">
2025-07-20 19:20:12 +08:00
<MOSTY.Department clearable v-model="searchObj[item.prop]" />
2025-04-12 14:54:02 +08:00
</template>
<!-- checkbox -->
<template v-else-if="item.showType === 'checkbox'">
<el-checkbox
v-if="item.showSelectAll"
v-model="item.checkAll"
:indeterminate="item.isIndeterminate"
2025-04-12 23:51:24 +08:00
@change="
(val) => {
handleCheckAllChange(val, item);
}
"
>全选</el-checkbox
>
2025-04-12 14:54:02 +08:00
<el-checkbox-group
v-model="searchObj[item.prop]"
2025-04-12 23:51:24 +08:00
@change="
(val) => {
handleCheckedCitiesChange(val, item);
}
"
>
2025-04-12 14:54:02 +08:00
<el-checkbox
v-for="obj in item.options"
:key="obj.value"
:label="obj.value"
>{{ obj.label }}</el-checkbox
>
</el-checkbox-group>
</template>
<!-- radio -->
<el-radio-group
v-else-if="item.showType === 'radio'"
v-model="searchObj[item.prop]"
2025-04-12 23:51:24 +08:00
@change="
(val) => {
handleRadioChange(val, item);
}
"
>
2025-04-12 14:54:02 +08:00
<el-radio
v-for="obj in item.options"
:key="obj.value"
:label="obj.value"
>{{ obj.label }}</el-radio
>
</el-radio-group>
<!-- 级联选择 -->
<el-cascader
v-else-if="item.showType === 'cascader'"
v-model="searchObj[item.prop]"
:props="item.props"
:show-all-levels="item.showAllLevels"
:clearable="item.clearable"
:options="getOptions[item.prop]"
:placeholder="item.placeholder"
/>
<div v-else-if="item.showType === 'defaultSlot'">
<slot name="defaultSlot"></slot>
2025-11-27 14:27:59 +08:00
</div>
<div v-else-if="item.showType === 'nameSlot'">
<slot name="nameSlot"></slot>
2025-04-12 14:54:02 +08:00
</div>
</div>
<div class="flex">
<el-button type="primary" @click="submit">确定</el-button>
<el-button type="" @click="reset">重置</el-button>
<slot> </slot>
</div>
</div>
</div>
</template>
<script setup>
2025-04-12 23:51:24 +08:00
import {
ref,
reactive,
watchEffect,
getCurrentInstance,
2025-09-15 14:58:42 +08:00
watch,
computed
2025-04-12 23:51:24 +08:00
} from "vue";
2025-04-12 14:54:02 +08:00
import * as MOSTY from "@/components/MyComponents/index";
const { proxy } = getCurrentInstance();
const props = defineProps({
searchArr: {
type: Array,
default: () => {
return [
{
showType: "select",
prop: "selectKey",
options: [
{
value: 1,
label: "选择1"
}
],
defaultVal: "",
label: "选择",
dict: "" // 字典编码
},
{
showType: "input",
prop: "inputKey",
defaultVal: "",
label: "输入"
},
2025-07-20 19:20:12 +08:00
{
showType: "department",
prop: "deptKey",
defaultVal: "",
label: "输入"
},
2025-04-12 14:54:02 +08:00
{
showType: "daterange",
prop: "daterangeKey",
defaultVal: "",
label: "输入"
},
{
showType: "date",
prop: "date",
defaultVal: ""
},
{
showType: "checkbox",
prop: "checkboxKey1",
options: [
{
value: 1,
label: "选择1"
}
],
defaultVal: ""
},
{
showType: "cascader",
prop: "cascaderKey",
label: "级联选择",
checkStrictly: false, //点击任意选中
defaultVal: ""
},
{
showType: "radio",
defaultVal: ""
},
{
showType: "defaultTime",
prop: "timeField",
2025-04-12 23:51:24 +08:00
options: []
2025-04-12 14:54:02 +08:00
}
];
}
},
marginBottom: {
type: Number,
default: 15
},
backgroundColor: {
type: String,
default: "rgb(255, 255, 255, 1)"
2025-09-15 14:58:42 +08:00
},
2025-04-12 14:54:02 +08:00
});
let loadingPage = ref(false);
const emit = defineEmits(["submit", "reset"]);
let searchObj = reactive({});
2025-07-20 19:20:12 +08:00
2025-04-12 14:54:02 +08:00
// select 的一些默认配置
const selectDefault = {
clearable: true, // 是否可以清空
filterable: true, // 是否可以筛选
multiple: false, // 是否多选
placeholder: "请选择"
};
// 重新定义下拉框的选项
let getOptions = reactive({});
// input 的一些默认配置
const inputDefault = {
clearable: true, // 是否可以清空
placeholder: "请输入"
};
const shortcuts = [
{
text: "今天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 0);
return [start, end];
}
},
{
text: "昨天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
return [start, end];
}
},
{
text: "最近7天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
return [start, end];
}
},
{
text: "最近30天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
return [start, end];
}
},
{
text: "最近90天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
return [start, end];
}
}
];
// daterange 的一些默认配置
const daterangeDefault = {
rangeSeparator: "至",
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
shortcuts: [], // 快捷选择
defaultShortcuts: true // 是否显示快捷选择 如果要自定义快捷选择传入一个shortcuts就可以了
};
// date 的一些默认配置
const defaultDate = {
clearable: true, // 是否可以清空
placeholder: "请输入",
shortcuts: [], // 快捷选择
defaultShortcuts: true // 是否显示快捷选择 如果要自定义快捷选择传入一个shortcuts就可以了
};
const dateShortcuts = [
{
text: "今天",
value: new Date()
},
{
text: "昨天",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
return date;
}
},
{
text: "7天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
return date;
}
},
{
text: "30天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 30);
return date;
}
},
{
text: "90天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 90);
return date;
}
}
];
// 设置不可选的日期
const disabledDate = (time) => {
return time.getTime() > Date.now();
};
// checkbox 的一些默认配置
const defaultCheckbox = reactive({
defaultVal: [],
checkAll: false, // 全选的值
isIndeterminate: false, // 控制全选按钮样式
showSelectAll: true // 是否显示全选
});
// 全选复选框的选中与不选中
const handleCheckAllChange = (val, obj) => {
searchObj[obj.prop] = val ? obj.checkboxValueArr : [];
obj.isIndeterminate = false;
};
// 单个复选框的选中与不选中
const handleCheckedCitiesChange = (value, obj) => {
const checkedCount = value.length;
obj.checkAll = checkedCount === obj.checkboxValueArr.length;
obj.isIndeterminate =
checkedCount > 0 && checkedCount < obj.checkboxValueArr.length;
};
//单选
const handleRadioChange = (val, obj) => {
console.log(val, obj);
};
// cascader 的一些默认配置
let defaultCascader = {
filterable: true, // 是否可以搜索
clearable: true, // 是否可以清空
placeholder: "请选择",
checkStrictly: true, // 控制是否父子联动(是否可以选择任意节点)
showAllLevels: false, // 是否显示完整路径
2025-09-15 14:58:42 +08:00
lazy: false, // 是否懒加载 当设置为false时就要传入options
2025-04-12 14:54:02 +08:00
portUrl: "", // 这里必须写 接口地址
props: {
label: "label",
value: "value",
children: "children"
},
options: []
};
// 在懒加载状态下cascader 的props的一些配置
const cascaderLazyProps = reactive({
value: "value",
label: "label",
2025-09-15 14:58:42 +08:00
lazy: false,
2025-04-12 14:54:02 +08:00
lazyLoad(node, resolve) {
// 这里要根据实际情况修改
const { level } = node;
let options = [];
switch (level) {
case 0:
options = [
{
value: 1,
label: "选择1",
leaf: false // 表示有下一级 必须有这个表示 不然获取不到值
},
{
value: 2,
label: "选择2",
leaf: false // 表示有下一级
},
{
value: 3,
label: "选择3",
leaf: false // 表示有下一级
},
{
value: 4,
label: "选择4",
leaf: true // 表示没有下一级了
}
];
break;
case 1:
options = [
{
value: 11,
label: "选择1_1",
leaf: true // 表示没有下一级了
},
{
value: 21,
label: "选择2_1",
leaf: true // 表示没有下一级了
},
{
value: 31,
label: "选择3_1",
leaf: true // 表示没有下一级了
},
{
value: 41,
label: "选择4_1",
leaf: true // 表示没有下一级了
}
];
}
resolve(options);
}
});
// 获取到传过来的参数
let getArr = reactive([]);
const submit = () => {
emit("submit", searchObj);
};
const reset = () => {
getArr.forEach((item) => {
2025-04-12 23:51:24 +08:00
searchObj[item.prop] = item.defaultVal;
2025-04-12 14:54:02 +08:00
});
emit("submit", searchObj);
emit("reset", false);
};
watchEffect(() => {
loadingPage.value = true;
2025-07-20 19:20:12 +08:00
let arr = JSON.parse(JSON.stringify(props.searchArr));
getArr = arr.map((item) => {
2025-04-12 14:54:02 +08:00
switch (item.showType) {
case "select":
item = { ...selectDefault, ...item };
item.options = reactive(item.options);
getOptions[item.prop] = item.options;
break;
2025-07-20 19:20:12 +08:00
case "input":
item = { ...inputDefault, ...item };
2025-04-12 14:54:02 +08:00
break;
case "daterange":
item = { ...daterangeDefault, ...item };
2025-07-20 19:20:12 +08:00
if (item.defaultShortcuts) item.shortcuts = shortcuts;
2025-04-12 14:54:02 +08:00
break;
case "date":
item = { ...defaultDate, ...item };
if (item.defaultShortcuts) {
item.shortcuts = dateShortcuts;
}
break;
case "checkbox":
item = reactive({ ...defaultCheckbox, ...item });
item.checkboxValueArr = item.options.map((obj) => {
return obj.value;
});
break;
case "cascader":
item = { ...defaultCascader, ...item };
if (item.lazy) {
cascaderLazyProps.checkStrictly = item.checkStrictly;
item.props = { ...cascaderLazyProps, ...(item.props || {}) };
delete item.options;
} else {
item.props = {
...defaultCascader.props,
...(item.props || {}),
...{ checkStrictly: item.checkStrictly }
};
getOptions[item.prop] = reactive(item.options);
}
break;
}
loadingPage.value = false;
2025-04-12 23:51:24 +08:00
searchObj[item.prop] = item.defaultVal;
2025-04-12 14:54:02 +08:00
return item;
});
});
</script>
2025-04-12 23:51:24 +08:00
<style lang="scss" scoped>
2025-04-12 14:54:02 +08:00
.pageSearch {
.box {
display: flex;
flex-wrap: wrap;
.item {
display: flex;
margin-right: 12px;
2025-04-12 14:54:02 +08:00
margin-bottom: 15px;
}
.label {
margin: auto;
margin-right: 5px;
white-space: nowrap;
color: #000;
}
}
}
2025-07-07 15:42:18 +08:00
::v-deep .el-date-editor .el-range-separator{
color: #333;
}
2025-04-12 23:51:24 +08:00
</style>