// 取消搜索的ck
onCancelTextClick = () => {
Taro.navigateBack();
};
// 点击回车搜索的ck
searchQuery = query => {
Taro.redirectTo({
url: `${pagePath.searchResult}?query=${query}&type=${this.state.type}`
});
};
// 点击历史记录的ck
onClickQuery = query => {
this.searchQuery(query);
};
2、Sug列表
sug要求:
根据用户输入关键字,生成不同的sug列表。
分为2类,项目词和机构词。在获取到用户地理位置的情况下,额外显示用户与机构之间的距离。
获取地理信息
class NewSearchPage extends Component {
constructor(args) {
super(args);
const query = this.$router.params.query && decodeURI(this.$router.params.query) || '';
const type = this.$router.params.type || ResultListType.zonghe;
const placeholder = this.$router.params.placeholder && decodeURI(this.$router.params.placeholder) || '';
this.state = {
query: query === 'undefined' ? '' : query,
type,
searchContent: '',
placeholder : placeholder === 'undefined' ? '' : placeholder,
latitude: null,
longitude: null
};
};
componentDidMount() {
this.getLocationInfo();
this.getSugList(this.state.query);
}
getLocationInfo = () => {
return new Promise(resolve => {
getLocation2().then(({latitude, longitude}) => {
this.setState({
latitude,
longitude
});
resolve();
});
});
}
getSugList(query) {
// getCity接口,后端根据IP返回userCity
query === '' ? this.onInputClear() : getCity().then(city => {
const paramObj = {
query,
userCityName: city,
latitude: JSON.stringify(this.state.latitude),
longitude: JSON.stringify(this.state.longitude)
};
searchApi.getSugList(paramObj).then(res => {
if (res.code === 0 && res.data) {
this.setState({
sugList: res.data.sugList,
query: query.trim()
});
} else {
this.setState({
sugList: []
});
}
});
});
}
onQuerySearch = query => {
this.setState({
searchContent: query
},() => {
this.searchQuery(query);
});
};
// 输入事件监听
onQueryChange = debounce(query => {
this.getSugList(query);
}, 200, false);
<NewSearchInputBar
// keyboardShow={keyboardShow}
// onQuerySearch={this.onQuerySearch}
onQueryChange={this.onQueryChange}
cancelTextShow={cancelTextShow} // 取消搜索的ck
onCancelTextClick={this.onCancelTextClick}
onInputClear={this.onInputClear} // 清空输入框的ck
placeholder={this.state.placeholder}
focus={focus}
value={this.state.query}
clear
/>
this.state.query === '' || (this.state.sugList && this.state.sugList.length <= 0)
? <NewSearchHistoryLayer
hotSearchWords={this.state.hotSearchWords}
searchContent={this.state.searchContent}
onClickQuery={this.onClickQuery}
/>
: (this.state.sugList && this.state.sugList.length > 0) && <SugList
list={this.state.sugList}
query={this.state.query}
isHasParams={this.state.latitude ? true : false}
></SugList>
sug列表组件
import HospitalSugCard from './hospitalSugCard';
import ProjectSugCard from './projectSugCard';
import {ResultListType} from '@src/packageSearch/pages/result/model';
import {pagePath} from "@src/common/constant/constant";
enum SugType {
project = 'project',
hospital = 'hospital'
};
const HREF_TYPE = {
[SugType.hospital]: ResultListType.hospital,
[SugType.project]: ResultListType.zonghe
};
export interface ProjectSug {
sug: string;
contentType: string;
count: number;
query: string;
};
export interface HospitalSug {
sug: string;
contentType: string;
hospitalId: number;
province: string;
city: string;
address: string;
doctorCount: number;
goodsCount: number;
distance: string;
query: string;
isHasParams: Boolean;
}
type SugItem = HospitalSug | ProjectSug;
export interface SugListProps {
list: SugItem[];
query: string,
isHasParams: Boolean
};
const SugList = (props: SugListProps) => {
const {list, query, isHasParams} = props;
const onClickQuery = (sugType, obj, index) => {
const url = sugType === SugType.hospital
? `${pagePath.hospitalDetail}?id=${obj.hospialId}&name=${obj.sug}`
: `${pagePath.searchResult}?query=${obj.sug}&type=${HREF_TYPE[sugType]}`;
Taro.redirectTo({
url
});
};
const listEl = list.map((item, index) => {
const type = item.contentType;
const showProjectSugCard = type === SugType.project ||
(type !== SugType.project && type !== SugType.hospital);
const showHospitalSugCard = type === SugType.hospital;
return (
<View className='sug-list-item' onClick={() => onClickQuery(type, item, index)}>
{showProjectSugCard && <ProjectSugCard {...(item as ProjectSug)} query={query}></ProjectSugCard>}
{showHospitalSugCard && <HospitalSugCard {...(item as HospitalSug)} query={query} isHasParams={isHasParams}></HospitalSugCard>}
</View>
);
});
return (
<View className='sug-list'>
{listEl}
</View>
);
};
export default SugList;
hospitalSugCard
const HospitalSugCard = (props: HospitalSug) => {
const distance = (Number(props.distance) / 1000).toFixed(1);
const {sug, query, isHasParams, goodsCount, doctorCount} = props;
const isShowDistance = (!!props.distance) && isHasParams;
return (
<View className='sug-hospital'>
<View className='sug-common'>
<View className='sug-hospital-name sug-common-left'>
<Image className='sug-item-img' src={bosImgs.searchHospital} />
<View className='sug-item-title single-line'>
<HighLight content={sug} highlightWords={query} />
</View>
<Image className='sug-hospital-sign'
src='https://lemon.cdn.bcebos.com/lemon-taro-c/anesthesiologist_attestation.png'
/>
</View>
{isShowDistance && (!distance ? '' : <View className='sug-hospital-distance sug-common-right'>
{`${Number(distance) > 50 ? '>50' : distance}km`}
</View>)}
</View>
<View className='sug-hospital-bottom'>
<Text className='sug-goodsCount'>商品数:{goodsCount}</Text>
<Text className='sug-doctorCount'>医生数:{doctorCount}</Text>
</View>
</View>
);
};
export default HospitalSugCard;
3、飘黄highLight组件
/*
* @file: 搜索结果页搜索词飘黄显示
*/
import {View, Text, Block} from "@tarojs/components";
import handlePosition from './handlePosition';
import './highlight.scss';
/**
* @param content 需要飘黄处理的字段
* @param highlightPos 飘黄位置
* @param highlightWords 飘黄文字
* @param children 文本前可选添加内容
* @param type 卡片类型
* @param doHighLight 是否要飘黄,例如机构相关推荐部分,无需飘黄传false
*/
interface HighlightParams {
content: string;
highlightPos?: string [];
highlightWords?: string;
children?: JSX.Element;
type?: string;
doHighLight?: boolean;
};
4、拓展:
函数防抖:
function debounce(fn, delay = 500, immediate = true) {
let timer = null;
return function () {
const context = this;
const args = arguments;
return new Promise((resolve, reject) => {
timer && clearTimeout(timer);
if (immediate) {
const doNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
doNow && resolve(fn.apply(context, args));
} else {
timer = setTimeout(() => {
resolve(fn.apply(context, args));
}, delay);
}
});
};
}
地理位置
// 获取地理位置 + 超时判断
export const getLocation2 = (time = 1500) => {
return new Promise((resolve, reject) => {
getLocation().then(resolve)
.catch(() => {
reject();
});
});
};
Taro中获取经纬度
export const getLocation = (timeout = 5000) => {
return new Promise(function (resolve, reject) {
const latitude = Taro.getStorageSync(v.latitude);
const setTime = Taro.getStorageSync(v.setPosTime);
const currentTime = new Date().getTime();
if (latitude && currentTime - Number(setTime) < 8640000) {
resolve({
longitude: Taro.getStorageSync(v.longitude),
latitude: Taro.getStorageSync(v.latitude)
});
} else {
// H5中,taro最后实际调用的是window.navigator.geolocation.getCurrentPosition
// 这个方法在某些特殊case下不会有回调,设置一个超时时间,强制失败
const timer = setTimeout(() => {
reject();
}, timeout);
Taro.getLocation().then(({latitude, longitude}) => {
Taro.setStorage({key: v.latitude, data: latitude});
Taro.setStorage({key: v.longitude, data: longitude});
Taro.setStorage({key: v.setPosTime, data: `${currentTime}`});
clearTimeout(timer);
resolve({
latitude,
longitude
});
})
.catch(() => {
clearTimeout(timer);
reject();
});
}
});
};
toFixed() 方法使用定点表示法来格式化一个数值。
function financial(x) {
return Number.parseFloat(x).toFixed(2);
}
console.log(financial(123.456));
// expected output: "123.46"
console.log(financial(0.004));
// expected output: "0.00"
digits
小数点后数字的个数;介于 0 到 20 (包括)之间,实现环境可能支持更大范围。如果忽略该参数,则默认为 0。
返回值
使用定点表示法表示给定数字的字符串。