feat: eslint

This commit is contained in:
pk5ls20
2024-11-25 20:02:50 +08:00
parent 7fba9960bf
commit 4be821137d
13 changed files with 273 additions and 233 deletions

View File

@@ -3,20 +3,15 @@
<router-view /> <router-view />
</div> </div>
<div v-if="show"> <div v-if="show">
<t-sticky-tool <t-sticky-tool shape="round" placement="right-bottom" :offset="[-50, 10]" @click="changeTheme">
shape="round" <t-sticky-item label="浅色" popup="切换浅色模式">
placement="right-bottom" <template #icon><sunny-icon /></template>
:offset="[-50, 10]"
@click="changeTheme"
>
<t-sticky-item label="浅色" popup="切换浅色模式" >
<template #icon><sunny-icon/></template>
</t-sticky-item> </t-sticky-item>
<t-sticky-item label="深色" popup="切换深色模式" > <t-sticky-item label="深色" popup="切换深色模式">
<template #icon><mode-dark-icon/></template> <template #icon><mode-dark-icon /></template>
</t-sticky-item> </t-sticky-item>
<t-sticky-item label="自动" popup="跟随系统" > <t-sticky-item label="自动" popup="跟随系统">
<template #icon><control-platform-icon/></template> <template #icon><control-platform-icon /></template>
</t-sticky-item> </t-sticky-item>
</t-sticky-tool> </t-sticky-tool>
</div> </div>
@@ -40,11 +35,11 @@ enum ThemeMode {
Auto = 'auto', Auto = 'auto',
} }
const themeLabelMap: Record<string, ThemeMode> = { const themeLabelMap: Record<string, ThemeMode> = {
'浅色': ThemeMode.Light, 浅色: ThemeMode.Light,
'深色': ThemeMode.Dark, 深色: ThemeMode.Dark,
'自动': ThemeMode.Auto, 自动: ThemeMode.Auto,
}; };
const show = ref<boolean>(true) const show = ref<boolean>(true);
const createSetThemeAttributeFunction = () => { const createSetThemeAttributeFunction = () => {
let mediaQueryForAutoTheme: MediaQueryList | null = null; let mediaQueryForAutoTheme: MediaQueryList | null = null;
return (mode: ThemeMode | null) => { return (mode: ThemeMode | null) => {
@@ -64,9 +59,9 @@ const createSetThemeAttributeFunction = () => {
}; };
mediaQueryForAutoTheme.addEventListener('change', handleMediaChange); mediaQueryForAutoTheme.addEventListener('change', handleMediaChange);
const event = new Event('change'); const event = new Event('change');
Object.defineProperty(event,'matches', { Object.defineProperty(event, 'matches', {
value: mediaQueryForAutoTheme.matches, value: mediaQueryForAutoTheme.matches,
writable: false writable: false,
}); });
mediaQueryForAutoTheme.dispatchEvent(event); mediaQueryForAutoTheme.dispatchEvent(event);
onBeforeUnmount(() => { onBeforeUnmount(() => {
@@ -107,13 +102,11 @@ const haddingFbars = () => {
}; };
onMounted(() => { onMounted(() => {
initTheme(); initTheme();
haddingFbars() haddingFbars();
window.addEventListener('resize', haddingFbars); window.addEventListener('resize', haddingFbars);
}); });
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', haddingFbars); window.removeEventListener('resize', haddingFbars);
}); });
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -74,7 +74,7 @@ export class QQLoginManager {
} }
return false; return false;
} }
public async checkQQLoginStatusWithQrcode(): Promise<{ qrcodeurl: string, isLogin: string } | undefined> { public async checkQQLoginStatusWithQrcode(): Promise<{ qrcodeurl: string; isLogin: string } | undefined> {
try { try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, { const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, {
method: 'POST', method: 'POST',

View File

@@ -20,7 +20,6 @@ interface MenuItem {
route: string; route: string;
} }
const menuItems = ref<MenuItem[]>([ const menuItems = ref<MenuItem[]>([
{ value: 'item1', icon: 'dashboard', label: '基础信息', route: '/dashboard/basic-info' }, { value: 'item1', icon: 'dashboard', label: '基础信息', route: '/dashboard/basic-info' },
{ value: 'item3', icon: 'wifi-1', label: '网络配置', route: '/dashboard/network-config' }, { value: 'item3', icon: 'wifi-1', label: '网络配置', route: '/dashboard/network-config' },
@@ -28,9 +27,9 @@ const menuItems = ref<MenuItem[]>([
{ value: 'item5', icon: 'system-log', label: '日志查看', route: '/dashboard/log-view' }, { value: 'item5', icon: 'system-log', label: '日志查看', route: '/dashboard/log-view' },
{ value: 'item6', icon: 'info-circle', label: '关于我们', route: '/dashboard/about-us' }, { value: 'item6', icon: 'info-circle', label: '关于我们', route: '/dashboard/about-us' },
]); ]);
const menuRef=ref<any>(null) const menuRef = ref<any>(null);
emitter.on('sendMenu', (event) => { emitter.on('sendMenu', (event) => {
emitter.emit('sendWidth',menuRef.value.offsetWidth); emitter.emit('sendWidth', menuRef.value.offsetWidth);
localStorage.setItem('menuWidth', menuRef.value.offsetWidth); localStorage.setItem('menuWidth', menuRef.value.offsetWidth);
}); });
onMounted(() => { onMounted(() => {
@@ -39,7 +38,6 @@ onMounted(() => {
</script> </script>
<style scoped> <style scoped>
.dashboard-container { .dashboard-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -52,7 +50,6 @@ onMounted(() => {
z-index: 2; z-index: 2;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.content { .content {
padding: 10px; padding: 10px;

View File

@@ -3,22 +3,22 @@
<div class="login-container"> <div class="login-container">
<h2 class="sotheby-font">QQ Login</h2> <h2 class="sotheby-font">QQ Login</h2>
<div class="login-methods"> <div class="login-methods">
<t-tooltip content="快速登录" > <t-tooltip content="快速登录">
<t-button <t-button
id="quick-login" id="quick-login"
class="login-method" class="login-method"
:class="{ active: loginMethod === 'quick' }" :class="{ active: loginMethod === 'quick' }"
@click="loginMethod = 'quick'" @click="loginMethod = 'quick'"
>Quick Login</t-button >Quick Login</t-button
> >
</t-tooltip> </t-tooltip>
<t-tooltip content="二维码登录" > <t-tooltip content="二维码登录">
<t-button <t-button
id="qrcode-login" id="qrcode-login"
class="login-method" class="login-method"
:class="{ active: loginMethod === 'qrcode' }" :class="{ active: loginMethod === 'qrcode' }"
@click="loginMethod = 'qrcode'" @click="loginMethod = 'qrcode'"
>QR Code</t-button >QR Code</t-button
> >
</t-tooltip> </t-tooltip>
</div> </div>
@@ -109,7 +109,7 @@ onMounted(() => {
</script> </script>
<style scoped> <style scoped>
.layout{ .layout {
height: 100vh; height: 100vh;
} }
.login-container { .login-container {

View File

@@ -1,5 +1,5 @@
<template> <template>
<t-card class="layout"> <t-card class="layout">
<div class="login-container"> <div class="login-container">
<h2 class="sotheby-font">WebUi Login</h2> <h2 class="sotheby-font">WebUi Login</h2>
<t-form ref="form" :data="formData" colon :label-width="0" @submit="onSubmit"> <t-form ref="form" :data="formData" colon :label-width="0" @submit="onSubmit">
@@ -96,7 +96,7 @@ const onSubmit = async ({ validateResult }: { validateResult: boolean }) => {
</script> </script>
<style scoped> <style scoped>
.layout{ .layout {
height: 100vh; height: 100vh;
} }
.login-container { .login-container {

View File

@@ -1,10 +1,10 @@
<template> <template>
<t-menu theme="light" default-value="2-1" :collapsed="collapsed" class="sidebar-menu"> <t-menu theme="light" default-value="2-1" :collapsed="collapsed" class="sidebar-menu">
<template #logo> <template #logo>
<div class="logo"> <div class="logo">
<img class="logo-img" :width="collapsed ? 35 : 'auto'" src="@/assets/logo_webui.png" alt="logo" /> <img class="logo-img" :width="collapsed ? 35 : 'auto'" src="@/assets/logo_webui.png" alt="logo" />
<div class="logo-textBox"> <div class="logo-textBox">
<div class="logo-text">{{ collapsed? '' : 'NapCat' }}</div> <div class="logo-text">{{ collapsed ? '' : 'NapCat' }}</div>
</div> </div>
</div> </div>
</template> </template>
@@ -19,7 +19,13 @@
</t-tooltip> </t-tooltip>
</router-link> </router-link>
<template #operations> <template #operations>
<t-button :disabled="disBtn" class="t-demo-collapse-btn" variant="text" shape="square" @click="changeCollapsed"> <t-button
:disabled="disBtn"
class="t-demo-collapse-btn"
variant="text"
shape="square"
@click="changeCollapsed"
>
<template #icon><t-icon :name="iconName" /></template> <template #icon><t-icon :name="iconName" /></template>
</t-button> </t-button>
</template> </template>
@@ -51,9 +57,9 @@ const changeCollapsed = (): void => {
localStorage.setItem('sidebar-collapsed', collapsed.value.toString()); localStorage.setItem('sidebar-collapsed', collapsed.value.toString());
}; };
watch(collapsed, (newValue, oldValue) => { watch(collapsed, (newValue, oldValue) => {
setTimeout(()=>{ setTimeout(() => {
emitter.emit('sendMenu', collapsed.value); emitter.emit('sendMenu', collapsed.value);
},300) }, 300);
}); });
onMounted(() => { onMounted(() => {
const mediaQuery = window.matchMedia('(max-width: 800px)'); const mediaQuery = window.matchMedia('(max-width: 800px)');
@@ -65,9 +71,9 @@ onMounted(() => {
}; };
mediaQuery.addEventListener('change', handleMediaChange); mediaQuery.addEventListener('change', handleMediaChange);
const event = new Event('change'); const event = new Event('change');
Object.defineProperty(event,'matches', { Object.defineProperty(event, 'matches', {
value: mediaQuery.matches, value: mediaQuery.matches,
writable: false writable: false,
}); });
mediaQuery.dispatchEvent(event); mediaQuery.dispatchEvent(event);
return () => { return () => {
@@ -91,17 +97,17 @@ onMounted(() => {
width: 100px; /* 移动端侧边栏宽度 */ width: 100px; /* 移动端侧边栏宽度 */
} }
} }
.logo{ .logo {
display: flex; display: flex;
width: auto; width: auto;
height: 100%; height: 100%;
} }
.logo-img{ .logo-img {
object-fit: contain; object-fit: contain;
margin-top: 8px; margin-top: 8px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.logo-textBox{ .logo-textBox {
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 10px; margin-left: 10px;

View File

@@ -4,11 +4,12 @@
<t-divider align="right"> <t-divider align="right">
<t-button @click="addConfig()"> <t-button @click="addConfig()">
<template #icon><add-icon /></template> <template #icon><add-icon /></template>
添加配置</t-button> 添加配置</t-button
>
</t-divider> </t-divider>
</div> </div>
<div v-if="loadPage" ref="setting" class="setting"> <div v-if="loadPage" ref="setting" class="setting">
<t-tabs ref="tabsRef" :style="{width:tabsWidth+'px'}" default-value="all" @change="selectType"> <t-tabs ref="tabsRef" :style="{ width: tabsWidth + 'px' }" default-value="all" @change="selectType">
<t-tab-panel value="all" label="全部"></t-tab-panel> <t-tab-panel value="all" label="全部"></t-tab-panel>
<t-tab-panel value="httpServers" label="HTTP 服务器"></t-tab-panel> <t-tab-panel value="httpServers" label="HTTP 服务器"></t-tab-panel>
<t-tab-panel value="httpClients" label="HTTP 客户端"></t-tab-panel> <t-tab-panel value="httpClients" label="HTTP 客户端"></t-tab-panel>
@@ -16,69 +17,98 @@
<t-tab-panel value="websocketClients" label="WebSocket 客户端"></t-tab-panel> <t-tab-panel value="websocketClients" label="WebSocket 客户端"></t-tab-panel>
</t-tabs> </t-tabs>
</div> </div>
<div v-if="loadPage" class="card-box" :style="{width:tabsWidth+'px'}"> <div v-if="loadPage" class="card-box" :style="{ width: tabsWidth + 'px' }">
<div class="setting-box" :style="{maxHeight:cardHeight+'px'}" v-if="cardConfig.length>0"> <div class="setting-box" :style="{ maxHeight: cardHeight + 'px' }" v-if="cardConfig.length > 0">
<div v-for="(item,index) in cardConfig" :key="index"> <div v-for="(item, index) in cardConfig" :key="index">
<t-card :title="item.name" :style="{width:cardWidth+'px'}" :header-bordered="true" class="setting-card"> <t-card
:title="item.name"
:style="{ width: cardWidth + 'px' }"
:header-bordered="true"
class="setting-card"
>
<template #actions> <template #actions>
<t-space> <t-space>
<edit2-icon size="20px" @click="editConfig(item)"></edit2-icon> <edit2-icon size="20px" @click="editConfig(item)"></edit2-icon>
<t-popconfirm theme="danger" content="确认删除" @confirm="delConfig(item)"> <t-popconfirm theme="danger" content="确认删除" @confirm="delConfig(item)">
<delete-icon size="20px" ></delete-icon> <delete-icon size="20px"></delete-icon>
</t-popconfirm> </t-popconfirm>
</t-space> </t-space>
</template> </template>
<div class="setting-content"> <div class="setting-content">
<div>类型{{item.type}}</div> <div>类型{{ item.type }}</div>
<div class="setting-address"> <div class="setting-address">
<div v-if="item.host" class="local">地址{{item.host}}</div> <div v-if="item.host" class="local">地址{{ item.host }}</div>
<div v-if="item.url" class="local">地址{{item.url}}</div> <div v-if="item.url" class="local">地址{{ item.url }}</div>
<div class="none-box"></div> <div class="none-box"></div>
<div v-if="item.port" class="port">端口{{ item.port }}</div> <div v-if="item.port" class="port">端口{{ item.port }}</div>
<div v-if="item.heartInterval&&!item.port" class="port">心跳间隔{{ item.heartInterval }}</div> <div v-if="item.heartInterval && !item.port" class="port">
心跳间隔{{ item.heartInterval }}
</div>
</div>
<div v-if="item.heartInterval && item.port" class="port">
心跳间隔{{ item.heartInterval }}
</div> </div>
<div v-if="item.heartInterval&&item.port" class="port">心跳间隔{{ item.heartInterval }}</div>
<div class="setting-address"> <div class="setting-address">
<div class="local">Token{{item.token}}</div> <div class="local">Token{{ item.token }}</div>
<div class="none-box"></div> <div class="none-box"></div>
<div class="port">消息格式{{item.messagePostFormat}}</div> <div class="port">消息格式{{ item.messagePostFormat }}</div>
</div> </div>
<div class="setting-status"> <div class="setting-status">
<div class="status-tag"> <div class="status-tag">
<div >状态</div> <div>状态</div>
<t-tag class="tag-item" :theme="(item.enable ? 'success' : 'danger')"> {{item.enable ? "启用" : "禁用"}}</t-tag> <t-tag class="tag-item" :theme="item.enable ? 'success' : 'danger'">
{{ item.enable ? '启用' : '禁用' }}</t-tag
>
</div> </div>
<div class="none-box"></div> <div class="none-box"></div>
<div class="status-deBug"> <div class="status-deBug">
<div>调试</div> <div>调试</div>
<t-tag class="tag-item" :theme="(item.debug ? 'success' : 'danger')"> {{item.debug ? "开启" : "关闭"}}</t-tag> <t-tag class="tag-item" :theme="item.debug ? 'success' : 'danger'">
{{ item.debug ? '开启' : '关闭' }}</t-tag
>
</div> </div>
</div> </div>
<div class="setting-status"> <div class="setting-status">
<div v-if="item.hasOwnProperty('enableWebsocket')" class="status-tag"> <div v-if="item.hasOwnProperty('enableWebsocket')" class="status-tag">
<div >WS </div> <div>WS </div>
<t-tag class="tag-item" :theme="(item.enableWebsocket ? 'success' : 'danger')"> {{item.enableWebsocket ? "启用" : "禁用"}}</t-tag> <t-tag class="tag-item" :theme="item.enableWebsocket ? 'success' : 'danger'">
{{ item.enableWebsocket ? '启用' : '禁用' }}</t-tag
>
</div> </div>
<div class="none-box"></div> <div class="none-box"></div>
<div v-if="item.hasOwnProperty('enableCors')" class="status-deBug"> <div v-if="item.hasOwnProperty('enableCors')" class="status-deBug">
<div>跨域</div> <div>跨域</div>
<t-tag class="tag-item" :theme="(item.enableCors ? 'success' : 'danger')"> {{item.enableCors ? "开启" : "关闭"}}</t-tag> <t-tag class="tag-item" :theme="item.enableCors ? 'success' : 'danger'">
{{ item.enableCors ? '开启' : '关闭' }}</t-tag
>
</div> </div>
</div> </div>
<div v-if="item.hasOwnProperty('reportSelfMessage')" class="status-deBug" style="margin-top: 2px"> <div
v-if="item.hasOwnProperty('reportSelfMessage')"
class="status-deBug"
style="margin-top: 2px"
>
<div>上报自身消息</div> <div>上报自身消息</div>
<t-tag class="tag-item" :theme="(item.reportSelfMessage ? 'success' : 'danger')"> {{item.reportSelfMessage ? "开启" : "关闭"}}</t-tag> <t-tag class="tag-item" :theme="item.reportSelfMessage ? 'success' : 'danger'">
{{ item.reportSelfMessage ? '开启' : '关闭' }}</t-tag
>
</div> </div>
<div v-if="item.hasOwnProperty('enableForcePushEvent')" class="status-deBug" style="margin-top: 2px"> <div
v-if="item.hasOwnProperty('enableForcePushEvent')"
class="status-deBug"
style="margin-top: 2px"
>
<div>强制推送事件</div> <div>强制推送事件</div>
<t-tag class="tag-item" :theme="(item.enableForcePushEvent ? 'success' : 'danger')"> {{item.enableForcePushEvent ? "开启" : "关闭"}}</t-tag> <t-tag class="tag-item" :theme="item.enableForcePushEvent ? 'success' : 'danger'">
{{ item.enableForcePushEvent ? '开启' : '关闭' }}</t-tag
>
</div> </div>
</div> </div>
</t-card> </t-card>
</div> </div>
<div style="height: 20vh"></div> <div style="height: 20vh"></div>
</div> </div>
<t-card class="card-none" v-else > <t-card class="card-none" v-else>
<div class="card-noneText">暂无网络配置</div> <div class="card-noneText">暂无网络配置</div>
</t-card> </t-card>
</div> </div>
@@ -91,11 +121,21 @@
:on-confirm="saveConfig" :on-confirm="saveConfig"
> >
<div slot="body" class="dialog-body"> <div slot="body" class="dialog-body">
<t-form ref="form" :data="newTab" labelAlign="left" :model="newTab" > <t-form ref="form" :data="newTab" labelAlign="left" :model="newTab">
<t-form-item style="text-align: left" :rules="[{ required: true, message: '请输入名称',trigger: 'blur' }]" label="名称" name="name"> <t-form-item
style="text-align: left"
:rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]"
label="名称"
name="name"
>
<t-input v-model="newTab.name" /> <t-input v-model="newTab.name" />
</t-form-item> </t-form-item>
<t-form-item style="text-align: left" :rules="[{ required: true, message: '请选择类型',trigger: 'change'}]" label="类型" name="type"> <t-form-item
style="text-align: left"
:rules="[{ required: true, message: '请选择类型', trigger: 'change' }]"
label="类型"
name="type"
>
<t-select v-model="newTab.type" @change="onloadDefault"> <t-select v-model="newTab.type" @change="onloadDefault">
<t-option value="httpServers">HTTP 服务器</t-option> <t-option value="httpServers">HTTP 服务器</t-option>
<t-option value="httpClients">HTTP 客户端</t-option> <t-option value="httpClients">HTTP 客户端</t-option>
@@ -104,7 +144,10 @@
</t-select> </t-select>
</t-form-item> </t-form-item>
<div> <div>
<component :is="resolveDynamicComponent(getComponent(newTab.type as ConfigKey))" :config="newTab.data" /> <component
:is="resolveDynamicComponent(getComponent(newTab.type as ConfigKey))"
:config="newTab.data"
/>
</div> </div>
</t-form> </t-form>
</div> </div>
@@ -135,17 +178,17 @@ import WebsocketClientComponent from '@/pages/network/WebsocketClientComponent.v
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import { QQLoginManager } from '@/backend/shell'; import { QQLoginManager } from '@/backend/shell';
const tabsWidth=ref<number>(0) const tabsWidth = ref<number>(0);
const menuWidth=ref<number>(0) const menuWidth = ref<number>(0);
const cardWidth=ref<number>(0) const cardWidth = ref<number>(0);
const cardHeight=ref<number>(0) const cardHeight = ref<number>(0);
const mediumScreen = window.matchMedia('(min-width: 768px) and (max-width: 1024px)'); const mediumScreen = window.matchMedia('(min-width: 768px) and (max-width: 1024px)');
const largeScreen = window.matchMedia('(min-width: 1025px)'); const largeScreen = window.matchMedia('(min-width: 1025px)');
const headerBox=ref<any>(null) const headerBox = ref<any>(null);
const setting=ref<any>(null) const setting = ref<any>(null);
const loadPage=ref<boolean>(false); const loadPage = ref<boolean>(false);
const visibleBody=ref<boolean>(false); const visibleBody = ref<boolean>(false);
const newTab = ref<{ name: string; data:any; type: string }>({ name: '', data:{},type: '' }); const newTab = ref<{ name: string; data: any; type: string }>({ name: '', data: {}, type: '' });
const dialogTitle = ref<string>(''); const dialogTitle = ref<string>('');
type ConfigKey = 'httpServers' | 'httpClients' | 'websocketServers' | 'websocketClients'; type ConfigKey = 'httpServers' | 'httpClients' | 'websocketServers' | 'websocketClients';
@@ -184,20 +227,22 @@ interface NetworkConfigType {
httpServers: any[]; httpServers: any[];
} }
const networkConfig: NetworkConfigType = { const networkConfig: NetworkConfigType = {
"websocketClients": [], websocketClients: [],
"websocketServers": [], websocketServers: [],
"httpClients": [], httpClients: [],
"httpServers": [] httpServers: [],
}; };
//挂载的数据 //挂载的数据
const WebConfg = ref(new Map<string, Array<null>>([ const WebConfg = ref(
["all", []], new Map<string, Array<null>>([
["httpServers", []], ['all', []],
["httpClients", []], ['httpServers', []],
["websocketServers", []], ['httpClients', []],
["websocketClients", []] ['websocketServers', []],
])); ['websocketClients', []],
])
);
interface TypeChType { interface TypeChType {
[key: string]: string; [key: string]: string;
httpServers: string; httpServers: string;
@@ -205,93 +250,91 @@ interface TypeChType {
websocketServers: string; websocketServers: string;
websocketClients: string; websocketClients: string;
} }
const typeCh:TypeChType = { const typeCh: TypeChType = {
"httpServers":"HTTP 服务器" , httpServers: 'HTTP 服务器',
"httpClients":"HTTP 客户端", httpClients: 'HTTP 客户端',
"websocketServers":"WebSocket 服务器", websocketServers: 'WebSocket 服务器',
"websocketClients":"WebSocket 客户端" websocketClients: 'WebSocket 客户端',
}; };
const getKeyByValue=(obj: TypeChType, value: string): string | undefined =>{ const getKeyByValue = (obj: TypeChType, value: string): string | undefined => {
return Object.entries(obj).find(([_, v]) => v === value)?.[0]; return Object.entries(obj).find(([_, v]) => v === value)?.[0];
} };
const cardConfig = ref<any>([]) const cardConfig = ref<any>([]);
const getComponent = (type: ComponentKey) => { const getComponent = (type: ComponentKey) => {
return componentMap[type]; return componentMap[type];
}; };
const addConfig=()=>{ const addConfig = () => {
dialogTitle.value="添加配置" dialogTitle.value = '添加配置';
newTab.value={ name: '', data:{},type: '' }; newTab.value = { name: '', data: {}, type: '' };
operateType.value='add' operateType.value = 'add';
visibleBody.value=true; visibleBody.value = true;
} };
const editConfig = (item:any) => { const editConfig = (item: any) => {
dialogTitle.value="修改配置" dialogTitle.value = '修改配置';
const type = getKeyByValue(typeCh,item.type) const type = getKeyByValue(typeCh, item.type);
if (type){ if (type) {
newTab.value={ name: item.name, data:item,type:type }; newTab.value = { name: item.name, data: item, type: type };
} }
operateType.value='edit' operateType.value = 'edit';
configIndex.value=networkConfig[newTab.value.type].findIndex((obj:any) => obj.name === item.name); configIndex.value = networkConfig[newTab.value.type].findIndex((obj: any) => obj.name === item.name);
visibleBody.value=true; visibleBody.value = true;
} };
const delConfig = (item:any) => { const delConfig = (item: any) => {
const type = getKeyByValue(typeCh,item.type) const type = getKeyByValue(typeCh, item.type);
if (type){ if (type) {
newTab.value={ name: item.name, data:item,type:type }; newTab.value = { name: item.name, data: item, type: type };
} }
configIndex.value=configIndex.value=networkConfig[newTab.value.type].findIndex((obj:any) => obj.name === item.name); configIndex.value = configIndex.value = networkConfig[newTab.value.type].findIndex(
operateType.value='delete' (obj: any) => obj.name === item.name
saveConfig() );
} operateType.value = 'delete';
saveConfig();
};
const selectType = (key: string) => { const selectType = (key: string) => {
cardConfig.value = WebConfg.value.get(key) cardConfig.value = WebConfg.value.get(key);
} };
const onloadDefault = (key: ConfigKey) => { const onloadDefault = (key: ConfigKey) => {
console.log(key) console.log(key);
newTab.value.data=structuredClone(defaultConfigs[key]) newTab.value.data = structuredClone(defaultConfigs[key]);
} };
//检测重名 //检测重名
const checkName=(name:string) =>{ const checkName = (name: string) => {
const allConfigs = WebConfg.value.get('all')?.findIndex((obj:any) => obj.name === name); const allConfigs = WebConfg.value.get('all')?.findIndex((obj: any) => obj.name === name);
if (newTab.value.name===''|| newTab.value.type===''){ if (newTab.value.name === '' || newTab.value.type === '') {
MessagePlugin.error('请填写完整信息'); MessagePlugin.error('请填写完整信息');
return false; return false;
} } else if (allConfigs === -1 || newTab.value.data.name === name) {
else if(allConfigs===-1||newTab.value.data.name===name){
return true; return true;
} } else {
else {
MessagePlugin.error('名称已存在'); MessagePlugin.error('名称已存在');
return false; return false;
} }
} };
//保存 //保存
const saveConfig = async () => { const saveConfig = async () => {
if(operateType.value=='add'){ if (operateType.value == 'add') {
if(!checkName(newTab.value.name))return; if (!checkName(newTab.value.name)) return;
newTab.value.data.name=newTab.value.name newTab.value.data.name = newTab.value.name;
networkConfig[newTab.value.type].push(newTab.value.data); networkConfig[newTab.value.type].push(newTab.value.data);
} } else if (operateType.value == 'edit') {
else if(operateType.value=='edit'){ if (!checkName(newTab.value.name)) return;
if(!checkName(newTab.value.name))return; newTab.value.data.name = newTab.value.name;
newTab.value.data.name=newTab.value.name networkConfig[newTab.value.type][configIndex.value] = newTab.value.data;
networkConfig[newTab.value.type][configIndex.value]=newTab.value.data; } else if (operateType.value == 'delete') {
} networkConfig[newTab.value.type].splice(configIndex.value, 1);
else if(operateType.value=='delete'){
networkConfig[newTab.value.type].splice(configIndex.value,1)
} }
const userConfig = await getOB11Config(); const userConfig = await getOB11Config();
if (!userConfig) return; if (!userConfig) return;
userConfig.network = networkConfig; userConfig.network = networkConfig;
const success = await setOB11Config(userConfig); const success = await setOB11Config(userConfig);
if (success) { if (success) {
operateType.value=''; operateType.value = '';
configIndex.value=0 configIndex.value = 0;
MessagePlugin.success('配置保存成功'); MessagePlugin.success('配置保存成功');
await loadConfig() await loadConfig();
visibleBody.value=false; visibleBody.value = false;
} else { } else {
MessagePlugin.error('配置保存失败'); MessagePlugin.error('配置保存失败');
} }
@@ -317,65 +360,64 @@ const setOB11Config = async (config: OneBotConfig): Promise<boolean> => {
}; };
//获取卡片数据 //获取卡片数据
const getAllData = (data: NetworkConfig) => { const getAllData = (data: NetworkConfig) => {
cardConfig.value=[] cardConfig.value = [];
WebConfg.value.set("all", []) WebConfg.value.set('all', []);
Object.entries(data).forEach(([key, configs]) => { Object.entries(data).forEach(([key, configs]) => {
if (key in defaultConfigs) { if (key in defaultConfigs) {
networkConfig[key]=[...configs] networkConfig[key] = [...configs];
const newConfigsArray = configs.map((config:any) => ({ const newConfigsArray = configs.map((config: any) => ({
...config, ...config,
type:typeCh[key] type: typeCh[key],
})); }));
WebConfg.value.set(key,newConfigsArray); WebConfg.value.set(key, newConfigsArray);
const allConfigs = WebConfg.value.get('all'); const allConfigs = WebConfg.value.get('all');
if (allConfigs) { if (allConfigs) {
const newAllConfigs = [...allConfigs,...newConfigsArray]; const newAllConfigs = [...allConfigs, ...newConfigsArray];
WebConfg.value.set('all', newAllConfigs); WebConfg.value.set('all', newAllConfigs);
} }
cardConfig.value=WebConfg.value.get("all") cardConfig.value = WebConfg.value.get('all');
} }
}); });
} };
const loadConfig = async () => { const loadConfig = async () => {
try { try {
const userConfig = await getOB11Config(); const userConfig = await getOB11Config();
if (!userConfig) return; if (!userConfig) return;
const mergedConfig = mergeOneBotConfigs(userConfig); const mergedConfig = mergeOneBotConfigs(userConfig);
getAllData(mergedConfig.network) getAllData(mergedConfig.network);
} catch (error) { } catch (error) {
console.error('Error loading config:', error); console.error('Error loading config:', error);
} }
}; };
const handleResize = () => { const handleResize = () => {
tabsWidth.value = window.innerWidth- 40 -menuWidth.value tabsWidth.value = window.innerWidth - 40 - menuWidth.value;
if (mediumScreen.matches) { if (mediumScreen.matches) {
cardWidth.value = (tabsWidth.value-20)/2; cardWidth.value = (tabsWidth.value - 20) / 2;
} } else if (largeScreen.matches) {
else if(largeScreen.matches) { cardWidth.value = (tabsWidth.value - 40) / 3;
cardWidth.value = (tabsWidth.value-40)/3; } else {
}else {
cardWidth.value = tabsWidth.value; cardWidth.value = tabsWidth.value;
} }
loadPage.value=true loadPage.value = true;
setTimeout(()=>{ setTimeout(() => {
cardHeight.value=window.innerHeight-headerBox.value.offsetHeight-setting.value.offsetHeight-20; cardHeight.value = window.innerHeight - headerBox.value.offsetHeight - setting.value.offsetHeight - 20;
},300) }, 300);
}; };
emitter.on('sendWidth', (width) => { emitter.on('sendWidth', (width) => {
if (typeof width === 'number' &&!isNaN(width)) { if (typeof width === 'number' && !isNaN(width)) {
menuWidth.value = width; menuWidth.value = width;
handleResize() handleResize();
} }
}); });
onMounted(() => { onMounted(() => {
loadConfig() loadConfig();
const cachedWidth = localStorage.getItem('menuWidth'); const cachedWidth = localStorage.getItem('menuWidth');
if (cachedWidth) { if (cachedWidth) {
menuWidth.value = parseInt(cachedWidth); menuWidth.value = parseInt(cachedWidth);
setTimeout(()=>{ setTimeout(() => {
handleResize() handleResize();
},300) }, 300);
} }
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
}); });
@@ -384,7 +426,6 @@ onUnmounted(() => {
}); });
</script> </script>
<style scoped> <style scoped>
.title { .title {
padding: 20px 20px 0 20px; padding: 20px 20px 0 20px;
@@ -405,40 +446,40 @@ onUnmounted(() => {
.setting-card { .setting-card {
width: 100%; width: 100%;
} }
.setting-content{ .setting-content {
width: 100%; width: 100%;
text-align: left; text-align: left;
} }
.setting-address{ .setting-address {
display: flex; display: flex;
margin-top: 2px; margin-top: 2px;
} }
.local{ .local {
flex: 5.5; flex: 5.5;
margin-bottom: 1px; margin-bottom: 1px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.none-box{ .none-box {
flex: 0.5; flex: 0.5;
} }
.port{ .port {
flex: 4; flex: 4;
margin-top: 1px; margin-top: 1px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.setting-status{ .setting-status {
display: flex; display: flex;
margin-top: 2px; margin-top: 2px;
} }
.status-deBug{ .status-deBug {
display: flex; display: flex;
flex: 4; flex: 4;
} }
.status-tag{ .status-tag {
display: flex; display: flex;
flex: 5.5; flex: 5.5;
} }
@@ -453,7 +494,7 @@ onUnmounted(() => {
.setting-box { .setting-box {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.setting-address{ .setting-address {
display: block; display: block;
} }
} }
@@ -468,7 +509,7 @@ onUnmounted(() => {
.card-noneText { .card-noneText {
font-size: 16px; font-size: 16px;
} }
.dialog-body{ .dialog-body {
max-height: 60vh; max-height: 60vh;
overflow-y: auto; overflow-y: auto;
} }

View File

@@ -89,16 +89,15 @@ onMounted(() => {
const handleMediaChange = (e: MediaQueryListEvent) => { const handleMediaChange = (e: MediaQueryListEvent) => {
if (e.matches) { if (e.matches) {
labelAlign.value = 'top'; labelAlign.value = 'top';
} } else {
else {
labelAlign.value = 'left'; labelAlign.value = 'left';
} }
}; };
mediaQuery.addEventListener('change', handleMediaChange); mediaQuery.addEventListener('change', handleMediaChange);
const event = new Event('change'); const event = new Event('change');
Object.defineProperty(event,'matches', { Object.defineProperty(event, 'matches', {
value: mediaQuery.matches, value: mediaQuery.matches,
writable: false writable: false,
}); });
mediaQuery.dispatchEvent(event); mediaQuery.dispatchEvent(event);
return () => { return () => {
@@ -108,10 +107,10 @@ onMounted(() => {
</script> </script>
<style scoped> <style scoped>
.title{ .title {
padding: 20px 20px 0 20px; padding: 20px 20px 0 20px;
} }
.card{ .card {
margin: 0 20px; margin: 0 20px;
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
@@ -140,5 +139,4 @@ onMounted(() => {
justify-content: center; justify-content: center;
margin-top: 20px; margin-top: 20px;
} }
</style> </style>

View File

@@ -4,7 +4,7 @@
<t-form-item label="启用"> <t-form-item label="启用">
<t-checkbox v-model="config.enable" /> <t-checkbox v-model="config.enable" />
</t-form-item> </t-form-item>
<t-form-item label="URL" > <t-form-item label="URL">
<t-input v-model="config.url" /> <t-input v-model="config.url" />
</t-form-item> </t-form-item>
<t-form-item label="消息格式"> <t-form-item label="消息格式">
@@ -33,16 +33,17 @@ const props = defineProps<{
const messageFormatOptions = ref([ const messageFormatOptions = ref([
{ label: 'Array', value: 'array' }, { label: 'Array', value: 'array' },
{ label: 'String', value: 'string' } { label: 'String', value: 'string' },
]); ]);
watch(() => props.config.messagePostFormat, (newValue) => { watch(
if (newValue !== 'array' && newValue !== 'string') { () => props.config.messagePostFormat,
props.config.messagePostFormat = 'array'; (newValue) => {
if (newValue !== 'array' && newValue !== 'string') {
props.config.messagePostFormat = 'array';
}
} }
}); );
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<t-form labelAlign="left"> <t-form labelAlign="left">
<t-form-item label="启用"> <t-form-item label="启用">
<t-checkbox v-model="config.enable" /> <t-checkbox v-model="config.enable" />
</t-form-item> </t-form-item>
<t-form-item label="端口"> <t-form-item label="端口">
@@ -39,16 +39,17 @@ const props = defineProps<{
const messageFormatOptions = ref([ const messageFormatOptions = ref([
{ label: 'Array', value: 'array' }, { label: 'Array', value: 'array' },
{ label: 'String', value: 'string' } { label: 'String', value: 'string' },
]); ]);
watch(() => props.config.messagePostFormat, (newValue) => { watch(
if (newValue !== 'array' && newValue !== 'string') { () => props.config.messagePostFormat,
props.config.messagePostFormat = 'array'; (newValue) => {
if (newValue !== 'array' && newValue !== 'string') {
props.config.messagePostFormat = 'array';
}
} }
}); );
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -36,16 +36,17 @@ const props = defineProps<{
const messageFormatOptions = ref([ const messageFormatOptions = ref([
{ label: 'Array', value: 'array' }, { label: 'Array', value: 'array' },
{ label: 'String', value: 'string' } { label: 'String', value: 'string' },
]); ]);
watch(() => props.config.messagePostFormat, (newValue) => { watch(
if (newValue !== 'array' && newValue !== 'string') { () => props.config.messagePostFormat,
props.config.messagePostFormat = 'array'; (newValue) => {
if (newValue !== 'array' && newValue !== 'string') {
props.config.messagePostFormat = 'array';
}
} }
}); );
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -42,15 +42,17 @@ const props = defineProps<{
const messageFormatOptions = ref([ const messageFormatOptions = ref([
{ label: 'Array', value: 'array' }, { label: 'Array', value: 'array' },
{ label: 'String', value: 'string' } { label: 'String', value: 'string' },
]); ]);
watch(() => props.config.messagePostFormat, (newValue) => { watch(
if (newValue !== 'array' && newValue !== 'string') { () => props.config.messagePostFormat,
props.config.messagePostFormat = 'array'; (newValue) => {
if (newValue !== 'array' && newValue !== 'string') {
props.config.messagePostFormat = 'array';
}
} }
}); );
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -1,3 +1,3 @@
import mitt from "mitt" import mitt from 'mitt';
const emitter = mitt(); const emitter = mitt();
export default emitter; export default emitter;