新增功能:合并多开器
This commit is contained in:
parent
942d93417b
commit
dc32d7e53e
11 changed files with 456 additions and 34 deletions
|
@ -1,34 +1,238 @@
|
|||
<script setup>
|
||||
import { useConfigStore } from '@/stores/config.js'
|
||||
import { form_item_label_style } from '@/styles/styles.js'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { Add, Pencil, Play, Folder, TrashOutline, Archive } from '@vicons/ionicons5'
|
||||
|
||||
const conf = useConfigStore().config
|
||||
function webview() {
|
||||
pywebview.api.run('webview', 'mower-ng')
|
||||
const notification = useNotification()
|
||||
|
||||
const config_store = useConfigStore()
|
||||
const conf = config_store.config
|
||||
const instance_name_input_refs = ref([])
|
||||
const update_instance_name_index = ref(null)
|
||||
const migrate_options = [
|
||||
{
|
||||
label: '迁移单开配置',
|
||||
key: 'default'
|
||||
},
|
||||
{
|
||||
label: '迁移多开配置',
|
||||
key: 'instances'
|
||||
}
|
||||
]
|
||||
const check_all = computed(
|
||||
() => conf.instances.length > 0 && conf.instances.every((item) => item.checked)
|
||||
)
|
||||
const check_part = computed(() => !check_all.value && conf.instances.some((item) => item.checked))
|
||||
function click_check_all(ckecked) {
|
||||
if (ckecked) {
|
||||
conf.instances.forEach((item) => {
|
||||
item.checked = true
|
||||
})
|
||||
} else {
|
||||
conf.instances.forEach((item) => {
|
||||
item.checked = false
|
||||
})
|
||||
}
|
||||
}
|
||||
function setInstanceNameInputRef(el, index) {
|
||||
if (el) {
|
||||
instance_name_input_refs.value[index] = el
|
||||
}
|
||||
}
|
||||
async function add_instance() {
|
||||
const instance_path = await pywebview.api.add_instance()
|
||||
conf.instances.push({
|
||||
checked: false,
|
||||
name: '新实例',
|
||||
path: instance_path
|
||||
})
|
||||
}
|
||||
async function delete_instance(index, path) {
|
||||
await pywebview.api.delete_instance(path)
|
||||
conf.instances.splice(index, 1)
|
||||
}
|
||||
|
||||
function manager() {
|
||||
pywebview.api.run('manager', 'mower-ng')
|
||||
function start_update_instance_name(index) {
|
||||
update_instance_name_index.value = index
|
||||
nextTick(() => {
|
||||
instance_name_input_refs.value[index]?.focus()
|
||||
})
|
||||
}
|
||||
function end_update_instance_name() {
|
||||
update_instance_name_index.value = null
|
||||
}
|
||||
function open_folder(path) {
|
||||
pywebview.api.run('open_folder', null, { folder_path: path })
|
||||
}
|
||||
function start_instance(instance) {
|
||||
pywebview.api.run('webview', 'mower-ng', {
|
||||
instance_path: instance.path
|
||||
})
|
||||
}
|
||||
function start_checked_instance() {
|
||||
pywebview.api.start_checked_instance()
|
||||
}
|
||||
async function handle_migrate(key) {
|
||||
if (key == 'default') {
|
||||
const response = await pywebview.api.migrate_default_instance()
|
||||
console.log(response)
|
||||
if (response.status) {
|
||||
conf.instances.push({
|
||||
checked: false,
|
||||
name: '默认实例',
|
||||
path: response.data
|
||||
})
|
||||
notification['success']({
|
||||
content: '信息',
|
||||
meta: response.message,
|
||||
duration: 3000
|
||||
})
|
||||
} else {
|
||||
notification['error']({
|
||||
content: '错误',
|
||||
meta: response.message,
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const response = await pywebview.api.migrate_instances_config()
|
||||
console.log('多开配置内容:', response)
|
||||
if (response.data) {
|
||||
await config_store.load_config()
|
||||
conf.instances = [...config_store.config.instances]
|
||||
}
|
||||
if (response.status) {
|
||||
notification['info']({
|
||||
title: '信息',
|
||||
content: response.message,
|
||||
duration: 3000
|
||||
})
|
||||
} else {
|
||||
notification['error']({
|
||||
title: '错误',
|
||||
content: response.message,
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-flex vertical style="gap: 16px; height: 100%; padding: 16px; box-sizing: border-box">
|
||||
<n-form label-placement="left" :show-feedback="false" label-width="auto" label-align="left">
|
||||
<n-form-item label="启动程序" :label-style="form_item_label_style">
|
||||
<n-space size="large">
|
||||
<n-button class="launch-btn" type="primary" secondary size="large" @click="webview"> 单开运行 </n-button>
|
||||
<n-button class="launch-btn" type="primary" secondary size="large" @click="manager"> 多开器 </n-button>
|
||||
<n-space class="top" justify="space-between">
|
||||
<n-space>
|
||||
<n-button class="launch-btn" type="primary" secondary @click="add_instance">
|
||||
<template #icon>
|
||||
<n-icon :component="Add"></n-icon>
|
||||
</template>
|
||||
添加实例
|
||||
</n-button>
|
||||
<n-button
|
||||
class="launch-btn"
|
||||
type="primary"
|
||||
secondary
|
||||
@click="start_checked_instance"
|
||||
:disabled="!check_all && !check_part"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon :component="Play"></n-icon>
|
||||
</template>
|
||||
启动所选实例
|
||||
</n-button>
|
||||
<n-dropdown trigger="click" :options="migrate_options" @select="handle_migrate">
|
||||
<n-button class="launch-btn" type="primary" secondary>
|
||||
<template #icon>
|
||||
<n-icon :component="Archive"></n-icon>
|
||||
</template>
|
||||
迁移配置
|
||||
</n-button>
|
||||
</n-dropdown>
|
||||
</n-space>
|
||||
|
||||
<div class="is_show_log_switch">
|
||||
<n-switch v-model:value="conf.is_show_log" />
|
||||
显示日志
|
||||
</div>
|
||||
</n-space>
|
||||
<n-list class="instance-list" bordered>
|
||||
<n-list-item>
|
||||
<template #prefix>
|
||||
<n-checkbox
|
||||
v-model:checked="check_all"
|
||||
:indeterminate="check_part"
|
||||
style="white-space: nowrap"
|
||||
@update:checked="click_check_all"
|
||||
>全选</n-checkbox
|
||||
>
|
||||
</template>
|
||||
</n-list-item>
|
||||
<n-list-item v-for="(item, index) in conf.instances" :key="index">
|
||||
<template #prefix>
|
||||
<n-checkbox v-model:checked="item.checked"></n-checkbox>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-space v-if="update_instance_name_index != index">
|
||||
<n-text>{{ item.name }}</n-text>
|
||||
<n-button size="tiny" @click="start_update_instance_name(index)">
|
||||
<template #icon>
|
||||
<n-icon :component="Pencil"></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button @click="open_folder(item.path)" size="tiny">
|
||||
<template #icon>
|
||||
<n-icon :component="Folder"></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<log-component />
|
||||
<n-input
|
||||
v-else
|
||||
:ref="(el) => setInstanceNameInputRef(el, index)"
|
||||
v-model:value="item.name"
|
||||
@blur="end_update_instance_name"
|
||||
></n-input>
|
||||
</n-space>
|
||||
<template #suffix>
|
||||
<n-space :wrap="false">
|
||||
<n-button type="primary" size="small" @click="start_instance(item)">
|
||||
<template #icon>
|
||||
<n-icon :component="Play"></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="delete_instance(index, item.path)">
|
||||
<template #trigger>
|
||||
<n-button type="error" ghost size="small">
|
||||
<template #icon>
|
||||
<n-icon :component="TrashOutline"></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</template>
|
||||
删除操作将导致实例配置丢失,请谨慎操作。
|
||||
</n-popconfirm>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
<log-component v-show="conf.is_show_log" class="log" />
|
||||
</n-flex>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.launch-btn {
|
||||
width: 120px;
|
||||
height: 48px;
|
||||
height: 38px;
|
||||
}
|
||||
</style>
|
||||
.instance-list {
|
||||
overflow: auto;
|
||||
}
|
||||
.log {
|
||||
min-height: 40vh;
|
||||
max-height: 40vh;
|
||||
margin-top: auto;
|
||||
}
|
||||
.top {
|
||||
align-items: center;
|
||||
}
|
||||
.is_show_log_switch {
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useConfigStore = defineStore('config', () => {
|
||||
class Instance {
|
||||
constructor(instance) {
|
||||
this.checked = instance.checked
|
||||
this.name = instance.name
|
||||
this.path = instance.path
|
||||
}
|
||||
}
|
||||
|
||||
class Config {
|
||||
constructor(conf) {
|
||||
// 整体 Total
|
||||
|
@ -9,21 +17,25 @@ export const useConfigStore = defineStore('config', () => {
|
|||
// 更新代码 UpdatePart
|
||||
this.branch = conf.branch
|
||||
this.mirror = conf.mirror
|
||||
// 启动程序 LaunchPart
|
||||
this.instances = []
|
||||
this.is_show_log = conf.is_show_log
|
||||
Object.assign(this, conf)
|
||||
}
|
||||
}
|
||||
|
||||
const config = ref({})
|
||||
const config = reactive({})
|
||||
|
||||
async function load_config() {
|
||||
const conf = await pywebview.api.load_config()
|
||||
config.value = new Config(conf)
|
||||
console.log('config.value', config.value)
|
||||
Object.assign(config, new Config(conf))
|
||||
console.log('响应式配置已更新', config)
|
||||
}
|
||||
|
||||
watch(
|
||||
config,
|
||||
() => {
|
||||
pywebview.api.save_config(config.value)
|
||||
pywebview.api.save_config(config)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue