首页🐱🐱
This commit is contained in:
parent
b588915cb2
commit
e4b562ed86
@ -1,4 +1,3 @@
|
||||
|
||||
<template>
|
||||
<div class="config-editor">
|
||||
<div class="page-header">
|
||||
@ -6,6 +5,41 @@
|
||||
</div>
|
||||
|
||||
<div class="editor-container">
|
||||
<!-- 新增的侧边栏 -->
|
||||
<div class="sidebar" v-if="tagList.length > 0">
|
||||
<h3>标签列表</h3>
|
||||
<!-- 添加搜索框 -->
|
||||
<div class="search-box">
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchQuery"
|
||||
placeholder="输入ID搜索..."
|
||||
@input="searchTags"
|
||||
/>
|
||||
<button @click="clearSearch" class="clear-btn">×</button>
|
||||
</div>
|
||||
<div class="tag-list">
|
||||
<div
|
||||
v-for="tag in filteredTags"
|
||||
:key="tag.id"
|
||||
class="tag-item"
|
||||
draggable="true"
|
||||
@dragstart="dragStart(tag)"
|
||||
@click="insertTag(tag)"
|
||||
>
|
||||
<span class="tag-type">{{ tag.type }}</span>
|
||||
<span class="tag-id">{{ tag.id }}</span>
|
||||
<!-- 添加缓存值预览 -->
|
||||
<span class="tag-preview" v-if="tag.content.length > 50">
|
||||
{{ tag.content.substring(0, 50) }}...
|
||||
</span>
|
||||
<span class="tag-preview" v-else>
|
||||
{{ tag.content }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-section">
|
||||
<div class="button-group">
|
||||
<button @click="addEntry" class="gradient-btn">添加</button>
|
||||
@ -14,6 +48,8 @@
|
||||
<button @click="insertTemplate('LogicCommand')" class="gradient-btn">预设 LogicCommand</button>
|
||||
<button @click="insertTemplate('LogicCommandSet')" class="gradient-btn">预设 LogicCommandSet</button>
|
||||
<button @click="clearAll" class="gradient-btn">清空所有</button>
|
||||
<input type="file" id="fileInput" accept=".xml" @change="handleFileUpload" style="display: none">
|
||||
<button @click="triggerFileInput" class="gradient-btn">上传 XML</button>
|
||||
</div>
|
||||
|
||||
<div class="message-section">
|
||||
@ -28,6 +64,8 @@
|
||||
v-model="newEntry"
|
||||
placeholder="输入 LogicCommand 或 LogicCommandSet 标签"
|
||||
class="entry-textarea"
|
||||
@dragover.prevent
|
||||
@drop="dropTag"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@ -51,7 +89,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import '../../assets/styles/common.css'
|
||||
|
||||
// 响应式数据
|
||||
@ -63,6 +101,168 @@ const xmlContent = ref('')
|
||||
const errorMsg = ref('')
|
||||
const warningMsg = ref('')
|
||||
const lastModified = ref('')
|
||||
const draggedTag = ref(null)
|
||||
const searchQuery = ref('')
|
||||
const filteredTags = ref([])
|
||||
// 修改计算属性:从entries和uploadedTags中提取标签列表
|
||||
const tagList = computed(() => {
|
||||
const tags = []
|
||||
|
||||
// 从编辑区条目中提取标签
|
||||
entries.value.forEach(entry => {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(entry, 'application/xml')
|
||||
const element = doc.documentElement
|
||||
const id = element.getAttribute('id')
|
||||
if (id) {
|
||||
tags.push({
|
||||
id: id,
|
||||
type: element.tagName,
|
||||
content: entry,
|
||||
source: 'editor'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 从上传的标签中提取
|
||||
uploadedTags.value.forEach(tag => {
|
||||
tags.push({
|
||||
id: tag.id,
|
||||
type: tag.type,
|
||||
content: tag.content,
|
||||
source: 'upload'
|
||||
})
|
||||
})
|
||||
|
||||
// 初始化过滤后的标签
|
||||
filteredTags.value = [...tags]
|
||||
return tags
|
||||
})
|
||||
// 拖拽开始
|
||||
const dragStart = (tag) => {
|
||||
draggedTag.value = tag
|
||||
}
|
||||
//搜索标签
|
||||
const searchTags = () => {
|
||||
if (!searchQuery.value.trim()) {
|
||||
filteredTags.value = [...tagList.value]
|
||||
return
|
||||
}
|
||||
|
||||
const query = searchQuery.value.toLowerCase()
|
||||
filteredTags.value = tagList.value.filter(tag =>
|
||||
tag.id.toLowerCase().includes(query) ||
|
||||
tag.content.toLowerCase().includes(query)
|
||||
)
|
||||
}
|
||||
//清除搜索
|
||||
const clearSearch = () => {
|
||||
searchQuery.value = ''
|
||||
filteredTags.value = [...tagList.value]
|
||||
}
|
||||
// 放置标签
|
||||
const dropTag = (e) => {
|
||||
if (draggedTag.value) {
|
||||
insertTag(draggedTag.value)
|
||||
draggedTag.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 插入标签
|
||||
const insertTag = (tag) => {
|
||||
// 直接使用标签的内容,无论是来自编辑区还是上传
|
||||
newEntry.value = tag.content
|
||||
}
|
||||
|
||||
// 触发文件输入
|
||||
const triggerFileInput = () => {
|
||||
document.getElementById('fileInput').click()
|
||||
}
|
||||
|
||||
// 处理文件上传
|
||||
const handleFileUpload = (event) => {
|
||||
const file = event.target.files[0]
|
||||
if (!file) return
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const content = e.target.result
|
||||
parseAndImportXml(content)
|
||||
} catch (error) {
|
||||
errorMsg.value = '文件解析失败: ' + error.message
|
||||
}
|
||||
}
|
||||
reader.readAsText(file)
|
||||
}
|
||||
|
||||
// 在响应式数据部分添加新的变量
|
||||
const uploadedTags = ref([])
|
||||
|
||||
|
||||
// 修改后的解析并导入XML内容
|
||||
const parseAndImportXml = (xmlString) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const xmlDoc = parser.parseFromString(xmlString, 'application/xml')
|
||||
|
||||
// 检查解析错误
|
||||
const parserError = xmlDoc.querySelector('parsererror')
|
||||
if (parserError) {
|
||||
throw new Error('XML格式错误: ' + parserError.textContent)
|
||||
}
|
||||
|
||||
// 提取LogicCommand和LogicCommandSet节点
|
||||
const commands = xmlDoc.getElementsByTagName('LogicCommand')
|
||||
const commandSets = xmlDoc.getElementsByTagName('LogicCommandSet')
|
||||
|
||||
// 清空之前上传的标签
|
||||
uploadedTags.value = []
|
||||
|
||||
// 添加提取的节点到上传标签列表
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
const command = commands[i]
|
||||
const id = command.getAttribute('id')
|
||||
if (id) {
|
||||
// 获取原始标签内容(不经过XMLSerializer处理)
|
||||
const rawContent = command.outerHTML
|
||||
.replace(/ xmlns="[^"]*"/g, '') // 移除xmlns属性
|
||||
.replace(/\s+/g, ' ') // 压缩多余空格
|
||||
.trim()
|
||||
|
||||
uploadedTags.value.push({
|
||||
id: id,
|
||||
type: 'LogicCommand',
|
||||
content: rawContent
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < commandSets.length; i++) {
|
||||
const commandSet = commandSets[i]
|
||||
const id = commandSet.getAttribute('id')
|
||||
if (id) {
|
||||
// 获取原始标签内容(不经过XMLSerializer处理)
|
||||
const rawContent = commandSet.outerHTML
|
||||
.replace(/ xmlns="[^"]*"/g, '') // 移除xmlns属性
|
||||
.replace(/\s+/g, ' ') // 压缩多余空格
|
||||
.trim()
|
||||
|
||||
uploadedTags.value.push({
|
||||
id: id,
|
||||
type: 'LogicCommandSet',
|
||||
content: rawContent
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
warningMsg.value = `成功解析 ${commands.length + commandSets.length} 个标签,可在标签列表中选择添加到编辑区`
|
||||
errorMsg.value = ''
|
||||
} catch (error) {
|
||||
errorMsg.value = 'XML解析错误: ' + error.message
|
||||
warningMsg.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
// 方法
|
||||
const addEntry = () => {
|
||||
@ -105,7 +305,6 @@ const addEntry = () => {
|
||||
updateContent()
|
||||
newEntry.value = ''
|
||||
errorMsg.value = ''
|
||||
warningMsg.value = ''
|
||||
warningMsg.value = '条目添加成功!'
|
||||
formatXml()
|
||||
} catch (e) {
|
||||
@ -310,13 +509,53 @@ const getFileSize = () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 新增的搜索框样式 */
|
||||
.search-box {
|
||||
position: relative;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 100%;
|
||||
padding: 8px 30px 8px 12px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.search-box input:focus {
|
||||
outline: none;
|
||||
border-color: #1a237e;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.clear-btn:hover {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.config-editor {
|
||||
padding: 20px;
|
||||
max-width: 1200px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
@ -324,7 +563,76 @@ const getFileSize = () => {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* 新增的侧边栏样式 */
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
min-width: 250px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
border: 1px solid #e0e0e0;
|
||||
overflow-y: auto;
|
||||
max-height: 800px;
|
||||
}
|
||||
|
||||
.sidebar h3 {
|
||||
color: #1a237e;
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tag-item {
|
||||
padding: 10px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e0e0e0;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.tag-preview {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.tag-item:hover {
|
||||
border-color: #1a237e;
|
||||
background: #f0f2ff;
|
||||
}
|
||||
|
||||
.tag-item:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.tag-type {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.tag-id {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
flex: 1;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@ -394,6 +702,10 @@ const getFileSize = () => {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.editor-section {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.editor-section h3 {
|
||||
color: #1a237e;
|
||||
margin-bottom: 12px;
|
||||
@ -443,6 +755,17 @@ const getFileSize = () => {
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1024px) {
|
||||
.editor-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.config-editor {
|
||||
padding: 16px;
|
||||
@ -464,5 +787,13 @@ const getFileSize = () => {
|
||||
.xml-textarea {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.xml-stats {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.xml-stats span {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user