<script setup lang="ts">
import { ref, onMounted } from 'vue';
import {
NLayout,
NLayoutHeader,
NLayoutContent,
NLayoutFooter,
NIcon,
NInput,
NInputGroup,
NButton,
NUpload,
NCode,
NScrollbar,
NEmpty,
NConfigProvider // 引入配置提供器
} from 'naive-ui';
import { SearchOutline as SearchIcon } from '@vicons/ionicons5';
import hljs from 'highlight.js/lib/core';
import python from 'highlight.js/lib/languages/python';
import 'highlight.js/styles/github.css'; // 导入github主题
// 注册语言
hljs.registerLanguage('python', python);
// 可以在这里注册更多语言,如javascript、typescript等
const searchQuery = ref('');
const fileContent = ref('');
const fileName = ref('');
// 根据文件后缀获取语言类型
const getLanguageByExtension = (filename: string) => {
const extension = filename.split('.').pop()?.toLowerCase() || '';
const langMap: Record<string, string> = {
'js': 'javascript',
'jsx': 'javascript',
'ts': 'typescript',
'tsx': 'typescript',
'html': 'html',
'css': 'css',
'json': 'json',
'vue': 'html',
'py': 'python',
'java': 'java',
'c': 'c',
'cpp': 'cpp',
'cs': 'csharp',
'php': 'php',
'rb': 'ruby',
'go': 'go',
'rs': 'rust',
'swift': 'swift',
'kt': 'kotlin',
'sh': 'shell',
'md': 'markdown',
'yaml': 'yaml',
'yml': 'yaml',
'xml': 'xml'
};
return langMap[extension] || 'text';
};
const handleFileChange = ({ file }: any) => {
const selectedFile = file.file as File;
if (selectedFile) {
if (!selectedFile.type.startsWith('text/') &&
!selectedFile.name.match(/\.(js|jsx|ts|tsx|html|css|json|vue|py|java|c|cpp|cs|php|rb|go|rs|swift|kt|sh|md|yaml|yml|xml)$/i)) {
window.alert('请选择文本或代码文件');
return;
}
fileName.value = selectedFile.name;
searchQuery.value = selectedFile.name;
const reader = new FileReader();
reader.onload = (e: ProgressEvent<FileReader>) => {
if (e.target?.result) {
fileContent.value = e.target.result as string;
}
};
reader.readAsText(selectedFile);
}
};
const handleNext = () => {
console.log('下一步操作', fileContent.value);
window.alert('进入下一步操作!');
};
</script>
<template>
<!-- 在n-config-provider中注入hljs -->
<n-config-provider :hljs="hljs">
<n-layout class="container">
<!-- 顶部图标 -->
<n-layout-header class="header">
<n-icon size="48" color="#2080f0">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>
</n-icon>
<h1 class="title">自动化测试平台</h1>
</n-layout-header>
<!-- 搜索区域 -->
<n-layout-content class="search-section">
<n-input-group>
<div class="source-label">Source:</div>
<n-input
v-model="searchQuery"
placeholder="输入文件路径或选择文件"
readonly
size="large"
/>
<n-upload
action=""
:show-file-list="false"
@change="handleFileChange"
>
<n-button type="primary" size="large">
<template #icon>
<n-icon><search-icon /></n-icon>
</template>
选择文件
</n-button>
</n-upload>
</n-input-group>
</n-layout-content>
<n-layout-content class="content-display">
<n-scrollbar style="height: 100%">
<div v-if="fileContent">
<!-- 使用n-code组件,并设置show-line-numbers和word-wrap -->
<n-code
:code="fileContent"
:language="getLanguageByExtension(fileName)"
show-line-numbers
word-wrap
/>
</div>
<n-empty v-else description="未选择文件" />
</n-scrollbar>
</n-layout-content>
<!-- 底部操作区域 -->
<n-layout-footer class="footer">
<n-button
type="primary"
size="large"
:disabled="!fileContent"
@click="handleNext"
class="action-button"
>
下一步
</n-button>
</n-layout-footer>
</n-layout>
</n-config-provider>
</template>
<style scoped>
.container {
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.header {
flex: 0 0 auto;
display: flex;
flex-direction: column;
align-items: center;
padding: 15px 0;
}
.title {
font-size: 24px;
font-weight: bold;
margin-top: 8px;
color: #333;
}
.search-section {
flex: 0 0 auto;
padding: 10px 0 20px;
width: 100%;
}
.n-input-group {
display: flex;
align-items: center;
width: 100%;
padding: 0 20px;
box-sizing: border-box;
}
.source-label {
font-size: 16px;
font-weight: bold;
color: #333;
white-space: nowrap;
margin-right: 12px;
}
.content-display {
flex: 1;
min-height: 0;
padding: 0 20px;
overflow: auto; /* 单一滚动条控制 */
}
.code-container {
background: #f5f5f5;
border-radius: 4px;
padding: 15px;
max-height: calc(100vh - 250px); /* 动态高度计算 */
}
/* 覆盖n-code的样式,确保背景色一致 */
:deep(.n-code) {
background: #f5f5f5 !important;
padding: 15px;
font-size: 15px;
line-height: 1.5;
max-height: 100%;
overflow: auto;
}
:deep(.n-code-line) {
white-space: pre-wrap !important;
word-break: break-word !important;
}
.footer {
flex: 0 0 auto;
display: flex;
justify-content: flex-end;
padding: 15px 20px;
width: 100%;
box-sizing: border-box;
}
.action-button {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
@media (max-width: 768px) {
.search-section,
.content-display,
.footer {
padding-left: 10px;
padding-right: 10px;
}
.n-input-group {
flex-direction: column;
align-items: flex-start;
}
.source-label {
margin-bottom: 8px;
margin-right: 0;
}
.n-upload {
margin-top: 10px;
width: 100%;
}
.n-button {
width: 100%;
}
.action-button {
width: 100%;
margin-top: 10px;
}
}
</style>我修改样式和布局,这个页面我在鼠标往下滚动的滚动条(因为父组件已经有了)如果这个页面再来一黑色的滚动条,特别丑,所以给我修改,使其屏幕上只有一个滚动条