txw/txw-mhzc-web/src/pages/index/components/header-search/index.vue
2026-04-03 11:04:28 +08:00

325 lines
8.8 KiB
Vue

<template>
<t-form
:data="formData"
labelWidth="calc(8em + 8px)"
ref="form"
@reset="onReset"
:rules="formRules"
@submit="onSubmit"
scrollToFirstError="smooth"
>
<g-filter-wrapper :expand="expand" :colNum="colNum" col-style="margin-bottom: 24px" class="filter-from">
<t-form-item
class="form-item-wrap"
v-for="(item, key) in config"
:key="key"
v-bind="colProps"
:name="item.key"
:rules="item.rule"
>
<template slot="label">
<t-tooltip v-if="shouldEllipsis(item.label)" :content="item.label">
<span>{{ sliceText(item.label) }}</span>
</t-tooltip>
<span v-else>{{ item.label }}</span>
</template>
<slot :name="item.key" :item="item" :formData="formData">
<t-select
v-if="item.type === 'select'"
v-bind="item.selectProps"
v-model="formData[item.key]"
:options="item.selectList"
:disabled="item.disabled || false"
:placeholder="item.placeholder || '请选择'"
:multiple="item.multiple || false"
v-on="item.events || {}"
:clearable="item.clearable || false"
:onChange="(value) => handleSelectChange(value, item)"
></t-select>
<t-date-picker
v-else-if="item.type === 'datepicker'"
v-model="formData[item.key]"
mode="date"
style="width: 100%"
placeholder="请选择"
:clearable="item.clearable || true"
:disableDate="(date) => getDisableDate(date, item)"
/>
<t-date-picker
v-else-if="item.type === 'range-datepicker'"
range
v-model="formData[item.key]"
mode="date"
style="width: 100%"
v-bind="item.rangeDatepickerProps"
:placeholder="['开始时间', '结束时间']"
:clearable="item.clearable || true"
/>
<t-tree-select
v-else-if="item.type === 'tree-select'"
style="width: 100%"
v-bind="item.treeSelectProps"
:data="item.selectList"
v-model="formData[item.key]"
placeholder="请选择"
:multiple="item.multiple || false"
:filterable="item.filterable || false"
/>
<all-select
v-else-if="item.type === 'all-select'"
v-bind="item.allSelectProps"
v-model="formData[item.key]"
:options="item.selectList"
:minCollapsedNum="1"
:placeholder="'请选择'"
:allowCheckAll="item.allowCheckAll || true"
/>
<t-tooltip
:content="formData[item.key]"
:showArrow="false"
:overlayStyle="{ display: !formData[item.key] || !item.popup ? 'none' : 'block' }"
v-else
>
<t-input
v-bind="item.inputProps"
v-model="formData[item.key]"
:placeholder="item.placeholder || '请输入'"
:clearable="item.clearable || false"
:disabled="item.disabled || false"
>
<t-icon v-if="item.iconName" :name="item.iconName" slot="suffix-icon" />
</t-input>
</t-tooltip>
</slot>
</t-form-item>
<t-form-item class="filter-btns" :class="shouldShowExtend ? 'float-right' : ''" labelWidth="0">
<t-button theme="default" variant="base" type="reset">重置</t-button>
<t-button theme="primary" type="submit">{{ submitText }}</t-button>
<t-button v-if="shouldShowExtend" theme="primary" variant="text" @click="changeChevron">
<span>
{{ expand ? '收起' : '展开' }}
<t-icon :name="expand ? 'chevron-up' : 'chevron-down'" slot="icon" />
</span>
</t-button>
</t-form-item>
</g-filter-wrapper>
</t-form>
</template>
<script>
// import FilterWrapper from '../filter-wrapper.vue';
import dayjs from 'dayjs';
import { GFilterWrapper } from '@gtff/tdesign-gt-vue';
import allSelect from '@/pages/index/components/all-select/_base.vue';
const LABEL_THRESHOLD = 8;
const DOUBLE_BYTE_THRESHOLD = 255;
export default {
components: {
GFilterWrapper,
allSelect,
},
props: {
config: [Object, Array],
colNum: {
type: Number,
default: 4,
},
defaultExpand: {
type: Boolean,
default: false,
},
formRules: {
type: Object,
default: () => {},
},
submitText: {
type: String,
default: '查询',
},
},
data() {
return {
expand: true,
colProps: {
xs: 6, // >= 768
md: 4, // >= 992px
lg: 3, // >= 1200px
xl: 3, // >= 1400 px
xxl: 2, // >= 1880
},
isShowHighSearchButton: false,
formData: {},
formRef: null,
inputRef: null,
};
},
computed: {
shouldShowExtend() {
return Object.keys(this.config).length >= this.colNum;
},
},
watch: {
formData: {
immediate: true,
deep: true,
handler(val, oldVal) {
// 忽略首次加载
if (oldVal) {
this.$emit('formChange', val);
}
},
},
},
mounted() {
this.expand = this.defaultExpand;
this.setFormData(this.config);
this.formRef = this.$refs.form;
this.formRef.reset();
this.inputRef = this.$refs.input;
},
methods: {
handleSelectChange(value, item) {
const { multiple, multipleAllValue, selectList } = item;
function isEqualArr(arr1, arr2) {
return arr1.every((values) => arr2.includes(values));
}
// 处理多选情况下,有全选的值
if (multiple && typeof multipleAllValue !== 'undefined') {
// without all value
const allSelectValue = selectList
.filter((itemss) => itemss.value !== multipleAllValue)
.map((items1) => items1.value);
console.log(allSelectValue, value, isEqualArr(allSelectValue, value));
if (value.includes(multipleAllValue) || isEqualArr(allSelectValue, value)) {
this.formData[item.key] = selectList.map((itemss) => itemss.value);
}
}
// 增加回调方法
this.$emit('changeSelect', value, item);
},
getDisableDate(date, item) {
if (!item.relation || !item.timeRange) return false;
const selectData = this.formData[item.relation];
if (!selectData) return false;
const formatDate = dayjs(selectData).hour(0).minute(0).second(0);
if (item.timeRange === 'start') {
// 大于选中结束时间的都不可选
return date > new Date(formatDate);
}
if (item.timeRange === 'end') {
// 小于选中开始时间的都不可选
return date < new Date(formatDate);
}
return false;
},
changeChevron() {
this.expand = !this.expand;
},
// 计算字符串字节长度,英文字母为单字节字符,中文汉字为双字节字符
getStringLength(str) {
const strLength = str.length;
let count = 0;
for (let i = 0; i < strLength; i++) {
count += str.charCodeAt(i) > DOUBLE_BYTE_THRESHOLD ? 2 : 1;
}
return count;
},
// 根据预设值判断label是否显示省略
shouldEllipsis(str) {
return this.getStringLength(str) > LABEL_THRESHOLD * 2;
},
// label文字切割
sliceText(text, length = 7) {
if (this.shouldEllipsis(text)) {
return `${text.slice(0, length)}...`;
}
return text;
},
onReset() {
this.$emit('reset');
},
onSubmit({ validateResult }) {
if (validateResult === true) {
this.$emit('search');
}
},
setFormData(data) {
const formData = {};
Object.keys(data).forEach((key) => {
const item = data[key];
if (item) {
formData[item.key] = item.value;
}
});
this.formData = formData;
},
getParams(key) {
if (key) return this.formData[key];
return { ...this.formData };
},
setParams(formData) {
this.formData = formData;
},
},
};
</script>
<style scoped lang="less">
.float-right {
float: right;
}
.filter-btns {
button {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}
// .float-right {
// float: right;
// }
.ie-wrapper {
.filter-from /deep/ .form-item-wrap {
min-height: 0;
}
.g-filter-wrapper {
padding: 0 24px;
margin-bottom: 24px;
}
}
// .filter-btns {
// button {
// margin-right: 8px;
// &:last-child {
// margin-right: 0;
// }
// }
// }
// .ie-wrapper .g-filter-wrapper {
// padding: 0 24px;
// }
.g-filter-wrapper {
padding: 0 24px;
/deep/ .t-row {
// g-filter-wrapper组件问题
/* stylelint-disable-next-line declaration-no-important */
row-gap: 0 !important;
}
}
.form-item-wrap {
min-height: 56px;
}
</style>