Compare commits
No commits in common. "79f1daf525045dda89683b1515194c64b81bad82" and "b588915cb255409023385173005a9086ae48ee17" have entirely different histories.
79f1daf525
...
b588915cb2
10
node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts
generated
vendored
10
node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts
generated
vendored
@ -40,6 +40,14 @@ export {};
|
|||||||
expose?: (exposed: T) => void,
|
expose?: (exposed: T) => void,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
type __VLS_NormalizeSlotReturns<S, R = NonNullable<S> extends (...args: any) => infer K ? K : any> = R extends any[] ? {
|
||||||
|
[K in keyof R]: R[K] extends infer V
|
||||||
|
? V extends Element ? V
|
||||||
|
: V extends new (...args: any) => infer R ? ReturnType<__VLS_FunctionalComponent<R>>
|
||||||
|
: V extends (...args: any) => infer R ? R
|
||||||
|
: any
|
||||||
|
: never
|
||||||
|
} : R;
|
||||||
type __VLS_IsFunction<T, K> = K extends keyof T
|
type __VLS_IsFunction<T, K> = K extends keyof T
|
||||||
? __VLS_IsAny<T[K]> extends false
|
? __VLS_IsAny<T[K]> extends false
|
||||||
? unknown extends T[K]
|
? unknown extends T[K]
|
||||||
@ -105,7 +113,7 @@ export {};
|
|||||||
index: number,
|
index: number,
|
||||||
][];
|
][];
|
||||||
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
|
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
|
||||||
D extends (...args: infer P) => any ? P : any[];
|
__VLS_PickNotAny<NonNullable<D>, (...args: any) => any> extends (...args: infer P) => any ? P : any[];
|
||||||
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
|
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
|
||||||
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
|
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
|
||||||
: T extends (...args: any) => any
|
: T extends (...args: any) => any
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="config-editor">
|
<div class="config-editor">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
@ -5,41 +6,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="editor-container">
|
<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="input-section">
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<button @click="addEntry" class="gradient-btn">添加</button>
|
<button @click="addEntry" class="gradient-btn">添加</button>
|
||||||
@ -48,8 +14,6 @@
|
|||||||
<button @click="insertTemplate('LogicCommand')" class="gradient-btn">预设 LogicCommand</button>
|
<button @click="insertTemplate('LogicCommand')" class="gradient-btn">预设 LogicCommand</button>
|
||||||
<button @click="insertTemplate('LogicCommandSet')" class="gradient-btn">预设 LogicCommandSet</button>
|
<button @click="insertTemplate('LogicCommandSet')" class="gradient-btn">预设 LogicCommandSet</button>
|
||||||
<button @click="clearAll" class="gradient-btn">清空所有</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>
|
||||||
|
|
||||||
<div class="message-section">
|
<div class="message-section">
|
||||||
@ -64,8 +28,6 @@
|
|||||||
v-model="newEntry"
|
v-model="newEntry"
|
||||||
placeholder="输入 LogicCommand 或 LogicCommandSet 标签"
|
placeholder="输入 LogicCommand 或 LogicCommandSet 标签"
|
||||||
class="entry-textarea"
|
class="entry-textarea"
|
||||||
@dragover.prevent
|
|
||||||
@drop="dropTag"
|
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -89,7 +51,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref } from 'vue'
|
||||||
import '../../assets/styles/common.css'
|
import '../../assets/styles/common.css'
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
@ -101,168 +63,6 @@ const xmlContent = ref('')
|
|||||||
const errorMsg = ref('')
|
const errorMsg = ref('')
|
||||||
const warningMsg = ref('')
|
const warningMsg = ref('')
|
||||||
const lastModified = 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 = () => {
|
const addEntry = () => {
|
||||||
@ -305,6 +105,7 @@ const addEntry = () => {
|
|||||||
updateContent()
|
updateContent()
|
||||||
newEntry.value = ''
|
newEntry.value = ''
|
||||||
errorMsg.value = ''
|
errorMsg.value = ''
|
||||||
|
warningMsg.value = ''
|
||||||
warningMsg.value = '条目添加成功!'
|
warningMsg.value = '条目添加成功!'
|
||||||
formatXml()
|
formatXml()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -509,53 +310,13 @@ const getFileSize = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<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 {
|
.config-editor {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
max-width: 1400px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-container {
|
.editor-container {
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||||
@ -563,76 +324,7 @@ const getFileSize = () => {
|
|||||||
padding: 24px;
|
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 {
|
.input-section {
|
||||||
flex: 1;
|
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,10 +394,6 @@ const getFileSize = () => {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-section {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-section h3 {
|
.editor-section h3 {
|
||||||
color: #1a237e;
|
color: #1a237e;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@ -755,17 +443,6 @@ const getFileSize = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 */
|
/* 响应式设计 */
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.editor-container {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.config-editor {
|
.config-editor {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
@ -787,13 +464,5 @@ const getFileSize = () => {
|
|||||||
.xml-textarea {
|
.xml-textarea {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xml-stats {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xml-stats span {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user