智处-弹窗表格筛选功能完整版

main
滕嵩 2025-03-20 09:55:51 +08:00
parent bc8e8dd36a
commit a3bf4db6e3
4 changed files with 1150 additions and 242 deletions

View File

@ -5,34 +5,28 @@ import { chartInitConfig } from '@/settings/designSetting'
import { ZhiChu_ModalTableConfig } from './index' import { ZhiChu_ModalTableConfig } from './index'
import dataJson from './data.json' import dataJson from './data.json'
const {header, source} = dataJson; const {header, source, filterset} = dataJson;
export const option = { export const option = {
header: header, header: header,
dataset: source, dataset: source,
filterset: filterset,
dataStyle: { dataStyle: {
mapshow: ['水源', '物资', '营房', '防火通道', '', ], colLeft: 4,
distance: '1',
// filterSet: [ filterMarginTop: 20,
// { label: '地图显示', field:'circle', showType: '', value: ''},
// { label: '资源列表', field:'', showType: '', value: ''},
// { label: '重点资源', field:'', showType: '', value: ''},
// { label: '距离', field:'', showType: '', value: ''},
// ],
filterHeight: 200,
filterMarginTop: 40,
filterMarginLeft: 50, filterMarginLeft: 50,
filterItemHeight: 45,
filterTitleAlign: 'left',
filterTitleFontSize: 24, filterTitleFontSize: 24,
filterTitleFontColor: '#ADFFC0', filterTitleFontColor: '#ADFFC0',
filterTitleWidth: 100,
filterTitleMarginRight: 20,
filterContentAlign: 'left',
filterChooseFontSize: 18, filterChooseFontSize: 18,
filterChooseFontColor: '#FFFFFF', filterChooseFontColor: '#FFFFFF',
tableMarginTop: 10, tableMarginTop: 20,
tableMarginLeft: 20, tableMarginLeft: 20,
tableBordered: false, tableBordered: false,
tableSigleColumn: true, tableSigleColumn: true,
@ -41,9 +35,9 @@ export const option = {
tableSize: 'small', tableSize: 'small',
tableAlign: 'center', tableAlign: 'center',
// 表头 // 表头
tableHeaderShow: true, tableHeaderShow: false,
// 序号 // 序号
orderBumberShow: true, orderBumberShow: false,
// 操作 // 操作
buttonDivShow: true, buttonDivShow: true,
buttonDivShow1: true, buttonDivShow1: true,
@ -64,7 +58,7 @@ export const option = {
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {
public key = ZhiChu_ModalTableConfig.key public key = ZhiChu_ModalTableConfig.key
public attr = { ...chartInitConfig, w: 995, h: 544, zIndex: -1 } public attr = { ...chartInitConfig, w: 1060, h: 485, zIndex: -1 }
public chartConfig = cloneDeep(ZhiChu_ModalTableConfig) public chartConfig = cloneDeep(ZhiChu_ModalTableConfig)
public option = cloneDeep(option) public option = cloneDeep(option)
} }

View File

@ -1,5 +1,349 @@
<template> <template>
<!-- 筛选项数据显示设置 -->
<CollapseItem name="筛选项数据显示设置" :expanded="true">
<div style="overflow-x: auto">
<span style="font-size: 12px; margin-left: 8px"> 筛选项字段与类型 </span>
<n-table
class="go-request-header-table-box"
style="margin-top: 12px"
:single-line="false"
size="small"
>
<thead>
<tr>
<th>标题名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in props.optionData.filterset" :key="index">
<td>
<n-input v-model:value="item.title" type="text" size="small" />
</td>
<td>
<div style="width: 70px">
<n-button
class="go-ml-2"
type="primary"
size="small"
ghost
@click="
props.optionData.filterset.splice(index + 1, 0, {
title: null,
field: null,
compareType: null,
showType: null,
value: [],
options: [{ label: null, value: null }],
})
"
>
+
</n-button>
<n-button
class="go-ml-2"
type="warning"
size="small"
ghost
:disabled="props.optionData.filterset.length === 1"
@click="
if (props.optionData.filterset.length !== 1) {
props.optionData.filterset.splice(index, 1);
}
"
>
-
</n-button>
</div>
</td>
</tr>
</tbody>
</n-table>
</div>
</CollapseItem>
<CollapseItem
:expanded="false"
v-for="(filtersetItem, filtersetIndex) in optionData.filterset"
:key="filtersetIndex"
:alone="false"
:name="'筛选项【' + filtersetItem.title + '】设置'"
>
<SettingItem name="筛选类型">
<n-select
v-model:value="filtersetItem.showType"
:options="[
{ label: '多选框', value: 'checkbox' },
{ label: '单选框', value: 'radio' },
{ label: '下拉框', value: 'select' },
{ label: '下拉框(多选)', value: 'selectGroup' },
{ label: '按钮组', value: 'buttonGroup' },
{ label: '按钮组(多选)', value: 'buttonGroupList' },
{ label: '列搜索框', value: 'inputSearch' },
{ label: '全数据搜索框', value: 'inputSearchAll' },
{ label: '时间选择器', value: 'timePicker' },
{ label: '时间范围', value: 'timeRange' },
]"
clearable
size="small"
placeholder="筛选类型"
@change="
filtersetItem.compareType = null;
filtersetItem.value = null;
"
/>
<!-- { label: '日期范围', value: 'dateRange' }, -->
</SettingItem>
<SettingItem v-if="!['inputSearchAll'].includes(filtersetItem.showType)" name="对应字段">
<n-select
v-model:value="filtersetItem.field"
:options="columnsOptions"
size="small"
clearable
placeholder="对应字段"
/>
</SettingItem>
<SettingItem name="筛选方式">
<n-select
v-model:value="filtersetItem.compareType"
:options="getOptionsByShowType(filtersetItem)"
clearable
size="small"
placeholder="筛选方式"
/>
</SettingItem>
<!-- 默认值搜索框无默认值 -->
<SettingItem
v-if="!['inputSearch', 'inputSearchAll'].includes(filtersetItem.showType)"
name="默认值"
>
<!-- 多选框下拉框多选按钮组 多选-->
<n-select
v-if="['checkbox', 'selectGroup', 'buttonGroupList'].includes(filtersetItem.showType)"
v-model:value="filtersetItem.value"
:options="filtersetItem.options"
multiple
clearable
size="small"
placeholder="默认值"
/>
<!-- 时间选择器 -->
<n-time-picker
v-else-if="['timePicker'].includes(filtersetItem.showType)"
v-model:formatted-value="filtersetItem.value"
value-format="HH:mm:ss"
format="HH:mm:ss"
size="small"
clearable
placeholder="默认时间"
/>
<!-- 时间范围 -->
<div v-else-if="['timeRange'].includes(filtersetItem.showType)">
<n-time-picker
v-model:formatted-value="filtersetItem.value"
value-format="HH:mm:ss"
format="HH:mm:ss"
size="small"
clearable
placeholder="开始时间"
/>
<n-time-picker
v-model:formatted-value="filtersetItem.value2"
value-format="HH:mm:ss"
format="HH:mm:ss"
size="small"
clearable
placeholder="结束时间"
/>
</div>
<!-- 日期范围 -->
<n-date-picker
v-else-if="['dateRange'].includes(filtersetItem.showType)"
v-model:formatted-value="filtersetItem.value"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
size="small"
clearable
/>
<!-- 其他 -->
<n-select
v-else
v-model:value="filtersetItem.value"
:options="filtersetItem.options"
clearable
size="small"
placeholder="默认值"
/>
</SettingItem>
<!-- 搜索框时间日期框无选项 -->
<n-table
v-if="
!['inputSearch', 'inputSearchAll', 'timePicker', 'timeRange', 'dateRange'].includes(
filtersetItem.showType,
)
"
class="go-request-header-table-box"
style="margin-top: 12px"
:single-line="false"
size="small"
>
<thead>
<tr>
<th>名称</th>
<th></th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(optionsItem, optionsIndex) in filtersetItem.options" :key="optionsIndex">
<td>
<n-input
v-model:value="optionsItem.label"
type="text"
size="small"
placeholder="名称"
/>
</td>
<td>
<n-input v-model:value="optionsItem.value" type="text" size="small" placeholder="值" />
</td>
<td>
<div style="width: 70px">
<n-button
class="go-ml-2"
type="primary"
size="small"
ghost
@click="
filtersetItem.options.splice(optionsIndex + 1, 0, {
label: null,
value: null,
})
"
>
+
</n-button>
<n-button
class="go-ml-2"
type="warning"
size="small"
ghost
:disabled="optionsItem.length === 1"
@click="
if (filtersetItem.options.length !== 1) {
filtersetItem.options.splice(optionsIndex, 1);
}
"
>
-
</n-button>
</div>
</td>
</tr>
</tbody>
</n-table>
</CollapseItem>
<br />
<!-- 筛选项样式设置 -->
<CollapseItem name="筛选项样式设置" :expanded="true">
<SettingItemBox :alone="false" name="整体设置">
<SettingItem :alone="false" name="上方距离">
<n-input-number
v-model:value="optionData.dataStyle.filterMarginTop"
:min="0"
size="small"
placeholder="上方距离"
/>
</SettingItem>
<SettingItem :alone="false" name="左右距离">
<n-input-number
v-model:value="optionData.dataStyle.filterMarginLeft"
:min="0"
size="small"
placeholder="左右距离"
/>
</SettingItem>
<SettingItem :alone="false" name="单个筛选项高度">
<n-input-number
v-model:value="optionData.dataStyle.filterItemHeight"
:min="0"
size="small"
placeholder="单个筛选项高度"
/>
</SettingItem>
<SettingItem name="标题对齐方式">
<n-select
v-model:value="optionData.dataStyle.filterTitleAlign"
:options="[
{ label: '靠左', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '靠右', value: 'right' },
]"
size="small"
/>
</SettingItem>
<SettingItem name="内容对齐方式">
<n-select
v-model:value="optionData.dataStyle.filterContentAlign"
:options="[
{ label: '靠左', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '靠右', value: 'right' },
]"
size="small"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox :alone="false" name="标题样式">
<SettingItem :alone="false" name="标题占比">
<n-space vertical>
<n-slider v-model:value="optionData.dataStyle.colLeft" :step="1" :min="0" :max="24" />
<n-input-number v-model:value="optionData.dataStyle.colLeft" size="small">
<template #suffix> / 24 </template>
</n-input-number>
</n-space>
</SettingItem>
</SettingItemBox>
<SettingItemBox :alone="false" name="字体设置">
<SettingItem name="筛选标题字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.dataStyle.filterTitleFontColor"
></n-color-picker>
</SettingItem>
<SettingItem name="筛选标题字体大小">
<n-input-number
v-model:value="optionData.dataStyle.filterTitleFontSize"
:min="0"
size="small"
placeholder="筛选标题字体大小"
></n-input-number>
</SettingItem>
<SettingItem name="筛选内容字体颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.dataStyle.filterChooseFontColor"
></n-color-picker>
</SettingItem>
<SettingItem name="筛选内容字体大小">
<n-input-number
v-model:value="optionData.dataStyle.filterChooseFontSize"
:min="0"
size="small"
placeholder="筛选内容字体大小"
></n-input-number>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="表格数据显示设置" :expanded="true"> <CollapseItem name="表格数据显示设置" :expanded="true">
<div style="overflow-x: auto">
<span style="font-size: 12px; margin-left: 8px"> <span style="font-size: 12px; margin-left: 8px">
表格数据请先确定数据部分再确定表格数据 表格数据请先确定数据部分再确定表格数据
</span> </span>
@ -48,8 +392,30 @@
</tr> </tr>
</tbody> </tbody>
</n-table> </n-table>
</div>
<SettingItemBox :alone="true" name="表格宽度">
<SettingItem :alone="true" name="不包含序列和操作列">
<n-input v-model:value="columnsWidths" type="text" size="small" />
</SettingItem>
<SettingItem :alone="false" name="序列宽度">
<n-input-number
v-model:value="optionData.dataStyle.orderDivWidth"
:min="0"
size="small"
placeholder="序列宽度"
/>
</SettingItem>
<SettingItem :alone="false" name="操作列宽度">
<n-input-number
v-model:value="optionData.dataStyle.buttonDivWidth"
:min="0"
size="small"
placeholder="操作列宽度"
/>
</SettingItem>
</SettingItemBox>
<br />
<span style="font-size: 12px; margin-left: 8px"> 表格数据前缀和后缀 </span> <span style="font-size: 12px; margin-left: 8px"> 表格数据前缀和后缀 </span>
<n-table <n-table
class="go-request-header-table-box" class="go-request-header-table-box"
@ -113,71 +479,7 @@
</tr> </tr>
</tbody> </tbody>
</n-table> </n-table>
</CollapseItem>
<CollapseItem name="表格样式设置" :expanded="true">
<SettingItemBox :alone="true" name="表格宽度">
<SettingItem :alone="true" name="不包含序列和操作列">
<n-input v-model:value="columnsWidths" type="text" size="small" />
</SettingItem>
<SettingItem :alone="false" name="序列宽度">
<n-input-number
v-model:value="optionData.dataStyle.orderDivWidth"
:min="0"
size="small"
placeholder="序列宽度"
/>
</SettingItem>
<SettingItem :alone="false" name="操作列宽度">
<n-input-number
v-model:value="optionData.dataStyle.buttonDivWidth"
:min="0"
size="small"
placeholder="操作列宽度"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="整体设置">
<SettingItem name="上方距离">
<n-input-number
v-model:value="optionData.dataStyle.tableMarginTop"
:min="0"
size="small"
placeholder="上方距离"
/>
</SettingItem>
<SettingItem name="左右距离">
<n-input-number
v-model:value="optionData.dataStyle.tableMarginLeft"
:min="0"
size="small"
placeholder="左右距离"
/>
</SettingItem>
<SettingItem name="对齐方式">
<n-select
v-model:value="optionData.dataStyle.tableAlign"
size="small"
:options="[
{ label: '靠左', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '靠右', value: 'right' },
]"
/>
</SettingItem>
<SettingItem name="表格尺寸大小">
<n-select
v-model:value="optionData.dataStyle.tableSize"
size="small"
:options="[
{ label: '小', value: 'small' },
{ label: '中', value: 'medium' },
{ label: '大', value: 'large' },
]"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox :alone="false" name="显示设置"> <SettingItemBox :alone="false" name="显示设置">
<SettingItem name="是否显示边框"> <SettingItem name="是否显示边框">
<n-space> <n-space>
@ -226,6 +528,50 @@
</n-space> </n-space>
</SettingItem> </SettingItem>
</SettingItemBox> </SettingItemBox>
</CollapseItem>
<CollapseItem name="表格样式设置" :expanded="true">
<SettingItemBox name="整体设置">
<SettingItem name="上方距离">
<n-input-number
v-model:value="optionData.dataStyle.tableMarginTop"
:min="0"
size="small"
placeholder="上方距离"
/>
</SettingItem>
<SettingItem name="左右距离">
<n-input-number
v-model:value="optionData.dataStyle.tableMarginLeft"
:min="0"
size="small"
placeholder="左右距离"
/>
</SettingItem>
<SettingItem name="对齐方式">
<n-select
v-model:value="optionData.dataStyle.tableAlign"
:options="[
{ label: '靠左', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '靠右', value: 'right' },
]"
size="small"
/>
</SettingItem>
<SettingItem name="表格尺寸大小">
<n-select
v-model:value="optionData.dataStyle.tableSize"
:options="[
{ label: '小', value: 'small' },
{ label: '中', value: 'medium' },
{ label: '大', value: 'large' },
]"
size="small"
/>
</SettingItem>
</SettingItemBox>
<SettingItemBox :alone="false" name="字体设置"> <SettingItemBox :alone="false" name="字体设置">
<!-- <SettingItem name="表头背景颜色"> <!-- <SettingItem name="表头背景颜色">
<n-color-picker <n-color-picker
@ -309,9 +655,9 @@
title: '', title: '',
align: props.optionData.dataStyle.tableAlign, align: props.optionData.dataStyle.tableAlign,
width: '200', width: '200',
prefix: '', prefix: null,
suffix: '', suffix: null,
convert: '', convert: null,
}); });
}; };
@ -352,4 +698,94 @@
}); });
}, },
); );
//
function getOptionsByShowType(filtersetItem) {
let result: any = [];
if (filtersetItem.showType) {
switch (filtersetItem.showType) {
case 'checkbox':
//
result = [
{ label: '等于', value: 'equal' },
{ label: '含有', value: 'contain' },
];
break;
case 'radio':
//
result = [
{ label: '大于', value: 'greater' },
{ label: '小于', value: 'less' },
{ label: '大于等于', value: 'greaterAndEqual' },
{ label: '小于等于', value: 'lessAndEqual' },
{ label: '等于', value: 'equal' },
{ label: '不等于', value: 'notequal' },
{ label: '含有', value: 'contain' },
{ label: '不含有', value: 'notcontain' },
];
break;
case 'select':
//
result = [
{ label: '等于', value: 'equal' },
{ label: '含有', value: 'contain' },
];
break;
case 'selectGroup':
//
result = [
{ label: '等于', value: 'equal' },
{ label: '含有', value: 'contain' },
];
break;
case 'buttonGroup':
//
result = [
{ label: '等于', value: 'equal' },
{ label: '不等于', value: 'notequal' },
{ label: '含有', value: 'contain' },
{ label: '不含有', value: 'notcontain' },
];
break;
case 'buttonGroupList':
//
result = [
{ label: '等于', value: 'equal' },
{ label: '不等于', value: 'notequal' },
{ label: '含有', value: 'contain' },
{ label: '不含有', value: 'notcontain' },
];
break;
case 'inputSearch':
//
result = [{ label: '含有', value: 'contain' }];
break;
case 'inputSearchAll':
//
result = [{ label: '含有', value: 'contain' }];
break;
case 'timePicker':
//
result = [
{ label: '大于', value: 'greater' },
{ label: '小于', value: 'less' },
{ label: '大于等于', value: 'greaterAndEqual' },
{ label: '小于等于', value: 'lessAndEqual' },
{ label: '等于', value: 'equal' },
{ label: '不等于', value: 'notequal' },
];
break;
case 'timeRange':
//
result = [{ label: '在两者之间', value: 'between' }];
break;
case 'dateRange':
//
result = [{ label: '在两者之间', value: 'between' }];
break;
}
}
return result;
}
</script> </script>

