提交 02a407c0 编写于 作者: KK's avatar KK

快速搜索组件

上级 35d65085
.app-seach-history{ .app-seach-history{
.record{
font-size: 30px;
padding: 10px 0;
ion-icon{
text-align: center;
background: #5475ab;
border-radius: 50%;
padding: 7px;
color: #fff;
}
.record_icon {
text-align: center;
padding: 10px;
border-radius: 50%;
width: 70px;
height: 70px;
margin: 0 auto;
line-height: 70px;
}
.speaking{
background: #c6dfcc;
}
.record_text{
font-size: 12px;
text-align: center;
}
}
.history{ .history{
.hisText{ .hisText{
display: flex; display: flex;
......
<template> <template>
<div class="app-seach-history"> <div class="app-seach-history">
<ion-toolbar> <ion-toolbar>
<ion-searchbar style="height: 36px; padding-bottom: 0px;" :placeholder="$t('app.fastsearch')" debounce="500" @ionChange="quickValueChange($event)" show-cancel-button="focus" :cancel-button-text="$t('app.button.cancel')" @ionFocus="showHistory" @ionBlur="hideHistory" @search="searchVal" ref="searchbar"></ion-searchbar> <ion-searchbar style="height: 36px; padding-bottom: 0px;" :placeholder="$t('app.fastsearch')" debounce="500" @ionChange="quickValueChange($event)" show-cancel-button="focus" :cancel-button-text="$t('app.button.cancel')" @ionFocus="searchbarFocus" @ionBlur="searchbarBlur" @search="searchVal" ref="searchbar"></ion-searchbar>
<ion-button v-if="showfilter" class="filter-btn" size="small" slot="end" @click="openSearchform"><ion-icon slot="end" name="filter-outline"></ion-icon>过滤</ion-button> <ion-button v-if="showfilter" class="filter-btn" size="small" slot="end" @click="openSearchform"><ion-icon slot="end" name="filter-outline"></ion-icon>过滤</ion-button>
</ion-toolbar> </ion-toolbar>
<div class="history" v-if="hasHistory"> <div class="history" v-if="hasHistory && (searchbarIsFocus || isSpeaking ) ">
<div class="hisText"><div>最近搜索</div> <van-icon name="delete" @click="clearHistory"/></div> <div class="hisText"><div>最近搜索</div> <van-icon name="delete" @click="clearHistory"/></div>
<div class="hisItems"> <div class="hisItems">
<van-tag type="primary" v-for="item in historyList" :key="item.index" round size="medium" color="#ededed" text-color="#333" @click="clickTag">{{item}}</van-tag> <van-tag type="primary" v-for="item in historyList" :key="item.index" round size="medium" color="#ededed" text-color="#333" @click="searchbarValueChange(item)">{{item}}</van-tag>
</div> </div>
</div> </div>
<div class="record" v-show="searchbarIsFocus || isSpeaking" >
<div class="record_icon" :class="{'speaking':isSpeaking}" >
<ion-icon name="mic-outline" @touchstart="gotouchstart" @touchmove="gotouchmove" @touchend="gotouchend"></ion-icon>
</div>
<div class="record_text" v-show="!isSpeaking"><div>按住说话</div></div>
<div class="record_text" v-show="isSpeaking"><div>请说话</div></div>
</div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { import { Vue, Component, Prop, Provide, Emit, Watch } from "vue-property-decorator";
Vue, import { ThirdPartyService } from "@ibiz-core";
Component,
Prop,
Provide,
Emit,
Watch
} from "vue-property-decorator";
@Component({ @Component({
components: {} components: {},
}) })
export default class AppRoundList extends Vue{ export default class AppRoundList extends Vue {
/**
* 第三方服务
*
* @type {boolean}
* @memberof AppSearchHistory
*/
public thirdPartyService: ThirdPartyService = ThirdPartyService.getInstance();
/** /**
* 视图模型数据 * 视图模型数据
...@@ -33,7 +40,7 @@ export default class AppRoundList extends Vue{ ...@@ -33,7 +40,7 @@ export default class AppRoundList extends Vue{
* @type {any} * @type {any}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
@Prop() public model:any; @Prop() public model: any;
/** /**
* 是否展示过滤按钮 * 是否展示过滤按钮
...@@ -41,57 +48,53 @@ export default class AppRoundList extends Vue{ ...@@ -41,57 +48,53 @@ export default class AppRoundList extends Vue{
* @type {boolean} * @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
@Prop() public showfilter!:boolean; @Prop() public showfilter!: boolean;
/** /**
* 快速搜索值变化 * 长按定时器
* *
* @param {*} event * @type {boolean}
* @returns
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public quickValueChange($event:any){ public timeOutEvent: any;
this.$emit('quickValueChange',$event);
this.searchVal($event);
}
/** /**
* 打开搜索表单 * 搜索框是否聚焦
* *
* @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public openSearchform(){ public searchbarIsFocus: boolean = false;
this.$emit('openSearchform');
}
/** /**
* 搜索历史数组 * 是否正在说话
* *
* @type {Array} * @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public historyList:Array<any> = []; public isSpeaking: boolean = false;
/** /**
* 监听搜索历史数组 * 搜索历史数组
* *
* @type {Array} * @type {Array}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
@Watch('historyList') public historyList: Array<any> = [];
onHistoryListChange(newVal:any){ @Watch("historyList")
onHistoryListChange(newVal: any) {
if (newVal.length != 0) { if (newVal.length != 0) {
this.hasHistory = true; this.hasHistory = true;
} }
} }
/** /**
* 每一类搜索历史 * 每一类搜索历史
* *
* @type {Object} * @type {Object}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public historyLists:any = {}; public historyLists: any = {};
/** /**
* 分类缓存搜索历史 * 分类缓存搜索历史
...@@ -99,7 +102,7 @@ export default class AppRoundList extends Vue{ ...@@ -99,7 +102,7 @@ export default class AppRoundList extends Vue{
* @type {Array} * @type {Array}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public historyStorage:Array<any> = []; public historyStorage: Array<any> = [];
/** /**
* 是否展开搜索历史 * 是否展开搜索历史
...@@ -107,7 +110,7 @@ export default class AppRoundList extends Vue{ ...@@ -107,7 +110,7 @@ export default class AppRoundList extends Vue{
* @type {boolean} * @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public hasHistory:boolean = false; public hasHistory: boolean = false;
/** /**
* 是否有搜索历史功能 * 是否有搜索历史功能
...@@ -115,59 +118,109 @@ export default class AppRoundList extends Vue{ ...@@ -115,59 +118,109 @@ export default class AppRoundList extends Vue{
* @type {boolean} * @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public enableHistory:boolean = true; public enableHistory: boolean = true;
/** /**
* 生命周期 * touchstart 开始长按
* *
* @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public mounted(){ public gotouchstart() {
this.afterMounted(); this.isSpeaking = true;
let that = this;
clearTimeout(this.timeOutEvent); //清除定时器
this.timeOutEvent = 0;
this.timeOutEvent = setTimeout(() => {
this.startRecord();
}, 700); //这里设置定时
} }
/** /**
* 执行mounted后的逻辑 * 开始录音
* *
* @type {boolean}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public afterMounted(){ public startRecord() {
setTimeout(() => { this.thirdPartyService.thirdPartyEvent("startRecord");
this.hasHistory = false;
}, 1);
let storage:any = localStorage.getItem('historyStorage');
if (storage) {
// 后续拿
let historystorage:any = JSON.parse(storage);
this.historyLists = historystorage.find((historyLists:any)=>{
return historyLists.viewname == this.model.viewname;
})
if (this.historyLists) {
// 如果是缓存过的模型
this.historyList = this.historyLists.historyList;
this.historyStorage = historystorage;
} else {
// 如果是未缓存过的模型 = 第一次拿
this.historyLists = {viewname:this.model.viewname,historyList:[]};
this.historyList = this.historyLists.historyList;
historystorage.push(this.historyLists);
this.historyStorage = historystorage;
} }
} else {
// 第一次拿 /**
this.historyLists = {viewname:this.model.viewname,historyList:[]}; * touchend 结束长按
this.historyList = this.historyLists.historyList; *
this.historyStorage.push(this.historyLists); * @type {any}
* @memberof AppSearchHistory
*/
public gotouchend() {
clearTimeout(this.timeOutEvent);
if (this.timeOutEvent != 0) {
this.stopRecord();
this.isSpeaking = false;
//这里写要执行的内容(尤如onclick事件)
} }
} }
/**
* touchmove
* 如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
* @type {any}
* @memberof AppSearchHistory
*/
public gotouchmove() {
clearTimeout(this.timeOutEvent); //清除定时器
this.timeOutEvent = 0;
this.isSpeaking = false;
}
/**
* 释放长按语音
*
* @type {any}
* @memberof AppSearchHistory
*/
public async stopRecord() {
let res = await this.thirdPartyService.thirdPartyEvent(
"translateVoice",
await this.thirdPartyService.thirdPartyEvent("stopRecord")
);
this.searchbarValueChange(res.content.replace("。", ""));
}
/**
* 快速搜索值变化
*
* @param {*} event
* @returns
* @memberof AppSearchHistory
*/
public quickValueChange($event: any) {
this.$emit("quickValueChange", $event);
this.searchVal($event);
}
/**
* 打开搜索表单
*
* @memberof AppSearchHistory
*/
public openSearchform() {
this.$emit("openSearchform");
}
/** /**
* 聚焦搜索框时 * 聚焦搜索框时
*
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public showHistory(){ public searchbarFocus() {
this.searchbarIsFocus = true;
// 显示历史记录
if (this.enableHistory) { if (this.enableHistory) {
if ( (Array.isArray(this.historyLists.historyList)) && (this.historyLists.historyList.length <= 0) ) { if (
Array.isArray(this.historyLists.historyList) &&
this.historyLists.historyList.length <= 0
) {
this.hasHistory = false; this.hasHistory = false;
} else { } else {
this.hasHistory = true; this.hasHistory = true;
...@@ -179,19 +232,17 @@ export default class AppRoundList extends Vue{ ...@@ -179,19 +232,17 @@ export default class AppRoundList extends Vue{
* 失焦搜索框时 * 失焦搜索框时
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public hideHistory(){ public searchbarBlur() {
setTimeout(() => { this.searchbarIsFocus = false;
this.hasHistory = false;
}, 100);
} }
/** /**
* 触发搜索 * 触发搜索
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public searchVal($event:any){ public searchVal($event: any) {
if ($event.target) { if ($event.target) {
let val:any = $event.target.value; let val: any = $event.target.value;
val = val.trim(); val = val.trim();
if (val === "") { if (val === "") {
return; return;
...@@ -210,11 +261,14 @@ export default class AppRoundList extends Vue{ ...@@ -210,11 +261,14 @@ export default class AppRoundList extends Vue{
this.historyList.pop(); this.historyList.pop();
} }
if (this.enableHistory) { if (this.enableHistory) {
this.historyLists = this.historyStorage.find((historyLists:any)=>{ this.historyLists = this.historyStorage.find((historyLists: any) => {
return historyLists.viewname == this.model.viewname; return historyLists.viewname == this.model.viewname;
}) });
this.historyLists.historyList = this.historyList; this.historyLists.historyList = this.historyList;
localStorage.setItem('historyStorage', JSON.stringify(this.historyStorage)) localStorage.setItem(
"historyStorage",
JSON.stringify(this.historyStorage)
);
} }
} }
} }
...@@ -222,15 +276,18 @@ export default class AppRoundList extends Vue{ ...@@ -222,15 +276,18 @@ export default class AppRoundList extends Vue{
/** /**
* 清除搜索历史 * 清除搜索历史
* *
* @type {boolean} * @type {function}
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public async clearHistory(){ public async clearHistory() {
const result = await this.$notice.confirm('提醒','是否清除搜索历史?'); const result = await this.$notice.confirm("提醒", "是否清除搜索历史?");
if (result) { if (result) {
this.historyList = []; this.historyList = [];
this.historyLists.historyList = []; this.historyLists.historyList = [];
localStorage.setItem('historyStorage', JSON.stringify(this.historyStorage)) localStorage.setItem(
"historyStorage",
JSON.stringify(this.historyStorage)
);
return true; return true;
} else { } else {
return false; return false;
...@@ -242,13 +299,59 @@ export default class AppRoundList extends Vue{ ...@@ -242,13 +299,59 @@ export default class AppRoundList extends Vue{
* *
* @memberof AppSearchHistory * @memberof AppSearchHistory
*/ */
public async clickTag($event:any){ public searchbarValueChange(value: string) {
let content:any = $event.target.textContent let searchbar: any = this.$refs.searchbar;
let searchbar:any = this.$refs.searchbar; if (searchbar) {
searchbar.value = content; searchbar.value = value;
this.quickValueChange({detail:{value:content}}); this.quickValueChange({ detail: { value: value } });
}
}
/**
* 执行mounted后的逻辑
*
* @memberof AppSearchHistory
*/
public afterMounted() {
setTimeout(() => {
this.hasHistory = false;
}, 1);
let storage: any = localStorage.getItem("historyStorage");
if (storage) {
// 后续拿
let historystorage: any = JSON.parse(storage);
this.historyLists = historystorage.find((historyLists: any) => {
return historyLists.viewname == this.model.viewname;
});
if (this.historyLists) {
// 如果是缓存过的模型
this.historyList = this.historyLists.historyList;
this.historyStorage = historystorage;
} else {
// 如果是未缓存过的模型 = 第一次拿
this.historyLists = { viewname: this.model.viewname, historyList: [] };
this.historyList = this.historyLists.historyList;
historystorage.push(this.historyLists);
this.historyStorage = historystorage;
} }
}; } else {
// 第一次拿
this.historyLists = { viewname: this.model.viewname, historyList: [] };
this.historyList = this.historyLists.historyList;
this.historyStorage.push(this.historyLists);
}
}
/**
* 生命周期
*
* @memberof AppSearchHistory
*/
public mounted() {
this.afterMounted();
}
}
</script> </script>
<style lang = "less"> <style lang = "less">
@import "./app-search-history.less"; @import "./app-search-history.less";
......
...@@ -170,4 +170,13 @@ ...@@ -170,4 +170,13 @@
background-color: @theme-color; background-color: @theme-color;
} }
} }
// 快速搜索组件主题
.app-seach-history{
.record{
ion-icon{
background: @theme-color;
color: @text-color;
}
}
}
} }
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册