587 lines
15 KiB
Vue
587 lines
15 KiB
Vue
<template>
|
|
<div v-loading="loadingPage" class="pageSearch searchBox" :style="`margin-bottom: ${marginBottom}px;background-color: ${backgroundColor}`">
|
|
<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"
|
|
/>
|
|
<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>
|
|
|
|
<!-- checkbox -->
|
|
<template v-else-if="item.showType === 'department'">
|
|
<MOSTY.Department clearable v-model="item.ssbmdm" />
|
|
</template>
|
|
<!-- checkbox -->
|
|
<template v-else-if="item.showType === 'checkbox'">
|
|
<el-checkbox
|
|
v-if="item.showSelectAll"
|
|
v-model="item.checkAll"
|
|
:indeterminate="item.isIndeterminate"
|
|
@change="
|
|
(val) => {
|
|
handleCheckAllChange(val, item);
|
|
}
|
|
"
|
|
>全选</el-checkbox
|
|
>
|
|
<el-checkbox-group
|
|
v-model="searchObj[item.prop]"
|
|
@change="
|
|
(val) => {
|
|
handleCheckedCitiesChange(val, item);
|
|
}
|
|
"
|
|
>
|
|
<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]"
|
|
@change="
|
|
(val) => {
|
|
handleRadioChange(val, item);
|
|
}
|
|
"
|
|
>
|
|
<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'"
|
|
@change="changeca"
|
|
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>
|
|
</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>
|
|
import {
|
|
ref,
|
|
reactive,
|
|
watch,
|
|
watchEffect,
|
|
nextTick,
|
|
getCurrentInstance,
|
|
toRefs
|
|
} from "vue";
|
|
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: "输入"
|
|
},
|
|
{
|
|
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: ""
|
|
// prop: "cascaderKey",
|
|
// label: "级联选择",
|
|
// checkStrictly: false //点击任意选中
|
|
},
|
|
{
|
|
showType: "defaultTime",
|
|
prop: "timeField",
|
|
options: []
|
|
}
|
|
];
|
|
}
|
|
},
|
|
marginBottom: {
|
|
type: Number,
|
|
default: 15
|
|
},
|
|
backgroundColor: {
|
|
type: String,
|
|
default: "rgb(255, 255, 255, 1)"
|
|
}
|
|
});
|
|
let loadingPage = ref(false);
|
|
const isShowDate = ref(false);
|
|
const emit = defineEmits(["submit", "reset"]);
|
|
let searchObj = reactive({});
|
|
const timeConfig = reactive({
|
|
//时间字典筛选和自定义日期组件相关数据
|
|
typeValue: "01", //时间字典类型默认
|
|
timeArry: [] //时间筛选自定义默认值
|
|
});
|
|
//全所或自定义选择按钮
|
|
const slectType = ref("qs");
|
|
// 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;
|
|
}
|
|
}
|
|
];
|
|
//自定义时间选择 item 配置项 value 选中的值
|
|
const screenSelect = (item, value) => {
|
|
if (value == "08") {
|
|
searchObj[item.prop] = value;
|
|
isShowDate.value = true;
|
|
} else {
|
|
timeConfig.typeValue = value;
|
|
searchObj[item.prop] = value;
|
|
submit();
|
|
}
|
|
};
|
|
//自定义时间确定时间
|
|
const chooseDateOk = (item) => {
|
|
timeConfig.typeValue = "08";
|
|
if (timeConfig.timeArry && timeConfig.timeArry.length) {
|
|
//选择了时间
|
|
searchObj[item.propStart] = timeConfig.timeArry[0];
|
|
searchObj[item.propEnd] = timeConfig.timeArry[1];
|
|
} else {
|
|
//清空了时间
|
|
searchObj[item.prop] = "01";
|
|
timeConfig.typeValue = "01";
|
|
}
|
|
isShowDate.value = false;
|
|
submit();
|
|
};
|
|
//全所-部门选择回调
|
|
const organizatioHland = (val) => {
|
|
let item = getArr.find((item) => item.showType == "qsOrZdy");
|
|
searchObj[item.propBm] = val?.data?.orgCode || "";
|
|
if (!val || val == "") {
|
|
//清空了部门选择后清空责任区ID
|
|
slectType.value = "qs";
|
|
delete searchObj[item.propZrq];
|
|
}
|
|
submit();
|
|
};
|
|
//全所-责任区回调
|
|
const zrqHland = (val) => {
|
|
let item = getArr.find((item) => item.showType == "qsOrZdy");
|
|
searchObj[item.propZrq] = val || ""; //责任区选择
|
|
submit();
|
|
};
|
|
//自定义时间取消事件
|
|
const popoverCancel = (item) => {
|
|
isShowDate.value = false;
|
|
};
|
|
// 设置不可选的日期
|
|
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, // 是否显示完整路径
|
|
lazy: true, // 是否懒加载 当设置为false时就要传入options
|
|
portUrl: "", // 这里必须写 接口地址
|
|
props: {
|
|
label: "label",
|
|
value: "value",
|
|
children: "children"
|
|
},
|
|
options: []
|
|
};
|
|
// 在懒加载状态下cascader 的props的一些配置
|
|
const cascaderLazyProps = reactive({
|
|
value: "value",
|
|
label: "label",
|
|
lazy: true,
|
|
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);
|
|
}
|
|
});
|
|
// 级联框选择
|
|
function changeca(v) {
|
|
console.log("vvvv", v);
|
|
}
|
|
// 获取到传过来的参数
|
|
let getArr = reactive([]);
|
|
const submit = () => {
|
|
emit("submit", searchObj);
|
|
};
|
|
const reset = () => {
|
|
getArr.forEach((item) => {
|
|
searchObj[item.prop] = item.defaultVal;
|
|
});
|
|
emit("submit", searchObj);
|
|
emit("reset", false);
|
|
};
|
|
let dataOptions = reactive([]); //时间字典筛选
|
|
watchEffect(() => {
|
|
loadingPage.value = true;
|
|
getArr = JSON.parse(JSON.stringify(props.searchArr));
|
|
getArr = getArr.map((item) => {
|
|
switch (item.showType) {
|
|
case "select":
|
|
item = { ...selectDefault, ...item };
|
|
item.options = reactive(item.options);
|
|
getOptions[item.prop] = item.options;
|
|
break;
|
|
case "input":
|
|
item = { ...inputDefault, ...item };
|
|
break;
|
|
case "daterange":
|
|
item = { ...daterangeDefault, ...item };
|
|
if (item.defaultShortcuts) {
|
|
item.shortcuts = shortcuts;
|
|
}
|
|
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;
|
|
searchObj[item.prop] = item.defaultVal;
|
|
return item;
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.pageSearch {
|
|
.box {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
.item {
|
|
display: flex;
|
|
margin-right: 12px;
|
|
margin-bottom: 15px;
|
|
}
|
|
.label {
|
|
margin: auto;
|
|
margin-right: 5px;
|
|
white-space: nowrap;
|
|
color: #000;
|
|
}
|
|
}
|
|
}
|
|
</style>
|