View File

@ -46,47 +46,130 @@
"convert": "1" "convert": "1"
} }
], ],
"filterset": [
{
"title": "地图显示",
"field": "type",
"compareType": "contain",
"showType": "checkbox",
"value": [ "水源", "物资", "营房", "防火通道", "三轮通道", "步行道" ],
"options": [
{ "label": "水源", "value": "水源" },
{ "label": "物资", "value": "物资" },
{ "label": "营房", "value": "营房" },
{ "label": "防火通道", "value": "防火通道" },
{ "label": "三轮通道", "value": "三轮通道" },
{ "label": "步行道", "value": "步行道" }
]
},
{
"title": "资源列表",
"field": "type",
"compareType": "equal",
"showType": "button",
"value": null,
"options": [
{ "label": "水源", "value": "水源" },
{ "label": "物资", "value": "物资" },
{ "label": "营房", "value": "营房" }
]
},
{
"title": "重点资源",
"field": null,
"compareType": null,
"showType": null,
"value": null,
"options": [
{ "label": null, "value": null }
]
},
{
"title": "距离",
"field": "distance",
"compareType": "lessAndEqual",
"showType": "radio",
"value": null,
"options": [
{ "label": "1km以内", "value": "1" },
{ "label": "5km以内", "value": "5" },
{ "label": "10km以内", "value": "10" },
{ "label": "20km以内", "value": "20" },
{ "label": "全部", "value": null }
]
}
],
"source": [ "source": [
{ {
"name": "坑塘", "name": "坑塘",
"type": "水源",
"area": null, "area": null,
"time": null, "time": null,
"distance": "1.14", "distance": "21.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
}, },
{ {
"name": "东蒙布袋口检查", "name": "东蒙布袋口检查",
"type": "物资",
"area": "300", "area": "300",
"time": "12.50", "time": "12.50",
"distance": "1.14", "distance": "14.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
}, },
{ {
"name": "北刘家庄蓄水池", "name": "北刘家庄蓄水池",
"type": "营房",
"area": "300", "area": "300",
"time": "12.50", "time": "12.50",
"distance": "0.14",
"estimatedTime": "00:05:45"
},
{
"name": "防火通道",
"type": "防火通道",
"area": null,
"time": null,
"distance": "2.14",
"estimatedTime": "00:05:45"
},
{
"name": "步行道",
"type": "步行道",
"area": "300",
"time": "5.50",
"distance": "1.14", "distance": "1.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
}, },
{
"name": "三轮通道",
"type": "三轮通道",
"area": "300",
"time": "9.50",
"distance": "5.14",
"estimatedTime": "00:05:45"
},
{ {
"name": "坑塘", "name": "坑塘",
"type": "水源",
"area": null, "area": null,
"time": null, "time": null,
"distance": "1.14", "distance": "10.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
}, },
{ {
"name": "东蒙布袋口检查", "name": "东蒙布袋口检查",
"type": "物资",
"area": "300", "area": "300",
"time": "12.50", "time": "12.50",
"distance": "1.14", "distance": "10.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
}, },
{ {
"name": "北刘家庄蓄水池", "name": "北刘家庄蓄水池",
"type": "营房",
"area": "300", "area": "300",
"time": "12.50", "time": "12.50",
"distance": "1.14", "distance": "19.14",
"estimatedTime": "00:05:45" "estimatedTime": "00:05:45"
} }
] ]

