2022-04-20 13:31:46 +00:00
|
|
|
|
import React, {Component} from 'react';
|
|
|
|
|
import './App.css';
|
2022-04-25 10:39:54 +00:00
|
|
|
|
import {Button, Dialog, Divider, Form, Input, List, Modal, NavBar, Popup, TextArea, Toast,} from "antd-mobile";
|
2022-04-20 13:31:46 +00:00
|
|
|
|
import {UnorderedListOutline} from "antd-mobile-icons";
|
|
|
|
|
import {ListItem} from "antd-mobile/es/components/list/list-item";
|
2022-09-10 13:43:29 +00:00
|
|
|
|
import {checkQrCode, getLog, getScore, getToken, getUsers, getLink, stopStudy, study, login, checkToken,getAbout,deleteUser, getExpiredUsers} from "./utils/api";
|
2022-04-20 13:31:46 +00:00
|
|
|
|
import QrCode from 'qrcode.react';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class App extends React.Component<any, any> {
|
|
|
|
|
constructor(props: any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
popup_visible: false,
|
2022-04-25 10:39:54 +00:00
|
|
|
|
index: "login",
|
2022-08-30 07:13:09 +00:00
|
|
|
|
is_login: false,
|
|
|
|
|
// 用户等级,1是管理员,2是普通用户
|
|
|
|
|
level: 2
|
2022-04-20 13:31:46 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:13:09 +00:00
|
|
|
|
set_level = (level:number)=>{
|
|
|
|
|
this.setState({
|
|
|
|
|
level: level
|
|
|
|
|
})
|
|
|
|
|
}
|
2022-04-25 10:39:54 +00:00
|
|
|
|
set_login = ()=>{
|
|
|
|
|
this.setState({
|
|
|
|
|
is_login: true
|
|
|
|
|
})
|
2022-08-30 07:13:09 +00:00
|
|
|
|
this.check_token()
|
2022-04-25 10:39:54 +00:00
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
2022-08-30 07:13:09 +00:00
|
|
|
|
check_token = ()=>{
|
|
|
|
|
checkToken().then((t) =>{
|
|
|
|
|
console.log(t)
|
|
|
|
|
if (!t){
|
|
|
|
|
console.log("未登录")
|
|
|
|
|
}else {
|
|
|
|
|
if (t.data === 1){
|
|
|
|
|
console.log("管理员登录")
|
|
|
|
|
this.set_level(1)
|
|
|
|
|
}else {
|
|
|
|
|
console.log("不是管理员登录")
|
|
|
|
|
this.set_level(2)
|
|
|
|
|
}
|
|
|
|
|
this.setState({
|
|
|
|
|
is_login: true
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
2022-08-30 07:13:09 +00:00
|
|
|
|
componentDidMount() {
|
|
|
|
|
this.check_token()
|
2022-04-25 10:39:54 +00:00
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
2022-04-25 10:39:54 +00:00
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
|
|
|
|
|
let home = (
|
|
|
|
|
<>
|
|
|
|
|
<NavBar style={{background: "#c0a8c0", margin: 10}} backArrow={false}
|
|
|
|
|
left={<UnorderedListOutline fontSize={36} onClick={this.back}/>}>
|
|
|
|
|
{"study_xxqg"}
|
|
|
|
|
</NavBar>
|
2022-08-30 07:13:09 +00:00
|
|
|
|
<Router data={this.state.index} level={this.state.level} set_level = {this.set_level}/>
|
2022-04-25 10:39:54 +00:00
|
|
|
|
<Popup
|
|
|
|
|
bodyStyle={{width: '50vw'}}
|
|
|
|
|
visible={this.state.popup_visible}
|
|
|
|
|
position={"left"}
|
|
|
|
|
onMaskClick={(() => {
|
|
|
|
|
this.setState({popup_visible: false})
|
|
|
|
|
})}>
|
|
|
|
|
<h1 style={{textAlign:"center"}}>XXQG</h1>
|
|
|
|
|
<List>
|
|
|
|
|
<ListItem onClick={()=>{this.setState({"index":"login"})}}>添加用户</ListItem>
|
|
|
|
|
<ListItem onClick={()=>{this.setState({"index":"user_list"})}}>用户管理</ListItem>
|
|
|
|
|
<ListItem onClick={()=>{this.setState({"index":"config"})}}>配置管理</ListItem>
|
|
|
|
|
<ListItem onClick={()=>{this.setState({"index":"log"})}}>日志查看</ListItem>
|
|
|
|
|
<ListItem onClick={()=>{this.setState({"index":"help"})}}>帮助</ListItem>
|
|
|
|
|
<ListItem onClick={()=>{
|
|
|
|
|
window.localStorage.removeItem("xxqg_token")
|
|
|
|
|
this.setState({
|
|
|
|
|
is_login: false
|
|
|
|
|
})
|
|
|
|
|
}}>退出登录</ListItem>
|
|
|
|
|
</List>
|
|
|
|
|
</Popup>
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
if (this.state.is_login) {
|
|
|
|
|
return home
|
|
|
|
|
} else {
|
|
|
|
|
return <Login parent={this}/>
|
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
back = () => {
|
|
|
|
|
this.setState({
|
|
|
|
|
popup_visible: true,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-04-25 10:39:54 +00:00
|
|
|
|
class Login extends Component<any, any>{
|
|
|
|
|
constructor(props: any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
img : "你还未获取登录链接"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onFinish = (value:string)=>{
|
|
|
|
|
login(JSON.stringify(value)).then(resp => {
|
2022-08-26 00:25:07 +00:00
|
|
|
|
console.log(resp.message)
|
2022-08-30 07:13:09 +00:00
|
|
|
|
Dialog.alert({content: resp.message,closeOnMaskClick:false})
|
2022-04-25 10:39:54 +00:00
|
|
|
|
if (resp.success){
|
|
|
|
|
window.localStorage.setItem("xxqg_token",resp.data)
|
|
|
|
|
this.props.parent.set_login()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
return <>
|
|
|
|
|
<Form
|
|
|
|
|
onFinish = {this.onFinish}
|
|
|
|
|
footer={
|
|
|
|
|
<Button block type='submit' color='primary' size='large'>
|
|
|
|
|
登录
|
|
|
|
|
</Button>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<Form.Header><h1>XXQG 登录页</h1></Form.Header>
|
|
|
|
|
<Form.Item name='account' label='账号' rules={[{ required: true }]}>
|
|
|
|
|
<Input placeholder='请输入账号' />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item name='password' label='密码' rules={[{ required: true }]}>
|
|
|
|
|
<Input placeholder='请输入密码' type={"password"}/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</>;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-04-20 13:31:46 +00:00
|
|
|
|
class Router extends Component<any, any>{
|
|
|
|
|
|
|
|
|
|
constructor(props: any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
img : "你还未获取登录链接"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 10:39:54 +00:00
|
|
|
|
isWechat = ()=> {
|
|
|
|
|
if (/MicroMessenger/i.test(window.navigator.userAgent)){
|
|
|
|
|
return "inline"
|
|
|
|
|
}else {
|
|
|
|
|
return "none"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 13:31:46 +00:00
|
|
|
|
render() {
|
|
|
|
|
let login = <>
|
2022-04-25 10:39:54 +00:00
|
|
|
|
<h2 style={{margin:10,color:"red",display:this.isWechat()}}>当前环境为微信环境,请点击右上角在浏览器中打开</h2>
|
2022-04-20 13:31:46 +00:00
|
|
|
|
<Button onClick={this.click} color={"primary"} style={{margin:10,marginRight:10}} block>生成链接</Button>
|
|
|
|
|
<QrCode style={{margin:10}} fgColor={"#000000"} size={200} value={this.state.img} />
|
|
|
|
|
</>;
|
|
|
|
|
|
2022-08-30 07:13:09 +00:00
|
|
|
|
let userList = <Users data={"12"} level={this.props.level}/>;
|
2022-04-20 13:31:46 +00:00
|
|
|
|
let config = <h1>配置管理</h1>
|
|
|
|
|
let help = <Help />
|
|
|
|
|
let log = <Log />
|
|
|
|
|
if (this.props.data === "login"){
|
|
|
|
|
return login;
|
|
|
|
|
}else if (this.props.data === "user_list"){
|
|
|
|
|
return userList;
|
|
|
|
|
}else if (this.props.data === "help"){
|
|
|
|
|
return help;
|
|
|
|
|
} else if (this.props.data === "log"){
|
|
|
|
|
return log;
|
|
|
|
|
} else {
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 10:39:54 +00:00
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
if (this.state.check !== undefined){
|
|
|
|
|
clearInterval(this.state.check)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 13:31:46 +00:00
|
|
|
|
click = async () => {
|
2022-04-25 10:39:54 +00:00
|
|
|
|
let data = await getLink()
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
img: data.url
|
|
|
|
|
})
|
|
|
|
|
let check = setInterval(async ()=>{
|
|
|
|
|
let resp = await checkQrCode(data.code);
|
|
|
|
|
if (resp.success){
|
|
|
|
|
clearInterval(check)
|
|
|
|
|
console.log("登录成功")
|
|
|
|
|
console.log(resp.data)
|
|
|
|
|
|
|
|
|
|
let token = await getToken(resp.data.split("=")[1],data.sign)
|
|
|
|
|
console.log(token)
|
|
|
|
|
if (token.success){
|
|
|
|
|
Toast.show("登录成功")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},5000)
|
2022-04-25 10:39:54 +00:00
|
|
|
|
this.setState({
|
|
|
|
|
check: check
|
|
|
|
|
})
|
2022-04-20 13:31:46 +00:00
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
clearInterval(check)
|
|
|
|
|
},1000*300)
|
|
|
|
|
|
|
|
|
|
let element = document.createElement("a");
|
2022-04-20 14:00:23 +00:00
|
|
|
|
element.href = "dtxuexi://appclient/page/study_feeds?url="+escape(data.url)
|
2022-04-20 13:31:46 +00:00
|
|
|
|
element.click()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Log extends Component<any, any>{
|
|
|
|
|
|
|
|
|
|
constructor(props:any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
data : ""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 10:39:54 +00:00
|
|
|
|
reverse = ( str:string ):string=>{
|
|
|
|
|
return str.split("\n").reverse().join("\n").trim()
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-20 13:31:46 +00:00
|
|
|
|
timer: any
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
getLog().then(data=>{
|
|
|
|
|
this.setState({
|
2022-04-25 10:39:54 +00:00
|
|
|
|
data:this.reverse(data)
|
2022-04-20 13:31:46 +00:00
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
this.timer = setInterval(()=>{
|
2022-04-25 10:39:54 +00:00
|
|
|
|
getLog().then((data:string)=>{
|
2022-04-20 13:31:46 +00:00
|
|
|
|
this.setState({
|
2022-04-25 10:39:54 +00:00
|
|
|
|
data:this.reverse(data)
|
2022-04-20 13:31:46 +00:00
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
},30000)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
clearInterval(this.timer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
return <>
|
2022-04-25 10:39:54 +00:00
|
|
|
|
<TextArea style={{margin:10}} autoSize disabled={true} value={this.state.data}/>
|
2022-04-20 13:31:46 +00:00
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Help extends Component<any, any> {
|
2022-08-26 00:25:07 +00:00
|
|
|
|
|
|
|
|
|
constructor(props: any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
about: ""
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
getAbout().then((value)=>{
|
|
|
|
|
this.setState({
|
|
|
|
|
about:value.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
render() {
|
|
|
|
|
return <>
|
2022-04-25 10:39:54 +00:00
|
|
|
|
<h2 style={{margin:10}}>项目地址:<a href="https://github.com/johlanse/study_xxqg">https://github.com/johlanse/study_xxqg</a></h2>
|
2022-08-26 00:25:07 +00:00
|
|
|
|
<br/><h2 style={{margin:10}}>{this.state.about}</h2>
|
2022-04-20 13:31:46 +00:00
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Users extends Component<any, any>{
|
|
|
|
|
|
|
|
|
|
constructor(props: any) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
2022-09-10 13:43:29 +00:00
|
|
|
|
users:[],
|
|
|
|
|
expired_users:[]
|
2022-04-20 13:31:46 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
getUsers().then(users =>{
|
|
|
|
|
console.log(users)
|
|
|
|
|
this.setState({
|
|
|
|
|
users: users.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2022-09-10 13:43:29 +00:00
|
|
|
|
getExpiredUsers().then(users => {
|
|
|
|
|
console.log(users)
|
|
|
|
|
this.setState({
|
|
|
|
|
expired_users: users.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2022-04-20 13:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
format = (value:any)=> {
|
|
|
|
|
const date = new Date(value*1000);
|
|
|
|
|
let y = date.getFullYear(),
|
|
|
|
|
m = date.getMonth() + 1,
|
|
|
|
|
d = date.getDate(),
|
|
|
|
|
h = date.getHours(),
|
|
|
|
|
i = date.getMinutes(),
|
|
|
|
|
s = date.getSeconds();
|
|
|
|
|
if (m < 10) { m = parseInt('0') + m; }
|
|
|
|
|
if (d < 10) { d = parseInt('0') + d; }
|
|
|
|
|
if (h < 10) { h = parseInt('0') + h; }
|
|
|
|
|
if (i < 10) { i = parseInt('0') + i; }
|
|
|
|
|
if (s < 10) { s = parseInt('0') + s; }
|
|
|
|
|
return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getScore = (token:string,nick:string)=>{
|
|
|
|
|
getScore(token).then((data)=>{
|
|
|
|
|
console.log(data)
|
|
|
|
|
Modal.alert({
|
|
|
|
|
title: nick,
|
|
|
|
|
content: data.data,
|
|
|
|
|
closeOnMaskClick: true,
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkStudy = (is_study:boolean)=>{
|
|
|
|
|
if (is_study){
|
|
|
|
|
return "停止学习"
|
|
|
|
|
}else {
|
|
|
|
|
return "开始学习"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkStudyColor = (is_study:boolean)=>{
|
|
|
|
|
if (is_study){
|
|
|
|
|
return "danger"
|
|
|
|
|
}else {
|
|
|
|
|
return "primary"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
study = (uid:string,is_study:boolean) =>{
|
|
|
|
|
if (!is_study){
|
|
|
|
|
study(uid).then(()=>{
|
|
|
|
|
Toast.show("开始学习成功")
|
|
|
|
|
getUsers().then(users =>{
|
|
|
|
|
console.log(users)
|
|
|
|
|
this.setState({
|
|
|
|
|
users: users.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}else {
|
|
|
|
|
stopStudy(uid).then(()=>{
|
|
|
|
|
Toast.show("已停止学习")
|
|
|
|
|
getUsers().then(users =>{
|
|
|
|
|
console.log(users)
|
|
|
|
|
this.setState({
|
|
|
|
|
users: users.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:13:09 +00:00
|
|
|
|
delete_user = (uid:string,nick:string)=>{
|
|
|
|
|
Dialog.confirm({content:"你确定要删除用户"+nick+"吗?"}).then((confirm) => {
|
|
|
|
|
if (confirm){
|
|
|
|
|
deleteUser(uid).then((data) => {
|
|
|
|
|
if (data.success){
|
|
|
|
|
getUsers().then(users =>{
|
|
|
|
|
console.log(users)
|
|
|
|
|
this.setState({
|
|
|
|
|
users: users.data
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}else {
|
|
|
|
|
Dialog.show({content:data.error})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
let elements = []
|
|
|
|
|
for (let i = 0; i < this.state.users.length; i++) {
|
2022-08-30 07:13:09 +00:00
|
|
|
|
console.log(this.props.level)
|
2022-04-20 13:31:46 +00:00
|
|
|
|
elements.push(
|
|
|
|
|
<>
|
|
|
|
|
<ListItem key={this.state.users[i].uid} style={{border:"blue soild 1px"}}>
|
|
|
|
|
<h3>姓名:{this.state.users[i].nick}</h3>
|
|
|
|
|
<h3>UID: {this.state.users[i].uid}</h3>
|
|
|
|
|
<h3>登录时间:{this.format(this.state.users[i].login_time)}</h3>
|
|
|
|
|
<Button onClick={this.study.bind(this,this.state.users[i].uid,this.state.users[i].is_study)} color={this.checkStudyColor(this.state.users[i].is_study)} block={true}>
|
|
|
|
|
{this.checkStudy(this.state.users[i].is_study)}
|
|
|
|
|
</Button>
|
|
|
|
|
<br />
|
|
|
|
|
<Button onClick={this.getScore.bind(this,this.state.users[i].token,this.state.users[i].nick)} color={"success"} block={true}>积分查询</Button>
|
2022-08-30 07:13:09 +00:00
|
|
|
|
<br />
|
|
|
|
|
<Button style={{display: this.props.level !== 1 ? "none" : "inline"}} onClick={this.delete_user.bind(this,this.state.users[i].uid,this.state.users[i].nick)} color={"danger"} block={true}>删除用户</Button>
|
2022-04-20 13:31:46 +00:00
|
|
|
|
</ListItem>
|
|
|
|
|
<Divider />
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-09-10 13:43:29 +00:00
|
|
|
|
|
|
|
|
|
for (let i = 0; i < this.state.expired_users.length; i++) {
|
|
|
|
|
console.log(this.state.expired_users[i].uid)
|
|
|
|
|
elements.push(
|
|
|
|
|
<>
|
|
|
|
|
<ListItem key={this.state.expired_users[i].uid} style={{border:"blue soild 1px",backgroundColor:"#cdced0"}}>
|
|
|
|
|
<h3>姓名:{this.state.expired_users[i].nick}</h3>
|
|
|
|
|
<h3>UID: {this.state.expired_users[i].uid}</h3>
|
|
|
|
|
<h3>登录时间:{this.format(this.state.expired_users[i].login_time)}</h3>
|
|
|
|
|
<Button style={{display: this.props.level !== 1 ? "none" : "inline"}} onClick={this.delete_user.bind(this,this.state.expired_users[i].uid,this.state.expired_users[i].nick)} color={"danger"} block={true}>删除用户</Button>
|
|
|
|
|
</ListItem>
|
|
|
|
|
<Divider />
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-26 00:25:07 +00:00
|
|
|
|
if (this.state.users.length === 0){
|
|
|
|
|
elements.push(<>
|
|
|
|
|
<span style={{color:"red"}}>未获取到有效用户</span>
|
|
|
|
|
</>)
|
|
|
|
|
}
|
2022-04-20 13:31:46 +00:00
|
|
|
|
|
|
|
|
|
return <List>{elements}</List>;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default App;
|