!30 新增选择器组件支持滚动加载

Merge pull request !30 from Metal/dev
This commit is contained in:
傲世孤尘
2023-07-06 13:27:54 +00:00
committed by Gitee
8 changed files with 258 additions and 21 deletions
+2 -4
View File
@@ -14,13 +14,11 @@ export function portPoolList() {
method: 'get'
})
}
export function availablePortList(licenseId) {
export function availablePortList(query) {
return request({
url: '/port-pool/get-available-port-list',
method: 'get',
params: {
licenseId: licenseId
}
params: query
})
}
@@ -0,0 +1,168 @@
<!--
采用github上面的开源组件https://github.com/johnhom1024/vue-load-select
不过有个bug就是没办法展示下拉的箭头目前修复的方式等dom加载完毕后补充箭头的class
参考https://blog.csdn.net/weixin_42381896/article/details/122258563
-->
<template>
<el-select
ref="selectLoadMore"
:value="value"
v-loadmore="loadMore"
@focus="focus"
@clear="clear"
filterable
remote
:filter-method="handleSearch"
:loading="loading"
clearable
v-bind="$attrs"
v-on="$listeners"
>
<el-option
v-for="option in data"
:label="option[dictLabel]"
:value="option[dictValue]"
:key="option.value"
></el-option>
<!-- 此处加载中的value可以随便设置只要不与其他数据重复即可 -->
<el-option
v-if="hasMore"
disabled
label="加载中..."
value="-1" />
<!--补充页面无数据时显示无数据的效果-->
<el-option
v-if="!hasMore && data.length==0"
disabled
label="暂无数据"
value="-2" />
</el-select>
</template>
<script>
export default {
name: "SelectLoadMore",
props: {
value: {
default: null
},
// 列表数据
data: {
type: Array,
default: () => []
},
dictLabel: {
type: String,
default: "label"
},
dictValue: {
type: String,
default: "value"
},
// 调用页数的接口
request: {
type: Function,
default: () => {
}
},
// 传入的页码
page: {
type: [Number, String],
default: 1
},
// 是否还有更多数据
hasMore: {
type: Boolean,
default: true
}
},
directives: {
// 这里实现一个组件内部的自定义指令
loadmore: {
// 指令的定义
bind(el, binding) {
const SELECTWRAP = el.querySelector(
".el-select-dropdown .el-select-dropdown__wrap"
);
if (!SELECTWRAP) {
throw new Error('获取不到"el-select-dropdown__wrap"节点');
}
SELECTWRAP.addEventListener("scroll", () => {
// scrollTop 这里可能因为浏览器缩放存在小数点的情况,导致了滚动到底部时
// scrollHeight 减去滚动到底部时的scrollTop ,依然大于clientHeight 导致无法请求更多数据
// 这里将scrollTop向上取整 保证滚到底部时,触发调用
const CONDITION =
SELECTWRAP.scrollHeight -
Math.ceil(SELECTWRAP.scrollTop) <=
SELECTWRAP.clientHeight;
// el.scrollTop !== 0 当输入时,如果搜索结果很少,以至于没看到滚动条,那么此时的CONDITION计算结果是true,会执行bind.value(),此时不应该执行,否则搜索结果不匹配
if (CONDITION && SELECTWRAP.scrollTop !== 0) {
binding.value();
}
});
}
}
},
data() {
return {
keyword: "", // 存储关键字用
loading: false
};
},
methods: {
// 请求下一页的数据
loadMore() {
// 如果没有更多数据,则不请求
if (!this.hasMore) {
return;
}
// 如果intercept属性为true则不请求数据,
if (this.loadMore.intercept) {
return;
}
this.loadMore.intercept = true;
this.request({
page: this.page + 1,
more: true,
keyword: this.keyword
}).then(() => {
this.loadMore.intercept = false;
});
},
// 选中下拉框没有数据时,自动请求第一页的数据
focus() {
if (!this.data.length) {
this.request({page: 1});
}
},
handleSearch(keyword) {
this.keyword = keyword;
this.loading = true;
console.log(keyword);
this.request({page: 1, keyword: keyword}).then(() => {
this.loading = false;
});
},
// 删除选中时,如果请求了关键字,则清除关键字再请求第一页的数据
clear() {
if (this.keyword) {
this.keyword = "";
this.request({page: 1});
}
}
},
mounted() {
this.$nextTick(function () {
// github代码有个bug,下拉的箭头无法加载的问题,需要等dom页面加载完毕后,添加箭头的class
let rulesDom = this.$refs["selectLoadMore"].$el.querySelector(
".el-input .el-input__suffix .el-input__suffix-inner .el-input__icon"
);// 找到dom
rulesDom.classList.add("el-icon-arrow-up");// 对dom新增class
})
}
}
</script>
<style scoped>
</style>
@@ -142,11 +142,22 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('服务端端口')" prop="serverPort">
<!--<el-form-item :label="$t('服务端端口')" prop="serverPort">
<el-select style="width: 280px;" class="filter-item" v-model="temp.serverPort" placeholder="请选择" filterable>
<el-option v-for="item in serverPortList" :key="item.port" :label="item.port" :value="item.port">
</el-option>
</el-select>
</el-form-item>-->
<el-form-item :label="$t('服务端端口')" prop="serverPort" >
<load-select style="width: 280px;" class="filter-item"
v-model="temp.serverPort"
:data="serverPortList"
:page="loadServerPortQuery.page"
:hasMore="more"
:clearable="false"
:dictLabel="'port'"
:dictValue="'port'"
:request="loadServerPort"/>
</el-form-item>
<el-form-item :label="$t('客户端IP')" prop="clientIp">
<el-input v-model="temp.clientIp"></el-input>
@@ -196,6 +207,8 @@ import waves from '@/directive/waves' // 水波纹指令
import { parseTime } from '@/utils'
import ButtonPopover from '../../components/Button/buttonPopover'
import DropdownTable from '../../components/Dropdown/DropdownTable'
// 下拉选择加载组件
import loadSelect from "@/components/Select/SelectLoadMore";
const calendarTypeOptions = [
{ key: 'CN', display_name: 'China' },
@@ -217,7 +230,8 @@ export default {
},
components: {
DropdownTable,
ButtonPopover
ButtonPopover,
loadSelect
},
data() {
return {
@@ -282,7 +296,13 @@ export default {
countryColumns: [
{ prop: 'userName', label: '用户名', align: 'center' },
{ prop: 'name', label: 'License', align: 'center' }
]
],
loadServerPortQuery:{ //下拉框加载数据请求参数
page:1,
size:50,
licenseId:null,
},
more: true,
}
},
filters: {
@@ -343,15 +363,9 @@ export default {
this.domainName = response.data.data
})
},
getPortPoolList() {
portPoolList().then(response => {
this.serverPortList = response.data.data
})
},
getAvailablePortList(licenseId) {
availablePortList(licenseId).then(response => {
this.serverPortList = response.data.data
})
this.loadServerPortQuery.licenseId = licenseId;
this.serverPortList = []; //清掉数据
},
getAllUserList() {
userList().then(response => {
@@ -408,6 +422,8 @@ export default {
userId: undefined
}
this.serverPortList = []
this.loadServerPortQuery.licenseId = null;
this.more = true;
},
handleCreate() {
this.resetTemp()
@@ -526,7 +542,37 @@ export default {
return v[j]
}
}))
}
},
// 传入给load-select组件的函数
loadServerPort({page = 1, more = false, keyword = ""} = {}) {
if(this.loadServerPortQuery.licenseId==null || this.loadServerPortQuery.licenseId==''){
this.more = false;
this.$message({
message: '请先选择License',
type: 'warning'
})
return ;
}
return new Promise(resolve => {
this.loadServerPortQuery.page = page;
this.loadServerPortQuery.keyword = keyword;
// 访问后端接口API
availablePortList(this.loadServerPortQuery).then(res => {
let result = res.data;
if (more) {
this.serverPortList = [...this.serverPortList, ...result.data.records];
} else {
this.serverPortList = result.data.records;
}
// this.loadServerPortQuery.page = result.data.current;
let {total, current, size} = result.data;
this.more = page * size < total;
this.loadServerPortQuery.page = current;
resolve();
});
});
},
}
}
</script>
@@ -102,7 +102,7 @@ public class PortPoolController {
@Get
@Mapping("/get-available-port-list")
public List<PortPoolListRes> getAvailablePortList(AvailablePortListReq req) {
public PageInfo<PortPoolListRes> getAvailablePortList(AvailablePortListReq req) {
ParamCheckUtil.checkNotNull(req, "req");
ParamCheckUtil.checkNotNull(req.getLicenseId(), "licenseId");
return portPoolService.getAvailablePortList(req);
@@ -12,4 +12,18 @@ public class AvailablePortListReq {
* licenseId
*/
private Integer licenseId;
/**
* 当前页
*/
private int page = 1;
/**
* 分页大小
*/
private int size = 10;
/**
* 搜索关键字
*/
private String keyword;
}
@@ -67,5 +67,5 @@ public interface PortPoolMapper extends BaseMapper<PortPoolDO> {
List<PortPoolListRes> selectResList(@Param("req") PortPoolListReq req);
List<PortPoolListRes> getAvailablePortList(@Param("licenseId") Integer licenseId,@Param("userId") Integer userId);
List<PortPoolListRes> getAvailablePortList(@Param("licenseId") Integer licenseId,@Param("userId") Integer userId, @Param("keyword") String keyword);
}
@@ -175,9 +175,17 @@ public class PortPoolService {
* 游客:全局端口 + 当前选择用户独占端口 + 当前选择license独占端口
* 非管理员身份时:下拉选择license,只能选当前用户下的LICENSE
*/
public List<PortPoolListRes> getAvailablePortList(AvailablePortListReq req) {
public PageInfo<PortPoolListRes> getAvailablePortList(AvailablePortListReq req) {
LicenseDO licenseDO = licenseMapper.queryById(req.getLicenseId());
return portPoolMapper.getAvailablePortList(req.getLicenseId(), licenseDO.getUserId());
if(StringUtils.isNotEmpty(req.getKeyword())){
req.setKeyword(req.getKeyword()+"%");
}
Page<PortPoolListRes> result = PageHelper.startPage(req.getPage(), req.getSize());
List<PortPoolListRes> portList = portPoolMapper.getAvailablePortList(req.getLicenseId(), licenseDO.getUserId(), req.getKeyword());
return PageInfo.of(portList, result.getTotal(), req.getPage(), req.getSize());
}
public void deleteBatch(List<Integer> ids) {
@@ -32,6 +32,9 @@
possessor_type = 0
OR ( possessor_type = 1 AND possessor_id = #{userId,jdbcType=INTEGER} )
OR ( possessor_type = 2 AND possessor_id = #{licenseId,jdbcType=INTEGER} )
)
)
<if test="keyword!=null and keyword!=''">
AND `port` LIKE #{keyword}
</if>
</select>
</mapper>