feat 临时
This commit is contained in:
@@ -1,21 +1,200 @@
|
||||
<script setup>
|
||||
import HelloWorld from './components/HelloWorld.vue'</script>
|
||||
import { ref, watch } from 'vue'
|
||||
import Sidebar from './components/Sidebar.vue'
|
||||
import { GetNovelContent, WriteNovelContent } from '../wailsjs/go/backend/App'
|
||||
|
||||
const activeButton = ref('')
|
||||
const content = ref('请选择要查看的小说')
|
||||
const currentTitle = ref('小说内容')
|
||||
const viewMode = ref('original')
|
||||
const currentFilename = ref('')
|
||||
const isLoading = ref(false)
|
||||
|
||||
// 监听 viewMode 变化
|
||||
watch(viewMode, (newMode) => {
|
||||
if (newMode === 'imitation') {
|
||||
content.value = currentFilename.value + ' 的仿写内容'
|
||||
} else if (newMode === 'original' && currentFilename.value) {
|
||||
// 切换回原文模式时,重新加载原文
|
||||
handleMenuClick({ id: activeButton.value, filename: currentFilename.value })
|
||||
}
|
||||
})
|
||||
|
||||
async function handleMenuClick(menuData) {
|
||||
if (menuData && menuData.id) {
|
||||
activeButton.value = menuData.id
|
||||
viewMode.value = 'original'
|
||||
|
||||
// 检查是否是小说文件
|
||||
if (menuData.id.startsWith('novel') && menuData.filename) {
|
||||
currentFilename.value = menuData.filename
|
||||
currentTitle.value = `小说内容 - ${menuData.filename}`
|
||||
content.value = '加载中...'
|
||||
|
||||
try {
|
||||
const novelContent = await GetNovelContent(menuData.filename)
|
||||
content.value = novelContent
|
||||
} catch (error) {
|
||||
console.error('Error loading novel content:', error)
|
||||
content.value = '加载小说内容失败'
|
||||
}
|
||||
} else {
|
||||
currentTitle.value = '小说内容'
|
||||
content.value = '请选择要查看的小说'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleImitation() {
|
||||
if (currentFilename.value) {
|
||||
isLoading.value = true
|
||||
content.value = '正在生成仿写内容...'
|
||||
|
||||
try {
|
||||
const imitationContent = await WriteNovelContent(currentFilename.value)
|
||||
content.value = imitationContent
|
||||
} catch (error) {
|
||||
console.error('Error generating imitation content:', error)
|
||||
content.value = '生成仿写内容失败'
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
} else {
|
||||
content.value = '请先选择要仿写的小说'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img id="logo" alt="Wails logo" src="./assets/images/logo-universal.png"/>
|
||||
<HelloWorld/>
|
||||
<div class="container">
|
||||
<Sidebar
|
||||
v-model:activeButton="activeButton"
|
||||
@menu-click="handleMenuClick"
|
||||
/>
|
||||
<div class="content">
|
||||
<div class="content-header">
|
||||
<h3>{{ currentTitle }}</h3>
|
||||
<div class="header-buttons" v-if="activeButton">
|
||||
<el-button
|
||||
:type="viewMode === 'original' ? 'primary' : 'default'"
|
||||
@click="viewMode = 'original'"
|
||||
>
|
||||
原文
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="viewMode === 'imitation' ? 'primary' : 'default'"
|
||||
@click="viewMode = 'imitation'"
|
||||
>
|
||||
仿文
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<div v-if="viewMode === 'original'">
|
||||
{{ content }}
|
||||
</div>
|
||||
<div v-else-if="viewMode === 'imitation'" class="imitation-container">
|
||||
<div v-if="!isLoading && (content === '请选择要查看的小说' || content === '正在生成仿写内容...' || content === currentFilename + ' 的仿写内容')" class="imitation-button-container">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
class="imitation-button"
|
||||
@click="handleImitation"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
仿写
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-else class="imitation-content">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#logo {
|
||||
display: block;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
margin: auto;
|
||||
padding: 10% 0 0;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-origin: content-box;
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #1b2636;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content-header h3 {
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.content-body {
|
||||
flex: 1;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
color: #ecf0f1;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.imitation-container {
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.imitation-button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.imitation-button {
|
||||
padding: 15px 30px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.imitation-content {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<script setup>
|
||||
import {reactive} from 'vue'
|
||||
import {Greet} from '../../wailsjs/go/backend/App'
|
||||
|
||||
const data = reactive({
|
||||
name: "",
|
||||
resultText: "Please enter your name below 👇",
|
||||
})
|
||||
|
||||
function greet() {
|
||||
Greet(data.name).then(result => {
|
||||
data.resultText = result
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main>
|
||||
<div id="result" class="result">{{ data.resultText }}</div>
|
||||
<div id="input" class="input-box">
|
||||
<input id="name" v-model="data.name" autocomplete="off" class="input" type="text"/>
|
||||
<button class="btn" @click="greet">Greet</button>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.result {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin: 1.5rem auto;
|
||||
}
|
||||
|
||||
.input-box .btn {
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
margin: 0 0 0 20px;
|
||||
padding: 0 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-box .btn:hover {
|
||||
background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.input-box .input {
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
background-color: rgba(240, 240, 240, 1);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.input-box .input:hover {
|
||||
border: none;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.input-box .input:focus {
|
||||
border: none;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
</style>
|
||||
114
frontend/src/components/Sidebar.vue
Normal file
114
frontend/src/components/Sidebar.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Document } from '@element-plus/icons-vue'
|
||||
import { GetNovelList } from '../../wailsjs/go/backend/App'
|
||||
|
||||
const props = defineProps({
|
||||
activeButton: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:activeButton', 'menu-click'])
|
||||
|
||||
const novels = ref([])
|
||||
|
||||
function handleNovelClick(novelId, novelLabel) {
|
||||
emit('update:activeButton', novelId)
|
||||
emit('menu-click', { id: novelId, filename: novelLabel })
|
||||
}
|
||||
|
||||
async function loadNovelList() {
|
||||
try {
|
||||
const novelList = await GetNovelList()
|
||||
novels.value = novelList.map((novel, index) => ({
|
||||
id: `novel${index + 1}`,
|
||||
label: novel
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Error loading novel list:', error)
|
||||
novels.value = []
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 组件挂载时加载小说列表
|
||||
loadNovelList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<h2>小说列表</h2>
|
||||
<div class="novel-list">
|
||||
<div
|
||||
v-for="novel in novels"
|
||||
:key="novel.id"
|
||||
class="novel-item"
|
||||
:class="{ active: activeButton === novel.id }"
|
||||
@click="handleNovelClick(novel.id, novel.label)"
|
||||
>
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ novel.label }}</span>
|
||||
</div>
|
||||
<div v-if="novels.length === 0" class="empty-state">
|
||||
暂无小说文件
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.sidebar {
|
||||
width: 400px;
|
||||
background-color: #2c3e50;
|
||||
padding: 20px 0;
|
||||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.novel-list {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.novel-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 15px;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 5px;
|
||||
color: #ecf0f1;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.novel-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.novel-item.active {
|
||||
background-color: #3498db;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.novel-item .el-icon {
|
||||
margin-right: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #95a5a6;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,12 @@
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue'
|
||||
import './style.css';
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
const app = createApp(App)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
app.use(ElementPlus).mount('#app')
|
||||
|
||||
Reference in New Issue
Block a user