<template>
<div class="utm-search-box" id="search-bar">
<p class="search-title">Search Options</p>
<!--普通搜索-->
<div class="utm-search-list" :style="{'overflow-y': searchData.noHidden ? 'unset' : 'auto'}">
<div class="search-tip-text" v-if="isNeedTip">
Default search radius is {{ ApiService.reportSearchTime }} days.
</div>
<template v-if="searchData.searchInfo && searchData.searchInfo.length > 0">
<template v-for="(item,index) in searchData.searchInfo">
<div class="utm-search-item" v-if="item.setOption !== false">
<span class="utm-search-title" v-if="!item.specialFlag">
<span v-if="(item.title=='Profile Photo Status' && !item.isSwitch)?false:true">{{item.title}}</span>
<!-- 字段旁添加说明 -->
<Tooltip :content="item.tooltip" v-if="item.tooltip" offset="-10" class="utm-tooltip" placement="bottom-start">
<psim-icon type="ivu-icon ivu-icon-ios-alert-outline" color="#005EB8" size="17"></psim-icon>
</Tooltip>
</span>
<!--输入框-->
<template v-if="item.type == 'input' && !item.isSpecial">
<div class="utm-input-box" :class="{'utm-input-clear': item.keyword || item.keyword === 0}">
<input v-model.trim="item.keyword" @keyup="checkIsNumber(item)" type="text" class="utm-input" maxlength="255"
:placeholder="'Please Input ' + item.title" @keyup.enter="refactoringData(searchData)"/>
<i class="ivu-icon ivu-icon-ios-close-circle clear-input-icon" @click.stop="item.keyword = ''"></i>
</div>
</template>
<!--字符中间只能输入一个空格的输入框-->
<template v-if="item.type == 'input' && item.isSpecial">
<div class="utm-input-box" :class="{'utm-input-clear': item.keyword || item.keyword === 0}">
<input v-model.trim="item.keyword" @keyup="checkIsNumber(item)" type="text" class="utm-input" maxlength="255"
onkeyup="value=(value.replace(/^\s+/,'')).replace(/\s+/g,' ')"
@blur="item.keyword=(item.keyword.replace(/^\s+/,'')).replace(/\s+/g,' ')"
:placeholder="'Please Input ' + item.title" @keyup.enter="refactoringData(searchData)"/>
<i class="ivu-icon ivu-icon-ios-close-circle clear-input-icon" @click.stop="item.keyword = ''"></i>
</div>
</template>
<!--数字输入框-->
<template v-if="item.type == 'input-number'">
<div class="utm-input-box" :class="{'utm-input-clear': item.keyword || item.keyword === 0}">
<input v-model.trim="item.keyword" @input="item.keyword = getValue(item.keyword)" type="text" class="utm-input" maxlength="255"
:placeholder="'Please Input ' + item.title" @keyup.enter="refactoringData(searchData)"/>
<i class="ivu-icon ivu-icon-ios-close-circle clear-input-icon" @click.stop="item.keyword = ''"></i>
</div>
</template>
<!--普通下拉框-->
<template v-else-if="item.type == 'select' ? (item.title=='Profile Photo Status' && !item.isSwitch)?false:true :false">
<Select v-model="item.keyword" class="utm-select" @on-change="(value) =>getOption(value,item)" label-in-value :placeholder="'Select ' + item.title" :clearable="true">
<Option v-for="(option,index) in item.selectData" :value="option[item.val] || option[item.val] === 0 ? option[item.val] : option.id" :key="index"
:label="item.textArray ? option[item.textArray[0]] + '(' + option[item.textArray[1]] + ')' :option[item.text] ? option[item.text]:option.name">
<span v-html="setHtml(option,item)"></span>
</Option>
</Select>
</template>
<!--分组下拉框-->
<template v-else-if="item.type == 'select-group'">
<Select v-model="item.keyword" class="utm-select" :placeholder="'Select' + item.title" :clearable="true">
<OptionGroup v-for="(option,index) in item.selectData" :key="index" :label="option[item.label]">
<Option :value="optionItem[item.val] || optionItem[item.val] === 0 ? optionItem[item.val]:optionItem.id" v-for="(optionItem,optionItemIndex) in option[item.array]" :key="optionItemIndex"
:label="item.textArray ? optionItem[item.textArray[0]] + '(' + optionItem[item.textArray[1]] + ')' :optionItem[item.text] ? optionItem[item.text]:optionItem.name">
<span v-html="setHtml(optionItem,item)"></span>
</Option>
</OptionGroup>
</Select>
</template>
<!--带搜索的下拉框-->
<template v-else-if="item.type == 'select-search'">
<Select
v-model="item.keyword"
filterable
filter-by-label
label-in-value
@on-open-change="(flag) =>openChangePanel(item,flag)"
v-scroll:[item]="handScroll"
:ref="item.filed"
v-on:keyup.enter.native ="searchNow(item)"
@on-change="(value) =>getOption(value,item)"
:remote-method="(value) =>{
searchTermChanged(value, item)
}"
class="utm-select utm-search-select utm-remote-search-select"
:placeholder="'Select ' + item.title"
:clearable="true"
:not-found-text="item.loading ? 'Loading...' : 'No matching data'"
>
<Option v-for="(option,index) in item.selectData" :value="option[item.val] || option[item.val] === 0? option[item.val]:option.id" :key="index"
:label="item.textArray ? option[item.textArray[0]] + '(' + option[item.textArray[1]] + ')' :option[item.text] ? option[item.text]:option.name">
<span v-html="setHtml(option,item)"></span>
</Option>
</Select>
</template>
<!--label-in-value-->
<!--带搜索的多选下拉框(下拉选项为实时数据)-->
<template v-else-if="item.type == 'select-search-multiple' && !item.specialFlag"> <!--specialFlag : 特殊情况(如办公室搜索只能在选择所有办公室情况下显示)-->
<Select
v-model="item.keyword"
label-in-value
:max-tag-count="item.maxTagCount || 2"
:max-tag-placeholder="maxTagPlaceholder"
@on-change="(value) =>getOption(value,item)"
@on-open-change="(flag) =>openChangePanel(item,flag)"
v-scroll:[item]="handScroll"
:ref="item.filed"
v-on:keyup.enter.native ="searchNow(item)"
filterable
filter-by-label
@on-query-change="(value) => {
searchTermChanged(value,item)
}"
multiple
class="utm-select utm-multiple-select utm-search-select utm-remote-search-select"
:placeholder="'Select ' + item.title"
:clearable="true"
:not-found-text="item.loading ? 'Loading...' : 'No matching data'"
>
<Option v-for="(option,index) in item.selectData" :style="item.width?'width:'+item.width+'px':''" :value="option[item.val] || option[item.val] === 0 ? option[item.val]:option.id" :key="index"
:label="item.textArray ? option[item.textArray[0]] + '(' + option[item.textArray[1]] + ')' :option[item.text] ? option[item.text]:option.name">
<span v-html="setHtml(option,item)"></span>
</Option>
</Select>
</template>
<!--带搜索的分组下拉框-->
<template v-else-if="item.type == 'select-group-search'">
<Select v-model="item.keyword" filterable filter-by-label multiple label-in-value @on-change="(value) =>getOption(value,item)" :max-tag-count="2" :max-tag-placeholder="maxTagPlaceholder" class="utm-select utm-multiple-select utm-search-select" :placeholder="'Select ' + item.title" :clearable="true">
<OptionGroup v-for="(option,index) in item.selectData" :key="index" :label="option[item.label]">
<Option :value="optionItem[item.val] || optionItem[item.val] === 0 ? optionItem[item.val]:optionItem.id" v-for="(optionItem,optionItemIndex) in option[item.array]" :key="optionItemIndex"
:label="item.textArray ? optionItem[item.textArray[0]] + '(' + optionItem[item.textArray[1]] + ')' :optionItem[item.text] ? optionItem[item.text]:optionItem.name">
<span v-html="setHtml(optionItem,item)"></span>
</Option>
</OptionGroup>
</Select>
</template>
<!--多选的分组下拉框-->
<template v-else-if="item.type == 'select-group-multiple'">
<Select v-model="item.keyword" multiple label-in-value @on-change="(value) =>getOption(value,item)" :max-tag-count="2" :max-tag-placeholder="maxTagPlaceholder" class="utm-select utm-multiple-select utm-search-select" :placeholder="'Select ' + item.title" :clearable="true">
<OptionGroup v-for="(option,index) in item.selectData" :key="index" :label="option[item.label]">
<Option :value="optionItem[item.val] || optionItem[item.val] === 0 ? optionItem[item.val]:optionItem.id" v-for="(optionItem,optionItemIndex) in option[item.array]" :key="optionItemIndex"
:label="item.textArray ? optionItem[item.textArray[0]] + '(' + optionItem[item.textArray[1]] + ')' :optionItem[item.text] ? optionItem[item.text]:optionItem.name">
<span v-html="setHtml(optionItem,item)"></span>
</Option>
</OptionGroup>
</Select>
</template>
<!--多选下拉框(下拉数据是固定的)-->
<template v-else-if="item.type == 'select-multiple'">
<Select v-model="item.keyword" :placement="item.placement || 'bottom-start'" class="utm-select utm-multiple-select" label-in-value @on-change="(value) =>getOption(value,item)" :max-tag-count="2" :max-tag-placeholder="maxTagPlaceholder" multiple :placeholder="'Select ' + item.title" :clearable="true"
>
<Option v-for="(option,index) in item.selectData" :value="option[item.val] || option[item.val] === 0 ? option[item.val] : option.id" :key="index"
:label="item.textArray ? option[item.textArray[0]] + '(' + option[item.textArray[1]] + ')' :option[item.text] ? option[item.text] : option.name">
<span v-html="setHtml(option,item)"></span>
</Option>
</Select>
</template>
<!--双下拉框-->
<!--
disableFilter: 禁用通过比较第二个select的filterKey值与第一个select所选值对比进行的过滤操作,为true时禁用;
content: 两个select数组,第一个select选的值,可以用于过滤第二个select的值;
content[i].selectData: select的可选值,每个可选项的关键字默认为label和value,可用content[i]的text和val设置取值的关键字;
content[i].keyword: select选的值;
onFilterKeywordChange: 第一个select选的值的change事件;
filterKey: 第二个select的数据的key, 用于与第一个select的filterKeyword对比,过滤第二个select的selectData的值;
-->
<template v-else-if="item.type == 'select-select'">
<div class="utm-select-group">
<Select class="utm-select select-group-left" clearable style="width: 35%" :placeholder="'Select ' + item.title" v-model="item.content[0].keyword"
@on-change="($event)=>{
item.onFilterKeywordChange ? item.onFilterKeywordChange($event, item.content[0].selectData, item) : undefined,
changeDoubleSelectInfo(item)
}">
<Option :value="type[item.content[0].val || 'value']" :label="type[item.content[0].text || 'label']" v-for="(type,index) in item.content[0].selectData" :key="index">
{{type[item.content[0].text || 'label']}}
</Option>
</Select>
<Select v-if="item.disableFilter" filter-by-label label-in-value filterable class="utm-select select-group-right" style="width: 65%" placeholder="Search or Select" v-model="item.content[1].keyword" @on-change="changeDoubleSelectInfo(item)">
<Option :value="sItem[item.content[1].val || 'value']" :label="sItem[item.content[1].text || 'label']" v-for="(sItem,index) in item.content[1].selectData" :key="index">{{sItem[item.content[1].text || 'label']}}</Option>
</Select>
<Select v-else filter-by-label label-in-value filterable class="utm-select select-group-right" style="width: 65%" placeholder="Search or Select" v-model="item.content[1].keyword" @on-change="changeDoubleSelectInfo(item)">
<Option :value="sItem[item.content[1].val || 'value']" :label="sItem[item.content[1].text || 'label']" v-for="(sItem,index) in item.content[1].selectData" :key="index" v-show="sItem[item.filterKey] === item.content[0].keyword || (!item.content[0].keyword && item.content[0].keyword !== 0)">{{sItem[item.content[1].text || 'label']}}</Option>
</Select>
</div>
</template>
<!--两个下拉框不相互影响-->
<template v-else-if="item.type == 'select-select-default'">
<div class="utm-select-group utm-select-group-default">
<template v-for="(subItem,cascaderIndex) in item.content">
<template>
<Select v-model="subItem.keyword" filterable filter-by-label label-in-value @on-change="(value) =>getMoreSelect(value,item,subItem)"
:max-tag-count="2" :max-tag-placeholder="maxTagPlaceholder" multiple
class="utm-select utm-search-select utm-multiple-select" placeholder="Select"
:clearable="true" :key="cascaderIndex">
<Option v-for="(option,index) in subItem.selectData" :value="option[item.val] || option[item.val] === 0? option[item.val]:option.id" :key="index"
:label="option[item.text] ? option[item.text]:option.name">
{{option[item.text] ? option[item.text]:option.name}}
</Option>
</Select>
</template>
</template>
</div>
</template>
<!--下拉选择组,第二个下拉为多选,且仅第二个条件生效-->
<template v-else-if="item.type == 'select-search-multiple-group'">
<div class="utm-select-group">
<Select
v-model="item.content[0].keyword"
filterable
filter-by-label
label-in-value
@on-change="(value) =>changeFilter('', item)"
style="width: 45%"
class="utm-select utm-search-select select-group-left"
:placeholder="'Select ' + item.content[0].title"
:clearable="item.content[0].clearable"
>
<Option v-for="(child,index) in item.content[0].selectData" :value="child[item.content[0].val] || child[item.content[0].val] === 0? child[item.content[0].val]:item.content[0].id" :key="index"
:label="child[item.content[0].text] || child.name">
</Option>
</Select>
<Select
:disabled="item.content[1].disabled"
v-model="item.keyword"
:max-tag-count="item.maxTagCount || 1"
:max-tag-placeholder="maxTagPlaceholder"
@on-change="(value) =>getOption(value,item)"
v-scroll:[item]="handScroll"
:ref="item.filed"
v-on:keyup.enter.native ="searchNow(item)"
label-in-value
filterable
filter-by-label
@on-query-change="(value) => {
searchTermChanged(value,item)
}"
multiple
style="width: 55%"
class="utm-select utm-multiple-select utm-search-select select-group-right"
:placeholder="'Select ' + item.title"
:clearable="true"
:not-found-text="item.loading ? 'Loading...' : 'No matching data'"
>
<Option v-for="(option,index) in item.selectData" :value="option[item.val] || option[item.val] === 0 ? option[item.val]:option.id" :key="index"
:label="item.textArray ? option[item.textArray[0]] + '(' + option[item.textArray[1]] + ')' :option[item.text] ? option[item.text]:option.name">
<span v-html="setHtml(option,item)"></span>
</Option>
</Select>
</div>
</template>
<!--联动下拉框-->
<!-- 添加addClass字段 -->
<template v-else-if="item.type == 'cascader'">
<Cascader class="utm-multistage-select" :class="item.addClass" :data="item.selectData" change-on-select filterable v-model="item.keyword"
@on-change="(value, selectedData) => changeCascader(value, selectedData, item, searchData)" :placeholder="getPlaceholderText(item.title)"></Cascader>
</template>
<!--下拉组合框-->
<!-- disabled:选择某项时可能需要禁用后面的选项 -->
<template v-else-if="item.type == 'select-input'">
<div class="utm-linkage">
<Select class="utm-select utm-search-select" filter-by-label clearable filterable @on-change="changeGroupInfo(item)" v-model="item.content[0].keyword" :placeholder="getPlaceholderText(item.content[0].title || item.title)">
<Option v-for="(option,optionIndex) in item.selectData" :value="option[item.val] || option[item.val] === 0 ? option[item.val] : option.id" :key="optionIndex" :label="option[item.text] ? option[item.text] : option.name">{{option[item.text] ? option[item.text] : option.name}}</Option>
</Select>
<template v-if="item.content[1].inputType === 'number'">
<InputNumber v-model="item.content[1].keyword" :min="item.content[1].min || 0" :max="item.content[1].max || Infinity"
:step="1" :formatter="value => item.content[1].formatter(value)"
:parser="value => item.content[1].parser(value)"
size="large" :disabled="item.disabled"
:placeholder="item.content[1].title || 'Input'"
@on-change="changeGroupInfo(item)"
@on-blur="item._handleBlur(item)"/>
</template>
<template v-else>
<input :type="item.content[1].inputType || 'text'" class="utm-linkage-input"
@keyup.enter="changeGroupInfo(item);refactoringData(searchData);"
:disabled="item.disabled" :class="{'disabled':item.disabled}"
:placeholder="item.content[1].title || 'Input'"
@blur="changeGroupInfo(item)" v-model="item.content[1].keyword"/>
</template>
</div>
</template>
<!--多选下拉框和输入框-->
<template v-else-if="item.type == 'multiple-select-input'">
<div class="utm-linkage">
<Select class="utm-select utm-search-select utm-search-input-multiple-select" :max-tag-placeholder="(count)=>{ return '+' + count }" multiple filter-by-label :max-tag-count="1" clearable filterable @on-change="changeMultipleGroupInfo(item)" v-model="item.content[0].keyword" :placeholder="'Select ' + getPlaceholderText(item.title)">
<Option v-for="(option,optionIndex) in item.selectData" :value="option[item.val] || option[item.val] === 0 ? option[item.val] : option.id" :key="optionIndex" :label="option[item.text] ? option[item.text] : option.name">{{option[item.text] ? option[item.text] : option.name}}</Option>
</Select>
<input @keyup.enter="changeMultipleGroupInfo(item);refactoringData(searchData);" class="utm-linkage-input" :placeholder="'Please Input '+item.title" @blur="changeMultipleGroupInfo(item)" v-model="item.content[1].keyword"/>
</div>
</template>
<!--普通日期-->
<template v-else-if="item.type == 'date'">
<DatePicker type="date" :placeholder="'Select ' + item.title" class="utm-date-picker" :editable="false"
:value="item.keyword"
:format="$root.Time[$root.Time.type].typeDate"
@on-change="item.keyword = $event;changeDate(searchData)"
@on-clear="clearDate">
</DatePicker>
</template>
<template v-else-if="item.type == 'date-time'">
<DatePicker type="datetime" :placeholder="'Select ' + item.title" class="utm-date-picker" :editable="false"
:value="item.keyword"
:format="item.formatStr ? $root.Time[$root.Time.type][item.formatStr] : $root.Time[$root.Time.type].typeDateHM"
@on-change="item.keyword = $event;changeDate(searchData,'',index)"
@on-clear="clearDate">
</DatePicker>
</template>
<!--不能选当前时间之前的日期-->
<template v-else-if="item.type == 'date-before'">
<DatePicker type="date" :placeholder="'Select ' + item.title" class="utm-date-picker" :options="options1"
:editable="false"
:format="$root.Time[$root.Time.type].typeDate"
:value="item.keyword"
@on-change="item.keyword = $event;changeDate(searchData)"
@on-clear="clearDate"></DatePicker>
</template>
<template v-else-if="item.type == 'date-time-before'">
<DatePicker type="datetime" :placeholder="'Select ' + item.title" class="utm-date-picker" :options="options1"
:editable="false"
:format="item.formatStr ? $root.Time[$root.Time.type][item.formatStr] : $root.Time[$root.Time.type].typeDateHM"
:value="item.keyword"
@on-change="item.keyword = $event;changeDate(searchData)"
@on-clear="clearDate"></DatePicker>
</template>
<!--不能选当前时间之后的日期-->
<template v-else-if="item.type == 'date-after'">
<DatePicker type="date" :placeholder="'Select ' + item.title" class="utm-date-picker" :options="options2"
:editable="false"
:format="$root.Time[$root.Time.type].typeDate"
:value="item.keyword"
@on-change="item.keyword = $event;changeDate(searchData)"
@on-clear="clearDate"></DatePicker>
</template>
<template v-else-if="item.type == 'date-time-after'">
<DatePicker type="datetime" :placeholder="'Select ' + item.title" class="utm-date-picker" :options="options2"
:editable="false"
:format="item.formatStr ? $root.Time[$root.Time.type][item.formatStr] : $root.Time[$root.Time.type].typeDateHM"
:value="item.keyword"
@on-change="item.keyword = $event;changeDate(searchData)"
@on-clear="clearDate"></DatePicker>
</template>
<!--可选择一个时间段的时间组日期-->
<template v-else-if="item.type == 'date-group'">
<div class="utm-date-group search-date-group">
<DatePicker type="date" placeholder="Start Time" class="utm-date-picker" :editable="false"
:format="$root.Time[$root.Time.type].typeDate"
:options="currentOptionsStart"
:value="item.content[0].keyword"
@on-change="item.content[0].keyword = $event;changeDate(searchData,'defaultTime',index)"
@on-open-change="getCurrentData(item,'defaultTime',index)"
@on-clear="item.content[0].keyword = ''"></DatePicker>
<span class="select-time-to">to</span>
<DatePicker type="date" placeholder="End Time" class="utm-date-picker" :editable="false"
:format="$root.Time[$root.Time.type].typeDate"
:options="currentOptionsEnd"
:value="item.content[1].keyword"
@on-change="item.content[1].keyword = $event;changeDate(searchData,'defaultTime',index)"
@on-open-change="getCurrentEndData(item,'defaultTime',index)"
@on-clear="item.content[1].keyword = ''" placement="bottom-end"></DatePicker>
</div>
</template>
<template v-else-if="item.type == 'date-time-group'">
<div class="utm-date-group search-date-group">
<DatePicker type="datetime" placeholder="Start Time" class="utm-date-picker" :editable="false"
:format="item.formatStr ? $root.Time[$root.Time.type][item.formatStr] : $root.Time[$root.Time.type].typeDateHM"
:options="currentOptionsStart"
:value="item.content[0].keyword"
@on-change="item.content[0].keyword = $event,changeDate(searchData, 'date-time-group', index, 0)"
@on-open-change="flag =>getFlag(flag,item,0,index)"
@on-clear="clearDate"></DatePicker>
<span class="select-time-to">to</span>
<DatePicker type="datetime" placeholder="End Time" class="utm-date-picker" :editable="false"
:format="item.formatStr ? $root.Time[$root.Time.type][item.formatStr] : $root.Time[$root.Time.type].typeDateHM"
:options="currentOptionsEnd"
:value="item.content[1].keyword"
@on-change="item.content[1].keyword = $event,changeDate(searchData, 'date-time-group', index, 1)"
@on-open-change="flag =>getFlag(flag,item,1,index)"
@on-clear="clearDate"></DatePicker>
</div>
</template>
<!--普通时间-->
<template v-else-if="item.type == 'time'">
<TimePicker v-model="item.keyword" :format="item.formatStr" :placeholder="'Select ' + item.title" class="utm-date-picker"
:editable="false"
@on-clear="clearDate" @on-open-change="(flag) => changeTime(flag,searchData)"></TimePicker>
</template>
<!--可以选一段时间的时间组-->
<template v-else-if="item.type == 'time-group'">
<div class="utm-date-group search-date-group">
<TimePicker v-model="item.content[0].keyword" :format="item.formatStr" placeholder="Start Time"
class="utm-date-picker" :editable="false" @on-change="changeDate(searchData,'date-time-group',index)"
@on-clear="clearDate" @on-open-change="(flag) => changeDate(searchData,'time-group',index)"></TimePicker>
<span class="select-time-to">to</span>
<TimePicker v-model="item.content[1].keyword" :format="item.formatStr" placeholder="End Time"
class="utm-date-picker" :editable="false" @on-change="changeDate(searchData,'date-time-group',index)"
@on-clear="clearDate" @on-open-change="(flag) => changeDate(searchData,'time-group',index)"></TimePicker>
</div>
</template>
<!--有效期-->
<template v-else-if="item.type === 'validity'">
<Select class="utm-select" clearable v-model="item.keyword" @on-change="value =>getViewValidity(value,item)" placeholder="Select Validity">
<Option :value="1">Permanent</Option>
<Option :value="2">Temporary</Option>
</Select>
<div class="utm-date-group search-date-group" style="margin-top: 16px" v-if="item.keyword === 1">
<DatePicker style="width:55%" type="datetime" placeholder="Start Time" class="utm-date-picker" :editable="false"
:format="$root.Time[$root.Time.type].typeDateHM"
:options="currentOptionsStart"
:value="item.content[0].keyword"
@on-change="item.content[0].keyword = $event;getViewValidity(1,item)"
@on-open-change="getCurrentData(item,'defaultTime',index,1)"
@on-clear="item.content[0].keyword = ''"></DatePicker>
<span class="permanent-text">Till Profile End</span>
</div>
<div class="utm-date-group search-date-group" style="margin-top: 16px" v-if="item.keyword === 2">
<DatePicker type="datetime" placeholder="Start Time" class="utm-date-picker" :editable="false"
:format="$root.Time[$root.Time.type].typeDateHM"
:options="currentOptionsStart"
:value="item.content[0].keyword"
@on-change="item.content[0].keyword = $event;getViewValidity(2,item)"
@on-open-change="getCurrentData(item,'defaultTime',index,2)"
@on-clear="item.content[0].keyword = ''"></DatePicker>
<span class="select-time-to">to</span>
<DatePicker type="datetime" placeholder="End Time" class="utm-date-picker" :editable="false"
:format="$root.Time[$root.Time.type].typeDateHM"
:options="currentOptionsEnd"
:value="item.content[1].keyword"
@on-change="item.content[1].keyword = $event;getViewValidity(2,item)"
@on-open-change="getCurrentEndData(item)"
@on-clear="item.content[1].keyword = ''" placement="bottom-end"></DatePicker>
</div>
</template>
<!--搜索一个区间-->
<template v-else-if="item.type == 'input-group'">
<div class="utm-date-group input-group-box">
<template v-if="item.content[0].type == 'number-input'">
<InputNumber class="utm-input-box" :min="item.content[0].min || 0" :max="item.content[0].max || Infinity"
v-model="item.content[0].keyword"
:step="1" :formatter="value => item.content[0].formatter(value)"
:parser="value => item.content[0].parser(value)"
size="large" @on-change="changeString(searchData,index)"
@on-blur="item._handleBlur(item)"
:placeholder="item.content[0].placeholder || 'Please input'"/>
</template>
<template v-else>
<div class="utm-input-box" style="width: 100%" :class="{'utm-input-clear': item.content[0].keyword || item.content[0].keyword === 0}">
<input v-model.trim="item.content[0].keyword" type="text" class="utm-input" :maxlength="item.maxLen || 255"
:placeholder="item.content[0].placeholder || 'Please input'"
@keyup.enter="refactoringData(searchData)"
@input="changeString(searchData,index)"/>
<i class="ivu-icon ivu-icon-ios-close-circle clear-input-icon" @click.stop="item.content[0].keyword = ''"></i>
</div>
</template>
<span class="select-time-to" style="width: 100%;padding: 8px">to</span>
<template v-if="item.content[1].type == 'number-input'">
<InputNumber class="utm-input-box" :min="item.content[1].min || 0" :max="item.content[1].max || Infinity"
v-model="item.content[1].keyword"
:step="1" :formatter="value => item.content[1].formatter(value)"
:parser="value => item.content[1].parser(value)"
size="large" @on-change="changeString(searchData,index)"
@on-blur="item._handleBlur(item)"
:placeholder="item.content[1].placeholder || 'Please input'"/>
</template>
<template v-else>
<div class="utm-input-box" style="width: 100%" :class="{'utm-input-clear': item.content[1].keyword || item.content[1].keyword === 0}">
<input v-model.trim="item.content[1].keyword" type="text" class="utm-input" :maxlength="item.maxLen || 255"
:placeholder="item.content[1].placeholder || 'Please input'"
@keyup.enter="refactoringData(searchData)"
@input="changeString(searchData,index)"/>
<i class="ivu-icon ivu-icon-ios-close-circle clear-input-icon" @click.stop="item.content[1].keyword = ''"></i>
</div>
</template>
</div>
</template>
<!--范围划分-->
<!-- 添加参数noEditAble 因为在arms中目前没有需要可以编辑的需求 所提添加了一个进行判断 -->
<template v-else-if="item.type == 'range-division'">
<div class="utm-linkage" :contenteditable="item.noEditAble?false:true">
<Select class="utm-select utm-search-select"
filter-by-label clearable filterable
@on-change="getRangeText(item)"
v-model="item.content[0].keyword"
:placeholder="getPlaceholderText(item.title)"
>
<Option v-for="(option,optionIndex) in item.selectData" :value="option[item.val] " :key="optionIndex" :label="option[item.text] ">{{option[item.text] }}</Option>
</Select>
<input class="utm-linkage-input" type="number" :min="!item.isDecimal ? 1 : -99999"
:placeholder="item.isUpperCase ? ( 'Input ' + item.title ) : ( 'Input ' + item.title.toLowerCase() )"
@blur="getRangeText(item)" @keyup.enter="getRangeText(item);refactoringData(searchData);"
v-model="item.content[1].keyword"
/>
</div>
</template>
<!-- 人脸搜索 -->
<template v-else-if="item.type == 'face-search'">
<div class="face-upload-box" :class="{'abnormal':item.keyword && item.faceVerifyStatus > 0}">
<input id="upload-face-search" @change="handleFaceUp($event,item)" type="file" style="display: none" name="track-upload-title-file" />
<div class="upload-content" v-if="!item.keyword">
<span class="upload-btn" @click="uploadFace">
<i class="utm-font utm-add-icon"></i>
<span>Upload Photo</span>
</span>
<p class="upload-tips">
<span style="font-size: 14px;"> File Size Requirements </span>
<Tooltip theme="light" placement="bottom-start" offset="4" max-width="416px" transfer>
<i class="utm-font utm-icon-hide utm-face-tip-icon"></i>
<div slot="content" style="width: 416px;font-size:14px ;color: #666666;">
<div>File Size: Images should have a file size greater than 20 kilobytes (KB) and less than 2 megabytes (MB).</div>
<div style="margin: -18px 0 -18px 0;">File Type: jpeg, png & jpg. </div>
<div>Dimension: The width and height of the images must exceed 150 x 150 pixels and less than 4096 x 4096 pixels.</div>
</div>
</Tooltip>
</p>
</div>
<div v-else-if="item.keyword && item.faceVerifyStatus !== 0">
<div class="img-box">
<span class="loading-mask" v-show="isFaceVerifing">
<i class="ivu-icon ivu-icon-ios-loading loading-icon"></i>
</span>
<i class="ivu-icon ivu-icon-md-close-circle del-face" @click="resetInfo(item)"></i>
<img class="face-img" :src="item.keyword" alt="">
<span class="replace-btn" @click="uploadFace">Replace</span>
</div>
<div class="upload-status">
<i class="utm-font utm-more-info-icon"></i>
<span v-if="item.isFaceVerifing" class="checking-text">Checking in progress</span>
<span v-else>{{item.faceVerifyText}}</span>
</div>
</div>
<div class="img-box" v-else-if="item.keyword && item.faceVerifyStatus === 0">
<i class="ivu-icon ivu-icon-md-close-circle del-face" @click="resetInfo(item)"></i>
<img class="face-img" :src="item.keyword" alt="">
<span class="replace-btn" @click="uploadFace">Replace</span>
</div>
</div>
</template>
<template v-else></template>
</div>
</template>
</template>
<template v-else></template>
</div>
<div class="search-footer-btn" :class="{'transparent': transparentBg}">
<button type="button" class="utm-btn utm-blue-bg" @click="search(searchData)">
<i class="utm-font utm-search-icon"></i>
<span>Search</span>
</button>
<button type="button" class="utm-btn utm-main-line-btn" @click="reset(searchData)">
<i class="utm-font utm-reset-icon"></i>
<span>Clear</span>
</button>
</div>
</div>
</template>
<script src="./searchBar.js"></script>
export default {
name: "search-bar",
components: { utmEllipsis },
props: {
searchData: {
type: Object,
default() {
return {
searchInfo: []
}
}
},
transparentBg: {
type: Boolean,
default: false
},
isNeedTip: {
type: Boolean,
default: false
}
},
data() {
let _this = this;
return {
isReset: false,
searchDataFnMap: {}, // 记录下拉项的远程搜索方法
//当前时间之前的不能选
options1: {
disabledDate(date) {
return date && date.valueOf() < Date.now() - 86400000;
}
},
//当前时间之后的不能选
options2: {
disabledDate(date) {
return date && date.valueOf() > Date.now();
}
},
currentEndTime: '',
currentOptionsStart: {
disabledDate(date) {
let Time = _this.currentEndTime ? _this.moment(_this.currentEndTime, 'YYYY-MM-DD').format('YYYY/MM/DD') : '';
Time = Time + ' 23:59:59';
return date.valueOf() > new Date(Time).getTime();
}
},
currentTime: '',
currentOptionsEnd: {
disabledDate(date) {
return date.valueOf() < new Date(_this.currentTime).getTime() - 86400000;
}
},
timeOptions: {
0: 'A Period Of Time',
1: 'Office Hour',
2: 'After Office Hour',
3: 'Non-working Day',
4: 'Customize'
},/*时间选项*/
lineTime: null,
faceSize: window.g.uploadFaceSize || 1,
isFaceVerifing: false,
similaritys: [],
}
},
beforeMount: function () {
},
mounted() {
let _this = this;
_this.$root.slideDown = false;
_this.isAllLocation();
_this.getOptionData(true);
},
methods: {
// 判断是否增加location搜索项
isAllLocation: function () {
let _this = this;
if (_this.searchData.isNeedLocation) {
let obj = { title: 'Location', filed: 'buildingIds', type: 'select-multiple', keyword: '', selectData: [_this.$root.masterNodeInfo].concat(_this.$root.nodes), val: 'id', text: 'name' }
// 有的地方location不是在下面展示的而是向上展示
if (_this.searchData.locationPlacement)
obj.placement = _this.searchData.locationPlacement
_this.searchData.searchInfo.push(obj)
}
},
// 深克隆后重新添加远程搜索方法
handleAfterDeepClone: function () {
setTimeout(() => {
this.getOptionData(false);
}, 0);
},
// 根据filed属性值获取对象
getItemByFiled(filed) {
let _this = this;
let index = _this.searchData.searchInfo.findIndex((item) => {
return item.filed === filed;
});
if (index > -1) {
return _this.searchData.searchInfo[index];
}
},
// 获取筛选下拉查询数据
getOptionData: function (isInitial) {
let _this = this;
let searchData = _this.searchData;
if (searchData && searchData.searchInfo) {
searchData.searchInfo.forEach((item) => {
if (item.type === 'select-search' || item.type === 'select-search-multiple') {
if (!isInitial && _this.searchDataFnMap[item.filed]) { // 深克隆后,重新赋值需要远程筛选和分页查询的方法
item.queryFun = _this.searchDataFnMap[item.filed];
}
if (item.queryFun) { // 第一次执行,定义方法
item.hotUpdate = true; // 为了避免滚动指令在对象数据被深克隆后数据对象不更新的问题,添加该key,告诉scroll指令每次更新dom都要重新添加滚动
if (!_this.searchDataFnMap[item.filed]) { // 记录已定义的搜索方法
_this.searchDataFnMap[item.filed] = item.queryFun;
}
if (typeof item.page !== 'number') {
item.page = 1;
}
item.callback = function (success, result) {
item = _this.getItemByFiled(item.filed);
if (success) {
item.pageCount = result.pageCount;
item.loading = false;
if (item.page > 1) {
item.selectData = item.selectData.concat(result.items);
} else {
item.selectData = result.items;
}
} else {
item.loading = false;
}
}
if (isInitial) {
item.byScroll = false;
item.queryFun(item, item.callback);
}
}
}
});
}
},
/*获取当前对应的开始时间*/
getCurrentData: function (item, str, index, type) {
let _this = this;
let time = _this.common.formatDate(item.content[0].keyword, _this.$root.Time[_this.$root.Time.type].typeDate, true);
_this.currentTime = time;
let time2 = _this.common.formatDate(item.content[1].keyword, _this.$root.Time[_this.$root.Time.type].typeDate, true);
_this.currentEndTime = time2;
// 比较时间大小后更新顶部显示内容
if (item.type === 'validity') {
_this.getViewValidity(type, item);
} else {
_this.changeDate(_this.searchData, str, index);
}
},
/*获取当前对应的结束时间*/
getCurrentEndData: function (item, str, index) {
let _this = this;
let time = _this.common.formatDate(item.content[0].keyword, _this.$root.Time[_this.$root.Time.type].typeDate, true);
_this.currentTime = time;
let time2 = _this.common.formatDate(item.content[1].keyword, _this.$root.Time[_this.$root.Time.type].typeDate, true);
_this.currentEndTime = time2;
// 比较时间大小后更新顶部显示内容
if (item.type === 'validity') {
_this.getViewValidity(2, item);
} else {
_this.changeDate(_this.searchData, str, index);
}
},
getFlag: function (flag, item, type, index) {
let _this = this;
if (!flag) {
let startData = _this.common.formatDate(item.content[0].keyword, _this.$root.Time[_this.$root.Time.type].typeDateHM, 2);
let endData = _this.common.formatDate(item.content[1].keyword, _this.$root.Time[_this.$root.Time.type].typeDateHM, 2);
if (endData && startData >= endData) {
if (type === 0) { /*选开始时间*/
item.content[1].keyword = item.content[0].keyword.split(' ')[0] + ' 23:59';
} else { /*选结束时间*/
item.content[0].keyword = '';
}
}
}
this.getCurrentEndData(item, 'date-time-group', index);
},
/*点击搜索按钮*/
search: function (searchData) {
searchData = searchData || this.searchData;
this.refactoringData(searchData);
},
/*点击重置按钮*/
reset: function (searchData) {
let _this = this;
_this.isReset = false;
searchData.searchInfo.forEach((item, index) => {
if ('params' in item) {
item.params = [];
}
if (item.type == 'date-group' || item.type == 'date-time-group' || item.type == 'time-group' || item.type === 'validity') {/*日期组*/
item.content.forEach(value => {
value.keyword = '';
});
item.keyword = '';
} else if (item.type == 'cascader') {
item.keyword = [];
} else if (item.type == 'select-input' || item.type == 'multiple-select-input' || item.type == 'input-group' || item.type == 'select-select' || item.type == 'select-select-default' || item.type === 'range-division') {
item.content.forEach(subItem => {
if (subItem.inputType && subItem.inputType === 'number' || subItem.type === 'number-input') {
subItem.keyword = null;
} else {
subItem.keyword = '';
}
});
item.keyword = '';
} else if (_this.searchData.isNeedLocation && item.filed === 'queryNodeId') {
item.keyword = null;
} else if (item.type === 'face-search') {
item.ids = '';
item.keyword = '';
this.similaritys = [];
} else {
item.keyword = '';
}
});
if (this.$route.path !== '/incidentDashboard') {
_this.ApiService.cacheSearchInfo = searchData;
}
this.$emit('getSearch', {}, []);
},
/*切换下拉框*/
changeSelect: function (searchData) {
this.refactoringData(searchData)
},
/*清除下拉框内容*/
clearSelect: function () {
// this.refactoringData()
},
/*切换联动下拉框*/
changeCascader: function (value, selectedData, item, searchData) {
item.keyword = value;
if (selectedData.length > 0) {
item.params = selectedData;
}
},
// 切换下拉框-输入框组合信息
changeGroupInfo: function (item) {
let valueKey = item.val || 'id';
let labelKey = item.text || 'name';
item.keyword = '';
// 切换后续操作,如:切换到某项需禁用输入框
if (item.changeFun) {
item.changeFun(item);
}
if (item.content[0].keyword || item.content[0].keyword === 0 || item.content[1].keyword) {
if (item.isEnum) { /*存在枚举转换*/
let str = " ";
for (let obj of item.selectData) {
if (item.content[0].keyword === obj[valueKey]) {
str = obj[labelKey];
}
}
let str1 = item.content[1].keyword ? ' - ' + item.content[1].keyword : '';
item.keyword = str + str1;
}
else {
item.keyword = (item.content[0].keyword ? item.content[0].keyword : ' ') + ' - ' + item.content[1].keyword;
}
}
},
// 多选下拉框-输入框组合信息
changeMultipleGroupInfo: function (item) {
let valueKey = item.val || 'id';
let labelKey = item.text || 'name';
item.keyword = '';
if ((item.content[0].keyword && item.content[0].keyword.length) || item.content[1].keyword) {
if (item.isEnum) { /*存在枚举转换*/
let str = "";
for (let obj of item.selectData) {
if (item.content[0].keyword) {
item.content[0].keyword.forEach((child, childIndex) => {
if (child === obj[valueKey]) {
str = str + obj[labelKey] + ';';
}
})
}
}
if (str) {
item.keyword = str + ' - ' + item.content[1].keyword;
} else {
item.keyword = ' ' + item.content[1].keyword;
}
}
else if (item.content[0].keyword && item.content[0].keyword.length) {
let str = "";
item.content[0].keyword.forEach((child) => {
str = str + child + ";";
})
item.keyword = str + ' - ' + item.content[1].keyword;
} else {
item.keyword = ' ' + item.content[1].keyword;
}
}
},
// 多个下拉框信息
changeDoubleSelectInfo: function (item) {
item.keyword = '';
if (item.content[0].keyword || item.content[1].keyword || item.content[0].keyword === 0 || item.content[1].keyword === 0) {
let str = " ";
item.content.forEach((child, index) => {
let valueKey = child.val || 'id';
let labelKey = child.text || 'name';
for (let obj of child.selectData) {
if (child.keyword === obj[valueKey]) {
str = str + obj[labelKey];
}
}
if (index === 0) {
str = str + '-';
}
item.keyword = str;
})
}
},
/*切换时间*/
changeDate: function (searchData, str, index, dateIndex) {
let _this = this;
if (str && str == 'defaultTime' && searchData.searchInfo[index].content[1].keyword !== '') {
let endDate = searchData.searchInfo[index].content[1].keyword;
if (endDate.indexOf('23:59:59') > -1) {
endDate = endDate.split(' ')[0];
}
searchData.searchInfo[index].content[1].keyword = endDate + ' 23:59:59';
}
// date-time-group 选开始日期没选结束日期时,自动选当天最后一分钟
if (str === 'date-time-group' && typeof dateIndex === 'number') {
if (dateIndex === 0 && searchData.searchInfo[index].content[0].keyword && !searchData.searchInfo[index].content[1].keyword) {
let formatStr = _this.$root.Time[_this.$root.Time.type][searchData.searchInfo[index].formatStr] || _this.$root.Time[_this.$root.Time.type].typeDateHM;
formatStr = formatStr.replace(/d/g, 'D');
let val = this.moment(searchData.searchInfo[index].content[0].keyword, formatStr).endOf("day").format(formatStr);
searchData.searchInfo[index].content[1].keyword = val;
}
}
if (str && !(searchData.searchInfo[index].content[0].keyword == '' && searchData.searchInfo[index].content[1].keyword == '')) {
if (str === 'defaultTime') {
searchData.searchInfo[index].keyword = (searchData.searchInfo[index].content[0].keyword ? searchData.searchInfo[index].content[0].keyword + ' 00:00:00 ' : ' -- ') + ' -- ' + (searchData.searchInfo[index].content[1].keyword ? searchData.searchInfo[index].content[1].keyword : '--');
} else {
searchData.searchInfo[index].keyword = (searchData.searchInfo[index].content[0].keyword ? searchData.searchInfo[index].content[0].keyword : ' -- ') + ' -- ' + (searchData.searchInfo[index].content[1].keyword ? searchData.searchInfo[index].content[1].keyword : '--');
}
} else {
searchData.searchInfo[index].keyword = '';
}
},
changeString: function (searchData, index) {
let item = searchData.searchInfo[index];
if (item.isNumber) { // 如果是数字
item.content.forEach((child) => {
let value = child.keyword;
if (value || value === 0) {
if (typeof value !== 'string') {
value = String(value);
}
value = value.replace(/^[.]|[^\d.]/g, '');
value = value.replace(/([.])([^.]*)[.]*/g, '$1$2');
child.keyword = parseFloat(value);
if (isNaN(child.keyword)) {
child.keyword = '';
}
}
});
}
if (!(searchData.searchInfo[index].content[0].keyword == '' && searchData.searchInfo[index].content[1].keyword == '')) {
searchData.searchInfo[index].keyword = (searchData.searchInfo[index].content[0].keyword ? searchData.searchInfo[index].content[0].keyword : ' -- ') + ' -- ' + (searchData.searchInfo[index].content[1].keyword ? searchData.searchInfo[index].content[1].keyword : '--');
} else {
searchData.searchInfo[index].keyword = '';
}
if (typeof searchData.searchInfo[index].change === 'function') {
searchData.searchInfo[index].change(searchData.searchInfo[index]);
}
},
changeTime: function (flag, searchData) { },
/*清除时间数据*/
clearDate: function () { },
refactoringData: function (searchData) {
let _this = this;
let searchParams;
searchParams = this.reorganizationDate(searchData);
if (JSON.stringify(searchParams) !== '{}' && !this.isReset) {
this.isReset = true;
}
if (JSON.stringify(searchParams) === '{}' && this.isReset) {
this.isReset = false;
}
if (_this.$route.path !== '/incidentDashboard' && _this.$route.path !== '/areaManagement') {
this.ApiService.cacheSearchInfo = searchData;
}
this.$emit('getSearch', searchParams, this.similaritys);
},
/*重组数据*/
reorganizationDate: function (searchData) {
let searchParams = {};
let data = JSON.parse(JSON.stringify(searchData.searchInfo));
data.forEach((item, index) => {
/*单个日期 */
if (item.type == 'date' || item.type == 'date-before' || item.type == 'date-after'
|| item.type == 'date-time' || item.type == 'date-time-before' || item.type == 'date-time-after') {
if (item.keyword) {
if (item.timeZone) {
searchParams[item.filed] = this.common.formatZoneDate(item.keyword, item.timeZoneValue, this.$root.Time[this.$root.Time.type].typeTime, 1)
} else {
searchParams[item.filed] = this.common.formatDate(item.keyword, this.$root.Time[this.$root.Time.type].typeTime, 1);
}
}
} else if (item.type == 'date-group' || item.type == 'date-time-group' || item.type == 'time-group') {/*日期组*/
item.content.forEach(value => {
if (value.keyword && item.type != 'time-group') {
if (item.timeZone) {
searchParams[value.filed] = this.common.formatZoneDate(value.keyword, item.timeZoneValue, this.$root.Time[this.$root.Time.type].typeTime, 1);
} else {
searchParams[value.filed] = this.common.formatDate(value.keyword, this.$root.Time[this.$root.Time.type].typeTime, 2);
}
} else if (value.keyword && item.type == 'time-group') {
if (item.convertMinutesToNumber) { // 转化"HH:mm"成分钟数字
let nums = value.keyword.split(':');
let hour = Number(nums[0]);
let min = Number(nums[1]);
searchParams[value.filed] = hour * 60 + min;
} else {
searchParams[value.filed] = value.keyword;
}
}
});
} else if (item.type == 'input') { /*filed为对象*/
if (item.keyword || item.keyword === false || item.keyword === 0) {
// 自定义字段
if (item.isCustom) {
if (!searchParams.customFields) {
searchParams.customFields = {};
}
searchParams.customFields[item.filed] = item.keyword.trim();
} else {
// 普通输入
searchParams[item.filed] = item.keyword.trim();
}
if (item.isSpecial) {
searchParams[item.filed] = (item.keyword.replace(/^\s+/, '')).replace(/\s+/g, ' ');
}
}
} else if (item.type == 'cascader') {/*级联选择*/
if (item.keyword.length > 0) {
searchParams[item.filed] = item.keyword[item.keyword.length - 1];
}
} else if (item.type == 'select-input' || item.type == 'multiple-select-input' || item.type == 'input-group' || item.type == 'select-select' || item.type == 'select-select-default') {/*选择及输入组合*//*多个下拉框*/
item.content.forEach(value => {
if ((value.keyword != '' && value.keyword != null) || value.keyword === 0) {
searchParams[value.filed] = value.keyword;
}
})
} else if (item.type === 'range-division') {
let range = item.content[0];
let value = item.content[1];
if (range.keyword !== '' && value.keyword !== '') {
if (range.keyword === 0) {
searchParams[value.filed] = value.keyword / 1;
} else if (range.keyword === 1) {
searchParams[item.filed] = value.keyword / 1;
} else if (range.keyword === 2) {
searchParams[range.filed] = value.keyword / 1;
} else if (range.keyword === 3) { /*3-5 Maintenance Plan 出特殊搜索处理*/
searchParams[range.filed] = value.keyword / 1 + 1;
} else if (range.keyword === 4) {
searchParams[range.filed] = value.keyword / 1;
searchParams[value.filed] = value.keyword / 1;
} else if (range.keyword === 5) {
searchParams[value.filed] = value.keyword / 1 - 1;
}
}
} else if (item.type === 'validity') {
if (item.keyword > 0) {
searchParams[item.filed] = (item.keyword === 1);
}
item.content.forEach((value, index) => {
if (value.keyword) {
searchParams[value.filed] = this.common.formatDate(value.keyword, this.$root.Time[this.$root.Time.type].typeTime, 2)
}
})
} else if (item.type === 'face-search') {
if (item.ids && item.ids.length) {
searchParams.ids = item.ids;
} else {
delete searchParams.ids;
}
} else if (Array.isArray(item.keyword)) { /*数组*/
if (item.keyword.length > 0 || item.keyword === false || item.keyword === 0) {
searchParams[item.filed] = item.keyword;
}
/*字符串*/
} else if (item.keyword || item.keyword === false || item.keyword === 0) {
searchParams[item.filed] = item.keyword;
}
});
return searchParams;
},
// 下拉搜索项数据更新
searchTermChanged: function (value, data) {
data.page = 1;
if (data.onQueryChange) {
data.query = value;
data.onQueryChange(value, data);
} else if (data.queryFun) {
data.query = value;
clearTimeout(data.timer);
data.timer = setTimeout(() => {
if (typeof data.loading === 'boolean') {
data.loading = true;
}
data.byScroll = false;
data.selectData = []; // 清空数组,重新查询
data.needResetScrollbarTop = true; // 告诉scroll指令重新查询,需要重置滚动条top记录值
data.queryFun(data, data.callback);
}, 1000);
}
this.$emit('listUpdate', value, data);
},
// 多选最大数量值提示
maxTagPlaceholder: function (num) {
return 'more ' + num + '...';
},
// 获取选项内容
getOption: function (data, item) {
let _this = this;
if (item.type === 'select' || item.type === 'select-search') {
item.params = (data || data == 0) ? [data] : [];
item.keyword = (data || data == 0) ? item.keyword : '';
} else {
item.params = data || [];
}
// 避免分页使得数据不匹配
if (item.type === 'select-search-multiple' && data) {
let array = data.map(option => { return { [item.val || 'id']: option.value, [item.text || 'name']: option.label } })
item.selectData = _this.shareApi.dataDeduplication(item.selectData.concat(array), item.val || 'id');
}
},
//多个下拉框的选项内容
getMoreSelect: function (data, item, subItem) {
item.keyword = '';
subItem.params = data || [];
item.content.forEach(obj => {
if (obj.params && obj.params.length > 0) {
obj.params.forEach(value => {
item.keyword = item.keyword + value.label + '; ';
});
}
});
},
// 获取有效期查询显示
getViewValidity: function (type, data) {
if (type === 1) {
data.content[1].keyword = '';
data.params = [{ label: data.content[0].keyword + ' - ' + 'Till Profile End', value: type }];
}else if(type === 2){
data.params = [{label:'Temporary-' + data.content[0].keyword + ' - ' + data.content[1].keyword,value:type}];
}else{
data.content[0].keyword = '';
data.content[1].keyword = '';
}
},
//检查是否为数字格式的input
checkIsNumber: function (data) {
if (data.title === 'Report ID' || data.isNumber) {
data.keyword = data.keyword.replace(/^0[1-9]|[^\d]+/g, '')
}
},
getValue: function (value) {
if ((/^\d+$/.test(value) && value > 0) || value == '') {
if (value == 0) {
return ''
} else {
return value;
}
} else {
return 0;
}
},
getPlaceholderText: function (data) {
if (data === 'ID No.') {
return 'ID Type'
} else if (data === 'Card No.') {
return 'Card Type'
} else if (data === 'Tel No.' || data === 'Contact') {
return 'Country Code'
} else {
return 'Select ' + data
}
},
// 获取搜索范围文字
getRangeText: function (item) {
// isDecimal 是否可以为小数
if (!item.isDecimal && item.content[1].keyword < 1) {
item.content[1].keyword = '';
return;
}
let valueKey = item.val || 'value';
let labelKey = item.text || 'label';
item.keyword = '';
if ((item.content[0].keyword || item.content[0].keyword === 0) && item.content[1].keyword) {
let str = " ";
for (let obj of item.selectData) {
if (item.content[0].keyword === obj[valueKey]) {
str = obj[labelKey];
}
}
item.keyword = str + ' ' + item.content[1].keyword;
}
},
setHtml: function (option, item) {
if (item.vhtmlStr) {
return item.vhtmlStr(option);
} else {
return option[item.text] ? option[item.text] : option.name;
}
},
// 下拉滚动加载
handScroll: function (item) {
item = this.getItemByFiled(item.filed);
if (item.onQueryChange) {
item.onQueryChange(item.query, item);
}
if (item.queryFun) {
item.byScroll = true;
item.queryFun(item, item.callback);
}
},
// 立即搜索
searchNow: function (item) {
this.$refs[item.filed][0].visible = true;
clearTimeout(item.timer);
item.page = 1;
if (item.onQueryChange) {
item.onQueryChange(item.query, item);
}
if (item.queryFun) {
item.byScroll = false;
item.queryFun(item, item.callback);
}
},
// 切换筛选项,pege重置
changeFilter(name, item) {
if (item.onQueryChange) {
item.nodeId = item.content[0].keyword;
item.content[1].disabled = false;
item.keyword = [];
item.page = 1;
item.onQueryChange(name, item);
}
if (!item.content[0].keyword) {
item.content[1].disabled = true;
}
},
// 下拉框展开
openChangePanel(item, flag) {
let _this = this;
// 避免在清除v-model数据后,搜索词未改变,下拉项数据异常
if (!flag) {
item.loading = true;
// iview输入框在单选或者多选没选数据的情况下,失去焦点会关闭下拉选项面板并清空搜索词,这里手动查询无搜索词的情况
if ((item.type === 'select-search-multiple' && !item.keyword.length) || (item.type === 'select-search')) {
_this.searchTermChanged('', item);
}
}
},
//人脸搜索
uploadFace() {
$("#upload-face-search").val("");
$('#upload-face-search').click();
},
resetInfo(item) {
item.keyword = '';
item.ids = '';
this.isFaceVerifing = false;
item.faceVerifyText = '';
item.faceVerifyStatus = -1;
this.similaritys = [];
this.refactoringData(this.searchData);
},
handleFaceUp: function (e, item) {
let _this = this;
let file = e.target.files[0];
let acceptTypeArr = ["image/png", "image/x-png", "image/jpeg", "image/bmp"];
// 必须大于20kb且小于配置的大小
if (file && file.size > 20480 && file.size <= _this.faceSize * 1048576 && acceptTypeArr.indexOf(file.type) > -1) {
//
let img = new Image();
img.crossOrigin = "Anonymous";
img.src = window.URL.createObjectURL(file);
img.onload = function (e) {
if (this.width >= 150 && this.width <= 4096 && this.height >= 150 && this.height <= 4096) {
let reader = new FileReader();
let faceBase64 = ''
reader.onload = function (e) {
item.keyword = e.target.result;
faceBase64 = e.target.result.substring(e.target.result.indexOf('base64,') + 7, e.target.result.length);
_this.getfaceUserInfo(faceBase64, item);
};
reader.readAsDataURL(file);
} else {
e.target.value = "";
_this.messageNotice('error', _this.common.errMsg);
}
}
} else {
e.target.value = "";
_this.messageNotice('error', this.common.errMsg);
}
},
// 获取face照片信息
getfaceUserInfo: function (fileBase64, item) {
let _this = this;
_this.isFaceVerifing = true;
item.faceVerifyStatus = -1;
item.faceVerifyText = 'Checking in progress';
let base64 = JSON.stringify(JSON.parse(('"' + fileBase64 + '"')));
this.$ajax.post("Record/UserProfile/FaceSearch", base64, {
headers: {
noLoading: true, 'Content-Type': 'application/json'
},
}).then((res) => {
_this.isFaceVerifing = false;
if (res.data.success) {
let resData = res.data.data;
if (resData) { // 有数据
// resData.result 0:Completed;1:Completed but error;2:No Service;3:Image Format Error;4:No Face;5:Error
item.faceVerifyStatus = resData.result;
if (resData.result === 0) {
item.faceVerifyText = '';
} else if (resData.result === 1) {
item.faceVerifyText = 'Incomplete records';
this.abnormalServices = resData.errorServices || [];
} else if (resData.result === 2) {
item.faceVerifyText = 'Face tracking service error';
} else if (resData.result === 3) {
item.faceVerifyText = 'Image Format Error';
} else if (resData.result === 4) {
item.faceVerifyText = 'No face found';
} else if (resData.result === 5) {
item.faceVerifyText = 'Compare error';
}
if (resData.result === 0 || resData.result === 1) {
if (resData.items.length > 0) {
item.ids = resData.items.map(i => i.id);
let similaritys = [];
resData.items.forEach(it => {
similaritys.push({ 'id': it.id, 'similarity': Math.round(it.similarity) + '%' });
})
_this.similaritys = JSON.parse(JSON.stringify(similaritys));
this.refactoringData(this.searchData);
} else {
item.faceVerifyStatus = 4;
item.faceVerifyText = 'No face found';
item.ids = ['00000000-0000-0000-0000-000000000000'];
this.refactoringData(this.searchData);
}
}
} else {
_this.similaritys = [];
item.faceVerifyStatus = 4;
item.faceVerifyText = 'No face found';
item.ids = ['00000000-0000-0000-0000-000000000000'];
this.refactoringData(this.searchData);
}
} else {
_this.similaritys = [];
item.faceVerifyStatus = 5;
item.faceVerifyText = res.data.message;
item.ids = ['00000000-0000-0000-0000-000000000000'];
this.refactoringData(this.searchData);
}
}).catch(() => {
_this.isFaceVerifing = false;
_this.similaritys = [];
item.faceVerifyStatus = 5;
item.faceVerifyText = 'Compare error';
item.ids = ['00000000-0000-0000-0000-000000000000'];
this.refactoringData(this.searchData);
});
},
}
}
实际使用
return {
searchData: {
isNeedLocation: this.$root.curNodeInfo.id === null ? true : false,
searchInfo: [
{
title:'FR Photo',
filed:'image',
type: 'face-search',
keyword:'',
},
{
title: 'User Name',
filed: 'name',
keyword: '',
type: 'input',
},
{
title: 'Card No.',
type: 'multiple-select-input',
setOption:this.ApiService.cardSettingInfo.isEnable,
filed:'cardTypes',
keyword: '',
selectData: [],
content: [{
filed: 'cardTypes',
keyword: ''
}, {
filed: 'cardNo',
keyword: '',
}],
val:'value',
text:'label'
},
{
title: 'User Type',
filed: 'userTypes',
type: 'select-multiple',
keyword: '',
selectData: this.common.reportUserType,
val: 'value',
text: 'label',
},
{
title: 'ID No.',
type: 'multiple-select-input',
keyword: '',
isEnum: true,
selectData: this.common.icType,
content: [{
filed: 'identityCardTypes',
keyword: ''
}, {
filed: 'identityCardNo',
keyword: '',
}],
val: 'value',
text: 'label'
},
{
title: 'Contact',
type: 'select-input',
filed:'areaCode',
keyword: '',
selectData: [],
content: [{
filed: 'areaCodes',
title:'Country Code',
keyword: ''
}, {
filed: 'contact',
keyword: '',
}],
text: 'englishName',
val: 'code',
},
{
title: 'Tag',
filed: 'tagIds',
type: 'select-search-multiple',
keyword: '',
selectData: [],
text: 'name',
val: 'id',
page:1,
onQueryChange:(name, item)=>{
item.query = name;
clearTimeout(item.timer);
item.timer = setTimeout(()=>{
_this.getTagList(item,name);
},1000);
}
},
{
title: 'Assigned Status of Card',
filed: 'hasCard',
type: 'select',
keyword: '',
selectData: [{label:'Assigned',value:0},{label:'Unassigned',value:1}],
text: 'label',
val: 'value',
},
{
title: 'FR Photo Status',
filed: 'HasFRPhoto',
type: 'select',
keyword: '',
selectData: [{label:'Yes',value:0},{label:'No',value:1}],
text: 'label',
val: 'value',
},
{
title: 'Profile Photo Status',
filed: 'HasProfilePhoto',
type: 'select',
keyword: '',
selectData: [{label:'Yes',value:0},{label:'No',value:1}],
text: 'label',
val: 'value',
isSwitch:this.ApiService.isShowProfilephoto
},
{
title: 'Email',
filed: 'email',
keyword: '',
type: 'input',
},
{
title: 'Organization',
filed: 'organization',
keyword: '',
type: 'input',
},
{
title: 'Operator',
filed: 'operator',
keyword: '',
type: 'input',
},
{
title: 'Status',
filed: 'statuses',
type: 'select-multiple',
keyword: '',
selectData: this.common.userStatus,
val: 'value',
text: 'label',
},
{
title: 'Validity',
type: 'validity',
filed: 'isPermanentValidity',
keyword: '',
content: [{
filed: 'validityStartTime',
keyword: ''
}, {
filed: 'validityEndTime',
keyword: '',
}]
},
{
title: _this.ApiService.accessCodeName,
filed: 'accessCodeName',
keyword: '',
type: 'input',
},
{
title: 'Access Rule',
filed: 'accessRules',
type: 'select-multiple',
keyword: '',
selectData: [{label:'Single Entry',value:0},{label:'Multiple Entry',value:1}],
text: 'label',
val: 'value',
},
{
title: 'Last Update',
type:"date-time-group",
formatStr:'typeDateHM',
keyword: '',
content: [{
filed: 'startLastUpdateTime',
keyword: ''
}, {
filed: 'endLastUpdateTime',
keyword: '',
}]
}
],
},
methods: {
//搜索
getSearch(){
//该页面自己的搜索方法
}
}
Vue:
<SearchComponent ref="searchBar" :searchData="searchData" v-on:getSearch="getSearch"></SearchComponent>
页面效果: