|
@@ -1,5 +1,5 @@
|
|
|
<script setup>
|
|
|
-import { reactive, ref, watch } from 'vue'
|
|
|
+import { nextTick, reactive, ref, watch } from 'vue'
|
|
|
import { SearchIcon, Icon } from 'tdesign-icons-vue-next';
|
|
|
import { apiETAChart } from '@/api/etaChart'
|
|
|
import { apiSystemCommon } from '@/api/system'
|
|
@@ -8,32 +8,33 @@ import { useClassify } from '../hooks/useClassify'
|
|
|
const emits = defineEmits(['change', 'filter'])
|
|
|
|
|
|
const { userVal } = useClassify()
|
|
|
-function handleUserChange(value,context) {
|
|
|
- emits('filter')
|
|
|
- getClassify()
|
|
|
-}
|
|
|
|
|
|
const searchSelectKeys = {
|
|
|
value: 'ChartInfoId',
|
|
|
label: 'ChartName'
|
|
|
}
|
|
|
+const expandedclassify = ref([])
|
|
|
const searchVal = ref('')
|
|
|
const searchOpts = ref([])
|
|
|
const searchLoading = ref(false)
|
|
|
-let searchPage = 1
|
|
|
-const searchPageSize = 20
|
|
|
+let searchPage = ref(1)
|
|
|
+const searchPageSize = 15
|
|
|
let finished = false
|
|
|
+const totals = ref(0)
|
|
|
+const showSearchResults = ref(false)
|
|
|
function handleSearchChart(keyword) {
|
|
|
+ if (keyword === '' || keyword === null) return
|
|
|
finished = false
|
|
|
- searchPage = 1
|
|
|
+ searchPage.value = 1
|
|
|
searchOpts.value = []
|
|
|
handleGetSearchChartList(keyword)
|
|
|
}
|
|
|
async function handleGetSearchChartList(keyword) {
|
|
|
searchLoading.value = true
|
|
|
+ showSuggestions.value = true
|
|
|
const res = await apiETAChart.chartSearch({
|
|
|
PageSize: searchPageSize,
|
|
|
- CurrentIndex: searchPage,
|
|
|
+ CurrentIndex: searchPage.value,
|
|
|
SysUserIds: userVal.value?.join(','),
|
|
|
Keyword: keyword
|
|
|
})
|
|
@@ -42,15 +43,32 @@ async function handleGetSearchChartList(keyword) {
|
|
|
const arr = res.Data.List || []
|
|
|
searchOpts.value = [...searchOpts.value, ...arr]
|
|
|
finished = res.Data.Paging.IsEnd
|
|
|
+ totals.value = res.Data.Paging.Totals
|
|
|
+ if (searchOpts.value.length === 0 && searchPage.value === 1) {
|
|
|
+ showSuggestions.value = false
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
async function handleLoadMoreChart() {
|
|
|
if (finished || searchLoading.value) return
|
|
|
handleGetSearchChartList()
|
|
|
}
|
|
|
-function handleSelectChart(value, context) {
|
|
|
+function handleSelectChart(value) {
|
|
|
if (value) {
|
|
|
- emits('change', {ChartInfoId:value})
|
|
|
+ emits('change', value)
|
|
|
+ showSuggestions.value = false
|
|
|
+ const array = value.ClassifyLevels || []
|
|
|
+ array.forEach((element, index) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ expandedclassify.value.push(element)
|
|
|
+ // 如果是最后一个元素,执行nextTick
|
|
|
+ if (index === array.length - 1) {
|
|
|
+ nextTick(() => {
|
|
|
+ classifyActived.value = [value.UniqueCode];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, index*500);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -116,46 +134,81 @@ function handleClassifyActiveChange({ node }) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+const showSuggestions = ref(false)
|
|
|
+
|
|
|
+
|
|
|
+const handleBlur = (text) => {
|
|
|
+ showSuggestions.value = false
|
|
|
+ if(!text){
|
|
|
+ clearMenu()
|
|
|
+ }
|
|
|
+}
|
|
|
+const clearMenu = () => {
|
|
|
+ searchOpts.value = []
|
|
|
+ showSearchResults.value = false
|
|
|
+}
|
|
|
+const handleEnterInput = () => {
|
|
|
+ showSuggestions.value = false
|
|
|
+ showSearchResults.value = true
|
|
|
+}
|
|
|
+const handleFocusInput = () => {
|
|
|
+ if(!searchVal.value) return
|
|
|
+ handleSearchChart(searchVal.value)
|
|
|
+}
|
|
|
+const clearInput = () => {
|
|
|
+ searchVal.value = ''
|
|
|
+ showSearchResults.value = false
|
|
|
+ handleSearchChart(searchVal.value)
|
|
|
+}
|
|
|
+const searchLoad = (e) => {
|
|
|
+ const {scrollTop, clientHeight, scrollHeight} = e.target
|
|
|
+ if (scrollTop + clientHeight === scrollHeight){
|
|
|
+ if(finished) return
|
|
|
+ searchPage.value++
|
|
|
+ handleGetSearchChartList()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
<div class="bg-white classify-wrap">
|
|
|
- <div class="select-wrap">
|
|
|
- <select-chart-creator v-model="userVal" @change="handleUserChange"/>
|
|
|
- </div>
|
|
|
- <t-select
|
|
|
- v-model="searchVal"
|
|
|
- placeholder="请输入图表名称"
|
|
|
- clearable
|
|
|
- filterable
|
|
|
- :keys="searchSelectKeys"
|
|
|
- :loading="searchLoading"
|
|
|
- @search="handleSearchChart"
|
|
|
- @change="handleSelectChart"
|
|
|
- :popup-props="{ 'on-scroll-to-bottom': handleLoadMoreChart }"
|
|
|
+ <t-popup
|
|
|
+ placement="bottom-left"
|
|
|
+ trigger="context-menu"
|
|
|
+ :visible="showSuggestions"
|
|
|
+ @on-scroll-to-bottom="handleLoadMoreChart"
|
|
|
>
|
|
|
- <template #prefixIcon>
|
|
|
- <search-icon />
|
|
|
- </template>
|
|
|
-
|
|
|
- <template #valueDisplay="{ value,label }">
|
|
|
- <div style="max-width:180px" class="t-input__inner" v-html="label" v-if="value"></div>
|
|
|
- </template>
|
|
|
-
|
|
|
- <t-option
|
|
|
- v-for="item in searchOpts"
|
|
|
- :key="item.ChartInfoId"
|
|
|
- :value="item.ChartInfoId"
|
|
|
- :label="item.ChartName"
|
|
|
- :title="null"
|
|
|
+ <t-input
|
|
|
+ v-model="searchVal"
|
|
|
+ placeholder="请输入图表名称"
|
|
|
+ @change="handleSearchChart"
|
|
|
+ @blur="handleBlur"
|
|
|
+ @focus="handleFocusInput"
|
|
|
+ @enter="handleEnterInput"
|
|
|
>
|
|
|
+ </t-input>
|
|
|
+ <template #content>
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in searchOpts"
|
|
|
+ :key="index"
|
|
|
+ class="suggestions-item"
|
|
|
+ @click="handleSelectChart(item)"
|
|
|
+ >
|
|
|
<span v-html="item.ChartName"></span>
|
|
|
- </t-option>
|
|
|
- </t-select>
|
|
|
- <div class="classify-list-box">
|
|
|
+ </li>
|
|
|
+ </template>
|
|
|
+ </t-popup>
|
|
|
+
|
|
|
+
|
|
|
+ <div class="classify-list-box" ref="scrollView" @scroll="searchLoad">
|
|
|
<t-tree
|
|
|
+ v-if="!showSearchResults"
|
|
|
:actived="classifyActived"
|
|
|
:data="classifyList"
|
|
|
+ v-model:expanded="expandedclassify"
|
|
|
activable
|
|
|
transition
|
|
|
lazy
|
|
@@ -176,16 +229,44 @@ function handleClassifyActiveChange({ node }) {
|
|
|
/>
|
|
|
</template>
|
|
|
</t-tree>
|
|
|
+ <template v-else>
|
|
|
+ <div class="search-result flex-align">
|
|
|
+ <div>共<span class="total-text">{{ totals }}</span>条搜索结果</div>
|
|
|
+ <div @click="clearInput" class="clear-result flex-align">
|
|
|
+ 清除内容
|
|
|
+ <img src="@/assets/imgs/clear.png" alt="">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template v-for="(item, index) in searchOpts" :key="index">
|
|
|
+ <div class="list-item" @click="handleSelectChart(item)">
|
|
|
+ <div v-html="item.ChartName"></div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+
|
|
|
+// 美化滚动条
|
|
|
+::-webkit-scrollbar {
|
|
|
+ width: 4px;
|
|
|
+ height: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-track {
|
|
|
+ width: 1px;
|
|
|
+ background: rgba(#101F1C, 0.1);
|
|
|
+ -webkit-border-radius: 2em;
|
|
|
+ -moz-border-radius: 2em;
|
|
|
+ border-radius: 2em;
|
|
|
+}
|
|
|
+
|
|
|
.classify-wrap {
|
|
|
width: 300px;
|
|
|
flex-shrink: 0;
|
|
|
padding: 20px;
|
|
|
-
|
|
|
.select-wrap {
|
|
|
display: flex;
|
|
|
gap: 0 10px;
|
|
@@ -195,6 +276,54 @@ function handleClassifyActiveChange({ node }) {
|
|
|
padding-top: 10px;
|
|
|
height: calc(100vh - 260px);
|
|
|
overflow-y: auto;
|
|
|
+ .search-result {
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #999999;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .clear-result {
|
|
|
+ cursor: pointer;
|
|
|
+ img {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ margin-left: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .total-text {
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .list-item {
|
|
|
+ width: 244px;
|
|
|
+ cursor:pointer;
|
|
|
+ margin: 4px;
|
|
|
+ padding: 5px 5px;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ &:hover {
|
|
|
+ background-color: #ECF2FE; // 背景颜色变为浅灰色
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+.suggestions-item {
|
|
|
+ width: 244px;
|
|
|
+ cursor:pointer;
|
|
|
+ margin: 4px;
|
|
|
+ padding: 5px 5px;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ &:hover {
|
|
|
+ background-color: #ECF2FE; // 背景颜色变为浅灰色
|
|
|
+ }
|
|
|
+}
|
|
|
+.flex-align {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
</style>
|