mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2025-06-05 19:36:43 +08:00
finish first admin frontend
This commit is contained in:
parent
96a49fc78c
commit
82a13ceb66
@ -3,7 +3,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"homepage": "bison",
|
"homepage": "bison",
|
||||||
"proxy": "http://localhost:8080",
|
"proxy": "http://127.0.0.1:8080",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.6.4",
|
"@ant-design/icons": "^4.6.4",
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
|
@ -31,3 +31,8 @@ export async function delSubscribe(groupNumber: string, platformName: string, ta
|
|||||||
const res = await axios.delete(`${baseUrl}subs`, {params: {groupNumber, platformName, target}});
|
const res = await axios.delete(`${baseUrl}subs`, {params: {groupNumber, platformName, target}});
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateSubscribe(groupNumber: string, req: SubscribeConfig) {
|
||||||
|
return axios.patch(`${baseUrl}subs`, req, {params: {groupNumber}})
|
||||||
|
.then(res => res.data);
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Form, Input, Modal, Select, Tag } from 'antd';
|
import {Form, Input, Modal, Select, Tag} from 'antd';
|
||||||
import React, { useContext, useState } from "react";
|
import React, {useContext, useEffect, useState} from "react";
|
||||||
import { addSubscribe, getTargetName } from 'src/api/config';
|
import {addSubscribe, getTargetName, updateSubscribe} from 'src/api/config';
|
||||||
import { InputTag } from 'src/component/inputTag';
|
import {InputTag} from 'src/component/inputTag';
|
||||||
import { GlobalConfContext } from "src/utils/context";
|
import {GlobalConfContext} from "src/utils/context";
|
||||||
import { CategoryConfig } from 'src/utils/type';
|
import {CategoryConfig, SubscribeConfig} from 'src/utils/type';
|
||||||
|
|
||||||
interface InputTagCustomProp {
|
interface InputTagCustomProp {
|
||||||
value?: Array<string>,
|
value?: Array<string>,
|
||||||
@ -18,6 +18,11 @@ function InputTagCustom(prop: InputTagCustomProp) {
|
|||||||
prop.onChange(newVal);
|
prop.onChange(newVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
if (prop.value) {
|
||||||
|
setValue(prop.value);
|
||||||
|
}
|
||||||
|
}, [prop.value])
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
@ -38,14 +43,18 @@ interface AddModalProp {
|
|||||||
groupNumber: string,
|
groupNumber: string,
|
||||||
setShowModal: (s: boolean) => void,
|
setShowModal: (s: boolean) => void,
|
||||||
refresh: () => void
|
refresh: () => void
|
||||||
|
initVal?: SubscribeConfig
|
||||||
}
|
}
|
||||||
export function AddModal(prop: AddModalProp) {
|
export function AddModal({
|
||||||
|
showModal, groupNumber, setShowModal, refresh, initVal
|
||||||
|
}: AddModalProp) {
|
||||||
const [ confirmLoading, setConfirmLoading ] = useState<boolean>(false);
|
const [ confirmLoading, setConfirmLoading ] = useState<boolean>(false);
|
||||||
const { platformConf } = useContext(GlobalConfContext);
|
const { platformConf } = useContext(GlobalConfContext);
|
||||||
const [ hasTarget, setHasTarget ] = useState(false);
|
const [ hasTarget, setHasTarget ] = useState(false);
|
||||||
const [ categories, setCategories ] = useState({} as CategoryConfig);
|
const [ categories, setCategories ] = useState({} as CategoryConfig);
|
||||||
const [ enabledTag, setEnableTag ] = useState(false);
|
const [ enabledTag, setEnableTag ] = useState(false);
|
||||||
const [ form ] = Form.useForm();
|
const [ form ] = Form.useForm();
|
||||||
|
const [ inited, setInited ] = useState(false);
|
||||||
const changePlatformSelect = (platform: string) => {
|
const changePlatformSelect = (platform: string) => {
|
||||||
setHasTarget(_ => platformConf[platform].hasTarget);
|
setHasTarget(_ => platformConf[platform].hasTarget);
|
||||||
setCategories(_ => platformConf[platform].categories);
|
setCategories(_ => platformConf[platform].categories);
|
||||||
@ -74,23 +83,42 @@ export function AddModal(prop: AddModalProp) {
|
|||||||
if (newVal.target === '') {
|
if (newVal.target === '') {
|
||||||
newVal.target = 'default'
|
newVal.target = 'default'
|
||||||
}
|
}
|
||||||
addSubscribe(prop.groupNumber, newVal)
|
if (initVal) { // patch
|
||||||
.then(() => {
|
updateSubscribe(groupNumber, newVal)
|
||||||
setConfirmLoading(false);
|
.then(() => {
|
||||||
prop.setShowModal(false);
|
setConfirmLoading(false);
|
||||||
prop.refresh();
|
setShowModal(false);
|
||||||
});
|
form.resetFields();
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addSubscribe(groupNumber, newVal)
|
||||||
|
.then(() => {
|
||||||
|
setConfirmLoading(false);
|
||||||
|
setShowModal(false);
|
||||||
|
form.resetFields();
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const handleModleFinish = () => {
|
const handleModleFinish = () => {
|
||||||
form.submit();
|
form.submit();
|
||||||
setConfirmLoading(() => true);
|
setConfirmLoading(() => true);
|
||||||
}
|
}
|
||||||
|
useEffect(() => {
|
||||||
return <Modal title="添加订阅" visible={prop.showModal}
|
if (initVal && !inited) {
|
||||||
confirmLoading={confirmLoading} onCancel={() => prop.setShowModal(false)}
|
const platformName = initVal.platformName;
|
||||||
|
setHasTarget(platformConf[platformName].hasTarget);
|
||||||
|
setCategories(platformConf[platformName].categories);
|
||||||
|
setEnableTag(platformConf[platformName].enabledTag);
|
||||||
|
setInited(true)
|
||||||
|
form.setFieldsValue(initVal)
|
||||||
|
}
|
||||||
|
}, [initVal, form, platformConf, inited])
|
||||||
|
return <Modal title="添加订阅" visible={showModal}
|
||||||
|
confirmLoading={confirmLoading} onCancel={() => setShowModal(false)}
|
||||||
onOk={handleModleFinish}>
|
onOk={handleModleFinish}>
|
||||||
<Form form={form} labelCol={{ span: 6 }} name="b" onFinish={handleSubmit}
|
<Form form={form} labelCol={{ span: 6 }} name="b" onFinish={handleSubmit} >
|
||||||
initialValues={{tags: [], cats: []}}>
|
|
||||||
<Form.Item label="平台" name="platformName" rules={[]}>
|
<Form.Item label="平台" name="platformName" rules={[]}>
|
||||||
<Select style={{ width: '80%' }} onChange={changePlatformSelect}>
|
<Select style={{ width: '80%' }} onChange={changePlatformSelect}>
|
||||||
{Object.keys(platformConf).map(platformName =>
|
{Object.keys(platformConf).map(platformName =>
|
@ -18,6 +18,11 @@ export function InputTag(prop: InputTagProp) {
|
|||||||
const [ editInputValue, setEditInputValue ] = useState('');
|
const [ editInputValue, setEditInputValue ] = useState('');
|
||||||
const inputRef = useRef(null as any);
|
const inputRef = useRef(null as any);
|
||||||
const editInputRef = useRef(null as any);
|
const editInputRef = useRef(null as any);
|
||||||
|
useEffect(() => {
|
||||||
|
if (prop.value) {
|
||||||
|
setValue(prop.value);
|
||||||
|
}
|
||||||
|
}, [prop.value])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inputVisible) {
|
if (inputVisible) {
|
||||||
inputRef.current.focus()
|
inputRef.current.focus()
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import {CopyOutlined, DeleteOutlined} from '@ant-design/icons';
|
import {CopyOutlined, DeleteOutlined, EditOutlined} from '@ant-design/icons';
|
||||||
import {Card, Col, Form, message, Popconfirm, Select, Tag, Tooltip} from 'antd';
|
import {Card, Col, Form, message, Popconfirm, Select, Tag, Tooltip} from 'antd';
|
||||||
import Modal from 'antd/lib/modal/Modal';
|
import Modal from 'antd/lib/modal/Modal';
|
||||||
import React, {useContext, useState} from "react";
|
import React, {useContext, useState} from "react";
|
||||||
import {addSubscribe, delSubscribe} from 'src/api/config';
|
import {addSubscribe, delSubscribe} from 'src/api/config';
|
||||||
import {GlobalConfContext} from "src/utils/context";
|
import {GlobalConfContext} from "src/utils/context";
|
||||||
import {PlatformConfig, SubscribeConfig, SubscribeResp} from 'src/utils/type';
|
import {PlatformConfig, SubscribeConfig, SubscribeResp} from 'src/utils/type';
|
||||||
|
import {AddModal} from './addSubsModal';
|
||||||
|
|
||||||
interface CopyModalProp {
|
interface CopyModalProp {
|
||||||
setShowModal: (modalShow: boolean) => void
|
setShowModal: (modalShow: boolean) => void
|
||||||
@ -30,6 +31,7 @@ function CopyModal({setShowModal,config,
|
|||||||
setConfirmLoading(true)
|
setConfirmLoading(true)
|
||||||
postReqs(selectedGroups, config).then(() => {
|
postReqs(selectedGroups, config).then(() => {
|
||||||
setConfirmLoading(false)
|
setConfirmLoading(false)
|
||||||
|
setShowModal(false)
|
||||||
return reload()
|
return reload()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -57,6 +59,7 @@ interface SubscribeCardProp {
|
|||||||
export function SubscribeCard({groupNumber, config, reload, groupSubscribes}: SubscribeCardProp) {
|
export function SubscribeCard({groupNumber, config, reload, groupSubscribes}: SubscribeCardProp) {
|
||||||
const globalConf = useContext(GlobalConfContext);
|
const globalConf = useContext(GlobalConfContext);
|
||||||
const [showModal, setShowModal] = useState(false)
|
const [showModal, setShowModal] = useState(false)
|
||||||
|
const [showEditModal, setShowEditModal] = useState(false)
|
||||||
const platformConf = globalConf.platformConf[config.platformName] as PlatformConfig;
|
const platformConf = globalConf.platformConf[config.platformName] as PlatformConfig;
|
||||||
const handleDelete = (groupNumber: string, platformName: string, target: string) => () => {
|
const handleDelete = (groupNumber: string, platformName: string, target: string) => () => {
|
||||||
delSubscribe(groupNumber, platformName, target).then(() => {
|
delSubscribe(groupNumber, platformName, target).then(() => {
|
||||||
@ -67,13 +70,16 @@ export function SubscribeCard({groupNumber, config, reload, groupSubscribes}: Su
|
|||||||
<Col span={6} key={`${config.platformName}-${config.target}`}>
|
<Col span={6} key={`${config.platformName}-${config.target}`}>
|
||||||
<Card title={`${platformConf.name} - ${config.targetName}`}
|
<Card title={`${platformConf.name} - ${config.targetName}`}
|
||||||
actions={[
|
actions={[
|
||||||
|
<Tooltip title="编辑">
|
||||||
|
<EditOutlined onClick={()=>{setShowEditModal(state => !state)}}/>
|
||||||
|
</Tooltip>,
|
||||||
|
<Tooltip title="添加到其他群">
|
||||||
|
<CopyOutlined onClick={()=>{setShowModal(state => !state)}}/>
|
||||||
|
</Tooltip>,
|
||||||
<Popconfirm title={`确定要删除 ${platformConf.name} - ${config.targetName}`}
|
<Popconfirm title={`确定要删除 ${platformConf.name} - ${config.targetName}`}
|
||||||
onConfirm={handleDelete(groupNumber, config.platformName, config.target || 'default')}>
|
onConfirm={handleDelete(groupNumber, config.platformName, config.target || 'default')}>
|
||||||
<Tooltip title="删除" ><DeleteOutlined /></Tooltip>
|
<Tooltip title="删除" ><DeleteOutlined /></Tooltip>
|
||||||
</Popconfirm>,
|
</Popconfirm>,
|
||||||
<Tooltip title="添加到其他群">
|
|
||||||
<CopyOutlined onClick={()=>{setShowModal(state => !state)}}/>
|
|
||||||
</Tooltip>
|
|
||||||
]}>
|
]}>
|
||||||
<Form labelCol={{ span: 6 }}>
|
<Form labelCol={{ span: 6 }}>
|
||||||
<Form.Item label="订阅类型">
|
<Form.Item label="订阅类型">
|
||||||
@ -89,6 +95,8 @@ export function SubscribeCard({groupNumber, config, reload, groupSubscribes}: Su
|
|||||||
</Card>
|
</Card>
|
||||||
<CopyModal setShowModal={setShowModal} reload={reload} currentGroupNumber={groupNumber}
|
<CopyModal setShowModal={setShowModal} reload={reload} currentGroupNumber={groupNumber}
|
||||||
showModal={showModal} config={config} groups={groupSubscribes}/>
|
showModal={showModal} config={config} groups={groupSubscribes}/>
|
||||||
|
<AddModal showModal={showEditModal} setShowModal={setShowEditModal}
|
||||||
|
groupNumber={groupNumber} refresh={reload} initVal={config}/>
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import React, {ReactElement, useEffect, useState} from "react";
|
|||||||
import {getSubscribe} from 'src/api/config';
|
import {getSubscribe} from 'src/api/config';
|
||||||
import {SubscribeCard} from 'src/component/subscribeCard';
|
import {SubscribeCard} from 'src/component/subscribeCard';
|
||||||
import {SubscribeResp} from 'src/utils/type';
|
import {SubscribeResp} from 'src/utils/type';
|
||||||
import {AddModal} from './AddSubsModal';
|
import {AddModal} from 'src/component/addSubsModal';
|
||||||
|
|
||||||
interface ConfigPageProp {
|
interface ConfigPageProp {
|
||||||
tab: string
|
tab: string
|
||||||
@ -34,11 +34,11 @@ export function ConfigPage(prop: ConfigPageProp) {
|
|||||||
for (let key of Object.keys(configData)) {
|
for (let key of Object.keys(configData)) {
|
||||||
let value = configData[key];
|
let value = configData[key];
|
||||||
groups.push(
|
groups.push(
|
||||||
<Collapse.Panel header={
|
<Collapse.Panel key={key} header={
|
||||||
<span>{`${key} - ${value.name}`}<Button style={{float: "right"}} onClick={clickNew(key)}>添加</Button></span>
|
<span>{`${key} - ${value.name}`}<Button style={{float: "right"}} onClick={clickNew(key)}>添加</Button></span>
|
||||||
} key={key}>
|
}>
|
||||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }} align="middle">
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }} align="middle">
|
||||||
{value.subscribes.map((subs) => <SubscribeCard
|
{value.subscribes.map((subs, idx) => <SubscribeCard key={idx}
|
||||||
groupNumber={key} config={subs} groupSubscribes={configData} reload={loadData}
|
groupNumber={key} config={subs} groupSubscribes={configData} reload={loadData}
|
||||||
/>)}
|
/>)}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -18,7 +18,7 @@ import functools
|
|||||||
|
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
|
||||||
from .api import del_group_sub, test, get_global_conf, auth, get_subs_info, get_target_name, add_group_sub
|
from .api import del_group_sub, test, get_global_conf, auth, get_subs_info, get_target_name, add_group_sub, update_group_sub
|
||||||
from .token_manager import token_manager as tm
|
from .token_manager import token_manager as tm
|
||||||
from .jwt import load_jwt
|
from .jwt import load_jwt
|
||||||
from ..plugin_config import plugin_config
|
from ..plugin_config import plugin_config
|
||||||
@ -72,7 +72,7 @@ def register_router_fastapi(driver: Driver, socketio):
|
|||||||
platformName: str
|
platformName: str
|
||||||
target: str
|
target: str
|
||||||
targetName: str
|
targetName: str
|
||||||
cats: list[str]
|
cats: list[int]
|
||||||
tags: list[str]
|
tags: list[str]
|
||||||
|
|
||||||
app = driver.server_app
|
app = driver.server_app
|
||||||
@ -91,7 +91,10 @@ def register_router_fastapi(driver: Driver, socketio):
|
|||||||
async def _add_group_subs(groupNumber: str, req: AddSubscribeReq):
|
async def _add_group_subs(groupNumber: str, req: AddSubscribeReq):
|
||||||
return await add_group_sub(group_number=groupNumber, platform_name=req.platformName,
|
return await add_group_sub(group_number=groupNumber, platform_name=req.platformName,
|
||||||
target=req.target, target_name=req.targetName, cats=req.cats, tags=req.tags)
|
target=req.target, target_name=req.targetName, cats=req.cats, tags=req.tags)
|
||||||
|
@app.patch(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
|
||||||
|
async def _update_group_subs(groupNumber: str, req: AddSubscribeReq):
|
||||||
|
return await update_group_sub(group_number=groupNumber, platform_name=req.platformName,
|
||||||
|
target=req.target, target_name=req.targetName, cats=req.cats, tags=req.tags)
|
||||||
@app.delete(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
|
@app.delete(SUBSCRIBE_URL, dependencies=[Depends(check_group_permission)])
|
||||||
async def _del_group_subs(groupNumber: str, target: str, platformName: str):
|
async def _del_group_subs(groupNumber: str, target: str, platformName: str):
|
||||||
return await del_group_sub(groupNumber, platformName, target)
|
return await del_group_sub(groupNumber, platformName, target)
|
||||||
|
@ -100,3 +100,15 @@ async def del_group_sub(group_number: str, platform_name: str, target: str):
|
|||||||
except (NoSuchUserException, NoSuchSubscribeException):
|
except (NoSuchUserException, NoSuchSubscribeException):
|
||||||
return { 'status': 400, 'msg': '删除错误' }
|
return { 'status': 400, 'msg': '删除错误' }
|
||||||
return { 'status': 200, 'msg': '' }
|
return { 'status': 200, 'msg': '' }
|
||||||
|
|
||||||
|
|
||||||
|
async def update_group_sub(group_number: str, platform_name: str, target: str,
|
||||||
|
target_name: str, cats: list[str], tags: list[str]):
|
||||||
|
config = Config()
|
||||||
|
try:
|
||||||
|
config.update_subscribe(int(group_number), 'group',
|
||||||
|
target, target_name, platform_name, cats, tags)
|
||||||
|
except (NoSuchUserException, NoSuchSubscribeException):
|
||||||
|
return { 'status': 400, 'msg': '更新错误' }
|
||||||
|
return { 'status': 200, 'msg': '' }
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ from typing import DefaultDict, Mapping
|
|||||||
import nonebot
|
import nonebot
|
||||||
from tinydb import Query, TinyDB
|
from tinydb import Query, TinyDB
|
||||||
|
|
||||||
|
from .platform import platform_manager
|
||||||
from .plugin_config import plugin_config
|
from .plugin_config import plugin_config
|
||||||
from .types import Target, User
|
from .types import Target, User
|
||||||
from .utils import Singleton
|
from .utils import Singleton
|
||||||
from .platform import platform_manager
|
|
||||||
|
|
||||||
supported_target_type = platform_manager.keys()
|
supported_target_type = platform_manager.keys()
|
||||||
|
|
||||||
@ -86,6 +86,25 @@ class Config(metaclass=Singleton):
|
|||||||
return
|
return
|
||||||
raise NoSuchSubscribeException()
|
raise NoSuchSubscribeException()
|
||||||
|
|
||||||
|
def update_subscribe(self, user, user_type, target, target_name, target_type, cats, tags):
|
||||||
|
user_query = Query()
|
||||||
|
query = (user_query.user == user) & (user_query.user_type == user_type)
|
||||||
|
if (user_data := self.user_target.get(query)):
|
||||||
|
# update
|
||||||
|
subs: list = user_data.get('subs', [])
|
||||||
|
find_flag = False
|
||||||
|
for item in subs:
|
||||||
|
if item['target'] == target and item['target_type'] == target_type:
|
||||||
|
item['target_name'], item['cats'], item['tags'] = \
|
||||||
|
target_name, cats, tags
|
||||||
|
find_flag = True
|
||||||
|
break
|
||||||
|
if not find_flag:
|
||||||
|
raise NoSuchSubscribeException()
|
||||||
|
self.user_target.update({"subs": subs}, query)
|
||||||
|
else:
|
||||||
|
raise NoSuchUserException()
|
||||||
|
|
||||||
def update_send_cache(self):
|
def update_send_cache(self):
|
||||||
res = {target_type: defaultdict(list) for target_type in supported_target_type}
|
res = {target_type: defaultdict(list) for target_type in supported_target_type}
|
||||||
cat_res = {target_type: defaultdict(lambda: defaultdict(list)) for target_type in supported_target_type}
|
cat_res = {target_type: defaultdict(lambda: defaultdict(list)) for target_type in supported_target_type}
|
||||||
|
@ -24,3 +24,15 @@ def test_create_and_get(config: 'nonebot_bison.config.Config', plugin_module: 'n
|
|||||||
assert(len(confs) == 1)
|
assert(len(confs) == 1)
|
||||||
assert(config.target_user_cache['weibo']['weibo_id'] == \
|
assert(config.target_user_cache['weibo']['weibo_id'] == \
|
||||||
[plugin_module.types.User('123', 'group')])
|
[plugin_module.types.User('123', 'group')])
|
||||||
|
assert(confs[0]['cats'] == [])
|
||||||
|
config.update_subscribe(
|
||||||
|
user='123',
|
||||||
|
user_type='group',
|
||||||
|
target='weibo_id',
|
||||||
|
target_name='weibo_name',
|
||||||
|
target_type='weibo',
|
||||||
|
cats=['1'],
|
||||||
|
tags=[])
|
||||||
|
confs = config.list_subscribe('123', 'group')
|
||||||
|
assert(len(confs) == 1)
|
||||||
|
assert(confs[0]['cats'] == ['1'])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user