mirror of
https://github.com/YMFE/yapi.git
synced 2024-12-09 05:00:30 +08:00
fix: 项目迁移权限
This commit is contained in:
parent
4647fae137
commit
0e322e1ddc
@ -24,6 +24,7 @@ export default class BreadcrumbNavigation extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const getItem = this.props.breadcrumb.map((item, index) => {
|
||||
if (item.href) {
|
||||
return (<Breadcrumb.Item key={index}><Link to={item.href}>{item.name}</Link></Breadcrumb.Item>);
|
||||
|
@ -16,7 +16,8 @@ import ProjectData from './Setting/ProjectData/ProjectData.js';
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
curProject: state.project.currProject
|
||||
curProject: state.project.currProject,
|
||||
currGroup: state.group.currGroup
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -34,26 +35,21 @@ export default class Project extends Component {
|
||||
getProject: PropTypes.func,
|
||||
location: PropTypes.object,
|
||||
fetchGroupMsg: PropTypes.func,
|
||||
setBreadcrumb: PropTypes.func
|
||||
setBreadcrumb: PropTypes.func,
|
||||
currGroup: PropTypes.object
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
currGroup: {}
|
||||
}
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
await this.props.getProject(this.props.match.params.id);
|
||||
const groupMsg = await this.props.fetchGroupMsg(this.props.curProject.group_id);
|
||||
await this.props.fetchGroupMsg(this.props.curProject.group_id);
|
||||
|
||||
this.setState({
|
||||
currGroup: groupMsg.payload.data.data
|
||||
})
|
||||
this.props.setBreadcrumb([{
|
||||
name: groupMsg.payload.data.data.group_name,
|
||||
href: '/group/' + groupMsg.payload.data.data._id
|
||||
name: this.props.currGroup.group_name,
|
||||
href: '/group/' + this.props.currGroup._id
|
||||
}, {
|
||||
name: this.props.curProject.name
|
||||
}]);
|
||||
@ -78,7 +74,7 @@ export default class Project extends Component {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let subnavData = [{
|
||||
name: routers.interface.name,
|
||||
path: `/project/${match.params.id}/interface/api`
|
||||
@ -95,7 +91,7 @@ export default class Project extends Component {
|
||||
name: routers.setting.name,
|
||||
path: `/project/${match.params.id}/setting`
|
||||
}];
|
||||
if (this.state.currGroup.type === 'private') {
|
||||
if (this.props.currGroup.type === 'private') {
|
||||
subnavData = subnavData.filter(item => {
|
||||
return item.name != '成员管理'
|
||||
})
|
||||
@ -115,7 +111,7 @@ export default class Project extends Component {
|
||||
<Route path={routers.activity.path} component={Activity} />
|
||||
<Route path={routers.interface.path} component={Interface} />
|
||||
<Route path={routers.setting.path} component={Setting} />
|
||||
{this.state.currGroup.type !== 'private' ?
|
||||
{this.props.currGroup.type !== 'private' ?
|
||||
<Route path={routers.members.path} component={ProjectMember} />
|
||||
: null
|
||||
}
|
||||
|
@ -1,9 +1,30 @@
|
||||
import React, { PureComponent as Component } from 'react'
|
||||
import { Form, Input, Switch, Select, Icon, Tooltip, Button, Row, Col, message, Card, Radio, Alert, Modal, Popover } from 'antd';
|
||||
import React, { PureComponent as Component } from 'react';
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Switch,
|
||||
Select,
|
||||
Icon,
|
||||
Tooltip,
|
||||
Button,
|
||||
Row,
|
||||
Col,
|
||||
message,
|
||||
Card,
|
||||
Radio,
|
||||
Alert,
|
||||
Modal,
|
||||
Popover
|
||||
} from 'antd';
|
||||
import PropTypes from 'prop-types';
|
||||
import { updateProject, delProject, getProject, upsetProject } from '../../../../reducer/modules/project';
|
||||
import {
|
||||
updateProject,
|
||||
delProject,
|
||||
getProject,
|
||||
upsetProject
|
||||
} from '../../../../reducer/modules/project';
|
||||
import { fetchGroupMsg } from '../../../../reducer/modules/group';
|
||||
import { fetchGroupList } from '../../../../reducer/modules/group.js'
|
||||
import { fetchGroupList } from '../../../../reducer/modules/group.js';
|
||||
import { connect } from 'react-redux';
|
||||
const { TextArea } = Input;
|
||||
import { withRouter } from 'react-router';
|
||||
@ -31,15 +52,14 @@ const formItemLayout = {
|
||||
|
||||
const Option = Select.Option;
|
||||
|
||||
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
projectList: state.project.projectList,
|
||||
groupList: state.group.groupList,
|
||||
projectMsg: state.project.currProject
|
||||
}
|
||||
projectMsg: state.project.currProject,
|
||||
currGroup: state.group.currGroup
|
||||
};
|
||||
},
|
||||
{
|
||||
updateProject,
|
||||
@ -55,10 +75,10 @@ class ProjectMessage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
protocol: 'http:\/\/',
|
||||
protocol: 'http://',
|
||||
projectMsg: {},
|
||||
showDangerOptions: false
|
||||
}
|
||||
};
|
||||
}
|
||||
static propTypes = {
|
||||
projectId: PropTypes.number,
|
||||
@ -72,84 +92,93 @@ class ProjectMessage extends Component {
|
||||
groupList: PropTypes.array,
|
||||
projectList: PropTypes.array,
|
||||
projectMsg: PropTypes.object,
|
||||
fetchGroupList: PropTypes.func
|
||||
}
|
||||
|
||||
|
||||
fetchGroupList: PropTypes.func,
|
||||
currGroup: PropTypes.object
|
||||
};
|
||||
|
||||
// 确认修改
|
||||
handleOk = (e) => {
|
||||
handleOk = e => {
|
||||
e.preventDefault();
|
||||
const { form, updateProject, projectMsg } = this.props;
|
||||
form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
let assignValue = Object.assign(projectMsg, values);
|
||||
values.protocol = this.state.protocol.split(':')[0];
|
||||
|
||||
updateProject(assignValue).then((res) => {
|
||||
if (res.payload.data.errcode == 0) {
|
||||
this.props.getProject(this.props.projectId);
|
||||
message.success('修改成功! ');
|
||||
// this.props.history.push('/group');
|
||||
}
|
||||
}).catch(() => {
|
||||
});
|
||||
|
||||
const group_id = assignValue.group_id;
|
||||
updateProject(assignValue)
|
||||
.then(res => {
|
||||
if (res.payload.data.errcode == 0) {
|
||||
this.props.getProject(this.props.projectId);
|
||||
message.success('修改成功! ');
|
||||
this.props.fetchGroupMsg(group_id);
|
||||
// this.props.history.push('/group');
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
form.resetFields();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
showConfirm = () => {
|
||||
let that = this;
|
||||
confirm({
|
||||
title: "确认删除 " + that.props.projectMsg.name + " 项目吗?",
|
||||
content: <div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
|
||||
<Alert message="警告:此操作非常危险,会删除该项目下面所有接口,并且无法恢复!" type="warning" banner />
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<p style={{ marginBottom: '8px' }}><b>请输入项目名称确认此操作:</b></p>
|
||||
<Input id="project_name" size="large" />
|
||||
title: '确认删除 ' + that.props.projectMsg.name + ' 项目吗?',
|
||||
content: (
|
||||
<div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
|
||||
<Alert
|
||||
message="警告:此操作非常危险,会删除该项目下面所有接口,并且无法恢复!"
|
||||
type="warning"
|
||||
banner
|
||||
/>
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<p style={{ marginBottom: '8px' }}>
|
||||
<b>请输入项目名称确认此操作:</b>
|
||||
</p>
|
||||
<Input id="project_name" size="large" />
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
),
|
||||
onOk() {
|
||||
let groupName = trim(document.getElementById('project_name').value);
|
||||
if (that.props.projectMsg.name !== groupName) {
|
||||
message.error('项目名称有误')
|
||||
message.error('项目名称有误');
|
||||
return new Promise((resolve, reject) => {
|
||||
reject('error')
|
||||
})
|
||||
reject('error');
|
||||
});
|
||||
} else {
|
||||
that.props.delProject(that.props.projectId).then((res) => {
|
||||
that.props.delProject(that.props.projectId).then(res => {
|
||||
if (res.payload.data.errcode == 0) {
|
||||
message.success('删除成功!');
|
||||
that.props.history.push('/group/' + that.props.projectMsg.group_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
iconType: 'delete',
|
||||
onCancel() { }
|
||||
onCancel() {}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 修改项目头像的背景颜色
|
||||
changeProjectColor = (e) => {
|
||||
changeProjectColor = e => {
|
||||
const { _id, color, icon } = this.props.projectMsg;
|
||||
this.props.upsetProject({ id: _id, color: e.target.value || color, icon }).then((res) => {
|
||||
this.props.upsetProject({ id: _id, color: e.target.value || color, icon }).then(res => {
|
||||
if (res.payload.data.errcode === 0) {
|
||||
this.props.getProject(this.props.projectId);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
// 修改项目头像的图标
|
||||
changeProjectIcon = (e) => {
|
||||
changeProjectIcon = e => {
|
||||
const { _id, color, icon } = this.props.projectMsg;
|
||||
this.props.upsetProject({ id: _id, color, icon: e.target.value || icon }).then((res) => {
|
||||
this.props.upsetProject({ id: _id, color, icon: e.target.value || icon }).then(res => {
|
||||
if (res.payload.data.errcode === 0) {
|
||||
this.props.getProject(this.props.projectId);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 点击“查看危险操作”按钮
|
||||
toggleDangerOptions = () => {
|
||||
@ -157,195 +186,237 @@ class ProjectMessage extends Component {
|
||||
this.setState({
|
||||
showDangerOptions: !this.state.showDangerOptions
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async componentWillMount() {
|
||||
|
||||
await this.props.fetchGroupList();
|
||||
// await this.props.getProject(this.props.projectId);
|
||||
const groupMsg = await this.props.fetchGroupMsg(this.props.projectMsg.group_id);
|
||||
this.setState({
|
||||
currGroup: groupMsg.payload.data.data.group_name
|
||||
});
|
||||
await this.props.fetchGroupMsg(this.props.projectMsg.group_id);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const { projectMsg } = this.props;
|
||||
const mockUrl = location.protocol + '//' + location.hostname + (location.port !== "" ? ":" + location.port : "") + `/mock/${projectMsg._id}${projectMsg.basepath}+$接口请求路径`
|
||||
const { projectMsg, currGroup } = this.props;
|
||||
const mockUrl =
|
||||
location.protocol +
|
||||
'//' +
|
||||
location.hostname +
|
||||
(location.port !== '' ? ':' + location.port : '') +
|
||||
`/mock/${projectMsg._id}${projectMsg.basepath}+$接口请求路径`;
|
||||
let initFormValues = {};
|
||||
const { name, basepath, desc, project_type, group_id, switch_notice } = projectMsg;
|
||||
initFormValues = { name, basepath, desc, project_type, group_id, switch_notice };
|
||||
|
||||
const colorArr = entries(constants.PROJECT_COLOR);
|
||||
const colorSelector = (<RadioGroup onChange={this.changeProjectColor} value={projectMsg.color} className="color">
|
||||
{colorArr.map((item, index) => {
|
||||
return (<RadioButton key={index} value={item[0]} style={{ backgroundColor: item[1], color: '#fff', fontWeight: 'bold' }}>{item[0] === projectMsg.color ? <Icon type="check" /> : null}</RadioButton>);
|
||||
})}
|
||||
</RadioGroup>);
|
||||
const iconSelector = (<RadioGroup onChange={this.changeProjectIcon} value={projectMsg.icon} className="icon">
|
||||
{constants.PROJECT_ICON.map((item) => {
|
||||
return (<RadioButton key={item} value={item} style={{ fontWeight: 'bold' }}><Icon type={item} /></RadioButton>);
|
||||
})}
|
||||
</RadioGroup>);
|
||||
const colorSelector = (
|
||||
<RadioGroup onChange={this.changeProjectColor} value={projectMsg.color} className="color">
|
||||
{colorArr.map((item, index) => {
|
||||
return (
|
||||
<RadioButton
|
||||
key={index}
|
||||
value={item[0]}
|
||||
style={{ backgroundColor: item[1], color: '#fff', fontWeight: 'bold' }}
|
||||
>
|
||||
{item[0] === projectMsg.color ? <Icon type="check" /> : null}
|
||||
</RadioButton>
|
||||
);
|
||||
})}
|
||||
</RadioGroup>
|
||||
);
|
||||
const iconSelector = (
|
||||
<RadioGroup onChange={this.changeProjectIcon} value={projectMsg.icon} className="icon">
|
||||
{constants.PROJECT_ICON.map(item => {
|
||||
return (
|
||||
<RadioButton key={item} value={item} style={{ fontWeight: 'bold' }}>
|
||||
<Icon type={item} />
|
||||
</RadioButton>
|
||||
);
|
||||
})}
|
||||
</RadioGroup>
|
||||
);
|
||||
const selectDisbaled = projectMsg.role === 'owner' || projectMsg.role === 'admin';
|
||||
return (
|
||||
<div>
|
||||
<div className="m-panel">
|
||||
<Row className="project-setting">
|
||||
<Col xs={6} lg={{ offset: 1, span: 3 }} className="setting-logo">
|
||||
<Popover placement="bottom" title={colorSelector} content={iconSelector} trigger="click" overlayClassName="change-project-container">
|
||||
<Icon type={projectMsg.icon || 'star-o'} className="ui-logo" style={{ backgroundColor: constants.PROJECT_COLOR[projectMsg.color] || constants.PROJECT_COLOR.blue }} />
|
||||
<Popover
|
||||
placement="bottom"
|
||||
title={colorSelector}
|
||||
content={iconSelector}
|
||||
trigger="click"
|
||||
overlayClassName="change-project-container"
|
||||
>
|
||||
<Icon
|
||||
type={projectMsg.icon || 'star-o'}
|
||||
className="ui-logo"
|
||||
style={{
|
||||
backgroundColor:
|
||||
constants.PROJECT_COLOR[projectMsg.color] || constants.PROJECT_COLOR.blue
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
</Col>
|
||||
<Col xs={18} sm={15} lg={19} className="setting-intro">
|
||||
<h2 className="ui-title">{(this.state.currGroup || '') + ' / ' + (projectMsg.name || '')}</h2>
|
||||
<h2 className="ui-title">
|
||||
{(currGroup.group_name || '') + ' / ' + (projectMsg.name || '')}
|
||||
</h2>
|
||||
{/* <p className="ui-desc">{projectMsg.desc}</p> */}
|
||||
</Col>
|
||||
</Row>
|
||||
<hr className="breakline" />
|
||||
<Form>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="项目ID"
|
||||
>
|
||||
<span >{this.props.projectMsg._id}</span>
|
||||
|
||||
<Form>
|
||||
<FormItem {...formItemLayout} label="项目ID">
|
||||
<span>{this.props.projectMsg._id}</span>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="项目名称"
|
||||
>
|
||||
<FormItem {...formItemLayout} label="项目名称">
|
||||
{getFieldDecorator('name', {
|
||||
initialValue: initFormValues.name,
|
||||
rules: nameLengthLimit('项目')
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="所属分组"
|
||||
>
|
||||
<FormItem {...formItemLayout} label="所属分组">
|
||||
{getFieldDecorator('group_id', {
|
||||
initialValue: initFormValues.group_id + '',
|
||||
rules: [{
|
||||
required: true, message: '请选择项目所属的分组!'
|
||||
}]
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择项目所属的分组!'
|
||||
}
|
||||
]
|
||||
})(
|
||||
<Select>
|
||||
<Select disabled={!selectDisbaled}>
|
||||
{this.props.groupList.map((item, index) => (
|
||||
<Option value={item._id.toString()} key={index}>{item.group_name}</Option>
|
||||
<Option value={item._id.toString()} key={index}>
|
||||
{item.group_name}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
)}
|
||||
</FormItem>
|
||||
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={(
|
||||
label={
|
||||
<span>
|
||||
接口基本路径
|
||||
<Tooltip title="基本路径为空表示根路径">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('basepath', {
|
||||
initialValue: initFormValues.basepath,
|
||||
rules: [{
|
||||
required: false, message: '请输入基本路径! '
|
||||
}]
|
||||
})(
|
||||
<Input />
|
||||
)}
|
||||
rules: [
|
||||
{
|
||||
required: false,
|
||||
message: '请输入基本路径! '
|
||||
}
|
||||
]
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={(
|
||||
label={
|
||||
<span>
|
||||
MOCK地址
|
||||
<Tooltip title="具体使用方法请查看文档">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
}
|
||||
>
|
||||
|
||||
<Input disabled value={mockUrl} onChange={() => { }} />
|
||||
|
||||
<Input disabled value={mockUrl} onChange={() => {}} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="描述"
|
||||
>
|
||||
<FormItem {...formItemLayout} label="描述">
|
||||
{getFieldDecorator('desc', {
|
||||
initialValue: initFormValues.desc,
|
||||
rules: [{
|
||||
required: false
|
||||
}]
|
||||
})(
|
||||
<TextArea rows={8} />
|
||||
)}
|
||||
rules: [
|
||||
{
|
||||
required: false
|
||||
}
|
||||
]
|
||||
})(<TextArea rows={8} />)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="默认开启邮件通知"
|
||||
>
|
||||
{getFieldDecorator('switch_notice', { valuePropName: 'checked', initialValue: initFormValues.switch_notice })(
|
||||
<Switch checkedChildren="开" unCheckedChildren="关" />
|
||||
)}
|
||||
<FormItem {...formItemLayout} label="默认开启邮件通知">
|
||||
{getFieldDecorator('switch_notice', {
|
||||
valuePropName: 'checked',
|
||||
initialValue: initFormValues.switch_notice
|
||||
})(<Switch checkedChildren="开" unCheckedChildren="关" />)}
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label="权限"
|
||||
>
|
||||
<FormItem {...formItemLayout} label="权限">
|
||||
{getFieldDecorator('project_type', {
|
||||
rules: [{
|
||||
required: true
|
||||
}],
|
||||
rules: [
|
||||
{
|
||||
required: true
|
||||
}
|
||||
],
|
||||
initialValue: initFormValues.project_type
|
||||
})(
|
||||
<RadioGroup>
|
||||
<Radio value="private" className="radio">
|
||||
<Icon type="lock" />私有<br /><span className="radio-desc">只有组长和项目开发者可以索引并查看项目信息</span>
|
||||
<Icon type="lock" />私有<br />
|
||||
<span className="radio-desc">只有组长和项目开发者可以索引并查看项目信息</span>
|
||||
</Radio>
|
||||
<br />
|
||||
<Radio value="public" className="radio">
|
||||
<Icon type="unlock" />公开<br /><span className="radio-desc">任何人都可以索引并查看项目信息</span>
|
||||
<Icon type="unlock" />公开<br />
|
||||
<span className="radio-desc">任何人都可以索引并查看项目信息</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
)}
|
||||
)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
<div className="btnwrap-changeproject">
|
||||
<Button className="m-btn btn-save" icon="save" type="primary" size="large" onClick={this.handleOk} >保 存</Button>
|
||||
<Button
|
||||
className="m-btn btn-save"
|
||||
icon="save"
|
||||
type="primary"
|
||||
size="large"
|
||||
onClick={this.handleOk}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 只有组长和管理员有权限删除项目 */}
|
||||
{projectMsg.role === 'owner' || projectMsg.role === 'admin' ?
|
||||
{projectMsg.role === 'owner' || projectMsg.role === 'admin' ? (
|
||||
<div className="danger-container">
|
||||
<div className="title">
|
||||
<h2 className="content"><Icon type="exclamation-circle-o" /> 危险操作</h2>
|
||||
<Button onClick={this.toggleDangerOptions}>查 看<Icon type={this.state.showDangerOptions ? 'up' : 'down'} /></Button>
|
||||
<h2 className="content">
|
||||
<Icon type="exclamation-circle-o" /> 危险操作
|
||||
</h2>
|
||||
<Button onClick={this.toggleDangerOptions}>
|
||||
查 看<Icon type={this.state.showDangerOptions ? 'up' : 'down'} />
|
||||
</Button>
|
||||
</div>
|
||||
{this.state.showDangerOptions ? <Card hoverable={true} className="card-danger">
|
||||
<div className="card-danger-content">
|
||||
<h3>删除项目</h3>
|
||||
<p>项目一旦删除,将无法恢复数据,请慎重操作!</p>
|
||||
<p>只有组长和管理员有权限删除项目。</p>
|
||||
</div>
|
||||
<Button type="danger" ghost className="card-danger-btn" onClick={this.showConfirm}>删除</Button>
|
||||
</Card> : null}
|
||||
</div> : null}
|
||||
{this.state.showDangerOptions ? (
|
||||
<Card hoverable={true} className="card-danger">
|
||||
<div className="card-danger-content">
|
||||
<h3>删除项目</h3>
|
||||
<p>项目一旦删除,将无法恢复数据,请慎重操作!</p>
|
||||
<p>只有组长和管理员有权限删除项目。</p>
|
||||
</div>
|
||||
<Button
|
||||
type="danger"
|
||||
ghost
|
||||
className="card-danger-btn"
|
||||
onClick={this.showConfirm}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Card>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ export default (state = initialState, action) => {
|
||||
return {
|
||||
...state,
|
||||
role: action.payload.data.data.role,
|
||||
currGroup: action.payload.data.data,
|
||||
field: {
|
||||
name: action.payload.data.data.custom_field1.name,
|
||||
enable: action.payload.data.data.custom_field1.enable
|
||||
|
@ -26,6 +26,14 @@
|
||||
|
||||
<img src="./images/usage/project_setting_logo.png" />
|
||||
|
||||
## 项目迁移
|
||||
|
||||
YApi中支持项目迁移到不同的分组中
|
||||
|
||||
迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。
|
||||
|
||||
> Tips: owner权限判断的优先级是 项目权限 > 分组权限
|
||||
|
||||
|
||||
## 删除项目
|
||||
|
||||
|
@ -8,6 +8,12 @@
|
||||
### 进阶篇
|
||||
* [权限](manage.md)
|
||||
* [项目操作](project.md)
|
||||
* [新建项目](project.md#新建项目)
|
||||
* [修改项目](project.md#修改项目)
|
||||
* [项目迁移](project.md#项目迁移)
|
||||
* [配置环境](project.md#配置环境)
|
||||
* [请求配置](project.md#请求配置)
|
||||
* [token配置](project.md#token配置)
|
||||
* [接口操作](api.md)
|
||||
* [数据Mock](mock.md)
|
||||
* [高级Mock](adv_mock.md)
|
||||
|
@ -28,6 +28,13 @@
|
||||
|
||||
<img src="./images/usage/project_setting_logo.png" />
|
||||
|
||||
## 项目迁移
|
||||
|
||||
YApi中支持项目迁移到不同的分组中。
|
||||
|
||||
迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。
|
||||
|
||||
> Tips: owner权限判断的优先级是 项目权限 > 分组权限
|
||||
|
||||
## 删除项目
|
||||
|
||||
|
@ -128,6 +128,7 @@ class baseController {
|
||||
let projectInst = yapi.getInst(projectModel);
|
||||
let projectData = await projectInst.get(id);
|
||||
if (projectData.uid === this.getUid()) {
|
||||
// 建立项目的人
|
||||
return 'owner';
|
||||
}
|
||||
let memberData = _.find(projectData.members, (m) => {
|
||||
@ -135,6 +136,7 @@ class baseController {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
if (memberData && memberData.role) {
|
||||
if (memberData.role === 'owner') {
|
||||
@ -152,11 +154,12 @@ class baseController {
|
||||
if (type === 'group') {
|
||||
let groupInst = yapi.getInst(groupModel);
|
||||
let groupData = await groupInst.get(id);
|
||||
// 建立分组的人
|
||||
if (groupData.uid === this.getUid()) {
|
||||
return 'owner';
|
||||
}
|
||||
|
||||
|
||||
|
||||
let groupMemberData = _.find(groupData.members, (m) => {
|
||||
if (m.uid === this.getUid()) {
|
||||
return true;
|
||||
@ -188,6 +191,7 @@ class baseController {
|
||||
*/
|
||||
async checkAuth(id, type, action) {
|
||||
let role = await this.getProjectRole(id, type);
|
||||
console.log(role);
|
||||
if (action === 'danger') {
|
||||
if (role === 'admin' || role === 'owner') {
|
||||
return true;
|
||||
|
@ -1,19 +1,19 @@
|
||||
<html lang="zh-CN"><head><meta charSet="UTF-8"/><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="apple-mobile-web-app-status-bar-style" content="black"/><link rel="apple-touch-icon" sizes="180x180" href="../ydoc/images/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="../ydoc/images/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="../ydoc/images/favicon-16x16.png"/><link rel="manifest" href="../ydoc/images/manifest.json"/><link rel="mask-icon" href="../ydoc/images/safari-pinned-tab.svg"" color="#5bbad5"/><meta name="theme-color" content="#ffffff"/><meta http-equiv="Cache-Control" content="no-transform"/><meta http-equiv="Cache-Control" content="no-siteapp"/><title>内网部署</title><link rel="stylesheet" href="../ydoc/styles/style.css"/><meta name="author" content="ymfe"/><meta name="keywords" content="api管理,接口管理,接口文档,api文档"/><meta name="description" content="YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理"/><meta id="releativePath" content=".."/><link rel="stylesheet" href="../ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="../ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="../web.css"/></head><body><div class="g-doc"><div><div class="m-summary" id="js-menu"><div class="m-summary-content" id="js-menu-content"><div class="m-summary-block"><ul class="m-summary-list"><li class="item"><a href="index.html#%e5%ae%89%e8%a3%85" class="href">安装</a></li><li class="item"><a href="index.html#%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%ae%a1%e7%90%86" class="href">服务器管理</a></li><li class="item"><a href="index.html#%e5%8d%87%e7%ba%a7" class="href">升级</a></li><li class="item"><a href="index.html#%e9%85%8d%e7%bd%aeldap%e7%99%bb%e5%bd%95" class="href">配置LDAP登录</a></li></ul></div></div></div><div class="m-summary-switch" id="js-summary-switch"><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="bottom"><g transform="translate(904.92214,-879.1482)"><path d="m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,-55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894,0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892,-174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696,-174.68583 0.6895,0 26.281,25.03215 56.8701,55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,-104.0616 -231.873,-231.248 z" fill="#fff"></path></g></svg><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="top"><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="aaa" fill="#fff" fill-rule="nonzero"><path d="M231.2455,342.502 L0,111.25397 L55.6165,55.62697 C86.2056,25.03212 111.7971,-2.99999998e-05 112.4866,-2.99999998e-05 C113.176,-2.99999998e-05 192.3503,78.60859 288.4293,174.6858 L463.1185,349.3716 L637.8077,174.6858 C733.8867,78.60859 813.060896,-2.99999997e-05 813.750396,-2.99999997e-05 C814.439896,-2.99999997e-05 840.031396,25.03212 870.620496,55.62697 L926.236996,111.25397 L694.9915,342.502 C567.8065,469.6884 463.4636,573.75 463.1185,573.75 C462.7734,573.75 358.4305,469.6884 231.2455,342.502 Z" id="Shape" transform="translate(463.118498, 286.874985) scale(1, -1) translate(-463.118498, -286.874985) "></path></g></g></svg></div></div><div class="m-main" id="js-panel"><header class="m-header" id="js-header"><div class="m-header-title js-logo"><a href="../index.html" target="_self"><img class="logo" width="36" src="../documents/images/logo_header@2x.png"/><h6 class="name">YApi</h6></a></div><div><div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索文档内容" />
|
||||
<html lang="zh-CN"><head><meta charSet="UTF-8"/><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="apple-mobile-web-app-status-bar-style" content="black"/><link rel="apple-touch-icon" sizes="180x180" href="../ydoc/images/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="../ydoc/images/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="../ydoc/images/favicon-16x16.png"/><link rel="manifest" href="../ydoc/images/manifest.json"/><link rel="mask-icon" href="../ydoc/images/safari-pinned-tab.svg"" color="#5bbad5"/><meta name="theme-color" content="#ffffff"/><meta http-equiv="Cache-Control" content="no-transform"/><meta http-equiv="Cache-Control" content="no-siteapp"/><title>内网部署</title><link rel="stylesheet" href="../ydoc/styles/style.css"/><meta name="author" content="ymfe"/><meta name="keywords" content="api管理,接口管理,接口文档,api文档"/><meta name="description" content="YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理"/><meta id="releativePath" content=".."/><link rel="stylesheet" href="../ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="../ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="../web.css"/></head><body><div class="g-doc"><div class="m-aside"><div class="m-summary" id="js-menu"><div class="m-summary-content" id="js-menu-content"><div class="m-summary-block"><ul class="m-summary-list"><li class="item"><a href="index.html#%e5%ae%89%e8%a3%85" class="href">安装</a></li><li class="item"><a href="index.html#%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%ae%a1%e7%90%86" class="href">服务器管理</a></li><li class="item"><a href="index.html#%e5%8d%87%e7%ba%a7" class="href">升级</a></li><li class="item"><a href="index.html#%e9%85%8d%e7%bd%aeldap%e7%99%bb%e5%bd%95" class="href">配置LDAP登录</a></li></ul></div></div></div><div class="m-summary-switch" id="js-summary-switch"><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="bottom"><g transform="translate(904.92214,-879.1482)"><path d="m -673.67664,1221.6502 -231.2455,-231.24803 55.6165,-55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894,0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892,-174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696,-174.68583 0.6895,0 26.281,25.03215 56.8701,55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,-104.0616 -231.873,-231.248 z" fill="#fff"></path></g></svg><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="top"><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="aaa" fill="#fff" fill-rule="nonzero"><path d="M231.2455,342.502 L0,111.25397 L55.6165,55.62697 C86.2056,25.03212 111.7971,-2.99999998e-05 112.4866,-2.99999998e-05 C113.176,-2.99999998e-05 192.3503,78.60859 288.4293,174.6858 L463.1185,349.3716 L637.8077,174.6858 C733.8867,78.60859 813.060896,-2.99999997e-05 813.750396,-2.99999997e-05 C814.439896,-2.99999997e-05 840.031396,25.03212 870.620496,55.62697 L926.236996,111.25397 L694.9915,342.502 C567.8065,469.6884 463.4636,573.75 463.1185,573.75 C462.7734,573.75 358.4305,469.6884 231.2455,342.502 Z" id="Shape" transform="translate(463.118498, 286.874985) scale(1, -1) translate(-463.118498, -286.874985) "></path></g></g></svg></div></div><div class="m-main" id="js-panel"><header class="m-header" id="js-header"><div class="m-header-title js-logo"><a href="../index.html" target="_self"><img class="logo" width="36" src="../documents/images/logo_header@2x.png"/><h6 class="name">YApi</h6></a></div><div><div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索" />
|
||||
<div class="m-search-result js-search-result"></div>
|
||||
</div>
|
||||
<div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索文档内容" />
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索" />
|
||||
<div class="m-search-result js-search-result"></div>
|
||||
</div></div><nav class="m-header-nav js-nav"><ul class="m-header-items"><li class="item "><a class="href" href="../documents/index.html">教程</a></li><li class="item active"><a class="href" href="">内网部署</a></li></ul></nav><div id="js-nav-btn" class="m-header-btn ui-font-ydoc"></div></header><div class="m-content" id="js-content"><div id="markdown-body" class="m-content-container markdown-body"><h1>内网部署</h1>
|
||||
<p>使用我们提供的 yapi-cli 工具,部署 YApi 平台是非常容易的。建议部署成 http 站点,因 chrome 浏览器安全限制,部署成 https 会导致测试功能在请求 http 站点时文件上传功能异常。</p>
|
||||
<p>如果您是将服务器代理到 nginx 服务器,请配置 nginx 支持 websocket。</p>
|
||||
<pre><code>在location /添加
|
||||
<pre><code>在location /添加
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Connection "upgrade";
|
||||
</code></pre>
|
||||
<h2 id="环境要求">环境要求</h2>
|
||||
<ul>
|
||||
@ -23,25 +23,25 @@ proxy_set_header Connection "upgrade";
|
||||
<h2 id="安装">安装</h2>
|
||||
<h3 id="安装-方式一.-可视化部署[推荐]">方式一. 可视化部署[推荐]</h3>
|
||||
<p>执行 yapi server 启动可视化部署程序,输入相应的配置和点击开始部署,就能完成整个网站的部署。部署完成之后,可按照提示信息,执行 node/{网站路径/server/app.js} 启动服务器。在浏览器打开指定url, 点击登录输入您刚才设置的管理员邮箱,默认密码(ymfe.org) 登录系统(默认密码可在个人中心修改)。</p>
|
||||
<pre><code class="language-bash">npm install -g yapi-cli --registry https://registry.npm.taobao.org
|
||||
<pre><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> -g yapi-cli --registry https://registry.npm.taobao.org
|
||||
yapi server
|
||||
</code></pre>
|
||||
<h3 id="安装-方式二.-命令行部署">方式二. 命令行部署</h3>
|
||||
<p>如果 github 压缩文件无法下载,或需要部署到一些特殊的服务器,可尝试此方法</p>
|
||||
<pre><code class="language-bash">mkdir yapi
|
||||
<span class="hljs-built_in">cd</span> yapi
|
||||
git <span class="hljs-built_in">clone</span> https://github.com/YMFE/yapi.git vendors //或者下载 zip 包解压到 vendors 目录
|
||||
cp vendors/config_example.json ./config.json //复制完成后请修改相关配置
|
||||
<span class="hljs-built_in">cd</span> vendors
|
||||
npm install --production --registry https://registry.npm.taobao.org
|
||||
npm run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
|
||||
node server/app.js //启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候
|
||||
<pre><code class="language-bash"><span class="token function">mkdir</span> yapi
|
||||
<span class="token function">cd</span> yapi
|
||||
<span class="token function">git</span> clone https://github.com/YMFE/yapi.git vendors //或者下载 <span class="token function">zip</span> 包解压到 vendors 目录
|
||||
<span class="token function">cp</span> vendors/config_example.json ./config.json //复制完成后请修改相关配置
|
||||
<span class="token function">cd</span> vendors
|
||||
<span class="token function">npm</span> <span class="token function">install</span> --production --registry https://registry.npm.taobao.org
|
||||
<span class="token function">npm</span> run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
|
||||
node server/app.js //启动服务器后,请访问 127.0.0.1:<span class="token punctuation">{</span>config.json配置的端口<span class="token punctuation">}</span>,初次运行会有个编译的过程,请耐心等候
|
||||
</code></pre>
|
||||
<p>安装后的目录结构如下:</p>
|
||||
<pre><code>|-- config.json
|
||||
|-- init.lock
|
||||
|-- log
|
||||
`-- vendors
|
||||
`-- vendors
|
||||
|-- CHANGELOG.md
|
||||
|-- LICENSE
|
||||
|-- README.md
|
||||
@ -60,7 +60,7 @@ node server/app.js //启动服务器后,请访问 127.0.0.1:{config.json配置
|
||||
|-- webpack.alias.js
|
||||
|-- yapi-base-flow.jpg
|
||||
|-- ydocfile.js
|
||||
`-- ykit.config.js
|
||||
`-- ykit.config.js
|
||||
</code></pre>
|
||||
<h2 id="服务器管理">服务器管理</h2>
|
||||
<p>推荐使用 pm2 管理 node 服务器启动,停止,具体使用方法可参考下面的教程:</p>
|
||||
@ -78,17 +78,17 @@ yapi update -v v1.1.0 //升级到指定版本
|
||||
<h2 id="配置邮箱">配置邮箱</h2>
|
||||
<p>打开项目目录 config.json 文件,新增 mail 配置, 替换默认的邮箱配置</p>
|
||||
<pre><code>{
|
||||
"port": "*****",
|
||||
"adminAccount": "********",
|
||||
"db": {...},
|
||||
"mail": {
|
||||
"enable": true,
|
||||
"host": "smtp.163.com", //邮箱服务器
|
||||
"port": 465, //端口
|
||||
"from": "***@163.com", //发送人邮箱
|
||||
"auth": {
|
||||
"user": "***@163.com", //邮箱服务器账号
|
||||
"pass": "*****" //邮箱服务器密码
|
||||
"port": "*****",
|
||||
"adminAccount": "********",
|
||||
"db": {...},
|
||||
"mail": {
|
||||
"enable": true,
|
||||
"host": "smtp.163.com", //邮箱服务器
|
||||
"port": 465, //端口
|
||||
"from": "***@163.com", //发送人邮箱
|
||||
"auth": {
|
||||
"user": "***@163.com", //邮箱服务器账号
|
||||
"pass": "*****" //邮箱服务器密码
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,17 +97,17 @@ yapi update -v v1.1.0 //升级到指定版本
|
||||
<h2 id="配置ldap登录">配置LDAP登录</h2>
|
||||
<p>打开项目目录 config.json 文件,添加如下字段:</p>
|
||||
<pre><code>{
|
||||
"port": "*****",
|
||||
"adminAccount": "********",
|
||||
"db": {...},
|
||||
"mail": {...},
|
||||
"ldapLogin": {
|
||||
"enable": true,
|
||||
"server": "ldap://l-ldapt1.ops.dev.cn0.qunar.com",
|
||||
"baseDn": "CN=Admin,CN=Users,DC=test,DC=com",
|
||||
"bindPassword": "password123",
|
||||
"searchDn": "OU=UserContainer,DC=test,DC=com",
|
||||
"searchStandard": "mail"
|
||||
"port": "*****",
|
||||
"adminAccount": "********",
|
||||
"db": {...},
|
||||
"mail": {...},
|
||||
"ldapLogin": {
|
||||
"enable": true,
|
||||
"server": "ldap://l-ldapt1.ops.dev.cn0.qunar.com",
|
||||
"baseDn": "CN=Admin,CN=Users,DC=test,DC=com",
|
||||
"bindPassword": "password123",
|
||||
"searchDn": "OU=UserContainer,DC=test,DC=com",
|
||||
"searchStandard": "mail"
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
static/doc/documents/images/usage/adv-mock-case4 2.png
Normal file
BIN
static/doc/documents/images/usage/adv-mock-case4 2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
BIN
static/doc/documents/images/usage/chrome-2 2.jpg
Normal file
BIN
static/doc/documents/images/usage/chrome-2 2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
BIN
static/doc/documents/images/usage/json-schema-mock 2.jpg
Normal file
BIN
static/doc/documents/images/usage/json-schema-mock 2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
BIN
static/doc/documents/images/usage/project_setting_env 2.png
Normal file
BIN
static/doc/documents/images/usage/project_setting_env 2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,13 +1,13 @@
|
||||
<html lang="zh-CN"><head><meta charSet="UTF-8"/><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="apple-mobile-web-app-status-bar-style" content="black"/><link rel="apple-touch-icon" sizes="180x180" href="ydoc/images/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="ydoc/images/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="ydoc/images/favicon-16x16.png"/><link rel="manifest" href="ydoc/images/manifest.json"/><link rel="mask-icon" href="ydoc/images/safari-pinned-tab.svg"" color="#5bbad5"/><meta name="theme-color" content="#ffffff"/><meta http-equiv="Cache-Control" content="no-transform"/><meta http-equiv="Cache-Control" content="no-siteapp"/><title>YApi 接口管理平台</title><link rel="stylesheet" href="ydoc/styles/style.css"/><meta name="author" content="ymfe"/><meta name="keywords" content="api管理,接口管理,接口文档,api文档"/><meta name="description" content="YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理"/><meta id="releativePath" content=""/><link rel="stylesheet" href="ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="web.css"/></head><body><div class="g-doc"><div class="m-main" id="js-panel"><header class="m-header" id="js-header"><div class="m-header-title js-logo"><a href="" target="_self"><img class="logo" width="36" src="documents/images/logo_header@2x.png"/><h6 class="name">YApi</h6></a></div><div><div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索文档内容" />
|
||||
<html lang="zh-CN"><head><meta charSet="UTF-8"/><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="apple-mobile-web-app-status-bar-style" content="black"/><link rel="apple-touch-icon" sizes="180x180" href="ydoc/images/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="ydoc/images/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="ydoc/images/favicon-16x16.png"/><link rel="manifest" href="ydoc/images/manifest.json"/><link rel="mask-icon" href="ydoc/images/safari-pinned-tab.svg"" color="#5bbad5"/><meta name="theme-color" content="#ffffff"/><meta http-equiv="Cache-Control" content="no-transform"/><meta http-equiv="Cache-Control" content="no-siteapp"/><title>YApi 接口管理平台</title><link rel="stylesheet" href="ydoc/styles/style.css"/><meta name="author" content="ymfe"/><meta name="keywords" content="api管理,接口管理,接口文档,api文档"/><meta name="description" content="YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理"/><meta id="releativePath" content=""/><link rel="stylesheet" href="ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="ydoc/ydoc-plugin-search/search.css"/><link rel="stylesheet" href="web.css"/></head><body><div class="g-doc"><div class="m-main" id="js-panel"><header class="m-header" id="js-header"><div class="m-header-title js-logo"><a href="" target="_self"><img class="logo" width="36" src="documents/images/logo_header@2x.png"/><h6 class="name">YApi</h6></a></div><div><div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索" />
|
||||
<div class="m-search-result js-search-result"></div>
|
||||
</div>
|
||||
<div class="m-search">
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索文档内容" />
|
||||
<div class="icon"></div>
|
||||
<input type="text" class="input js-input" placeholder="搜索" />
|
||||
<div class="m-search-result js-search-result"></div>
|
||||
</div></div><nav class="m-header-nav js-nav"><ul class="m-header-items"><li class="item "><a class="href" href="documents/index.html">教程</a></li><li class="item "><a class="href" href="devops/index.html">内网部署</a></li></ul></nav><div id="js-nav-btn" class="m-header-btn ui-font-ydoc"></div></header><div class="m-content" id="js-content"><div><div class="g-home"><section class="m-section home"><div class="m-section-container"><div class="m-section-title"><h4 class="name">YApi</h4><p class="desc">旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API</p><div class="m-section-btngroup"><a href="./documents/index.html"><div class="btn ">开始</div></a><a href="https://github.com/ymfe/yapi"><div class="btn btn-ghost">Github ></div></a></div><p class="caption">当前版本: v1.3.9</p></div><div class="m-section-banner"><img src="./ydoc/images/dogbg@1x.png" alt="bg" srcSet="./ydoc/images/dogbg@2x.png 2x"/></div></div></section><section class="m-section feature"><div class="m-section-container"><div class="m-section-box"><div class="item"><h6 class="title">权限管理</h6><p class="desc">YApi 成熟的团队管理扁平化项目权限配置满足各类企业的需求</p></div><div class="item"><h6 class="title">可视化接口管理</h6><p class="desc">基于 websocket 的多人协作接口编辑功能和类 postman 测试工具,让多人协作成倍提升开发效率</p></div><div class="item"><h6 class="title">Mock Server</h6><p class="desc">易用的 Mock Server,再也不用担心 mock 数据的生成了</p></div><div class="item"><h6 class="title">自动化测试</h6><p class="desc">完善的接口自动化测试,保证数据的正确性</p></div><div class="item"><h6 class="title">数据导入</h6><p class="desc">支持导入 swagger, postman, har 数据格式,方便迁移旧项目</p></div><div class="item"><h6 class="title">插件机制</h6><p class="desc">强大的插件机制,满足各类业务需求</p></div></div></div></section></div><footer class="m-footer"><div class="m-footer-container"><div class="m-footer-links"><div class="group"><p class="title">团队网址</p><ul><li><a class="href" href="https://ymfe.org/">YMFE</a></li><li><a class="href" href="https://blog.ymfe.org/">YMFE Blog</a></li></ul></div><div class="group"><p class="title">Git仓库</p><ul><li><a class="href" href="https://github.com/YMFE/yapi">Github</a></li><li><a class="href" href="https://github.com/YMFE/yapi/issues">Github Issue</a></li></ul></div></div><div class="m-footer-title"><p class="copyright">© 2018 <a class="href" href="https://ymfe.org/">YMFE Team</a></p><p>Build by <a class="href" href="https://ydoc.ymfe.org/">ydoc</a></p></div></div></footer></div></div></div></div><div></div><script>
|
||||
</div></div><nav class="m-header-nav js-nav"><ul class="m-header-items"><li class="item "><a class="href" href="documents/index.html">教程</a></li><li class="item "><a class="href" href="devops/index.html">内网部署</a></li></ul></nav><div id="js-nav-btn" class="m-header-btn ui-font-ydoc"></div></header><div class="m-content" id="js-content"><div><div class="g-home"><section class="m-section home"><div class="m-section-container"><div class="m-section-title"><h4 class="name">YApi</h4><p class="desc">旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API</p><div class="m-section-btngroup"><a href="./documents/index.html"><div class="btn ">开始</div></a><a href="https://github.com/ymfe/yapi"><div class="btn btn-ghost">Github ></div></a></div><p class="caption">当前版本: v1.3.9</p></div><div class="m-section-banner"><img src="./ydoc/images/dogbg@1x.png" alt="bg" srcSet="./ydoc/images/dogbg@2x.png 2x"/></div></div></section><section class="m-section feature"><div class="m-section-container"><div class="m-section-box"><div class="item"><h6 class="title">权限管理</h6><p class="desc">YApi 成熟的团队管理扁平化项目权限配置满足各类企业的需求</p></div><div class="item"><h6 class="title">可视化接口管理</h6><p class="desc">基于 websocket 的多人协作接口编辑功能和类 postman 测试工具,让多人协作成倍提升开发效率</p></div><div class="item"><h6 class="title">Mock Server</h6><p class="desc">易用的 Mock Server,再也不用担心 mock 数据的生成了</p></div><div class="item"><h6 class="title">自动化测试</h6><p class="desc">完善的接口自动化测试,保证数据的正确性</p></div><div class="item"><h6 class="title">数据导入</h6><p class="desc">支持导入 swagger, postman, har 数据格式,方便迁移旧项目</p></div><div class="item"><h6 class="title">插件机制</h6><p class="desc">强大的插件机制,满足各类业务需求</p></div></div></div></section></div><footer class="m-footer"><div class="m-footer-container"><div class="m-footer-links"><div class="group"><p class="title">团队网址</p><ul><li><a class="href" href="https://ymfe.org/">YMFE</a></li><li><a class="href" href="https://blog.ymfe.org/">YMFE Blog</a></li></ul></div><div class="group"><p class="title">Git仓库</p><ul><li><a class="href" href="https://github.com/YMFE/yapi">Github</a></li><li><a class="href" href="https://github.com/YMFE/yapi/issues">Github Issue</a></li></ul></div></div><div class="m-footer-title"><p class="copyright">© 2018 <a class="href" href="https://ymfe.org/">YMFE Team</a></p><p>Build by <a class="href" href="https://ydoc.ymfe.org/">ydoc</a></p></div></div></footer></div></div></div></div><div></div><script>
|
||||
var $content = document.getElementById('js-content');
|
||||
var $summaryItems = Array.prototype.slice.call(document.querySelectorAll('#js-menu .href'));
|
||||
var $menu = document.getElementById('js-menu');
|
||||
|
@ -192,6 +192,11 @@ window.ydoc_plugin_search_json = {
|
||||
"url": "/documents/project.html#修改项目-修改项目图标",
|
||||
"content": "修改项目图标点击项目图标,可以修改图标及背景色:"
|
||||
},
|
||||
{
|
||||
"title": "项目迁移",
|
||||
"url": "/documents/project.html#项目迁移",
|
||||
"content": "项目迁移YApi中支持项目迁移到不同的分组中。迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。Tips: owner权限判断的优先级是 项目权限 > 分组权限\n"
|
||||
},
|
||||
{
|
||||
"title": "删除项目",
|
||||
"url": "/documents/project.html#删除项目",
|
||||
@ -249,6 +254,11 @@ window.ydoc_plugin_search_json = {
|
||||
"url": "/documents/project.html#修改项目-修改项目图标",
|
||||
"content": "修改项目图标点击项目图标,可以修改图标及背景色:"
|
||||
},
|
||||
{
|
||||
"title": "项目迁移",
|
||||
"url": "/documents/project.html#项目迁移",
|
||||
"content": "项目迁移YApi中支持项目迁移到不同的分组中。迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。Tips: owner权限判断的优先级是 项目权限 > 分组权限\n"
|
||||
},
|
||||
{
|
||||
"title": "删除项目",
|
||||
"url": "/documents/project.html#删除项目",
|
||||
@ -1035,10 +1045,20 @@ window.ydoc_plugin_search_json = {
|
||||
"content": "",
|
||||
"url": "/documents/CHANGELOG.html",
|
||||
"children": [
|
||||
{
|
||||
"title": "v1.3.12",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.12",
|
||||
"content": "v1.3.12Feature接口列表支持路径查询\nBug Fixed项目中访客权限的账号可以 增、删、改接口中高级mock的设置\n高级Mock 中的响应时间值无法保存(实际提示为:保存成功)\n分类为空时添加接口\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.11",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.11",
|
||||
"content": "v1.3.11修复 v1.3.10 websocket 连接问题\n修复运行报错问题\n修复数据导入 har 文件问题\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.9",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.9",
|
||||
"content": "v1.3.9Feature增加接口编辑返回数据预览\n修复旧的文档链接\n"
|
||||
"content": "v1.3.9Feature增加接口编辑返回数据预览\n修复旧的文档链接\nBug Fixed导入数据为空提示\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.8",
|
||||
@ -1152,10 +1172,20 @@ window.ydoc_plugin_search_json = {
|
||||
"content": "",
|
||||
"url": "/documents/CHANGELOG.html",
|
||||
"children": [
|
||||
{
|
||||
"title": "v1.3.12",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.12",
|
||||
"content": "v1.3.12Feature接口列表支持路径查询\nBug Fixed项目中访客权限的账号可以 增、删、改接口中高级mock的设置\n高级Mock 中的响应时间值无法保存(实际提示为:保存成功)\n分类为空时添加接口\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.11",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.11",
|
||||
"content": "v1.3.11修复 v1.3.10 websocket 连接问题\n修复运行报错问题\n修复数据导入 har 文件问题\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.9",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.9",
|
||||
"content": "v1.3.9Feature增加接口编辑返回数据预览\n修复旧的文档链接\n"
|
||||
"content": "v1.3.9Feature增加接口编辑返回数据预览\n修复旧的文档链接\nBug Fixed导入数据为空提示\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.8",
|
||||
|
BIN
static/doc/ydoc/images/dogbg@1x 2.png
Normal file
BIN
static/doc/ydoc/images/dogbg@1x 2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
static/doc/ydoc/images/favicon-32x32 2.png
Normal file
BIN
static/doc/ydoc/images/favicon-32x32 2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
87
static/doc/ydoc/scripts/app 2.js
Normal file
87
static/doc/ydoc/scripts/app 2.js
Normal file
@ -0,0 +1,87 @@
|
||||
var $panel = document.getElementById('js-panel'),
|
||||
$header = document.getElementById('js-header'),
|
||||
$content = document.getElementById('js-content'),
|
||||
$navIcon = document.getElementById('js-nav-btn'),
|
||||
$summaryItems = Array.prototype.slice.call(document.querySelectorAll('#js-menu .href')),
|
||||
$menu = document.getElementById('js-menu'),
|
||||
$menuContent = document.getElementById('js-menu-content'),
|
||||
$menuBar = document.getElementById('js-summary-switch'),
|
||||
navigation;
|
||||
|
||||
var utils = {
|
||||
debounce: function(func, wait) {
|
||||
var timeout;
|
||||
return function () {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(func, wait);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Add 'active' to summary item
|
||||
function itemAddActive() {
|
||||
var locationHref = window.location.href;
|
||||
$summaryItems.map(function (item, index) {
|
||||
if (item.href === locationHref) {
|
||||
// add 'active' for present summary item.
|
||||
item.parentElement.classList.add('active');
|
||||
} else {
|
||||
item.parentElement.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add EventListener
|
||||
function addEvents() {
|
||||
$panel.addEventListener('click', function (e) {
|
||||
itemAddActive();
|
||||
if (e.target.scrollTop > 0) {
|
||||
$header.classList.add('moved');
|
||||
} else {
|
||||
$header.classList.remove('moved');
|
||||
}
|
||||
});
|
||||
if ($menuContent) {
|
||||
$menuContent.addEventListener('click', function (e) {
|
||||
$menu.classList.remove('active');
|
||||
setTimeout(itemAddActive, 0);
|
||||
});
|
||||
}
|
||||
if ($menuBar) {
|
||||
$menuBar.addEventListener('click', function () {
|
||||
$menu.classList.toggle('active');
|
||||
// 侧栏菜单点击时收起 nav 导航
|
||||
if ($navIcon.classList.value.indexOf('active') !== -1) {
|
||||
navigation.toggle();
|
||||
}
|
||||
});
|
||||
}
|
||||
if ($menu) {
|
||||
$menu.addEventListener('scroll', function(e) {
|
||||
sessionStorage.setItem('menuScrollTop', e.target.scrollTop);
|
||||
});
|
||||
}
|
||||
if ($content) {
|
||||
$content.addEventListener('scroll', function (e) {
|
||||
sessionStorage.setItem('contentScrollTop', e.target.scrollTop);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// initial components
|
||||
function initComponents() {
|
||||
// nav
|
||||
navigation = responsiveNav('.js-nav', {
|
||||
customToggle: '#js-nav-btn',
|
||||
open: function() {
|
||||
$menu.classList.remove('active');
|
||||
setTimeout(itemAddActive, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
initComponents();
|
||||
addEvents();
|
||||
itemAddActive();
|
||||
|
@ -1,10 +1,12 @@
|
||||
var $panel = document.getElementById('js-panel');
|
||||
var $header = document.getElementById('js-header');
|
||||
var $content = document.getElementById('js-content');
|
||||
var $summaryItems = Array.prototype.slice.call(document.querySelectorAll('#js-menu .href'));
|
||||
var $menu = document.getElementById('js-menu');
|
||||
var $menuContent = document.getElementById('js-menu-content');
|
||||
var $menuBar = document.getElementById('js-summary-switch');
|
||||
var $panel = document.getElementById('js-panel'),
|
||||
$header = document.getElementById('js-header'),
|
||||
$content = document.getElementById('js-content'),
|
||||
$navIcon = document.getElementById('js-nav-btn'),
|
||||
$summaryItems = Array.prototype.slice.call(document.querySelectorAll('#js-menu .href')),
|
||||
$menu = document.getElementById('js-menu'),
|
||||
$menuContent = document.getElementById('js-menu-content'),
|
||||
$menuBar = document.getElementById('js-summary-switch'),
|
||||
navigation;
|
||||
|
||||
var utils = {
|
||||
debounce: function(func, wait) {
|
||||
@ -48,6 +50,10 @@ function addEvents() {
|
||||
if ($menuBar) {
|
||||
$menuBar.addEventListener('click', function () {
|
||||
$menu.classList.toggle('active');
|
||||
// 侧栏菜单点击时收起 nav 导航
|
||||
if ($navIcon.classList.value.indexOf('active') !== -1) {
|
||||
navigation.toggle();
|
||||
}
|
||||
});
|
||||
}
|
||||
if ($menu) {
|
||||
@ -65,11 +71,13 @@ function addEvents() {
|
||||
// initial components
|
||||
function initComponents() {
|
||||
// nav
|
||||
var navigation = responsiveNav('.js-nav', {
|
||||
customToggle: '#js-nav-btn'
|
||||
navigation = responsiveNav('.js-nav', {
|
||||
customToggle: '#js-nav-btn',
|
||||
open: function() {
|
||||
$menu.classList.remove('active');
|
||||
setTimeout(itemAddActive, 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
6
static/doc/ydoc/scripts/plugins/dollar.min 2.js
Normal file
6
static/doc/ydoc/scripts/plugins/dollar.min 2.js
Normal file
File diff suppressed because one or more lines are too long
1
static/doc/ydoc/scripts/plugins/responsive-nav.min 2.js
Normal file
1
static/doc/ydoc/scripts/plugins/responsive-nav.min 2.js
Normal file
File diff suppressed because one or more lines are too long
@ -559,79 +559,6 @@ a:link, a:visited {
|
||||
background-color: #051d33;
|
||||
}
|
||||
|
||||
/* From https://github.com/isagalaev/highlight.js/blob/9.8.0/src/styles/tomorrow.css */
|
||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
||||
/* Tomorrow Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #8e908c;
|
||||
}
|
||||
|
||||
/* Tomorrow Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-regexp,
|
||||
.hljs-deletion {
|
||||
color: #c82829;
|
||||
}
|
||||
|
||||
/* Tomorrow Orange */
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params,
|
||||
.hljs-meta,
|
||||
.hljs-link {
|
||||
color: #f5871f;
|
||||
}
|
||||
|
||||
/* Tomorrow Yellow */
|
||||
.hljs-attribute {
|
||||
color: #eab700;
|
||||
}
|
||||
|
||||
/* Tomorrow Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-addition {
|
||||
color: #718c00;
|
||||
}
|
||||
|
||||
/* Tomorrow Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #4271ae;
|
||||
}
|
||||
|
||||
/* Tomorrow Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #8959a8;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: white;
|
||||
color: #4d4d4c;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*! responsive-nav.js 1.0.39 by @viljamis */
|
||||
.m-header-nav ul {
|
||||
margin: 0;
|
||||
@ -1458,6 +1385,145 @@ body {
|
||||
border-bottom-color: rgba(3, 17, 31, 0.87);
|
||||
}
|
||||
|
||||
/* PrismJS 1.14.0
|
||||
http://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.g-doc {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@ -1622,7 +1688,7 @@ body {
|
||||
background-color: #fff;
|
||||
padding: .08rem 1.5em;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 50px 100px rgba(50, 50, 93, 0.1), 0 15px 35px rgba(50, 50, 93, 0.15), 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 10px 100px rgba(50, 50, 93, 0.1), 0 5px 35px rgba(50, 50, 93, 0.15), 0 2px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.m-header-nav .m-header-subtitle .item {
|
||||
margin: 0;
|
||||
@ -1659,9 +1725,14 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.m-aside {
|
||||
margin-top: .65rem;
|
||||
height: 100%;
|
||||
height: calc(100% - .65rem);
|
||||
}
|
||||
|
||||
.m-summary {
|
||||
padding: .24rem;
|
||||
padding-bottom: 0;
|
||||
padding: 0 .24rem;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -1669,8 +1740,9 @@ body {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow-y: auto;
|
||||
transform: translateY(0);
|
||||
-webkit-overflow-scrolling: touch;
|
||||
transition: all .2s;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
.m-summary ul, .m-summary ol, .m-summary li {
|
||||
@ -1680,6 +1752,9 @@ body {
|
||||
.m-summary.active {
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
padding: .24rem;
|
||||
padding-bottom: 0.89rem;
|
||||
transform: translateY(0.65rem);
|
||||
}
|
||||
|
||||
.m-summary.active .m-summary-content {
|
||||
@ -1779,8 +1854,7 @@ body {
|
||||
position: static;
|
||||
height: 100%;
|
||||
width: 2.4rem;
|
||||
padding: .4rem .32rem .8rem;
|
||||
margin-top: .64rem;
|
||||
padding: .4rem .32rem;
|
||||
flex: 3rem 0 0;
|
||||
}
|
||||
.m-summary-switch {
|
||||
@ -2029,7 +2103,7 @@ body {
|
||||
}
|
||||
|
||||
.g-home .m-section .btn:active {
|
||||
background-color: #d9edff;
|
||||
background-color: #0e5699;
|
||||
}
|
||||
|
||||
.g-home .m-section .btn.btn-ghost {
|
||||
|
125
static/doc/ydoc/ydoc-plugin-search/search 2.js
Normal file
125
static/doc/ydoc/ydoc-plugin-search/search 2.js
Normal file
@ -0,0 +1,125 @@
|
||||
$(function(){
|
||||
var $searchResult = $('.js-search-result'),
|
||||
$searchInput = $('.js-input'),
|
||||
activeIndex = 0;
|
||||
|
||||
// 去除空格
|
||||
String.prototype.trim = function () {
|
||||
return this.replace(/(^\s*)|(\s*$)/g, '');
|
||||
};
|
||||
|
||||
// 判断是否为空对象
|
||||
function realObj(obj) {
|
||||
for (var i in obj) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 防抖函数
|
||||
function debounce(func, wait) {
|
||||
var timeout;
|
||||
return function () {
|
||||
var context = this, args = arguments;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() {
|
||||
func.apply(context, args);
|
||||
}, wait);
|
||||
};
|
||||
}
|
||||
|
||||
var highlightTextPrevNum = 6;
|
||||
var highlightTextNextNum = 20;
|
||||
// 简化文本内容长度
|
||||
function simplifyStrDom(str, val) {
|
||||
var index = str.indexOf(val);
|
||||
var startIndex = index > highlightTextPrevNum ? index - highlightTextPrevNum : 0;
|
||||
var sliceStr = str.slice(startIndex, index + val.length + highlightTextNextNum);
|
||||
var addHighlightStr = sliceStr.replace(val, '<span class="highlight">' + val + '</span>');
|
||||
var ellipsis = (sliceStr.lastIndexOf(val) != -1) || (sliceStr.lastIndexOf(val) > highlightTextNextNum) ? '...' : '';
|
||||
return addHighlightStr + ellipsis;
|
||||
}
|
||||
|
||||
// 隐藏搜索结果框
|
||||
function hideSearchResult() {
|
||||
$searchResult.hide();
|
||||
}
|
||||
|
||||
// 监听输入的内容
|
||||
$searchInput.on('input', debounce(function(e) {
|
||||
var val = e.target.value.trim(),
|
||||
res = window.ydoc_plugin_search_core(val);
|
||||
|
||||
activeIndex = 0;
|
||||
$(document).off('keydown');
|
||||
$searchResult.show();
|
||||
if (realObj(res) || val === '') {
|
||||
var dom = '';
|
||||
for (var key in res) {
|
||||
dom += '<div class="headline">' + key + '</div>';
|
||||
res[key].forEach(function(item) {
|
||||
var contentDom = '';
|
||||
if (item.children.length) {
|
||||
item.children.forEach(function (i) {
|
||||
i.title = simplifyStrDom(i.title, val);
|
||||
i.content = simplifyStrDom(i.content, val);
|
||||
contentDom += '<a class="caption" href="' + i.url + '">' +
|
||||
'<div class="title">' + i.title + '</div>' +
|
||||
'<div class="desc">' + i.content + '</div></a>';
|
||||
});
|
||||
} else {
|
||||
item.title = simplifyStrDom(item.title, val);
|
||||
item.content = simplifyStrDom(item.content, val);
|
||||
contentDom = '<a class="caption" href="' + item.url + '">' +
|
||||
'<div class="title">' + item.title + '</div>' +
|
||||
'<div class="desc">' + item.content + '</div></a>';
|
||||
}
|
||||
dom += '<div class="row">' +
|
||||
'<a class="subtitle" href="' + item.url + '">' + item.title + '</a>' +
|
||||
'<div class="content">' + contentDom + '</div>' +
|
||||
'</div>';
|
||||
});
|
||||
}
|
||||
$searchResult.html(dom);
|
||||
|
||||
var $captions = $('.js-search-result .caption');
|
||||
var length = $captions.length;
|
||||
if ($captions.length) {
|
||||
$captions[activeIndex].classList.add('active');
|
||||
// 监听键盘事件 up: 38, down: 40, enter: 13
|
||||
$(document).on('keydown', function (e) {
|
||||
if (e.keyCode == 38) {
|
||||
$captions[activeIndex].classList.remove('active');
|
||||
activeIndex = (activeIndex + length - 1) % length;
|
||||
$captions[activeIndex].classList.add('active');
|
||||
} else if (e.keyCode == 40) {
|
||||
$captions[activeIndex].classList.remove('active');
|
||||
activeIndex = (activeIndex + 1) % length;
|
||||
$captions[activeIndex].classList.add('active');
|
||||
} else if (e.keyCode == 13) {
|
||||
window.open($captions[activeIndex].href, '_self');
|
||||
}
|
||||
});
|
||||
}
|
||||
// 按下 ESC 键,清空输入框并收起搜索结果框
|
||||
$(document).on('keydown', function (e) {
|
||||
if (e.keyCode == 27) {
|
||||
$searchInput[0].value = '';
|
||||
$searchResult.hide();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$searchResult.html('<div class="empty">没有找到关键词 <b>' + val + '</b> 的搜索结果</div>')
|
||||
}
|
||||
}, 300));
|
||||
|
||||
$searchResult.on('click', function(e){
|
||||
return false;
|
||||
})
|
||||
|
||||
$(document).on('click', function(e){
|
||||
$searchResult.hide();
|
||||
})
|
||||
|
||||
|
||||
})
|
@ -9,7 +9,8 @@
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
right: -.64rem;
|
||||
width: calc(100vw - 32px);
|
||||
right: -.48rem;
|
||||
top: .48rem;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
@ -29,18 +30,19 @@
|
||||
font-size: 18px;
|
||||
}
|
||||
.m-search .input {
|
||||
width: 150px;
|
||||
width: 72px;
|
||||
border: none;
|
||||
outline: none;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 .16rem 0 .32rem;
|
||||
padding: 0 .08rem 0 .32rem;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
transition: all .2s;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
.m-search .input:focus {
|
||||
background-color: #fbfbfb;
|
||||
width: 160px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.m-search .empty {
|
||||
padding: .32rem .24rem;
|
||||
@ -62,30 +64,32 @@
|
||||
padding: .04rem .08rem;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all .2s;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
.m-search .subtitle:hover {
|
||||
background-color: #f6f8fa;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.m-search .content {
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
border-left: 1px solid rgba(3, 17, 31, 0.14);
|
||||
padding: 0 .08rem;
|
||||
padding: 0;
|
||||
padding-right: .08rem;
|
||||
}
|
||||
.m-search .caption {
|
||||
padding: .04rem 0;
|
||||
padding-left: 0.08rem;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all .2s;
|
||||
transition: all .2s ease-in-out;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.m-search .caption:hover {
|
||||
background-color: #f6f8fa;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.m-search .caption.active {
|
||||
background-color: #f6f8fa;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.m-search .caption .desc {
|
||||
font-weight: normal;
|
||||
@ -98,6 +102,9 @@
|
||||
right: 0;
|
||||
width: 4rem;
|
||||
}
|
||||
.m-search .input:focus {
|
||||
width: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
/* PC 端不显示 nav 按钮 因此更靠右侧 */
|
||||
@ -105,4 +112,7 @@
|
||||
.m-search {
|
||||
right: .24rem;
|
||||
}
|
||||
.m-search .input:focus {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user