新增LiveFollow插件页面

This commit is contained in:
userA
2023-10-12 01:54:38 +08:00
parent 0c7c7c9ecd
commit fa5bf0aca1
15 changed files with 343 additions and 140 deletions

View File

@@ -151,12 +151,17 @@ public class InitPluginRegister {
throw PluginDependOnException.MissingFatherPlugin(needPlugin,pluginName);
}
}
if (initMachine.init()) {
registerPluginTable.put(pluginName,initMachine);
initMachine.afterInit();
return true;
}else{
return false;
try {
if (initMachine.init()) {
registerPluginTable.put(pluginName,initMachine);
initMachine.afterInit();
return true;
}else{
return false;
}
}catch (Exception e){
ChopperLogFactory.getLogger(LoggerType.System)
.error(String.format("❌ %s plugin start failed ! error:%s", pluginName,e.getMessage()));
}
}else{
return false;

View File

@@ -120,7 +120,7 @@ public class HotController {
@RequestParam(required = false) Integer focusBarrage,
@RequestParam(required = false) Long checkTime){
hotModuleService.liverFollowApi().changeSetting(
Map.of("focusList",focusLive,
Map.of("focusLive",focusLive,
"focusBarrage",focusBarrage,
"checkTime",checkTime
)
@@ -130,6 +130,14 @@ public class HotController {
);
}
@CheckPlugin(needPlugin = {PluginName.HOT_LIVER_FOLLOWER})
@GetMapping("/liveFollow/setting")
public Result changeLiverFollowSetting(){
return Result.success(
Map.of("setting",hotModuleService.liverFollowApi().getSetting())
);
}
@CheckPlugin(needPlugin = {PluginName.HOT_RECOMMENDATION_PLUGIN})
@GetMapping("/hotRecommendation/list")
public Result getFollowDogs(){

View File

@@ -52,10 +52,10 @@ public class LiverFollowApi {
}
public void changeSetting(Map<String,Object> settings){
ConfigFileUtil.changeSetting(settings,HotModuleConfig.getFullFilePath(),"liverFollower");
ConfigFileUtil.changeSetting(settings,HotModuleConfig.getFullFilePath(),"LiverFollower");
}
public Object getSetting(){
return ConfigFileUtil.getSetting(HotModuleConfig.getFullFilePath(),"liverFollower");
return ConfigFileUtil.getSetting(HotModuleConfig.getFullFilePath(),"LiverFollower");
}
}

View File

@@ -61,7 +61,7 @@ public class LiverFollower extends SpringBootPlugin {
FileCache fileCache = plugin.getFileCache(HotModuleConfig.getFullFilePath());
focusLive = (Integer)fileCache.get("LiverFollower", "focusLive")==1;
//focusBarrage = (Integer)fileCache.get("LiverFollower", "focusBarrage")==1;
checkTime = (Long)fileCache.get("LiverFollower", "checkTime");
checkTime = Integer.toUnsignedLong((Integer) fileCache.get("LiverFollower", "checkTime"));
focusRecord = (Integer)fileCache.get("LiverFollower", "focusRecord")==1;
checkTime = (Integer)fileCache.get("LiverFollower", "checkTime");
focusLivers = service.getFocusLivers();

View File

@@ -1,14 +1,14 @@
{
"updateTime":"2023-09-11 12:56:40",
"data":{
"LiverFollower":{
"checkTime":60000,
"focusLive":1,
"focusRecord":1,
"focusBarrage":1
},
"HotGuard":{
"GuardNum":10
},
"LiverFollower":{
"checkTime":120000,
"focusRecord":1,
"focusLive":1,
"focusBarrage":1
}
}
},
"updateTime":"2023-10-12 01:51:20"
}

View File

@@ -24,12 +24,12 @@
"HotRecommendation":true,
"BarrageScoreCurve":true,
"FileCacheManager":true,
"LiverFollower":false,
"LiverFollower":true,
"TaskMonitor":true,
"HotConfig":true,
"TaskCenter":true,
"CreeperConfig":true
}
},
"updateTime":"2023-10-11 18:15:50"
"updateTime":"2023-10-12 01:50:20"
}

View File

