| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- <script>
- import {handle} from "../../until/handle";
- import {rCode} from "../../map/rcodeMap_esm";
- import Loading from "../public/loading.vue";
- import HideScroll from "../public/hideScroll.vue";
- export default {
- name: "searchBox",
- components: {Loading, HideScroll},
- props: {
- searchPlaceholder: {
- type: String,
- default: '输入搜索关键字'
- },
- loadTip: {
- type: String,
- default: '加载中'
- },
- loadMsg: {
- type: String,
- default: '加载失败'
- },
- limit: {
- type: Number,
- default: 20
- },
- loadDataApi: {
- type: Function,
- default: () => {}
- },
- },
- data(){
- return {
- searchLoading:false,// 搜索加载框
- searchTimer: null,// 防抖搜索框
- searchKey: '',// 关键字
- page: 1,// 页数
- count: 20,// 每页数量
- total: 0,// 当前数据总量
- loadState: 0,// 加载状态
- loadLock: false,// 加载锁
- domPlaceholder: [],//当前的数据列表
- }
- },
- mounted() {
- this.loadData(1,true)
- },
- methods: {
- async loadData(page,isPush){
- if(isPush){
- page = 1;
- this.loadState = 0;
- }
- this.searchLoading = true;
- // console.log('---------')
- // console.log(page);
- let searchParam = {
- }
- // 1.搜索相关设备
- let [err,res] = await this.loadDataApi({
- key: this.searchKey,//
- page: page,// 当前页数
- });
- this.loadLock = false;
- this.searchLoading = false;
- // 2.检查返回值是否正常
- if (err){
- console.log(err);
- this.msg = err.message;
- isPush?this.loadState=2:this.$message.error(this.msg);
- return false;
- }
- this.loadState = 1;
- // 只有在第一页时会需要加载总数
- if(res.page <= 1){
- this.total = res.total;
- }
- // 3.根据是否为新设备创建新数据集合
- if(isPush || page===1){
- this.domPlaceholder = new Array(res.total)
- .fill({
- loaded: false,
- val:{}
- });
- }
- console.log('total' + this.domPlaceholder.length)
- // 4.将当前的分块请求结果填充至指定位置
- let startIndex = (res.page - 1) * res.limit;
- let key = res.key;
- console.log(`startIndex:${startIndex} , endIndex:${res.count+startIndex}`);
- for (let i = startIndex,n=0;n<res.count;n++,i++){
- let item = res.data[n];
- if(item){
- // 时间字段转换
- // info.subTitle = time.dateFormat(time.timeStamp_to_Date(info.loginTime),'YY-MM-DD H:m:s');
- // 展示字段转换
- item['showText'] = item.name || item.title;
- item['innerText'] = item.showText.replace(key,`<span style="color:red;">${key}</span>`);
- }
- this.$set(this.domPlaceholder,i,{
- loaded:!!item,
- val:item?item:{}
- });
- }
- // 判断当前位置
- },
- onSearch(v){
- console.log('search');
- console.log(v);
- if(this.loadLock){
- this.$message.info('加载设备列表中')
- return
- }
- this.loadLock = true;
- this.loadData(1);
- },
- async onScrollChange(data){
- let scrollTop = data.scrollTop;
- let index = data.index;
- console.log('onScrollChange'+scrollTop + 'index:' + index);
- //获取
- let page = Math.floor(scrollTop/50/this.limit);
- console.log(page);
- // 加载数据
- if(page < this.page){
- console.log(`不加载数据`);
- }else{
- await this.loadData(page + 1);
- }
- console.log(`检测是否加载数据 total: ${this.total} <=
- limit: ${this.limit} + index: ${index} ===> ${this.total <= this.limit + index}`)
- if(this.total <= this.limit + index){
- console.log(`同时获取下一页数据`);
- await this.loadData(page + 2);
- }
- },
- onSelectedItem(item){
- this.$emit('onSelectedItem',item);
- }
- }
- }
- </script>
- <template>
- <div class="w-full h-full rounded bg-yellow-50 flex flex-col">
- <div class="w-full h-auto">
- <!-- 其他搜索项 -->
- <slot name="otherSearchItem"></slot>
- </div>
- <div class="serarch mt-1 box-border px-1">
- <a-input-search
- :placeholder="searchPlaceholder"
- enter-button
- :loading="searchLoading"
- v-model="searchKey"
- @search="onSearch"
- allow-clear
- style="border-radius: 0;"
- />
- </div>
- <div class="devices w-full h-48 md:h-full bg-white mt-2 relative">
- <loading
- :loading-state="loadState"
- :tip="loadTip"
- >
- <hide-scroll
- @onScroll="onScrollChange"
- :itemHeight="50"
- >
- <div
- v-for="(item,i) in domPlaceholder"
- :key="'search-key:'+i"
- class="item cursor-default" >
- <div
- v-if="item.loaded"
- class="text text-base">
- <span v-html="item.val.innerText"></span>
- <div class="subText text-gray-300 text-xs">{{ item.val.subTitle }}</div>
- </div>
- <div
- v-if="item.loaded"
- class="action">
- <a-button class="mx-1" @click="onSelectedItem(item.val)">选中</a-button>
- </div>
- <div class="w-full h-full bg-black text-red-500 opacity-30" v-else-if="!item.loaded">
- {{i}}.....loading
- </div>
- </div>
- </hide-scroll>
- <template v-slot:loadFail>
- <div class="w-full h-full flex justify-center items-center">
- <h2 class="text-2xl text-red-700">{{loadMsg}}</h2>
- <a-button primary @click="loadData(1)">重新加载</a-button>
- </div>
- </template>
- </loading>
- </div>
- </div>
- </template>
- <style scoped>
- .item{
- width: 100%;
- height: 50px;
- display: flex;
- align-items: center;
- border-bottom: 1px solid #66ccff;
- padding: 0 0.25em;
- box-sizing: border-box;
- }
- .text{
- width: 100%;
- height: 100%;
- }
- .subText{
- width: 100%;
- color: #afa7a7;
- }
- .action{
- display: flex;
- }
- </style>
|