mirror of
https://github.com/YMFE/yapi.git
synced 2024-12-09 05:00:30 +08:00
Merge branch 'dev' of gitlab.corp.qunar.com:mfe/yapi into dev
This commit is contained in:
commit
650a25e98e
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Mock from 'mockjs'
|
||||
import { Button, Input, Select, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete } from 'antd'
|
||||
import { Button, Input, Select, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete, Switch } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import constants from '../../constants/variable.js'
|
||||
|
||||
@ -40,7 +40,7 @@ const mockDataSource = wordList.map(item => {
|
||||
});
|
||||
|
||||
|
||||
const { TextArea } = Input;
|
||||
// const { TextArea } = Input;
|
||||
const InputGroup = Input.Group;
|
||||
const Option = Select.Option;
|
||||
const Panel = Collapse.Panel;
|
||||
@ -71,7 +71,10 @@ export default class Run extends Component {
|
||||
loading: false,
|
||||
validRes: [],
|
||||
hasPlugin: true,
|
||||
test_status: null
|
||||
test_status: null,
|
||||
resTest: false,
|
||||
resStatusCode: null,
|
||||
resStatusText: ''
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@ -214,7 +217,12 @@ export default class Run extends Component {
|
||||
data: bodyType === 'form' ? this.arrToObj(bodyForm) : bodyOther,
|
||||
files: bodyType === 'form' ? this.getFiles(bodyForm) : {},
|
||||
file: bodyType === 'file' ? 'single-file' : null,
|
||||
success: (res, header) => {
|
||||
success: (res, header, third) => {
|
||||
console.log('suc',third);
|
||||
this.setState({
|
||||
resStatusCode: third.res.status,
|
||||
resStatusText: third.res.statusText
|
||||
})
|
||||
try {
|
||||
if (isJsonData(header)) {
|
||||
res = json_parse(res);
|
||||
@ -259,7 +267,12 @@ export default class Run extends Component {
|
||||
console.error(e.message)
|
||||
}
|
||||
},
|
||||
error: (err, header) => {
|
||||
error: (err, header, third) => {
|
||||
console.log('err',third);
|
||||
this.setState({
|
||||
resStatusCode: third.res.status,
|
||||
resStatusText: third.res.statusText
|
||||
})
|
||||
try {
|
||||
err = json_parse(err);
|
||||
} catch (e) {
|
||||
@ -496,6 +509,13 @@ export default class Run extends Component {
|
||||
console.log(index)
|
||||
}
|
||||
|
||||
@autobind
|
||||
onTestSwitched(checked) {
|
||||
this.setState({
|
||||
resTest: checked
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { method, domains, pathParam, pathname, query, headers, bodyForm, caseEnv, bodyType, resHeader, loading, validRes } = this.state;
|
||||
HTTP_METHOD[method] = HTTP_METHOD[method] || {}
|
||||
@ -722,30 +742,59 @@ export default class Run extends Component {
|
||||
</Collapse>
|
||||
|
||||
<h2 className="interface-title">返回结果</h2>
|
||||
<Spin spinning={this.state.loading}>
|
||||
<div className="res-code"></div>
|
||||
<Collapse defaultActiveKey={['0', '1']} bordered={true}>
|
||||
{this.state.resStatusCode ?
|
||||
<Spin spinning={this.state.loading}>
|
||||
<h2 className={'res-code ' + ((this.state.resStatusCode >= 200 && this.state.resStatusCode < 400 && !this.state.loading) ? 'success' : 'fail')}>{this.state.resStatusCode + ' ' + this.state.resStatusText}</h2>
|
||||
|
||||
<div className="container-header-body">
|
||||
<div className="header">
|
||||
<div className="container-title">
|
||||
<h4>Headers</h4>
|
||||
</div>
|
||||
<div id="res-headers-pretty" className="pretty-editor-header"></div>
|
||||
</div>
|
||||
<div className="resizer">
|
||||
<div className="container-title">
|
||||
<h4 style={{visibility: 'hidden'}}>1</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="body">
|
||||
<div className="container-title">
|
||||
<h4>Body</h4>
|
||||
</div>
|
||||
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>
|
||||
<div
|
||||
style={{display: isResJson ? 'none' : ''}}
|
||||
className="res-body-text"
|
||||
>{this.state.res && this.state.res.toString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Spin> : <p>发送请求后在这里查看返回结果。</p>}
|
||||
|
||||
{/*<Collapse defaultActiveKey={['0', '1']} bordered={true}>
|
||||
<Panel header="BODY" key="0" >
|
||||
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>
|
||||
<TextArea
|
||||
<div id="res-body-pretty" className="pretty-editor-body" style={{ display: isResJson ? '' : 'none' }}></div>*/}
|
||||
{/*<TextArea
|
||||
style={{ display: isResJson ? 'none' : '' }}
|
||||
value={this.state.res && this.state.res.toString()}
|
||||
autosize={{ minRows: 10, maxRows: 20 }}
|
||||
></TextArea>
|
||||
<h3 style={{ marginTop: '15px', display: isResJson ? '' : 'none' }}>返回 Body 验证结果:</h3>
|
||||
<div style={{ display: isResJson ? '' : 'none' }}>
|
||||
{validResView}
|
||||
</div>
|
||||
</Panel>
|
||||
<Panel header="HEADERS" key="1" >
|
||||
{/*<TextArea
|
||||
></TextArea>*/}
|
||||
{/*</Panel>
|
||||
<Panel header="HEADERS" key="1" >*/}
|
||||
{/*<TextArea
|
||||
value={typeof this.state.resHeader === 'object' ? JSON.stringify(this.state.resHeader, null, 2) : this.state.resHeader.toString()}
|
||||
autosize={{ minRows: 2, maxRows: 10 }}
|
||||
></TextArea>*/}
|
||||
<div id="res-headers-pretty" className="pretty-editor-header"></div>
|
||||
{/*<div id="res-headers-pretty" className="pretty-editor-header"></div>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
</Spin>
|
||||
</Collapse>*/}
|
||||
|
||||
<h2 className="interface-title">数据结构验证
|
||||
<Switch style={{verticalAlign: 'text-bottom', marginLeft: '8px'}} checked={this.state.resTest} onChange={this.onTestSwitched} />
|
||||
</h2>
|
||||
<div className={(isResJson && this.state.resTest) ? '' : 'none' }>
|
||||
{(isResJson && this.state.resTest) ? validResView : <div><p>若开启此功能,则发送请求后在这里查看验证结果。</p><p>数据结构验证在接口编辑页面配置,YApi 将根据 Response body 验证请求返回的结果。</p></div>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
13
client/containers/Project/Activity/Timeline/Timeline.js → client/components/TimeLine/TimeLine.js
Executable file → Normal file
13
client/containers/Project/Activity/Timeline/Timeline.js → client/components/TimeLine/TimeLine.js
Executable file → Normal file
@ -2,10 +2,10 @@ import React, { Component } from 'react'
|
||||
import { Timeline, Spin, Avatar } from 'antd'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { formatTime } from '../../../../common.js';
|
||||
import { formatTime } from '../../common.js';
|
||||
import { Link } from 'react-router-dom'
|
||||
import { fetchNewsData, fetchMoreNews } from '../../../../reducer/modules/news.js'
|
||||
import ErrMsg from '../../../../components/ErrMsg/ErrMsg.js';
|
||||
import { fetchNewsData, fetchMoreNews } from '../../reducer/modules/news.js'
|
||||
import ErrMsg from '../ErrMsg/ErrMsg.js';
|
||||
|
||||
function timeago(timestamp) {
|
||||
let minutes, hours, days, seconds, mouth, year;
|
||||
@ -78,7 +78,8 @@ class TimeTree extends Component {
|
||||
loading: PropTypes.bool,
|
||||
curpage: PropTypes.number,
|
||||
typeid: PropTypes.number,
|
||||
curUid: PropTypes.number
|
||||
curUid: PropTypes.number,
|
||||
type: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@ -95,7 +96,7 @@ class TimeTree extends Component {
|
||||
if (this.props.curpage <= this.props.newsData.total) {
|
||||
|
||||
this.setState({ loading: true });
|
||||
this.props.fetchMoreNews(this.props.typeid, 'project', this.props.curpage+1, 8).then(function () {
|
||||
this.props.fetchMoreNews(this.props.typeid, this.props.type, this.props.curpage+1, 8).then(function () {
|
||||
that.setState({ loading: false });
|
||||
if (that.props.newsData.total === that.props.curpage) {
|
||||
that.setState({ bidden: "logbidden" })
|
||||
@ -106,7 +107,7 @@ class TimeTree extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
|
||||
this.props.fetchNewsData(this.props.typeid, 'project', 1, 8)
|
||||
this.props.fetchNewsData(this.props.typeid, this.props.type, 1, 8)
|
||||
}
|
||||
|
||||
render() {
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import GroupList from './GroupList/GroupList.js';
|
||||
import ProjectList from './ProjectList/ProjectList.js';
|
||||
import MemberList from './MemberList/MemberList.js';
|
||||
import GroupLog from './GroupLog/GroupLog.js';
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
import { Tabs, Layout } from 'antd';
|
||||
const { Content, Sider } = Layout;
|
||||
@ -27,6 +28,7 @@ export default class Group extends Component {
|
||||
<Tabs type="card" className="m-tab" style={{height: '100%'}}>
|
||||
<TabPane tab="项目列表" key="1"><ProjectList/></TabPane>
|
||||
<TabPane tab="成员列表" key="2"><MemberList/></TabPane>
|
||||
<TabPane tab="分组动态" key="3"><GroupLog/></TabPane>
|
||||
</Tabs>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
36
client/containers/Group/GroupLog/GroupLog.js
Normal file
36
client/containers/Group/GroupLog/GroupLog.js
Normal file
@ -0,0 +1,36 @@
|
||||
import React, { Component } from 'react'
|
||||
import TimeTree from '../../../components/TimeLine/TimeLine'
|
||||
import { connect } from 'react-redux'
|
||||
import PropTypes from 'prop-types'
|
||||
// import { Button } from 'antd'
|
||||
@connect(
|
||||
state => {
|
||||
console.log(state);
|
||||
return {
|
||||
uid: state.user.uid + '',
|
||||
curGroupId: state.group.currGroup._id
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
class GroupLog extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
static propTypes = {
|
||||
uid: PropTypes.string,
|
||||
match: PropTypes.object,
|
||||
curGroupId: PropTypes.number
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className="g-row">
|
||||
<section className="news-box m-panel">
|
||||
<TimeTree type={"group"} typeid = {this.props.curGroupId} />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupLog;
|
@ -1,6 +1,6 @@
|
||||
import './Activity.scss'
|
||||
import React, { Component } from 'react'
|
||||
import TimeTree from './Timeline/Timeline'
|
||||
import TimeTree from '../../../components/TimeLine/TimeLine'
|
||||
import { connect } from 'react-redux'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Button } from 'antd'
|
||||
@ -41,7 +41,7 @@ class Activity extends Component {
|
||||
<Button type="primary"><a href = {`/api/project/download?project_id=${this.props.match.params.id}`}>下载Mock数据</a></Button>
|
||||
</div>
|
||||
</div>
|
||||
<TimeTree typeid = {+this.props.match.params.id} />
|
||||
<TimeTree type={"project"} typeid = {+this.props.match.params.id} />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
|
@ -127,9 +127,9 @@ class InterfaceColContent extends Component {
|
||||
status = 'ok';
|
||||
} else if (result.code === 1) {
|
||||
status = 'invalid'
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
status = 'error';
|
||||
status = 'error';
|
||||
result = e;
|
||||
}
|
||||
this.reports[curitem._id] = result;
|
||||
@ -177,7 +177,7 @@ class InterfaceColContent extends Component {
|
||||
headers: that.getHeadersObj(interfaceData.req_headers),
|
||||
data: interfaceData.req_body_type === 'form' ? that.arrToObj(interfaceData.req_body_form) : interfaceData.req_body_other,
|
||||
success: (res, header) => {
|
||||
res = json_parse(res);
|
||||
res = json_parse(res);
|
||||
result.res_header = header;
|
||||
result.res_body = res;
|
||||
if (res && typeof res === 'object') {
|
||||
@ -206,7 +206,7 @@ class InterfaceColContent extends Component {
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
err = err || '请求异常';
|
||||
result.code = 400;
|
||||
result.res_header = header;
|
||||
@ -442,7 +442,7 @@ class InterfaceColContent extends Component {
|
||||
|
||||
return (
|
||||
<div className="interface-col">
|
||||
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合 <a target="_blank" rel="noopener noreferrer" href="https://yapi.ymfe.org/case.html" >
|
||||
<h2 className="interface-title" style={{ display: 'inline-block', margin: 0, marginBottom: '16px' }}>测试集合 <a target="_blank" rel="noopener noreferrer" href="https://yapi.ymfe.org/case.html" >
|
||||
<Tooltip title="点击查看文档"><Icon type="question-circle-o" /></Tooltip>
|
||||
</a></h2>
|
||||
<Button type="primary" style={{ float: 'right' }} onClick={this.executeTests}>开始测试</Button>
|
||||
@ -478,4 +478,4 @@ class InterfaceColContent extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default InterfaceColContent
|
||||
export default InterfaceColContent
|
||||
|
@ -89,12 +89,11 @@
|
||||
}
|
||||
|
||||
.interface-col{
|
||||
padding: 16px;
|
||||
padding: 24px;
|
||||
.interface-col-table-header{
|
||||
background-color: rgb(238, 238, 238);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
font-size:14px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import '../../../../styles/mixin.scss';
|
||||
|
||||
.interface-edit{
|
||||
padding: 24px;
|
||||
.interface-edit-item{
|
||||
@ -61,3 +63,71 @@
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
// 容器:左侧是header 右侧是body
|
||||
.container-header-body {
|
||||
display: flex;
|
||||
padding-bottom: .36rem;
|
||||
.header, .body {
|
||||
flex: 1 0 300px;
|
||||
.pretty-editor-header, .pretty-editor-body {
|
||||
height: 100%;
|
||||
}
|
||||
.postman .pretty-editor-body {
|
||||
min-height: 200px;
|
||||
}
|
||||
.ace_print-margin {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
max-width: 400px;
|
||||
}
|
||||
.container-title {
|
||||
padding: .08rem 0;
|
||||
}
|
||||
.resizer {
|
||||
flex: 0 0 21px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background-color: $color-text-dark;
|
||||
opacity: .8;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
// res body 无返回json时显示text信息
|
||||
.res-body-text {
|
||||
height: 100%;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
.ant-spin-blur {
|
||||
.res-code.success {
|
||||
background-color: transparent;
|
||||
}
|
||||
.res-code.fail {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.res-code {
|
||||
padding: .08rem .28rem;
|
||||
color: #fff;
|
||||
margin-left: -.28rem;
|
||||
margin-right: -.28rem;
|
||||
transition: all .2s;
|
||||
position: relative;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.res-code.success {
|
||||
background-color: $color-antd-green;
|
||||
}
|
||||
.res-code.fail {
|
||||
background-color: $color-antd-red;
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ class View extends Component {
|
||||
return <p style={{whiteSpace: 'pre-wrap'}}>{item.example}</p>;
|
||||
}
|
||||
}, {
|
||||
title: '备注',
|
||||
title: '备注',
|
||||
dataIndex: 'desc',
|
||||
key: 'desc',
|
||||
render(_, item) {
|
||||
@ -304,11 +304,11 @@ class View extends Component {
|
||||
<Row className="row">
|
||||
<Col span={4} className="colKey">接口名称:</Col>
|
||||
<Col span={8}>{this.props.curData.title}</Col>
|
||||
<Col span={4} className="colKey">创建人:</Col>
|
||||
<Col span={4} className="colKey">创 建 人:</Col>
|
||||
<Col span={8} className="colValue"><Link className="user-name" to={"/user/profile/" + this.props.curData.uid} ><img src={'/api/user/avatar?uid=' + this.props.curData.uid} className="user-img" />{this.props.curData.username}</Link></Col>
|
||||
</Row>
|
||||
<Row className="row">
|
||||
<Col span={4} className="colKey">状 态:</Col>
|
||||
<Col span={4} className="colKey">状  态:</Col>
|
||||
<Col span={8} className={'tag-status ' + this.props.curData.status}>{status[this.props.curData.status]}</Col>
|
||||
<Col span={4} className="colKey">更新时间:</Col>
|
||||
<Col span={8}>{formatTime(this.props.curData.up_time)}</Col>
|
||||
|
@ -149,6 +149,17 @@
|
||||
.right-content{
|
||||
min-height: 5rem;
|
||||
background: #fff;
|
||||
.caseContainer {
|
||||
table {
|
||||
border-radius: 4px;
|
||||
// border-collapse: collapse;
|
||||
}
|
||||
.ant-table-small .ant-table-thead > tr > th {
|
||||
text-align: left;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
tr:nth-child(even){background: #f8f8f8;}
|
||||
}
|
||||
.interface-content{
|
||||
.ant-tabs-nav{
|
||||
width:100%;
|
||||
@ -195,11 +206,17 @@
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
background-color: #f8f8f8;
|
||||
text-indent: .4em;
|
||||
}
|
||||
tr {
|
||||
text-indent: .4em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px;
|
||||
}
|
||||
tr:nth-child(odd){background: rgba(236, 238, 241, 0.67);}
|
||||
tr:nth-child(odd){background: #f8f8f8;}
|
||||
tr:nth-child(even){background: #fff;}
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ class ProjectMember extends Component {
|
||||
</Row>
|
||||
</Modal>
|
||||
<Table columns={columns} dataSource={this.state.projectMemberList} pagination={false} locale={{emptyText: <ErrMsg type="noMemberInProject"/>}} className="setting-project-member"/>
|
||||
<Card title={this.state.groupName + ' 分组成员 ' + '(' + this.state.groupMemberList.length + ') 人'} noHovering className="setting-group">
|
||||
<Card bordered={false} title={this.state.groupName + ' 分组成员 ' + '(' + this.state.groupMemberList.length + ') 人'} noHovering className="setting-group">
|
||||
{this.state.groupMemberList.length ? this.state.groupMemberList.map((item, index) => {
|
||||
return (<div key={index} className="card-item">
|
||||
<img src={location.protocol + '//' + location.host + '/api/user/avatar?uid=' + item.uid} className="item-img" />
|
||||
|
@ -25,14 +25,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.setting-project-member {
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 2px;
|
||||
}
|
||||
// .setting-project-member {
|
||||
// border: 1px solid #e9e9e9;
|
||||
// border-radius: 4px;
|
||||
// }
|
||||
|
||||
.setting-group {
|
||||
margin-top: .48rem;
|
||||
border-radius: 2px;
|
||||
border-bottom: 1px solid #eee;
|
||||
.ant-card-head {
|
||||
background-color: #eee;
|
||||
padding: 0 .08rem !important;
|
||||
|
@ -8,6 +8,16 @@ $color-black-light: #404040;
|
||||
$color-bg-dark: #32363a; // 背景色 - header 用的深蓝色
|
||||
$box-shadow-panel: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
$color-text-dark: rgba(13, 27, 62, 0.65);
|
||||
|
||||
$color-antd-green: #00a854;
|
||||
$color-antd-yellow: #ffbf00;
|
||||
$color-antd-red: #f56a00;
|
||||
$color-antd-pink: #f5317f;
|
||||
$color-antd-cyan: #00a2ae;
|
||||
$color-antd-gray: #bfbfbf;
|
||||
$color-antd-purple: #7265e6;
|
||||
|
||||
@mixin row-width-limit {
|
||||
max-width: 12.2rem;
|
||||
min-width: 10.2rem;
|
||||
|
@ -100,6 +100,14 @@ class groupController extends baseController {
|
||||
let result = await groupInst.save(data);
|
||||
|
||||
result = yapi.commons.fieldSelect(result, ['_id', 'group_name', 'group_desc', 'uid', 'members']);
|
||||
let username = this.getUsername();
|
||||
yapi.commons.saveLog({
|
||||
content: `用户 "${username}" 新增了分组 "${params.group_name}"`,
|
||||
type: 'group',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: result._id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -165,6 +173,19 @@ class groupController extends baseController {
|
||||
delete groupUserdata._role;
|
||||
try {
|
||||
let result = await groupInst.addMember(params.id, groupUserdata);
|
||||
let username = this.getUsername();
|
||||
let rolename = {
|
||||
owner: "组长",
|
||||
dev: "开发者",
|
||||
guest: "访客"
|
||||
};
|
||||
yapi.commons.saveLog({
|
||||
content: `用户 "${username}" 新增了分组成员 "${groupUserdata.username}" 为 "${rolename[params.role]}"`,
|
||||
type: 'group',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -205,6 +226,20 @@ class groupController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await groupInst.changeMemberRole(params.id, params.member_uid, params.role);
|
||||
let username = this.getUsername();
|
||||
let rolename = {
|
||||
owner: "组长",
|
||||
dev: "开发者",
|
||||
guest: "访客"
|
||||
};
|
||||
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
|
||||
yapi.commons.saveLog({
|
||||
content: `用户 "${username}" 更改了分组成员 "${groupUserdata.username}" 的权限为 "${rolename[params.role]}"`,
|
||||
type: 'group',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -267,6 +302,20 @@ class groupController extends baseController {
|
||||
|
||||
try {
|
||||
let result = await groupInst.delMember(params.id, params.member_uid);
|
||||
let username = this.getUsername();
|
||||
let rolename = {
|
||||
owner: "组长",
|
||||
dev: "开发者",
|
||||
guest: "访客"
|
||||
};
|
||||
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
|
||||
yapi.commons.saveLog({
|
||||
content: `用户 "${username}" 删除了分组成员 "${groupUserdata.username}"`,
|
||||
type: 'group',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: params.id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, e.message);
|
||||
@ -379,6 +428,14 @@ class groupController extends baseController {
|
||||
ctx.body = yapi.commons.resReturn(null, 404, '分组名和分组描述不能为空');
|
||||
}
|
||||
let result = await groupInst.up(id, data);
|
||||
let username = this.getUsername();
|
||||
yapi.commons.saveLog({
|
||||
content: `用户 "${username}" 更新了 "${data.group_name}" 分组`,
|
||||
type: 'group',
|
||||
uid: this.getUid(),
|
||||
username: username,
|
||||
typeid: id
|
||||
});
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (err) {
|
||||
ctx.body = yapi.commons.resReturn(null, 402, err.message);
|
||||
|
Loading…
Reference in New Issue
Block a user