CentOS上安装rlwrap, 给Oracle sqlplus添加上下键功能

本文介绍如何通过安装rlwrap工具来提升SQL*Plus的用户体验,包括使用yum安装readline-devel,下载并编译rlwrap源码,以及如何通过rlwrap启动SQL*Plus。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

yum -y install readline-devel

wget http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap-0.37.tar.gz
mv rlwrap-0.37.tar.gz test/
cd test/
tar zxf rlwrap-0.37.tar.gz
cd rlwrap-0.37/
./configure
make
make install

[root@ora-11gr2 ~]# which  rlwrap

/usr/local/bin/rlwrap

========================================================

使用方法如下:

[oracle@ora-11gr2 ~]$ rlwrap sqlplus /nolog


SQL*Plus: Release 11.2.0.1.0 Production on Fri May 10 11:15:49 2013

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

SQL> connect sys as sysdba
Enter password:
Connected.
SQL> SELECT USERNAME, ACCOUNT_STATUS FROM dba_users WHERE USERNAME='HR';

USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
HR                             EXPIRED & LOCKED

SQL>

<template> <div class="detail-container"> <!-- 索引板块卡片 --> <el-card class="index-card"> <!-- 表单区域 --> <el-form :model="formData" label-position="top" ref="indexForm" class="mobile-form" > <!-- 问卷标题 --> <el-form-item label="问卷标题:" prop="dcWjTitle"> <el-input v-model="formData.dcWjTitle" placeholder="请输入问卷标题" clearable :prefix-icon="Document" /> </el-form-item> <!-- 被测评人 --> <el-form-item label="被测评人:" prop="dcId"> <el-select v-model="formData.dcId" multiple filterable remote reserve-keyword clearable placeholder="请选择被测评人" :remote-method="searchBdr" :loading="bdrLoading" @focus="handleBdrFocus" style="width: 100%" > <el-option v-for="item in bdrOptions" :key="item.dcId" :label="item.dcName" :value="item.dcId" /> </el-select> </el-form-item> <!-- 人员部门 --> <el-form-item label="人员部门:" prop="dcDept"> <el-input v-model="formData.dcDept" placeholder="请输入人员部门" clearable :prefix-icon="OfficeBuilding" /> </el-form-item> <!-- 提交状态 --> <el-form-item label="提交状态:" prop="state"> <el-select v-model="formData.state" placeholder="请选择提交状态" clearable class="mobile-select" > <el-option label="已提交" :value="1" /> <el-option label="未提交" :value="0" /> </el-select> </el-form-item> <!-- 新增:按钮区域 --> <el-form-item class="button-group"> <el-button type="primary" @click="handleSearch" class="action-button" :icon="Search" > 搜索 </el-button> <el-button @click="handleReset" class="action-button" :icon="Refresh" > 重置 </el-button> </el-form-item> </el-form> </el-card> <!-- 数据显示板块 --> <el-card class="data-card"> <template #header> <div class="card-header"> <el-button type="primary" size="small" :icon="Refresh" @click="fetchData" > 刷新数据 </el-button> </div> </template> <!-- 数据加载 --> <div v-loading="loading" class="card-container"> <div v-for="(item, index) in tableData" :key="item.dcWjId" class="data-card-item" > <!-- 顶部:序号问卷标题 --> <div class="card-header-section"> <!-- <div class="card-id">序号{{ item.dcWjId }}</div> --> <div class="card-title">{{ item.dcWjTitle }}</div> </div> <!-- 中间:其他数据 --> <div class="card-body-section"> <div class="card-row"> <span class="card-label">被测评人:</span> <span class="card-value">{{ item.dcName }}</span> </div> <div class="card-row"> <span class="card-label">部门:</span> <span class="card-value">{{ item.dcDept }}</span> </div> <div class="card-row"> <span class="card-label">创建时间:</span> <span class="card-value">{{ item.createTime }}</span> </div> <div class="card-row"> <span class="card-label">提交时间:</span> <span class="card-value">{{ item.updateTime || '-' }}</span> </div> </div> <!-- 底部:状态、得分操作按钮 --> <div class="card-footer-section"> <div class="status-container"> <el-tag :type="item.state === '1' ? 'success' : 'info'"> {{ item.state === '1' ? '已提交' : '未提交' }} </el-tag> <div class="score">总分: {{ item.score || '0' }}</div> </div> <el-button size="small" type="primary" @click="handleView(item)" class="action-btn" > 编辑/查看 </el-button> </div> </div> <!-- 空数据提示 --> <el-empty v-if="tableData.length === 0" description="暂无数据" /> </div> <!-- 分页控件 --> <div class="pagination-container"> <el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.size" :page-sizes="[5, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handleSizeChange" @current-change="handlePageChange" /> </div> </el-card> </div> </template> <script setup> // 确保正确导入所有 Vue 函数 import { ref, reactive, onMounted, onUnmounted } from 'vue'; import axios from 'axios'; import { Document, User, OfficeBuilding, Search, Refresh } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; import { useRouter } from 'vue-router'; const router = useRouter(); // 环境变量管理API地址 const API_BASE = import.meta.env.VITE_API_BASE || 'http://172.26.26.43/dev-api'; const API_URL = `${API_BASE}/wjdc/wj/listTx`; const BDR_API_URL = `${API_BASE}/wjdc/wj/getBdrList`; // 被测评人相关数据 const bdrOptions = ref([]); // 被测评人选项列表 const bdrLoading = ref(false); // 加载状态 const bdrCache = ref([]); // 缓存所有被测评人数据 // 表单数据 const formData = reactive({ dcWjTitle: '', dcId: [], dcDept: '', state: null }); // 表格数据 const tableData = ref([]); const loading = ref(false); // 分页配置 const pagination = reactive({ current: 1, size: 10, total: 0 }); // 表单引用 const indexForm = ref(null); // 请求取消令牌 let cancelTokenSource = axios.CancelToken.source(); // 处理被测评人输入框获取焦点 const handleBdrFocus = () => { if (bdrCache.value.length === 0) { fetchBdrList(''); } }; // 获取被测评人列表 const fetchBdrList = async (keyword = '') => { const token = getAuthToken(); if (!token) return; bdrLoading.value = true; try { const response = await axios.get(BDR_API_URL, { headers: { 'Authorization': `Bearer ${token}` } }); // 判断返回的数据是否是数组 if (Array.isArray(response.data)) { // 缓存所有数据 bdrCache.value = response.data; // 根据关键字过滤 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName && item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); // 最多显示10条 } else { // 未输入关键字时显示前10条 bdrOptions.value = bdrCache.value.slice(0, 10); } } else { // 如果不是数组,则按照原有格式处理(假设有codedata) if (response.data && response.data.code === 200) { bdrCache.value = response.data.data || []; // 同样的过滤逻辑 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } else { const msg = response.data?.msg || '返回数据格式不正确'; ElMessage.error('获取被测评人列表失败: ' + msg); } } } catch (error) { console.error('获取被测评人列表失败:', error); ElMessage.error('获取被测评人列表失败'); } finally { bdrLoading.value = false; } }; // 搜索被测评人(防抖) let searchBdrTimer = null; const searchBdr = (query) => { if (searchBdrTimer) clearTimeout(searchBdrTimer); searchBdrTimer = setTimeout(() => { if (bdrCache.value.length === 0) { fetchBdrList(query); } else { // 本地过滤 if (query) { const searchTerm = query.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } }, 300); }; // 获取认证令牌 const getAuthToken = () => { const token = localStorage.getItem('token'); if (!token) { ElMessage.warning('请先登录'); router.push('/login'); return null; } return token; }; // 搜索按钮处理函数 - 防抖 let searchTimer = null; const handleSearch = () => { // 检查被测评人选择数量 if (formData.dcId.length > 1) { ElMessage.warning({ message: '当前只能搜索一个被测人员', duration: 3000 }); return; } if (searchTimer) clearTimeout(searchTimer); searchTimer = setTimeout(() => { pagination.current = 1; fetchData(); }, 300); }; // 重置按钮处理函数 const handleReset = () => { if (indexForm.value) { indexForm.value.resetFields(); // 确保重置后 dcId 是空数组 formData.dcId = []; } handleSearch(); }; // 编辑/查看 const handleView = (row) => { router.push({ name: 'Operation', // 路由名称 params: { id: row.dcWjId // 传递问卷ID作为参数 } }); }; // 分页大小改变 const handleSizeChange = (size) => { pagination.size = size; fetchData(); }; // 页码改变 const handlePageChange = (page) => { pagination.current = page; fetchData(); }; // 获取数据 const fetchData = async () => { // 获取认证令牌 const token = getAuthToken(); if (!token) return; // 取消之前的请求 if (cancelTokenSource) { cancelTokenSource.cancel('请求被取消'); } cancelTokenSource = axios.CancelToken.source(); loading.value = true; try { // 构造请求参数 const params = { pageNum: pagination.current, pageSize: pagination.size, ...formData, // 安全处理:确保 dcId 是数组再 join dcId: Array.isArray(formData.dcId) ? formData.dcId.join(',') : '' // 将数组转换为逗号分隔的字符串 }; // 调用API - 添加认证头 const response = await axios.get(API_URL, { params, cancelToken: cancelTokenSource.token, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); // 处理响应数据 const { data } = response; if (data && data.code === 200) { // 修改点:直接使用 data.rows data.total tableData.value = data.rows || []; pagination.total = data.total || 0; // 空数据提示 if (tableData.value.length === 0) { ElMessage.info('没有找到匹配的数据'); } } else { const errorMsg = data?.msg || '未知错误'; console.error('API返回错误:', errorMsg); ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } catch (error) { // 处理认证失败 if (error.response && error.response.status === 401) { ElMessage.error('认证过期,请重新登录'); localStorage.removeItem('token'); router.push('/login'); return; } // 忽略取消请求的错误 if (!axios.isCancel(error)) { console.error('获取数据失败:', error); const errorMsg = error.response?.data?.message || '网络请求失败'; ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } finally { loading.value = false; } }; // 页面加载时获取初始数据 onMounted(() => { fetchData(); }); // 组件卸载时取消所有请求 onUnmounted(() => { if (cancelTokenSource) { cancelTokenSource.cancel('组件卸载,取消请求'); } }); </script> <style scoped> /* 移动端适配样式 */ .detail-container { padding: 12px; } /* 卡片容器样式 */ .card-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 16px; padding: 8px; } /* 单个卡片样式 */ .data-card-item { background: #fff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); padding: 16px; display: flex; flex-direction: column; transition: all 0.3s ease; border: 1px solid #ebeef5; } .data-card-item:hover { transform: translateY(-4px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); } /* 卡片头部(序号+标题) */ .card-header-section { padding-bottom: 12px; border-bottom: 1px solid #f0f2f5; margin-bottom: 12px; } .card-id { font-size: 14px; color: #909399; margin-bottom: 4px; } .card-title { font-size: 16px; font-weight: 600; color: #303133; line-height: 1.4; word-break: break-word; } /* 卡片主体(其他信息) */ .card-body-section { flex: 1; margin-bottom: 12px; } .card-row { display: flex; margin-bottom: 8px; font-size: 14px; } .card-label { color: #606266; min-width: 70px; text-align: right; } .card-value { color: #303133; flex: 1; word-break: break-word; } /* 卡片底部(状态+按钮) */ .card-footer-section { display: flex; justify-content: space-between; align-items: center; padding-top: 12px; border-top: 1px solid #f0f2f5; } .status-container { display: flex; align-items: center; gap: 8px; } .score { font-size: 14px; color: #e6a23c; font-weight: 500; } .action-btn { flex-shrink: 0; } /* 移动端响应式 */ @media (max-width: 768px) { .card-container { grid-template-columns: 1fr; } .card-row { flex-direction: column; margin-bottom: 12px; } .card-label { text-align: left; margin-bottom: 4px; font-weight: 500; } .card-footer-section { flex-direction: column; align-items: stretch; gap: 12px; } .status-container { justify-content: space-between; } } /* 添加选择器样式 */ :deep(.el-select) .el-input__inner { height: auto !important; min-height: 44px; padding: 5px 15px; } /* 标签样式 */ :deep(.el-tag) { margin: 2px 6px 2px 0; } /* 下拉菜单样式 */ :deep(.el-select-dropdown) { max-height: 300px; overflow-y: auto; } .index-card { border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .card-header { font-size: 18px; font-weight: 600; color: #1a1a1a; } .mobile-form { :deep(.el-form-item__label) { font-weight: 500; margin-bottom: 6px; } :deep(.el-input__inner) { height: 44px; border-radius: 8px; } } .mobile-select { width: 100%; :deep(.el-input__inner) { height: 44px; } } /* 按钮区域样式 */ .button-group { display: flex; gap: 12px; margin-top: 16px; } .action-button { flex: 1; height: 46px; font-size: 16px; border-radius: 8px; } /* 移动端响应式调整 */ @media (max-width: 480px) { .button-group { flex-direction: column; gap: 10px; } .action-button { width: 100%; } } </style> 帮我修改一下该页面的整体布局,使得该页面适用于移动端,而不是PC端
07-18
<template> <div :class="`${prefixCls}`"> <el-tabs v-model="tableDescIndex" editable :class="`${prefixCls}__tabs`" @tab-change="handleTabChange" @edit="handleTabsEdit" > <el-tab-pane v-for="(item, index) in routeDescTabs" :key="index" :label="item.routeAbbr" :name="index" > <template #label> <span @dblclick="handleTabDblClick(index)" class="tab-title"> <el-tooltip class="box-item" effect="dark" :content="item.lineDesc" placement="top" v-if="item.lineDesc" > {{ item.routeAbbr }} </el-tooltip> <span v-else>{{ item.routeAbbr }}</span> </span> </template> <el-table :data="item.planStopList" :class="`${prefixCls}__table`" :header-cell-style="headerCellStyle" :cell-style="cellStyle" > <el-table-column prop="sort" :label="t('lineEdit.sort')" width="90" align="center"> <template #default="scope"> <div> {{ scope.$index + 1 }} <el-icon @click="addColumnAfterRow(scope.$index)" class="add-icon"> <Plus /> </el-icon> <el-icon @click="removeRow(scope.$index)" class="add-icon"> <Delete /> </el-icon> </div> </template> </el-table-column> <el-table-column prop="stopId" :label="t('lineMapEdit.stationName')" align="center"> <template #default="scope"> <el-select v-model="scope.row.stopDesc" filterable :filter-method="handleSearch" virtual-scroll :virtual-scroll-item-size="40" :virtual-scroll-visible-items="15" v-select-loadmore="loadMoreData" placeholder="请选择或搜索" > <el-option v-for="item in visibleOptions" :key="item.stopId" :label="item.stopDesc" :value="item.stopId" /> </el-select> </template> </el-table-column> </el-table> </el-tab-pane> </el-tabs> </div> </template> <script lang="ts" setup> import { headerCellStyle, cellStyle } from '@/components/PlanningComps/common' import { Plus, Delete } from '@element-plus/icons-vue' import { ref } from 'vue' import { debounce } from 'lodash-es' import { getAllStopList } from '@/api/planning/stop/index' import { RouteTab, lineRouteInfoItem } from '@/api/planning/line/type' import { ElMessageBox } from 'element-plus' defineOptions({ name: 'RouteDesc' }) const props = defineProps<{ lineRouteInfoList: lineRouteInfoItem[] }>() const emit = defineEmits(['update:tabIndex', 'update-line-detail', 'stop-added', 'stop-deleted']) const { getPrefixCls } = useDesign() const prefixCls = getPrefixCls('route-desc') const message = useMessage() const { t } = useI18n() const tableDescIndex = ref(0) // 当前选中的选项 const routeDescTabs = ref<lineRouteInfoItem[]>([]) // 新增线路点 const wayPoint = ref([]) // 初始化响应式引用 const allOptions = ref([]) // 所有选项 const filteredOptions = ref([]) // 过滤后的选项 const currentPage = ref(1) // 当前页码 const pageSize = 50 // 每页大小 const hasMore = ref(true) // 是否还有更多数据 const isLoading = ref(false) // 加载状态 const selectKey = ref(0) const searchQuery = ref('') const loadedCount = ref(100) // 初始加载100条 // 新增对话框删除tab const handleTabsEdit = (targetName: TabPaneName | undefined, action: 'remove' | 'add') => { if (action === 'add') { ElMessageBox.prompt('Please enter the line name', 'Prompt', { confirmButtonText: 'Confirm', cancelButtonText: 'Cancel', inputPattern: /.+/, // 正则验证 inputErrorMessage: 'The input cannot be empty' }) .then(({ value }) => { const title = value.trim() routeDescTabs.value.push({ lineId: '', lineDesc: '', routeAbbr: title, planStopList: [{ stopId: '', stopDesc: '', sort: 1, lng: '', lat: '' }], routeGeometry: {} }) tableDescIndex.value = routeDescTabs.value.length - 1 handleTabChange() // lineRouteInfoItem 添加线路描述 emit('update-line-detail', routeDescTabs.value) }) .catch(() => { console.log('User cancellation') }) } else if (action === 'remove') { const tabs = routeDescTabs.value let activeName = tableDescIndex.value if (activeName === targetName) { tabs.forEach((tab, index) => { if (tab.name === targetName) { const nextTab = tabs[index + 1] || tabs[index - 1] if (nextTab) { activeName = nextTab.name } } }) } tableDescIndex.value = activeName routeDescTabs.value = tabs.filter((tab) => tab.name !== targetName) } } // 删除 const removeTab = (targetName: string) => { const tabs = routeDescTabs.value let activeName = tableDescIndex.value if (activeName === targetName) { tabs.forEach((tab, index) => { if (tab.name === targetName) { const nextTab = tabs[index + 1] || tabs[index - 1] if (nextTab) { activeName = nextTab.name } } }) } tableDescIndex.value = activeName routeDescTabs.value = tabs.filter((tab) => tab.name !== targetName) } // 判定索引位置 const determinePositionType = (index: number) => { const stops = routeDescTabs.value[tableDescIndex.value].planStopList if (index === 0) return 'start' if (index === stops.length - 1) return 'end' return 'middle' } // 新增行index 索引(新增包含lineID站点-保存新增索引-判断位置-传递事件-构建几何请求-重绘线路) const addColumnAfterRow = (index: number) => { const newIndex = index + 1 routeDescTabs.value[tableDescIndex.value].planStopList.splice(newIndex, 0, { sort: `${newIndex + 1}`, stopId: '', stopDesc: '', lng: '', lat: '' }) // 更新所有行的 No 值 routeDescTabs.value[tableDescIndex.value].planStopList.forEach((row, i) => { row.sort = `${i + 1}` }) } // 监听删除操作后重排序 const removeRow = (index) => { if (routeDescTabs.value[tableDescIndex.value].planStopList.length <= 1) return message.warning('Only one value cannot be deleted') // 触发线路更新事件,携带被删除站点的类型信息 if (routeDescTabs.value[tableDescIndex.value].lineId != '') { emit('stop-deleted', { delectIndex: index, // 删除站点索引 positionType: determinePositionType(index) // 删除站点位置类型 }) } routeDescTabs.value[tableDescIndex.value].planStopList.splice(index, 1) // 重置编号 routeDescTabs.value[tableDescIndex.value].planStopList.forEach((row, i) => { row.sort = `${i + 1}` }) message.success('Delete successfully') } // 获取站点列表 const getAllStopsList = async () => { try { const data = (await getAllStopList()) as StopListItem[] allOptions.value = data } catch (error) { console.error('获取站点列表失败:', error) allOptions.value = [] filteredOptions.value = [] } } // 防抖远程搜索 const handleSearch = debounce( (query) => { debugger if (!query) { // filteredOptions.value = [] return } try { searchQuery.value = query.toLowerCase() } catch (error) { console.error('搜索站点失败:', error) filteredOptions.value = [] } }, 300, { leading: true, trailing: true } ) // 局部注册自定义滚动指令翻页加载 const vSelectLoadmore = { mounted(el, binding) { // 使用nextTick确保DOM渲染完成 setTimeout(() => { const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap') if (SELECTWRAP_DOM) { SELECTWRAP_DOM.addEventListener('scroll', () => { // 精确计算是否滚动到底部 const isBottom = Math.ceil(SELECTWRAP_DOM.scrollTop + SELECTWRAP_DOM.clientHeight) >= SELECTWRAP_DOM.scrollHeight - 1 if (isBottom) { binding.value() // 触发绑定的加载函数 } }) } }, 100) } } // 分页加载函数 const loadMoreData = () => { if (loadedCount.value < allOptions.value.length) { loadedCount.value += 50 // 每次加载50条 } } // 动态计算可见选项(结合搜索分页) const visibleOptions = computed(() => { debugger let result = allOptions.value if (searchQuery.value) { result = result.filter((item) => item.stopDesc.toLowerCase().includes(searchQuery.value.toLowerCase()) ) } return result.slice(0, loadedCount.value) // 只返回当前加载的数据 }) // 双击修改方案名 const handleTabDblClick = (index: number) => { const currentTab = routeDescTabs.value[index] if (!currentTab) return ElMessageBox.prompt('Please enter the new line description', 'Modify the line name', { confirmButtonText: 'Confirm', cancelButtonText: 'Cancel', inputPattern: /.+/, inputErrorMessage: 'Please enter a valid line name', inputValue: currentTab.routeAbbr // 初始值为当前名称 }) .then(({ value }) => { // 更新 tab 的 lineDesc 字段 routeDescTabs.value[index].routeAbbr = value.trim() }) .catch(() => { console.log('User cancels modification') }) } const handleChangeSelectStops = (value, sort) => { console.log(value, sort, 'dddd') // debugger filteredOptions.value.some((item, index) => { if (item.stopId == value) { const tabIndex = tableDescIndex.value const stops = routeDescTabs.value[tabIndex].planStopList // // 获取新增索引 const addedIndex = sort - 1 // 获取原始 stopId // const oldStop = stops[addedIndex]?.stopId // 设置当前站点信息 routeDescTabs.value[tabIndex].planStopList[addedIndex] = { ...stops[addedIndex], stopId: item.stopId, stopDesc: item.stopDesc, lng: item.lng, lat: item.lat } // 新增及替换点的更改 if (routeDescTabs.value[tableDescIndex.value].lineId != '') { emit('stop-added', { stopIndex: addedIndex, positionType: determinePositionType(addedIndex), behindStation: addedIndex > 0 ? stops[addedIndex] : null }) } } }) } const handleTabChange = () => { emit('update:tabIndex', tableDescIndex.value) } // 计算当前选项卡的有效 stopId 数量 const validStopCount = computed(() => { const currentTab = routeDescTabs.value[tableDescIndex.value] if (!currentTab?.planStopList) return 0 return currentTab.planStopList.filter((stop) => stop.stopId).length }) // 监听站点数量变化并触发更新 watch( validStopCount, (newCount, oldCount) => { if (newCount !== oldCount) { // console.log('站点数量变化', newCount, oldCount, tableDescIndex.value, routeDescTabs.value) const currentTab = routeDescTabs.value[tableDescIndex.value] // 新增 if (currentTab && currentTab.lineId == '') { // debugger // console.log(routeDescTabs.value, 'routeDescTabs.value') emit('update-line-detail', routeDescTabs.value) } } }, { immediate: true } ) watchEffect(() => { if (props.lineRouteInfoList && props.lineRouteInfoList.length > 0) { routeDescTabs.value = [...props.lineRouteInfoList] console.log(routeDescTabs.value, 'routeDescTabs.value') } }) onBeforeMount(() => { getAllStopsList() }) onMounted(() => {}) </script> <style lang="scss" scoped> $prefix-cls: #{$namespace}-route-desc; .#{$prefix-cls} { .el-select-dropdown { max-height: 300px; } width: 458px; background: rgba(255, 255, 255, 0.7); border-radius: 4px; padding: 0px 16px; overflow-y: auto; &__tabs { height: calc(100vh - 110px); .tab-title { display: flex; align-items: center; gap: 6px; padding: 0 8px; &:hover .el-icon { opacity: 1; } .el-icon { opacity: 0; transition: opacity 0.2s; &:hover { color: #409eff; } } } } &__table { height: calc(100vh - 175px); // 表头圆角 :deep(.el-table__header) { border-radius: 6px; overflow: hidden; } // 表内容行间距 :deep(.el-table__body) { border-collapse: separate !important; border-spacing: 0 7px !important; /* 第二个值控制行间距 */ overflow: hidden !important; } // 表内容每一行的首尾单元格具有圆角效果 :deep(.el-table__body-wrapper table) { border-collapse: separate; overflow: hidden; } :deep(.el-table__body tr td:first-child), :deep(.el-table__body tr td:last-child) { position: relative; } :deep(.el-table__body tr td:first-child) { border-top-left-radius: 6px; border-bottom-left-radius: 6px; } :deep(.el-table__body tr td:last-child) { border-top-right-radius: 6px; border-bottom-right-radius: 6px; } .add-icon { opacity: 0; transition: opacity 0.2s ease; } tr:hover .add-icon { opacity: 1; cursor: pointer; margin-left: 6px; } } } </style> <style lang="scss"> $prefix-cls: #{$namespace}-route-desc; .#{$prefix-cls} { } </style> 当前页vSelectLoadmore 在搜索数据出来后无法获取到滚动事件的原因
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值