View File

@ -1,95 +1,199 @@
<template> <template>
<div class="ZhiChu_ModalTable"> <div class="ZhiChu_ModalTable">
<div class="filter"> <div class="filterDiv">
<div class="filterItem" v-for="(item, index) in option.filterset" :key="index">
<a-row> <a-row>
<!-- 地图显示 --> <!-- 筛选标题 -->
<a-col :span="6"> <a-col :span="option.dataStyle.colLeft">
<div class="filterTitle">地图显示</div> <div class="filterTitle">{{ item.title }}</div>
</a-col> </a-col>
<a-col :span="18"> <!-- 筛选内容 -->
<n-checkbox-group v-model:value="option.dataStyle.mapshow"> <!-- 多选框 -->
<n-space item-style="display: flex;"> <a-col :span="24 - option.dataStyle.colLeft" v-if="item.showType == 'checkbox'">
<n-checkbox value="水源"> <div class="filterContentDiv">
<n-checkbox-group v-model:value="item.value">
<n-checkbox
:style="{
marginRight: option.dataStyle.filterTitleFontSize + 'px',
}"
v-for="(checkboxItem, checkboxIndex) in item.options"
:key="checkboxIndex"
:value="checkboxItem.value"
>
<template #default> <template #default>
<span class="filterChoose">水源</span> <span class="filterContentFont">{{ checkboxItem.label }}</span>
</template> </template>
</n-checkbox> </n-checkbox>
<n-checkbox value="物资">
<template #default>
<span class="filterChoose">物资</span>
</template>
</n-checkbox>
<n-checkbox value="营房">
<template #default>
<span class="filterChoose">营房</span>
</template>
</n-checkbox>
<n-checkbox value="防火通道">
<template #default>
<span class="filterChoose">防火通道</span>
</template>
</n-checkbox>
<n-checkbox value="三轮通道">
<template #default>
<span class="filterChoose">三轮通道</span>
</template>
</n-checkbox>
<n-checkbox value="步行道">
<template #default>
<span class="filterChoose">步行道</span>
</template>
</n-checkbox>
</n-space>
</n-checkbox-group> </n-checkbox-group>
</a-col>
<!-- 资源列表 -->
<a-col :span="6">
<div class="filterTitle">资源列表</div>
</a-col>
<a-col :span="18">
<div style="display: inline-flex">
<div class="ziyuanlist_choose">水源</div>
<div class="ziyuanlist_nochoose">物资</div>
<div class="ziyuanlist_nochoose">营房</div>
</div> </div>
</a-col> </a-col>
<!-- 重点资源 --> <!-- 单选框 -->
<a-col :span="6"> <a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'radio'">
<div class="filterTitle">重点资源</div> <div class="filterContentDiv">
</a-col> <n-radio-group v-model:value="item.value" name="radiogroup">
<a-col :span="18">
<div class="filterChoose"></div>
</a-col>
<!-- 距离 -->
<a-col :span="6">
<div class="filterTitle">距离</div>
</a-col>
<a-col :span="18">
<div class="filterChoose">
<n-radio-group v-model:value="option.dataStyle.distance" name="radiogroup">
<n-space> <n-space>
<n-radio value="1"> <n-radio
<span class="filterChoose">1km以内</span> :style="{
</n-radio> marginRight: option.dataStyle.filterTitleFontSize + 'px',
<n-radio value="5"> }"
<span class="filterChoose">5km以内</span> v-for="(radioItem, radioIndex) in item.options"
</n-radio> :key="radioIndex"
<n-radio value="10"> :value="radioItem.value"
<span class="filterChoose">10km以内</span> >
</n-radio> <span class="filterContentFont">{{ radioItem.label }}</span>
<n-radio value="20">
<span class="filterChoose">20km以内</span>
</n-radio>
<n-radio value="all">
<span class="filterChoose">全部</span>
</n-radio> </n-radio>
</n-space> </n-space>
</n-radio-group> </n-radio-group>
</div> </div>
</a-col> </a-col>
<!-- 下拉框 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'select'">
<div class="filterContentDiv">
<n-select
v-model:value="item.value"
:options="item.options"
:style="{ width: '50%' }"
placeholder="请选择选项"
clearable
/>
</div>
</a-col>
<!-- 下拉框多选 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'selectGroup'">
<div class="filterContentDiv">
<n-select
v-model:value="item.value"
:options="item.options"
placeholder="请选择选项(可多选)"
clearable
multiple
/>
</div>
</a-col>
<!-- 按钮组 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'buttonGroup'">
<div class="filterContentDiv" style="display: inline-flex">
<div
:style="{
marginRight: option.dataStyle.filterTitleFontSize + 'px',
}"
v-for="(buttonItem, buttonIndex) in item.options"
:key="buttonIndex"
:class="
item.value == buttonItem.value
? 'filterContentFont_choose'
: 'filterContentFont_nochoose'
"
@click="clickFilterButton(item, buttonItem)"
>
{{ buttonItem.label }}
</div>
</div>
</a-col>
<!-- 按钮组多选 -->
<a-col
:span="24 - option.dataStyle.colLeft"
v-else-if="item.showType == 'buttonGroupList'"
>
<div class="filterContentDiv" style="display: inline-flex">
<div
:style="{
marginRight: option.dataStyle.filterTitleFontSize + 'px',
}"
v-for="(buttonItem, buttonIndex) in item.options"
:key="buttonIndex"
:class="
item.value && item.value.includes(buttonItem.value)
? 'filterContentFont_choose'
: 'filterContentFont_nochoose'
"
@click="clickFilterButtonList(item, buttonItem)"
>
{{ buttonItem.label }}
</div>
</div>
</a-col>
<!-- 列搜索框 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'inputSearch'">
<div class="filterContentDiv">
<n-input-group>
<n-input
v-model:value="item.value"
:style="{ width: '50%' }"
:placeholder="'请输入' + item.title"
clearable
/>
<n-button type="primary" ghost @click="search"> </n-button>
</n-input-group>
</div>
</a-col>
<!-- 全数据搜索框 -->
<a-col
:span="24 - option.dataStyle.colLeft"
v-else-if="item.showType == 'inputSearchAll'"
>
<div class="filterContentDiv">
<n-input-group>
<n-input
v-model:value="item.value"
:style="{ width: '50%' }"
placeholder="请输入搜索数据"
clearable
/>
<n-button type="primary" ghost @click="searchAll"> </n-button>
</n-input-group>
</div>
</a-col>
<!-- 时间选择器 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'timePicker'">
<div class="filterContentDiv">
<n-time-picker
v-model:formatted-value="item.value"
value-format="HH:mm:ss"
format="HH:mm:ss"
:style="{ width: '50%' }"
clearable
placeholder="请选择时间"
/>
</div>
</a-col>
<!-- 时间范围 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'timeRange'">
<div class="filterContentDiv" :style="{ display: 'inline-flex' }">
<n-time-picker
v-model:formatted-value="item.value"
value-format="HH:mm:ss"
format="HH:mm:ss"
:style="{ width: '40%', marginRight: '30px' }"
clearable
placeholder="请选择开始时间"
/>
<n-time-picker
v-model:formatted-value="item.value2"
value-format="HH:mm:ss"
format="HH:mm:ss"
:style="{ width: '40%' }"
clearable
placeholder="请选择结束时间"
/>
</div>
</a-col>
<!-- 日期范围 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else-if="item.showType == 'dateRange'">
<div class="filterContentDiv">
<n-date-picker />
</div>
</a-col>
<!-- 其他 -->
<a-col :span="24 - option.dataStyle.colLeft" v-else>
<div class="filterContent"> </div>
</a-col>
</a-row> </a-row>
</div> </div>
<div class="table"> </div>
<!-- 表格部分 -->
<div class="theadDiv">
<n-table <n-table
:bordered="option.dataStyle.tableBordered" :bordered="option.dataStyle.tableBordered"
:single-column="option.dataStyle.tableSigleColumn" :single-column="option.dataStyle.tableSigleColumn"
@ -102,14 +206,48 @@
backgroud: option.dataStyle.tableHeaderBackgroud, backgroud: option.dataStyle.tableHeaderBackgroud,
}" }"
> >
<th class="th" v-if="option.dataStyle.orderBumberShow"></th> <th
<th class="th" v-for="(item, index) in option.header" :key="index">{{ item.title }}</th> class="th"
<th class="th" v-if="option.dataStyle.buttonDivShow"></th> v-if="option.dataStyle.orderBumberShow"
:style="{
width: option.dataStyle.orderDivWidth + 'px',
}"
>
序号
</th>
<th
class="th"
v-for="(item, index) in option.header"
:key="index"
:style="{
width: item.width + 'px',
}"
>
{{ item.title }}
</th>
<th
class="th"
v-if="option.dataStyle.buttonDivShow"
:style="{
width: option.dataStyle.buttonDivWidth + 'px',
}"
>
操作
</th>
</tr> </tr>
</thead> </thead>
</n-table>
</div>
<div class="tbodyDiv">
<n-table
:bordered="option.dataStyle.tableBordered"
:single-column="option.dataStyle.tableSigleColumn"
:single-line="option.dataStyle.tableSingleLine"
:size="option.dataStyle.tableSize"
>
<tbody> <tbody>
<tr <tr
v-for="(dataItem, dataIndex) in option.dataset" v-for="(dataItem, dataIndex) in filterData"
:key="dataIndex" :key="dataIndex"
:class="dataIndex % 2 == 0 ? 'td1' : 'td2'" :class="dataIndex % 2 == 0 ? 'td1' : 'td2'"
> >
@ -131,21 +269,22 @@
}" }"
> >
<span> <span>
{{ dataItem[headerItem.key] ? convertData(headerItem, dataItem) : '--' }}</span {{ dataItem[headerItem.key] ? convertData(headerItem, dataItem) : '--' }}
> </span>
</td> </td>
<!-- 操作 --> <!-- 操作 -->
<td <td
v-if="option.dataStyle.buttonDivShow"
:style="{ :style="{
width: option.dataStyle.buttonDivWidth + 'px', width: option.dataStyle.buttonDivWidth + 'px',
}" }"
> >
<div v-if="option.dataStyle.buttonDivShow" class="buttonDiv"> <div class="buttonDiv">
<n-button <n-button
v-if="option.dataStyle.buttonDivShow1" v-if="option.dataStyle.buttonDivShow1"
size="small" size="small"
quaternary quaternary
@click="addRight(dataIndex)" @click="pitchLocation(dataItem, dataIndex)"
> >
<Button1 :dataStyle="option.dataStyle" /> <Button1 :dataStyle="option.dataStyle" />
</n-button> </n-button>
@ -159,7 +298,7 @@
v-if="option.dataStyle.buttonDivShow2" v-if="option.dataStyle.buttonDivShow2"
size="small" size="small"
quaternary quaternary
@click="removeRight(index1)" @click="moveLocation(dataItem, dataIndex)"
> >
<Button2 :dataStyle="option.dataStyle" /> <Button2 :dataStyle="option.dataStyle" />
</n-button> </n-button>
@ -179,6 +318,7 @@
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore';
import { useChartDataFetch } from '@/hooks'; import { useChartDataFetch } from '@/hooks';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { cloneDeep } from 'lodash-es';
import Button1 from './svg/button1.vue'; import Button1 from './svg/button1.vue';
import Button2 from './svg/button2.vue'; import Button2 from './svg/button2.vue';
@ -189,25 +329,244 @@
}, },
}); });
//
const inputData = ref('');
//
const filterData = computed(() => {
return option?.dataset?.filter((item: any) => {
return Object.values(item).some((val) => {
return String(val).toLowerCase().includes(inputData.value.toLowerCase());
});
});
});
const { w, h } = toRefs(props.chartConfig.attr); const { w, h } = toRefs(props.chartConfig.attr);
const option = reactive({ const option = reactive({
dataset: props.chartConfig.option.dataset,
header: props.chartConfig.option.header, header: props.chartConfig.option.header,
dataset: props.chartConfig.option.dataset,
filterset: props.chartConfig.option.filterset,
dataStyle: props.chartConfig.option.dataStyle, dataStyle: props.chartConfig.option.dataStyle,
}); });
//
const headHeight = computed(() => {
if (option.dataStyle.tableHeaderShow) {
return document.querySelector('.theadDiv')?.offsetHeight + 10;
} else {
return 0;
}
});
//
const searchFlag = ref(false);
const searchAllFlag = ref(false);
function search() {
searchFlag.value = true;
}
function searchAll() {
searchAllFlag.value = true;
}
//
const filterData = computed(() => {
let data = cloneDeep(option.dataset);
option.filterset.forEach((filtersetItem) => {
if (filtersetItem.value) {
switch (filtersetItem.field && filtersetItem.compareType) {
//
case 'greater':
if (['timePicker'].includes(filtersetItem.showType)) {
data = data.filter(
(d) =>
dayjs(d[filtersetItem.field], 'HH:mm:ss').diff(
dayjs(filtersetItem.value, 'HH:mm:ss'),
) > 0,
);
} else {
data = data.filter(
(d) => Number(d[filtersetItem.field]) > Number(filtersetItem.value),
);
}
break;
//
case 'less':
if (['timePicker'].includes(filtersetItem.showType)) {
data = data.filter(
(d) =>
dayjs(d[filtersetItem.field], 'HH:mm:ss').diff(
dayjs(filtersetItem.value, 'HH:mm:ss'),
) < 0,
);
} else {
data = data.filter(
(d) => Number(d[filtersetItem.field]) < Number(filtersetItem.value),
);
}
break;
//
case 'greaterAndEqual':
if (['timePicker'].includes(filtersetItem.showType)) {
data = data.filter(
(d) =>
dayjs(d[filtersetItem.field], 'HH:mm:ss').diff(
dayjs(filtersetItem.value, 'HH:mm:ss'),
) >= 0,
);
} else {
data = data.filter(
(d) => Number(d[filtersetItem.field]) >= Number(filtersetItem.value),
);
}
break;
//
case 'lessAndEqual':
if (['timePicker'].includes(filtersetItem.showType)) {
data = data.filter(
(d) =>
dayjs(d[filtersetItem.field], 'HH:mm:ss').diff(
dayjs(filtersetItem.value, 'HH:mm:ss'),
) <= 0,
);
} else {
data = data.filter(
(d) => Number(d[filtersetItem.field]) <= Number(filtersetItem.value),
);
}
break;
//
case 'equal':
if (['checkbox'].includes(filtersetItem.showType)) {
//
data = data.filter((d) =>
filtersetItem.value.some((li) => d[filtersetItem.field].includes(li)),
);
} else if (['selectGroup', 'buttonGroupList'].includes(filtersetItem.showType)) {
//
if (filtersetItem.value.length > 0) {
data = data.filter((d) =>
filtersetItem.value.some((li) => d[filtersetItem.field].includes(li)),
);
}
} else {
//
data = data.filter((d) => d[filtersetItem.field] == filtersetItem.value);
}
break;
//
case 'notequal':
if (['checkbox'].includes(filtersetItem.showType)) {
//
data = data.filter((d) =>
filtersetItem.value.some((li) => !d[filtersetItem.field].includes(li)),
);
} else if (['selectGroup', 'buttonGroupList'].includes(filtersetItem.showType)) {
//
if (filtersetItem.value.length > 0) {
data = data.filter((d) =>
filtersetItem.value.some((li) => !d[filtersetItem.field].includes(li)),
);
}
} else {
//
data = data.filter((d) => d[filtersetItem.field] !== filtersetItem.value);
}
break;
//
case 'contain':
if (['checkbox'].includes(filtersetItem.showType)) {
//
data = data.filter((d) =>
filtersetItem.value.some((li) => d[filtersetItem.field].includes(li)),
);
} else if (['selectGroup', 'buttonGroupList'].includes(filtersetItem.showType)) {
//
if (filtersetItem.value.length > 0) {
data = data.filter((d) =>
filtersetItem.value.some((li) => d[filtersetItem.field].includes(li)),
);
}
} else if (['inputSearch'].includes(filtersetItem.showType)) {
//
if (searchFlag.value) {
data = data.filter(
(d) => d[filtersetItem.field].indexOf(filtersetItem.value) !== -1,
);
searchFlag.value = false;
}
} else if (['inputSearchAll'].includes(filtersetItem.showType)) {
//
if (searchAllFlag.value) {
data = data.filter((d) => {
let flag = false;
option.header.some((headerLi) => {
if (d[headerLi.key]) {
flag = flag ? true : d[headerLi.key].includes(filtersetItem.value);
}
});
return flag;
});
searchAllFlag.value = false;
}
} else {
//
data = data.filter((d) => d[filtersetItem.field].indexOf(filtersetItem.value) !== -1);
}
break;
//
case 'notcontain':
if (['checkbox'].includes(filtersetItem.showType)) {
//
data = data.filter((d) =>
filtersetItem.value.some((li) => !d[filtersetItem.field].includes(li)),
);
} else if (['selectGroup', 'buttonGroupList'].includes(filtersetItem.showType)) {
//
if (filtersetItem.value.length > 0) {
data = data.filter((d) =>
filtersetItem.value.some((li) => !d[filtersetItem.field].includes(li)),
);
}
} else {
//
data = data.filter((d) => d[filtersetItem.field].indexOf(filtersetItem.value) == -1);
}
break;
//
case 'between':
if (['timeRange'].includes(filtersetItem.showType)) {
data = data.filter((d) => {
const time = dayjs(d[filtersetItem.field], 'HH:mm:ss');
const startTime = dayjs(filtersetItem.value, 'HH:mm:ss');
const endTime = dayjs(filtersetItem.value2, 'HH:mm:ss');
return time.diff(startTime) >= 0 && time.diff(endTime) <= 0;
});
}
if (['dateRange'].includes(filtersetItem.showType)) {
data = data.filter((d) => {
const time = dayjs(d[filtersetItem.field], 'yyyy-MM-dd HH:mm:ss');
const startTime = dayjs(filtersetItem.value, 'yyyy-MM-dd HH:mm:ss');
const endTime = dayjs(filtersetItem.value, 'yyyy-MM-dd HH:mm:ss');
return time.diff(startTime) >= 0 && time.diff(endTime) <= 0;
});
}
break;
}
}
});
return data;
});
// -
function clickFilterButton(item, buttonItem) {
if (item.value == buttonItem.value) {
item.value = '';
} else {
item.value = buttonItem.value;
}
}
// -
function clickFilterButtonList(item, buttonItem) {
if (!item.value) {
item.value = [];
}
if (item.value.includes(buttonItem.value)) {
item.value.splice(item.value.indexOf(buttonItem.value), 1);
} else {
item.value.push(buttonItem.value);
}
}
// //
function convertData(header, data) { function convertData(header, data) {
let prefix = header.prefix ? header.prefix : ''; let prefix = header.prefix ? header.prefix : '';
@ -250,6 +609,11 @@
} }
} }
//
function pitchLocation(dataItem, dataIndex) {}
function moveLocation(dataItem, dataIndex) {}
// setdata // setdata
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
props.chartConfig.option.dataset = newData; props.chartConfig.option.dataset = newData;
@ -268,62 +632,93 @@
user-select: none; user-select: none;
} }
.filter { .filterDiv {
width: 100%; width: 100%;
height: v-bind('`${option.dataStyle.filterHeight}px`'); padding-top: v-bind('`${option.dataStyle.filterMarginTop}px`');
margin-top: v-bind('`${option.dataStyle.filterMarginTop}px`'); padding-left: v-bind('`${option.dataStyle.filterMarginLeft}px`');
margin-left: v-bind('`${option.dataStyle.filterMarginLeft}px`'); padding-right: v-bind('`${option.dataStyle.filterMarginLeft}px`');
margin-right: v-bind('`${option.dataStyle.filterMarginLeft}px`');
} }
//
.filterTitle { .filterTitle {
align-items: center; text-align: v-bind('`${option.dataStyle.filterTitleAlign}`');
width: v-bind('`${option.dataStyle.filterTitleWidth}px`');
font-size: v-bind('`${option.dataStyle.filterTitleFontSize}px`'); font-size: v-bind('`${option.dataStyle.filterTitleFontSize}px`');
color: v-bind('`${option.dataStyle.filterTitleFontColor}`'); color: v-bind('`${option.dataStyle.filterTitleFontColor}`');
margin-right: v-bind('`${option.dataStyle.filterTitleMarginRight}px`');
font-family: font-family:
PingFangSC, PingFangSC,
PingFang SC; PingFang SC;
font-weight: 500; font-weight: 500;
line-height: 33px; line-height: v-bind('`${option.dataStyle.filterTitleFontSize}px`');
text-align: left; height: v-bind('`${option.dataStyle.filterItemHeight}px`');
font-style: normal; font-style: normal;
} }
.filterChoose { .filterContentDiv {
width: 100%;
height: v-bind('`${option.dataStyle.filterItemHeight}px`');
justify-content: v-bind('`${option.dataStyle.filterContentAlign}`');
text-align: v-bind('`${option.dataStyle.filterContentAlign}`');
align-items: v-bind('`${option.dataStyle.filterContentAlign}`');
}
//
.filterContentFont {
font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`'); font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`');
color: v-bind('`${option.dataStyle.filterChooseFontColor}`'); color: v-bind('`${option.dataStyle.filterChooseFontColor}`');
} }
::v-deep .n-checkbox-box {
width: v-bind('`${option.dataStyle.filterChooseFontSize}px`') !important;
height: v-bind('`${option.dataStyle.filterChooseFontSize}px`') !important;
}
::v-deep .n-radio__dot {
width: v-bind('`${option.dataStyle.filterChooseFontSize}px`') !important;
height: v-bind('`${option.dataStyle.filterChooseFontSize}px`') !important;
}
.ziyuanlist_nochoose { .filterContentFont_nochoose {
margin-right: 30px;
background: #1c211f; background: #1c211f;
color: #18d09d; color: #18d09d;
border: 1px solid #18d09d; border: 1px solid #18d09d;
font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`'); font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`');
width: 80px; width: v-bind('`${option.dataStyle.filterChooseFontSize + 62}px`');
height: 30px; height: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
border-radius: 30px; border-radius: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
text-align: center; text-align: center;
line-height: 30px; line-height: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
} }
.ziyuanlist_choose { .filterContentFont_choose {
margin-right: 30px;
background: #26d1ad; background: #26d1ad;
color: #0d2822; color: #0d2822;
font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`'); font-size: v-bind('`${option.dataStyle.filterChooseFontSize}px`');
width: 80px; width: v-bind('`${option.dataStyle.filterChooseFontSize + 62}px`');
height: 30px; height: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
border-radius: 30px; border-radius: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
text-align: center; text-align: center;
line-height: 30px; line-height: v-bind('`${option.dataStyle.filterChooseFontSize + 12}px`');
} }
.table { //
padding-top: v-bind('`${option.dataStyle.tableMarginTop}px`'); .theadDiv {
margin-top: v-bind('`${option.dataStyle.tableMarginTop}px`');
padding-left: v-bind('`${option.dataStyle.tableMarginLeft}px`'); padding-left: v-bind('`${option.dataStyle.tableMarginLeft}px`');
padding-right: v-bind('`${option.dataStyle.tableMarginLeft}px`'); padding-right: v-bind('`${option.dataStyle.tableMarginLeft}px`');
} }
//
.tbodyDiv {
overflow-y: auto;
height: v-bind(
'`${h - headHeight - option.dataStyle.filterMarginTop - option.dataStyle.filterItemHeight * option.filterset.length - option.dataStyle.tableMarginTop}px`'
);
padding-left: v-bind('`${option.dataStyle.tableMarginLeft}px`');
padding-right: v-bind('`${option.dataStyle.tableMarginLeft}px`');
}
.tbodyDiv::-webkit-scrollbar {
display: none;
}
.tbodyDiv {
scrollbar-width: none;
-ms-overflow-style: none;
}
.th { .th {
text-align: v-bind('`${option.dataStyle.tableAlign}`'); text-align: v-bind('`${option.dataStyle.tableAlign}`');
color: v-bind('`${option.dataStyle.tableHeaderFontColor}`'); color: v-bind('`${option.dataStyle.tableHeaderFontColor}`');