mirror of https://github.com/openspug/spug
A 微信token普通用户可以通过个人中心设置
parent
eae6f0b818
commit
02d9563367
|
@ -142,14 +142,20 @@ class RoleView(AdminView):
|
|||
|
||||
|
||||
class SelfView(View):
|
||||
def get(self, request):
|
||||
data = request.user.to_dict(selects=('nickname', 'wx_token'))
|
||||
return json_response(data)
|
||||
|
||||
def patch(self, request):
|
||||
form, error = JsonParser(
|
||||
Argument('old_password', required=False),
|
||||
Argument('new_password', required=False),
|
||||
Argument('nickname', required=False),
|
||||
).parse(request.body, True)
|
||||
Argument('nickname', required=False, help='请输入昵称'),
|
||||
Argument('wx_token', required=False),
|
||||
).parse(request.body)
|
||||
if error is None:
|
||||
if form.get('old_password') and form.get('new_password'):
|
||||
print(form)
|
||||
if form.old_password and form.new_password:
|
||||
if request.user.type == 'ldap':
|
||||
return json_response(error='LDAP账户无法修改密码')
|
||||
if len(form.new_password) < 6:
|
||||
|
@ -158,11 +164,14 @@ class SelfView(View):
|
|||
request.user.password_hash = User.make_password(form.new_password)
|
||||
request.user.token_expired = 0
|
||||
request.user.save()
|
||||
return json_response()
|
||||
else:
|
||||
return json_response(error='原密码错误,请重新输入')
|
||||
if form.get('nickname'):
|
||||
if form.nickname is not None:
|
||||
request.user.nickname = form.nickname
|
||||
request.user.save()
|
||||
if form.wx_token is not None:
|
||||
request.user.wx_token = form.wx_token
|
||||
request.user.save()
|
||||
return json_response(error=error)
|
||||
|
||||
|
||||
|
|
|
@ -20,13 +20,11 @@ class Argument(object):
|
|||
:param bool required: is required
|
||||
"""
|
||||
|
||||
def __init__(self, name, default=None, handler=None, required=True, type=str, filter=None, help=None,
|
||||
nullable=False):
|
||||
def __init__(self, name, default=None, handler=None, required=True, type=str, filter=None, help=None):
|
||||
self.name = name
|
||||
self.default = default
|
||||
self.type = type
|
||||
self.required = required
|
||||
self.nullable = nullable
|
||||
self.filter = filter
|
||||
self.help = help
|
||||
self.handler = handler
|
||||
|
@ -45,11 +43,12 @@ class Argument(object):
|
|||
elif value in [u'', '', None]:
|
||||
if self.default is not None:
|
||||
return self.default
|
||||
elif not self.nullable and self.required:
|
||||
raise ParseError(
|
||||
self.help or 'Value Error: %s must not be null' % self.name)
|
||||
elif self.required:
|
||||
raise ParseError(self.help or 'Value Error: %s must not be null' % self.name)
|
||||
elif self.help:
|
||||
raise ParseError(self.help)
|
||||
else:
|
||||
return None
|
||||
return value
|
||||
try:
|
||||
if self.type:
|
||||
if self.type in (list, dict) and isinstance(value, str):
|
||||
|
|
|
@ -3,37 +3,55 @@
|
|||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Form, Input, message } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Button, Form, Input, Spin, message } from 'antd';
|
||||
import styles from './index.module.css';
|
||||
import { http } from 'libs';
|
||||
import store from './store';
|
||||
|
||||
|
||||
export default function Basic(props) {
|
||||
const [nickname, setNickname] = useState(localStorage.getItem('nickname'));
|
||||
const [loading, setLoading] = useState(false);
|
||||
export default observer(function Basic(props) {
|
||||
const [form] = Form.useForm()
|
||||
const [fetching, setFetching] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (!store.user.nickname) {
|
||||
setFetching(true)
|
||||
store.fetchUser()
|
||||
.then(() => form.setFieldsValue(store.user))
|
||||
.finally(() => setFetching(false))
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
function handleSubmit() {
|
||||
setLoading(true);
|
||||
http.patch('/api/account/self/', {nickname})
|
||||
const formData = form.getFieldsValue();
|
||||
http.patch('/api/account/self/', formData)
|
||||
.then(() => {
|
||||
message.success('设置成功,重新登录或刷新页面后生效');
|
||||
localStorage.setItem('nickname', nickname)
|
||||
message.success('保存成功,昵称将在重新登录或刷新页面后生效');
|
||||
localStorage.setItem('nickname', formData.nickname);
|
||||
store.fetchUser()
|
||||
})
|
||||
.finally(() =>setLoading(false))
|
||||
.finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Spin spinning={fetching}>
|
||||
<div className={styles.title}>基本设置</div>
|
||||
<Form style={{maxWidth: 320}}>
|
||||
<Form.Item colon={false} label="昵称">
|
||||
<Input value={nickname} placeholder="请输入" onChange={e => setNickname(e.target.value)}/>
|
||||
<Form form={form} layout="vertical" style={{maxWidth: 320}} initialValues={store.user}>
|
||||
<Form.Item required name="nickname" label="昵称">
|
||||
<Input placeholder="请输入"/>
|
||||
</Form.Item>
|
||||
<Form.Item name="wx_token" label="微信Token" extra={<a target="_blank" rel="noopener noreferrer" href="https://spug.cc/docs/wx-token/">什么是微信Token?</a>}>
|
||||
<Input placeholder="请输入"/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" loading={loading} onClick={handleSubmit}>保存设置</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</React.Fragment>
|
||||
</Spin>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -38,13 +38,13 @@ export default function Reset(props) {
|
|||
<React.Fragment>
|
||||
<div className={styles.title}>修改密码</div>
|
||||
<Form style={{maxWidth: 320}} labelCol={{span: 6}} wrapperCol={{span: 18}}>
|
||||
<Form.Item label="原密码">
|
||||
<Form.Item required label="原密码">
|
||||
<Input.Password value={old_password} placeholder="请输入" onChange={e => setOldPassword(e.target.value)}/>
|
||||
</Form.Item>
|
||||
<Form.Item label="新密码">
|
||||
<Form.Item required label="新密码">
|
||||
<Input.Password value={new_password} placeholder="请输入" onChange={e => setNewPassword(e.target.value)}/>
|
||||
</Form.Item>
|
||||
<Form.Item label="再次确认">
|
||||
<Form.Item required label="再次确认">
|
||||
<Input.Password value={new2_password} placeholder="请输入" onChange={e => setNew2Password(e.target.value)}/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
|
|
|
@ -3,48 +3,40 @@
|
|||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Menu } from 'antd';
|
||||
import { Breadcrumb } from 'components';
|
||||
import Basic from './Basic';
|
||||
import Reset from './Reset';
|
||||
import styles from './index.module.css';
|
||||
|
||||
class Index extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedKeys: ['basic']
|
||||
}
|
||||
}
|
||||
function Index() {
|
||||
const [selectedKeys, setSelectedKeys] = useState(['basic'])
|
||||
|
||||
render() {
|
||||
const {selectedKeys} = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>个人中心</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.left}>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={selectedKeys}
|
||||
style={{border: 'none'}}
|
||||
onSelect={({selectedKeys}) => this.setState({selectedKeys})}>
|
||||
<Menu.Item key="basic">基本设置</Menu.Item>
|
||||
<Menu.Item key="reset">修改密码</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
{selectedKeys[0] === 'basic' && <Basic/>}
|
||||
{selectedKeys[0] === 'reset' && <Reset/>}
|
||||
</div>
|
||||
return (
|
||||
<div>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>个人中心</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.left}>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={selectedKeys}
|
||||
style={{border: 'none'}}
|
||||
onSelect={({selectedKeys}) => setSelectedKeys(selectedKeys)}>
|
||||
<Menu.Item key="basic">基本设置</Menu.Item>
|
||||
<Menu.Item key="reset">修改密码</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
{selectedKeys[0] === 'basic' && <Basic/>}
|
||||
{selectedKeys[0] === 'reset' && <Reset/>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Index
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 24px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Copyright (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import { observable } from 'mobx';
|
||||
import http from 'libs/http';
|
||||
|
||||
class Store {
|
||||
@observable user = {};
|
||||
|
||||
fetchUser = () => {
|
||||
return http.get('/api/account/self/')
|
||||
.then(res => this.user = res)
|
||||
}
|
||||
}
|
||||
|
||||
export default new Store()
|
Loading…
Reference in New Issue