| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- <template>
- <div class="form-filter">
- <el-form label-position="left" :model="queryForm" class='form-content'>
- <template v-for="(option, index) in option.queryFormFields" :key="index">
- <!-- input -->
- <el-form-item :label="option.label" class='form-input r-24 border position-box'
- v-if="option.inputType == 'input'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-input class="input-deep input-w" v-model="queryForm.data[option.key]" :placeholder="`请输入${option.label}`"
- clearable>
- </el-input>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- select -->
- <el-form-item :label="option.label" class='form-select-single r-24 border position-box'
- v-if="option.inputType == 'select-single'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-select class='min-w ' v-model="queryForm.data[option.key]" placeholder=""
- @change='singleChange($event,option)'>
- <el-option v-for="item in option.listOption" :key="item.value" :label="item.label" :value="item.value">
- </el-option>
- </el-select>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- select 多选-->
- <el-form-item :label="option.label" class='form-select-multiple r-24 border position-box'
- v-if="option.inputType == 'select-multiple'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-select class='min-w' multiple v-model="queryForm.data[option.key]" value-key="value" placeholder=""
- @change='moreChange($event,option,option.listOption)'>
- <el-option v-for="item in option.listOption" :key="item.value" :label="item.label" :value="item.value">
- </el-option>
- <template #tag>
- <view v-show='option.selectValue'>
- <text v-if='option.listOption'>{{option.selectValue}}</text>
- <text class='text-color' v-else>请选择</text>
- </view>
- </template>
- </el-select>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- 日期 -->
- <el-form-item :label="option.label" class='form-date-picker r-24 border position-box'
- v-if="option.inputType == 'date-picker'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-date-picker v-model="queryForm.data[option.key]" type="daterange" unlink-panels start-placeholder="开始日期"
- end-placeholder="结束日期" :shortcuts="shortcuts" value-format="YYYY-MM-DD">
- <template #range-separator>
- <view>⇀</view>
- </template>
- </el-date-picker>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- 年份 -->
- <el-form-item :label="option.label" class='form-date-picker r-24 border position-box'
- v-if="option.inputType == 'date-year'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-date-picker v-model="queryForm.data[option.key]" type="year" placeholder="选择年份" value-format="YYYY">
- <template #range-separator>
- <view>⇀</view>
- </template>
- </el-date-picker>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- tree selectValue: [], //选中的Key存储的值 listOption原始数据 -->
- <el-form-item :label="option.label" class='form-date-tree r-24 border position-box'
- v-if="option.inputType == 'date-tree'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-tree-select v-model="queryForm.data[option.key]" :data="option.listOption" :render-after-expand="false"
- :props="defaultProps" node-key="id" show-checkbox multiple
- @check="(data,checked)=>handleCheckChange(data,checked,option,queryForm.data[option.key])">
- <template #tag>
- <view v-show='option.selectValue'>{{option.selectValue}}</view>
- </template>
- </el-tree-select>
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- <!-- 级联选择 -->
- <el-form-item :label="option.label" class='form-date-cascader r-24 border position-box'
- v-if="option.inputType == 'date-cascader'" @mouseenter="option.isShowDelIcon = true"
- @mouseleave="option.isShowDelIcon = false">
- <el-cascader v-model="queryForm.data[option.key]" :options="option.listOption" clearable
- :props="optionProps" />
- <template v-if='!option.defaultFlag'>
- <view class='icon-del' @click='del(option)' v-show='option.isShowDelIcon'>
- <el-icon>
- <CircleCloseFilled color='#ccc' :size='30' />
- </el-icon>
- </view>
- </template>
- </el-form-item>
- </template>
- <el-button type="primary" @click='query'>查询</el-button>
- </el-form>
- </div>
- </template>
- <script setup lang="ts">
- import { useRouter } from "vue-router";
- import { timestampFormat } from "@/utils/dayjs";
- import api from "@/api";
- const emit = defineEmits(["query", "delSelect"]);
- const props = defineProps({
- option: {
- type: Object,
- default: () => {
- return {
- labelWidth: {}, // label宽度,
- };
- },
- },
- });
- const defaultProps = {
- children: "children",
- label: "name",
- };
- const optionProps = {
- value: "areaCode",
- label: "areaCname",
- children: "child",
- };
- const showDelete = ref(false);
- let queryForm = reactive({ data: {} });
- const shortcuts = [
- {
- text: "今日",
- value: () => {
- const end = new Date();
- const start = new Date();
- start.setTime(start.getTime());
- 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: "本月",
- value: () => {
- const year = new Date().getFullYear();
- const month = new Date().getMonth() + 1;
- const date = new Date(year, month, 0).getDate();
- const end = new Date(year, month - 1, date);
- const start = new Date(year, new Date().getMonth(), 1);
- return [start, end];
- },
- },
- {
- text: "本年",
- value: () => {
- const end = new Date(new Date().getFullYear(), 11, 31);
- const start = new Date(new Date().getFullYear(), 0, 1);
- return [start, end];
- },
- },
- ];
- //获取默认值
- const propsOption = props.option;
- const isEmptyValue = (value) => {
- return (
- value == null ||
- value == undefined ||
- (Array.isArray(value) && value.length === 0)
- );
- };
- const initDefaultSaveForm = () => {
- const defaultSaveForm = {};
- const { queryFormFields = [] } = propsOption;
- const currentTimestamp = Date.now();
- const formatTime = (timestamp, format = "") => {
- return timestampFormat(timestamp, format);
- };
- // 处理不同输入类型
- const typeHandlers = {
- "date-picker": (item, baseValue) => {
- if (isEmptyValue(baseValue)) {
- const defaultTime = formatTime(currentTimestamp);
- return [defaultTime, defaultTime];
- }
- return baseValue;
- },
- "date-year": () => {
- return [formatTime(currentTimestamp, "YYYY")];
- },
- "select-multiple": (item, baseValue) => {
- const value = item.listOption ? baseValue : "";
- return value === "0" ? ["0"] : value;
- },
- "select-single": (item, baseValue) => {
- const value = item.listOption ? baseValue : "";
- if (item.isFirst) {
- singleChange(baseValue, item);
- }
- return value;
- },
- default: (_, baseValue) => baseValue,
- };
- queryFormFields.forEach((item) => {
- if (!item?.key) return;
- const { key, inputType } = item;
- const baseValue = queryForm.data[key] ?? item.defaultValue;
- const handler = typeHandlers[inputType] || typeHandlers.default;
- defaultSaveForm[key] = handler(item, baseValue);
- });
- // 更新表单数据并返回
- queryForm.data = { ...defaultSaveForm };
- return queryForm.data;
- };
- //多选中发生变化
- const moreChange = (selectedValues: CheckboxValueType, item, foodList) => {
- const foodLabels = getMultiLabels(selectedValues, foodList, "value");
- item.selectValue = foodLabels.join(",");
- };
- //tree change
- const handleCheckChange = (data, row, option, ids) => {
- const foodLabels = getMultiLabels(ids, row.checkedNodes, "id");
- option.selectValue = foodLabels.join(",");
- };
- //数据过滤
- const getMultiLabels = (selectedValues, foodList, key) => {
- return selectedValues.map((targetValue) => {
- const matchedItem = foodList.find((item) => item[key] === targetValue);
- return matchedItem ? matchedItem.label || matchedItem.name : "";
- });
- };
- //单选查联动数据
- const singleChange = async (val, option) => {
- if (option.isFirst) {
- //查询合作的保险公司数据
- const { data } = await api.manageApi.getCompanyListByCompanyId({
- companyId: val,
- });
- propsOption.queryFormFields.forEach((e) => {
- if (e.key == "partnerCompanyIds") {
- e.listOption = data;
- e.listOption.unshift({
- value: "0",
- label: "全部",
- });
- e.selectValue = "全部";
- queryForm.data.partnerCompanyIds = ["0"];
- }
- });
- }
- };
- //查询
- const query = () => {
- const from = { ...queryForm.data };
- const { queryFormFields } = propsOption;
- const typeHandlers = {
- "select-single": (item, value) => {
- // 特殊处理companyId,其他单选转换为数组格式
- return item.key === "companyId" ? value : [value || "0"];
- },
- "date-tree": (item, value) => {
- // 日期树选择器:无默认值时转换为空数组
- return item.selectValue ? value : [];
- },
- "select-multiple": (item, value) => {
- // 多选框:无默认值时转换为空数组
- return item.defaultValue ? value : [];
- },
- "date-picker": (item, value) => {
- // 日期选择器:无值时转换为空数组
- return value ? value : [];
- },
- "date-year": (item, value) => {
- // 年份选择器:确保始终返回数组格式
- if (!value) return [];
- return Array.isArray(value) ? value : [value];
- },
- };
- queryFormFields.forEach((item) => {
- const { inputType, key } = item;
- const handler = typeHandlers[inputType];
- if (handler) {
- from[key] = handler(item, from[key]);
- }
- });
- emit("query", from);
- };
- //删除
- const del = (option) => {
- const { inputType, key, id } = option;
- const isInputOrCompanyId = inputType === "input" || key === "companyId";
- if (isInputOrCompanyId) {
- queryForm.data[key] = "";
- } else {
- option.selectValue = "";
- queryForm.data[key] = [];
- }
- emit("delSelect", id);
- };
- // 暴露给父组件的方法
- defineExpose({
- initDefaultSaveForm,
- });
- </script>
- <style scoped lang="scss">
- .form-content {
- display: flex;
- flex-wrap: wrap;
- .r-24 {
- margin-right: 24px;
- }
- .border {
- border-radius: 2px 2px 2px 2px;
- border: 1px solid #e5e5e5;
- }
- :deep(.el-form-item__label) {
- padding-left: 12px;
- }
- .min-w {
- min-width: 200px;
- }
- .input-w {
- width: 200px;
- }
- .position-box {
- position: relative;
- .icon-del {
- position: absolute;
- right: -8px;
- top: -14px;
- }
- :deep(.el-icon) {
- font-size: 20px;
- }
- }
- .text-color {
- color: #a3a8b3;
- }
- }
- // input
- .form-input {
- .input-deep {
- :deep(.el-input__wrapper) {
- box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color))
- inset;
- cursor: default;
- .el-input__inner {
- cursor: default !important;
- }
- }
- }
- }
- //select
- .form-select-single,
- .form-select-multiple {
- :deep(.el-select__wrapper) {
- border: none; /* 去除边框 */
- box-shadow: none;
- }
- }
- //picker
- .form-date-picker {
- :deep(.el-date-editor.el-input__wrapper) {
- border: none; /* 去除边框 */
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- width: 240px;
- }
- :deep(.el-input__wrapper) {
- border: none; /* 去除边框 */
- box-shadow: none;
- }
- :deep(.el-date-editor .el-range__icon) {
- display: none;
- }
- }
- //tree
- .form-date-tree {
- :deep(.el-select__wrapper) {
- box-shadow: none;
- min-width: 240px;
- }
- }
- //el-cascader
- .form-date-cascader {
- :deep(.el-cascader .el-input__wrapper) {
- box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color))
- inset;
- }
- }
- </style>
|