Files
AstrBot/dashboard/src/stores/common.js
T
2025-04-02 21:06:59 +08:00

151 lines
4.8 KiB
JavaScript

import { defineStore } from 'pinia';
import axios from 'axios';
export const useCommonStore = defineStore({
id: 'common',
state: () => ({
// @ts-ignore
eventSource: null,
log_cache: [],
sse_connected: false,
log_cache_max_len: 1000,
startTime: -1,
tutorial_map: {
"qq_official_webhook": "https://astrbot.app/deploy/platform/qqofficial/webhook.html",
"qq_official": "https://astrbot.app/deploy/platform/qqofficial/websockets.html",
"aiocqhttp": "https://astrbot.app/deploy/platform/aiocqhttp/napcat.html",
"wecom": "https://astrbot.app/deploy/platform/wecom.html",
"gewechat": "https://astrbot.app/deploy/platform/gewechat.html",
"lark": "https://astrbot.app/deploy/platform/lark.html",
"telegram": "https://astrbot.app/deploy/platform/telegram.html",
"dingtalk": "https: //astrbot.app/deploy/platform/dingtalk.html",
},
pluginMarketData: [],
}),
actions: {
createEventSource() {
if (this.eventSource) {
return
}
const controller = new AbortController();
const { signal } = controller;
const headers = {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + localStorage.getItem('token')
};
fetch('/api/live-log', {
method: 'GET',
headers,
signal,
cache: 'no-cache',
}).then(response => {
if (!response.ok) {
throw new Error(`SSE connection failed: ${response.status}`);
}
console.log('SSE stream opened');
this.sse_connected = true;
const reader = response.body.getReader();
const decoder = new TextDecoder();
const processStream = ({ done, value }) => {
if (done) {
console.log('SSE stream closed');
setTimeout(() => {
this.eventSource = null;
this.createEventSource();
}, 2000);
return;
}
const text = decoder.decode(value);
const lines = text.split('\n');
lines.forEach(line => {
if (line.startsWith('data:')) {
const data = line.substring(5).trim();
// {"type":"log","data":"[2021-08-01 00:00:00] INFO: Hello, world!"}
let data_json = JSON.parse(data)
if (data_json.type === 'log') {
let log = data_json.data
this.log_cache.push(log);
if (this.log_cache.length > this.log_cache_max_len) {
this.log_cache.shift();
}
}
}
});
return reader.read().then(processStream);
};
reader.read().then(processStream);
}).catch(error => {
console.error('SSE error:', error);
// Attempt to reconnect after a delay
this.log_cache.push('SSE Connection failed, retrying in 5 seconds...');
setTimeout(() => {
this.eventSource = null;
this.createEventSource();
}, 1000);
});
// Store controller to allow closing the connection
this.eventSource = controller;
},
closeEventSourcet() {
if (this.eventSource) {
this.eventSource.abort();
this.eventSource = null;
}
},
getLogCache() {
return this.log_cache
},
getStartTime() {
if (this.startTime !== -1) {
return this.startTime
}
axios.get('/api/stat/start-time').then((res) => {
this.startTime = res.data.data.start_time
})
},
getTutorialLink(platform) {
return this.tutorial_map[platform]
},
async getPluginCollections(force = false) {
// 获取插件市场数据
if (!force && this.pluginMarketData.length > 0) {
return Promise.resolve(this.pluginMarketData);
}
return axios.get('/api/plugin/market_list')
.then((res) => {
let data = []
for (let key in res.data.data) {
data.push({
"name": key,
"desc": res.data.data[key].desc,
"author": res.data.data[key].author,
"repo": res.data.data[key].repo,
"installed": false,
"version": res.data.data[key]?.version ? res.data.data[key].version : "未知",
"social_link": res.data.data[key]?.social_link,
"tags": res.data.data[key]?.tags ? res.data.data[key].tags : [],
"logo": res.data.data[key]?.logo ? res.data.data[key].logo : "",
"pinned": res.data.data[key]?.pinned ? res.data.data[key].pinned : false,
})
}
this.pluginMarketData = data;
return data;
})
.catch((err) => {
this.toast("获取插件市场数据失败: " + err, "error");
return Promise.reject(err);
});
},
}
});