@@ -30,7 +30,14 @@ export function unFollow(platform:string,liver:string){
});
}
export function changeSetting(checkTime:number,focusLive:string,focusBarrage:string){
export function getSetting(){
return request({
url: '/hot/liveFollow/setting',
method: 'get',
})
}
export function changeSetting(checkTime:number,focusLive:number,focusBarrage:number){
return request({
url: '/hot/liveFollow/changeSetting',
method: 'get',

View File

@@ -1,5 +1,7 @@
import axios from "axios";
import {useSnackbarStore} from "@/stores/snackbarStore";
const snackbarStore = useSnackbarStore();
const request = axios.create({
baseURL: "/appApi",
timeout: 100000,
@@ -16,8 +18,13 @@ request.interceptors.request.use(config => {
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
if(response.status!=200){
snackbarStore.showSuccessMessage("服务异常!")
}
let res = response.data;
if(res.code === 114514){
snackbarStore.showErrorMessage("该插件没有启动,请先启动插件!")
}
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res

View File

@@ -56,6 +56,11 @@ onMounted(async()=>{
})
})
setInterval(()=>{
getGuards().then(res=>{
hotGuardStore.guards = res.data['list']
})
},30000)
</script>

View File

@@ -1,12 +1,12 @@
<script setup lang="ts">
import {allCreeper} from "@/api/creeperApi";
import {useCreeperStore} from "@/views/app/creeper/creeperStore";
import {followList} from "@/api/hot/liveFollowApi";
import {useLiveFollowStore} from "@/views/app/hot/live_follow/liveFollowStore";
import LiveFollowCard from "@/views/app/hot/live_follow/component/LiveFollowCard.vue";
const creeperStore = useCreeperStore();
const liveFollowStore = useLiveFollowStore();
onMounted(async()=>{
await allCreeper().then(res=>{
creeperStore.creeperList = res.data['list']
await followList().then(res=>{
liveFollowStore.liveFollowList = res.data['list']
})
})
@@ -14,7 +14,7 @@ onMounted(async()=>{
<template>
<div class="app-container">
<LiveFollowCard :creepers="creeperStore.creeperList"></LiveFollowCard>
<LiveFollowCard :liveFollows="liveFollowStore.liveFollowList"></LiveFollowCard>
</div>
</template>

View File

@@ -0,0 +1,113 @@
<template>
<v-row justify="center">
<v-dialog
v-model="liveFollowStore.addDialog"
persistent
width="1024"
>
<v-card>
<v-card-title>
<span class="text-h5">User Profile</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal first name*"
required
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal middle name"
hint="example of helper text only on focus"
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
label="Email*"
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
label="Password*"
type="password"
required
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
>
<v-select
:items="['0-17', '18-29', '30-54', '54+']"
label="Age*"
required
></v-select>
</v-col>
<v-col
cols="12"
sm="6"
>
<v-autocomplete
:items="['Skiing', 'Ice hockey', 'Soccer', 'Basketball', 'Hockey', 'Reading', 'Writing', 'Coding', 'Basejump']"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue-darken-1"
variant="text"
@click="liveFollowStore.addDialog = false"
>
Close
</v-btn>
<v-btn
color="blue-darken-1"
variant="text"
@click="liveFollowStore.addDialog = false"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script setup lang="ts">
import {useLiveFollowStore} from "@/views/app/hot/live_follow/liveFollowStore";
const liveFollowStore = useLiveFollowStore();
</script>
<style scoped>
</style>

View File

@@ -1,17 +1,14 @@
<script setup lang="ts">
import CopyLabel from "@/components/common/CopyLabel.vue";
import {Creeper} from "../creeperTypes"
import {useLiveFollowStore} from "@/views/app/hot/live_follow/liveFollowStore";
import LiveFollowSetting from "@/views/app/hot/live_follow/component/LiveFollowSetting.vue";
import AddFormDiaLog from "@/views/app/hot/live_follow/component/AddFormDiaLog.vue";
import {FocusLiver} from "@/views/app/hot/live_follow/focusLiverTypes";
const liveFollowStore = useLiveFollowStore();
const props = defineProps<{
creepers: Creeper[];
liveFollows: FocusLiver[];
}>();
const dialog = ref(false)
const notifications = false
const sound = true
const widgets = false
const loading = ref(true);
const headers = [
@@ -20,6 +17,7 @@ const headers = [
{ text: "主播昵称", value: "author" },
{ text: "房间号", value: "group" },
{ text: "标签", value: "priority" },
{ text: "操作", value: "option" },
];
const open = (item) => {};
@@ -30,39 +28,15 @@ onMounted(() => {
}, 1000);
});
const searchKey = ref("")
const keys = ["group","name"]
const search = computed(()=> {
for (let i = 0; i < keys.length; i++) {
let key = keys[i]
if (searchKey.value.startsWith(key + ":")) {
let param = searchKey.value.split(key + ":")
if (param.length >= 2) {
return props.creepers.filter((creeper) => {
return creeper[key].includes(param[1].toLowerCase())
})
}
}
}
return props.creepers
})
const priorityColor = (priority:Number)=>{
if(priority<3){
return "green"
}else if(priority<5){
return "secondary"
}else if(priority<8){
return "orange"
}else{
return "red"
}
}
</script>
<template>
<!-- loading spinner -->
<LiveFollowSetting></LiveFollowSetting>
<AddFormDiaLog></AddFormDiaLog>
<div
v-if="loading"
class="h-full d-flex flex-grow-1 align-center justify-center"
@@ -74,77 +48,23 @@ const priorityColor = (priority:Number)=>{
<v-card-title class="font-weight-bold">
<span>Live Follow</span>
<v-spacer></v-spacer>
<v-btn
style="margin-right: 20px"
color="success"
@click="liveFollowStore.addDialog = true"
>
<v-icon start icon="mdi mdi-plus-box"></v-icon>
关注主播
</v-btn>
<v-btn
color="primary"
dark
v-bind="props"
@click=""
@click="liveFollowStore.dialog = true"
>
<v-icon start icon="mdi mdi-cog"></v-icon>
Setting
</v-btn>
<v-dialog
v-model="dialog"
fullscreen
:scrim="false"
transition="dialog-bottom-transition"
>
<v-card>
<v-toolbar
dark
color="primary"
>
<v-btn
icon
dark
@click="dialog = false"
>
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title>Settings</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn
variant="text"
@click="dialog = false"
>
Save
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-list
lines="two"
subheader
>
<v-list-subheader>User Controls</v-list-subheader>
<v-list-item title="Content filtering" subtitle="Set the content filtering level to restrict apps that can be downloaded"></v-list-item>
<v-list-item title="Password" subtitle="Require password for purchase or use password to restrict purchase"></v-list-item>
</v-list>
<v-divider></v-divider>
<v-list
lines="two"
subheader
>
<v-list-subheader>General</v-list-subheader>
<v-list-item title="Notifications" subtitle="Notify me about updates to apps or games that I downloaded">
<template v-slot:prepend>
<v-checkbox v-model="notifications"></v-checkbox>
</template>
</v-list-item>
<v-list-item title="Sound" subtitle="Auto-update apps at any time. Data charges may apply">
<template v-slot:prepend>
<v-checkbox v-model="sound"></v-checkbox>
</template>
</v-list-item>
<v-list-item title="Auto-add widgets" subtitle="Automatically add home screen widgets">
<template v-slot:prepend>
<v-checkbox v-model="widgets"></v-checkbox>
</template>
</v-list-item>
</v-list>
</v-card>
</v-dialog>
</v-card-title>
<v-table class="pa-3">
<thead>
@@ -155,24 +75,26 @@ const priorityColor = (priority:Number)=>{
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in search" :key="item.name">
<tr v-for="(item,index) in liveFollows" :key="item.id">
<td class="font-weight-bold">
<copy-label :text="`# ${index}`" />
</td>
<td>
<copy-label :text="item.name" />
<copy-label :text="item.platform" />
</td>
<td>{{ item.description }}</td>
<td>{{ item.author }}</td>
<td>{{ item.liver }}</td>
<td>{{ item.roomId }}</td>
<td>
<v-chip
class="ma-2"
color="cyan"
label>
<v-icon start icon="mdi mdi-earth-box"></v-icon>
{{ item.group }}
{{ item.tag }}
</v-chip>
</td>
<td>
<v-btn density="comfortable" color="red" icon="mdi mdi-trash-can"></v-btn>
</td>
</tr>
</tbody>
</v-table>
@@ -182,10 +104,7 @@ const priorityColor = (priority:Number)=>{
</template>
<style lang="scss" scoped>
.dialog-bottom-transition-enter-active,
.dialog-bottom-transition-leave-active {
transition: transform .2s ease-in-out;
}
.v-table {
table {
padding: 4px;

View File

@@ -1,13 +1,130 @@
<template>
<v-dialog
v-model="liveFollowStore.dialog"
fullscreen
:scrim="false"
transition="dialog-bottom-transition"
>
<v-card>
<v-toolbar
dark
color="primary"
>
<v-btn
icon
dark
@click="liveFollowStore.dialog = false"
>
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title>Plugin Setting</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn
variant="text"
@click="save()"
>
Save
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-list
lines="two"
subheader
>
<v-list-item title="focusLive" subtitle="是否自动爬取关注主播的直播"></v-list-item>
<v-list-item title="focusBarrage" subtitle="是否自动爬取关注主播的直播弹幕(该版本此配置项不生效)"></v-list-item>
<v-list-item title="checkTime" subtitle="多少秒检测一次主播开播情况(单位:毫秒)"></v-list-item>
</v-list>
<v-divider></v-divider>
<v-list
lines="two"
subheader
>
<v-text-field
label="checkTime"
v-model="setting.checkTime"
:rules="timeRules"
hide-details="auto"
></v-text-field>
<v-switch class="flex-col"
style=""
size="small"
v-model="setting.focusLive"
color="green"
label="focusLive"
inset
></v-switch>
<v-switch class="flex-col"
style=""
size="small"
disabled
v-model="setting.focusBarrage"
color="green"
label="focusBarrage"
inset
></v-switch>
</v-list>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: "LiveFollowSetting"
<script setup lang="ts">
import {useLiveFollowStore} from "@/views/app/hot/live_follow/liveFollowStore";
import {changeSetting, getSetting} from "@/api/hot/liveFollowApi";
import {useSnackbarStore} from "@/stores/snackbarStore";
type Setting = {
focusLive: boolean,
focusBarrage: boolean,
checkTime: number,
}
const snackbarStore = useSnackbarStore()
const liveFollowStore = useLiveFollowStore();
const setting = ref<Setting>({
focusLive: false,
focusBarrage: false,
checkTime:0
})
onMounted(()=>{
getSetting().then(res=>{
liveFollowStore.setting = res.data['setting']
setting.value = res.data['setting']
setting.value.focusBarrage = res.data['setting']?.focusBarrage===1
setting.value.focusLive = res.data['setting']?.focusLive===1
})
})
const timeRules = [
(v)=> !!v || "时间必须存在",
(v)=> v > 0 || "时间必须大于0",
(v)=> v >= 1000 || "时间必须大于1s",
]
const save = async () =>{
await changeSetting(setting.value.checkTime,
setting.value.focusLive?1:0,
setting.value.focusBarrage?1:0
).then(res=>{
if(res?.data?.success){
liveFollowStore.dialog = false
snackbarStore.showSuccessMessage("更新设置成功")
}else{
snackbarStore.showSuccessMessage("更新设置失败")
}
})
}
</script>
<style scoped>
.dialog-bottom-transition-enter-active,
.dialog-bottom-transition-leave-active {
transition: transform .2s ease-in-out;
}
</style>

View File

@@ -1,4 +1,5 @@
export interface FocusLiver{
id:number;
liver: string;
roomId: string;
platform: string;

View File

@@ -0,0 +1,21 @@
import { defineStore } from "pinia";
import {FocusLiver} from "@/views/app/hot/live_follow/focusLiverTypes"
export const useLiveFollowStore = defineStore({
id: "hotRecommend",
state:()=>({
dialog: ref(false),
addDialog: ref(false),
setting:ref({}),
liveFollowList: ref<FocusLiver[]>([]),
}),
getters:{
},
actions:{
}
})