Merge branch 'newVersion_forge' into dev_chain

This commit is contained in:
sylor_huang@126.com 2020-06-24 15:34:36 +08:00
commit 9fe7d6471c
12 changed files with 728 additions and 187 deletions

View File

@ -100,7 +100,7 @@ export function initAxiosInterceptors(props) {
// TODO 读取到package.json中的配置
var proxy = "http://localhost:3000"
// proxy = "https://pre-newweb.educoder.net"
proxy = "https://testforgeplus.trustie.net/"
proxy = "https://testforgeplus.trustie.net"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求

View File

@ -0,0 +1,70 @@
import React , { useState , useEffect } from 'react';
import { AutoComplete } from 'antd';
import { getImageUrl } from "educoder";
import axios from 'axios';
const Option = AutoComplete.Option;
export default ({ getUser })=>{
const [ searchKey , setSearchKey ] = useState(undefined);
const [ userDataSource , setUserDataSource ] = useState(undefined);
function getUserList(e){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: e,
},
})
.then((result) => {
if (result) {
setUserDataSource(result.data.users);
}
})
.catch((error) => {
console.log(error);
});
};
function changeInputUser(value){
setSearchKey(value);
getUserList(value);
}
function selectInputUser(id, option){
setSearchKey(option.props.searchValue);
getUserList(option.props.searchValue);
getUser && getUser(id);
}
const source =
userDataSource && userDataSource.map((item, key) => {
return (
<Option
key={key}
value={`${item.user_id}`}
searchValue={`${item.username}`}
>
<img
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>
{item.username}
<span className="color-grey ml10">({item.login})</span>
</span>
</Option>
);
});
return(
<AutoComplete
dataSource={source}
value={searchKey}
style={{ width: 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder="搜索需要添加的用户..."
/>
)
}

View File

@ -49,11 +49,12 @@ export const WhiteBack = styled.div`{
}`
export const Blueline = styled.a`{
height:32px;
line-height:32px;
line-height:30px;
border-radius:2px;
border:1px solid rgba(80,145,255,1);
color:rgba(80,145,255,1);
padding:0px 12px;
display:inline-block;
}`
export const Redline = styled.a`{
height:32px;

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import { Popconfirm, Select } from "antd";
import { Popconfirm, Select } from "antd";
import "./list.css";
import axios from "axios";
import Meditor from "../Newfile/m_editor";
@ -16,17 +16,85 @@ class CoderRootFileDetail extends Component {
super(props);
this.state = {
value: undefined,
language: undefined
language: undefined,
languages: undefined,
};
}
componentDidMount = () => {
const { detail } = this.props;
this.setState({
value: detail.content,
});
this.languages_total();
};
languages_total = () => {
const { detail } = this.props;
const file_name = detail.path.split("/").pop().split(".").pop();
let languages = [];
let default_language = "javascript";
let all_languages = {
apex: ["apex", "apxc"],
azcli: ["azcli"],
bat: ["bat"],
clojure: ["clj"],
coffee: ["coffee"],
cpp: ["cpp"],
csharp: ["cs"],
csp: ["csp"],
css: ["css"],
dockerfile: ["dockerfile", "docker", "yml"],
fsharp: ["fs"],
go: ["go"],
html: ["html", "htm", "erb"],
ini: ["ini"],
java: ["java", "class"],
javascript: ["js"],
json: ["json"],
less: ["less"],
lua: ["lua"],
markdown: ["markdown", "md", "rmd"],
msdax: ["dax"],
mysql: ["sql"],
objective: ["m", "mm", "o", "out"],
perl: ["perl"],
pgsql: ["sql"],
php: ["php"],
postiats: ["postiats"],
powerquery: [""],
powershell: ["ps1"],
pug: ["pug"],
python: ["py"],
r: ["r"],
razor: ["cshtml"],
redis: ["rdb"],
ruby: ["rb"],
rust: ["rs"],
sb: ["sb"],
scheme: ["scm", "ss"],
scss: ["scss"],
shell: ["sh"],
solidity: ["sol"],
sql: ["sql"],
st: ["st"],
swift: ["swift"],
typescript: ["ts"],
vb: ["vbp", "frm", "frx", "bas", "cls"],
xml: ["xml"],
yaml: ["yml"],
};
for (var item in all_languages) {
languages.push(item);
let item_values = all_languages[item];
if (item_values.indexOf(file_name) !== -1) {
default_language = item;
}
}
this.state.languages = languages;
this.state.language = default_language;
};
select_language = (e) => {
this.setState({
language: e,
@ -39,7 +107,6 @@ class CoderRootFileDetail extends Component {
// readOnly: false,
// });
};
// 编辑文件
@ -73,7 +140,6 @@ class CoderRootFileDetail extends Component {
});
};
updateCode = (value) => {
this.setState({
value,
@ -81,73 +147,30 @@ class CoderRootFileDetail extends Component {
};
render() {
const { readOnly , detail, current_user, isManager, isDeveloper } = this.props;
const { language } = this.state;
const {
readOnly,
detail,
current_user,
isManager,
isDeveloper,
} = this.props;
const { language, languages } = this.state;
let flag = current_user && current_user.login && (isManager || isDeveloper);
const Option = Select.Option;
const languages = [
"apex",
"azcli",
"bat",
"clojure",
"coffee",
"cpp",
"csharp",
"csp",
"css",
"dockerfile",
"fsharp",
"go",
"handlebars",
"html",
"ini",
"java",
"javascript",
"json",
"less",
"lua",
"markdown",
"msdax",
"mysql",
"objective",
"perl",
"pgsql",
"php",
"postiats",
"powerquery",
"powershell",
"pug",
"python",
"r",
"razor",
"redis",
"redshift",
"ruby",
"rust",
"sb",
"scheme",
"scss",
"shell",
"solidity",
"sql",
"st",
"swift",
"typescript",
"vb",
"xml",
"yaml",
];
return (
<div className="mb20">
<div className="grid-item branchTitle">
<div className="grid-item">
<span className="ml20 color-grey-6 font-16">{bytesToSize(detail && detail.size)}</span>
<span className="ml20 color-grey-6 font-16">
{bytesToSize(detail && detail.size)}
</span>
</div>
<p className="text-right">
{flag && (
<div>
{readOnly ? (
<a onClick={()=>this.EditFile(false)} className="ml20">
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
) : (
@ -160,14 +183,19 @@ class CoderRootFileDetail extends Component {
onChange={this.select_language}
>
<Option value={undefined}>请选择文本语言</Option>
{languages.map((item, key) => {
return <Option value={item}>{item}</Option>;
})}
{languages &&
languages.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
<button
type="button"
className="ant-btn ant-btn-sm ml20"
onClick={()=>this.EditFile(true)}
onClick={() => this.EditFile(true)}
>
<span> </span>
</button>
@ -187,20 +215,22 @@ class CoderRootFileDetail extends Component {
</Popconfirm>
</div>
)}
{
detail.image_type && detail.direct_download ?
<div className="ml20">
<a href={detail.download_url} className="color-blue font-15">
下载原始文件
</a>
</div>:""
}
</p>
</div>
<div>
{detail.image_type && detail.direct_download ? (
{detail.image_type ? (
<div className="edu-txt-center pt20 pb20">
<img alt="" src={detail.download_url} style={{maxWidth:"80%"}}/>
<img
alt=""
src={detail.download_url}
style={{ maxWidth: "80%" }}
/>
</div>
) : detail.direct_download ? (
<div className="mt20 text-center">
<a href={detail.download_url} className="color-blue font-15">
下载原始文件
</a>
</div>
) : (
<Meditor

View File

@ -12,7 +12,7 @@ class UserSubmitComponent extends Component {
this.state = {
submitType: "0",
filename: "",
isSpin: false
isSpin: false,
};
}
@ -22,19 +22,19 @@ class UserSubmitComponent extends Component {
});
};
// 命名文件
changeFileName = (e) => {
this.setState({
filename: e.target.value,
});
};
// 命名文件
changeFileName = (e) => {
this.setState({
filename: e.target.value,
});
};
// 提交变更
subMitFrom = () => {
const { filepath, content,editor_type } = this.props;
const { filepath, content, editor_type } = this.props;
const { branch, projectsId } = this.props.match.params;
const { submitType, filename } = this.state;
this.setState({isSpin: true})
this.setState({ isSpin: true });
let path = editor_type === "upload" ? filepath : filepath.substr(1);
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
@ -48,28 +48,28 @@ class UserSubmitComponent extends Component {
message: values.desc,
})
.then((result) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
if (result.data && result.data.name) {
let url = values.branchname
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
this.props.history.push(url);
this.props.showNotification("文件新建成功!");
}
})
.catch((error) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
console.log(error);
});
}else{
this.setState({isSpin: false})
} else {
this.setState({ isSpin: false });
}
});
};
// 确认修改文件
UpdateFile = () => {
this.setState({isSpin: true})
this.setState({ isSpin: true });
const { branch, detail, content, filepath } = this.props;
const { projectsId } = this.props.match.params;
const { submitType } = this.state;
@ -86,28 +86,28 @@ class UserSubmitComponent extends Component {
message: values.desc,
})
.then((result) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
if (result.data && result.data.status === 1) {
let url = values.branchname
? `/projects/${projectsId}/coders?branch=${values.branchname}`
: `/projects/${projectsId}/coders`;
this.props.history.push(url);
this.props.showNotification("修改成功!");
}
})
.catch((error) => {
this.setState({isSpin: false})
this.setState({ isSpin: false });
console.log(error);
});
}else{
this.setState({isSpin: false})
} else {
this.setState({ isSpin: false });
}
});
};
render() {
const { submitType,filename, isSpin } = this.state;
const { submitType, filename, isSpin } = this.state;
const { getFieldDecorator } = this.props.form;
const { branch, projectsId } = this.props.match.params;
@ -160,81 +160,89 @@ class UserSubmitComponent extends Component {
<span className="color-grey-8">提交变更</span>
</span>
<Spin spinning={isSpin}>
<div className="userScrew">
<div className="screwPanel">
<Form>
<Form.Item style={{display: editor_type === "upload" ? "block" : "none"}}>
{getFieldDecorator("path", {
rules: [],
})(
// <Input
// placeholder={`/${
// projectDetail && projectDetail.identifier
// }${filepath}`}
// readOnly
// />
<div className="setInputAddon">
<Input
addonBefore={`/${
projectDetail && projectDetail.identifier
}/`}
value={filename ? filename: filepath}
onChange={this.changeFileName}
placeholder="文件路径..."
/>
</div>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("desc", {
rules: [
{
required: true,
message: "请添加描述信息",
},
],
})(
<TextArea
placeholder={`必填,描述主要修改类型和内容`}
authSize={{ minRows: 3, maxRows: 5 }}
/>
)}
</Form.Item>
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
<Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{branch}</span>
</Radio>
<Radio value="1">
<Icon type="pull-request" className="mr5" />
为此提交创建一个<span className="font-bd">新的分支</span>
并发起合并请求
</Radio>
</Radio.Group>
{changeSubmitBranch()}
</Form>
<div className="userScrew">
<div className="screwPanel">
<Form>
<Form.Item
style={{
display: editor_type === "upload" ? "block" : "none",
}}
>
{getFieldDecorator("path", {
rules: [],
})(
// <Input
// placeholder={`/${
// projectDetail && projectDetail.identifier
// }${filepath}`}
// readOnly
// />
<div className="setInputAddon">
<Input
addonBefore={`/${
projectDetail && projectDetail.identifier
}/`}
value={filename ? filename : filepath}
onChange={this.changeFileName}
placeholder="文件路径..."
/>
</div>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator("desc", {
rules: [
{
required: true,
message: "请添加描述信息",
},
],
})(
<TextArea
placeholder={`必填,描述主要修改类型和内容`}
authSize={{ minRows: 3, maxRows: 5 }}
/>
)}
</Form.Item>
<Radio.Group
value={submitType}
onChange={this.changeSubmittype}
>
<Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{branch}</span>
</Radio>
<Radio value="1">
<Icon type="pull-request" className="mr5" />
为此提交创建一个<span className="font-bd">新的分支</span>
并发起合并请求
</Radio>
</Radio.Group>
{changeSubmitBranch()}
</Form>
</div>
</div>
<div className="mt20">
<Button
type="primary"
onClick={
editor_type === "update" ? this.UpdateFile : this.subMitFrom
}
className="mr30"
>
提交变更
</Button>
<Button
type="primary grey"
onClick={() => {
this.props.history.push(`/projects/${projectsId}/coders`);
}}
className="mr20"
>
取消
</Button>
</div>
</div>
<div className="mt20">
<Button
type="primary"
onClick={editor_type === "update" ? this.UpdateFile : this.subMitFrom}
className="mr30"
>
提交变更
</Button>
<Button
type="primary grey"
onClick={() => {
this.props.history.push(`/projects/${projectsId}/coders`);
}}
className="mr20"
>
取消
</Button>
</div>
</Spin>
</div>
);
}

View File

@ -174,16 +174,7 @@
border-bottom: none;
}
}
.required{
position: relative;
&::before{
content: "*";
color: red;
position: absolute;
left: -10px;
top: -2px;
}
}
.hooksNew{
.ant-select.ant-select-enabled{
width: 100%;

View File

@ -274,3 +274,51 @@
}
}
}
.warningBox{
border-radius:5px 5px 0px 0px;
border:1px solid rgba(219,39,41,1);
border-radius:5px 5px 0px 0px;
.warningTitle{
height:40px;
line-height: 40px;
background:rgba(255,232,230,1);
border-radius:5px 5px 0px 0px;
border-bottom:1px solid rgba(219,39,41,1);
color: #DB2729;
font-size: 16px;
padding:0px 30px;
}
.warningContent{
padding:20px 30px;
}
.warningDelete{
display: block;
height:26px;
line-height: 26px;
padding:0px 15px;
background:rgba(247,48,48,1);
border-radius:20px;
color: #fff;
}
}
// 组织成员管理
.teamMemberTable{
.ant-table-small{
border:none;
}
.ant-table-body{
margin:0px!important;
thead tr{
background-color: #F1F8FF;
color: #333;
}
tbody tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td{
background-color: #fff;
}
tbody tr td{
border-bottom: 1px solid #eee!important;
padding:15px 8px!important;
}
}
}

View File

@ -0,0 +1,106 @@
import React, { forwardRef , useCallback } from 'react';
import { Form , Input , Cascader , Radio ,Checkbox , Divider , Button } from 'antd';
import { WhiteBack , FlexAJ } from '../Component/layout';
import Title from '../Component/Title';
import styled from 'styled-components';
import { locData } from "../Utils/locData";
const TextArea = Input.TextArea;
const Div = styled.div`{
padding:20px 30px;
}`
const radioStyle = {
display: 'block',
height: '30px',
lineHeight: '30px',
};
export default Form.create()(
forwardRef(({ form })=>{
const { getFieldDecorator } = form;
const helper = useCallback(
(label, name, rules, widget , isRequired ) => (
<div>
<span className={isRequired?"required":""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</div>
),
[]
);
return(
<div>
<WhiteBack>
<Title>基本设置</Title>
<Div>
<Form>
{helper(
"组织名称:",
"name",
[{ required: true, message: "请输入组织名称" }],
<Input placeholder="请输入组织名称" />,true
)}
{helper(
"组织描述:",
"desc",
[],
<TextArea placeholder="请输入组织名称" />
)}
{helper(
"官方网站:",
"web",
[],
<Input placeholder="请输入官方网站" />
)}
{helper(
'所在地区:',
"area",
[],
<Cascader placeholder="请选择城市" options={locData}/>
)}
{helper(
'可见性:',
"opacity",
[],
<Radio.Group>
<Radio value="0" style={radioStyle}>公开</Radio>
<Radio value="0" style={radioStyle}>受限<span>仅对登录用户可见</span></Radio>
<Radio value="0" style={radioStyle}>私有<span>仅对组织成员可见</span></Radio>
</Radio.Group>
)}
{helper(
'权限:',
"operation",
[],
<Checkbox value="0" style={radioStyle}>仓库管理员可以添加或移除团队的访问权限</Checkbox>
)}
<Divider/>
{helper(
'最大仓库数:',
"number",
[],
<Input value="-1" style={{width:"350px"}}/>
)}
<Button type={"primary"}>更新仓库设置</Button>
</Form>
</Div>
</WhiteBack>
<WhiteBack className="padding20 mt20">
<div className="warningBox">
<div className="warningTitle">删除当前组织</div>
<div className="warningContent">
<p className="font-16 mb15">删除操作会永久清除该组织的信息并且不可恢复</p>
<FlexAJ>
<div>
<span className="required">密码</span>
<Input type="password" style={{width:"350px"}} />
</div>
<a className="warningDelete">删除组织</a>
</FlexAJ>
</div>
</div>
</WhiteBack>
</div>
)
})
)

View File

@ -0,0 +1,71 @@
import React from 'react';
import { WhiteBack , Banner , Blueline } from '../Component/layout';
import styled from 'styled-components';
const SpanName = styled.span`{
font-size:16px;
color:#333;
}`
const SpanFoot = styled.span`{
margin-right:5px;
color:#333
}`
const ALink = styled.a`{
border:1px solid #F73030;
color:#F73030!important;
height:32px;
line-height:30px;
display:block;
padding:0px 15px;
border-radius:2px;
}`
const ImgContent = styled.img`{
height:44px;
width:44px;
border-radius:50%;
margin:5px 20px 5px 0px;
}`
export default ()=>{
return(
<WhiteBack>
<Banner>组织团队管理</Banner>
<div className="groupBox">
<div>
<p className="g-head">
<SpanName>oweners</SpanName>
<span className="df">
<ALink>离开团队</ALink>
<Blueline className="ml15">团队设置</Blueline>
</span>
</p>
<div className="g-body">
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
</div>
<p className="g-foot">
<SpanFoot>2&nbsp;名成员</SpanFoot>
<SpanFoot>1&nbsp;个项目</SpanFoot>
</p>
</div>
<div>
<p className="g-head">
<SpanName>oweners</SpanName>
<span className="df">
<ALink>离开团队</ALink>
<Blueline className="ml15">团队设置</Blueline>
</span>
</p>
<div className="g-body">
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
</div>
<p className="g-foot">
<SpanFoot>2&nbsp;名成员</SpanFoot>
<SpanFoot>1&nbsp;个项目</SpanFoot>
</p>
</div>
</div>
</WhiteBack>
)
}

View File

@ -1,16 +1,46 @@
import React from 'react';
import React , { useEffect , useState } from 'react';
import { Box , Long , Short , Gap } from '../Component/layout';
import Title from '../Component/Title';
import Setnav from '../Component/Setnav';
export default (()=>{
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../Loading";
const Group = Loadable({
loader: () => import("./TeamSettingGroup"),
loading: Loading,
});
const Member = Loadable({
loader: () => import("./TeamSettingMember"),
loading: Loading,
});
const Common = Loadable({
loader: () => import("./TeamSettingCommon"),
loading: Loading,
});
export default (( props )=>{
const pathname = props.location.pathname;
const organizeId = props.match.params.organizeId;
function returnActive (pathname){
let a = 0;
if(pathname === `/organize/${organizeId}/setting/member`){
a = 1;
}else if(pathname === `/organize/${organizeId}/setting/group`){
a = 2;
}
return a;
}
const active = returnActive(pathname);
const array = {list:[
{name:'基本设置',icon:"icon-base",href:""},
{name:'组织成员',icon:"icon-zuzhichengyuan",href:""},
{name:'组织团队',icon:"icon-zuzhixiangmu",href:""},
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:""},
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:""},
{name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:""}
],
active:0
active
}
return(
<Box>
@ -19,6 +49,26 @@ export default (()=>{
</Short>
<Long>
<Gap>
<Switch>
<Route
path="/organize/:organizeId/setting/group"
render={() => (
<Group {...props} />
)}
></Route>
<Route
path="/organize/:organizeId/setting/member"
render={() => (
<Member {...props} />
)}
></Route>
<Route
path="/organize/:organizeId/setting"
render={() => (
<Common {...props} />
)}
></Route>
</Switch>
</Gap>
</Long>
</Box>

View File

@ -0,0 +1,152 @@
import React, { useState } from 'react';
import { WhiteBack , Blueline , AlignCenter , FlexAJ } from '../Component/layout';
import { Menu , Table , Pagination , Icon , Tooltip } from 'antd';
import Sort from '../Component/Sort';
import Title from '../Component/Title';
import Search from '../Component/Search';
import SearchUser from '../Component/SearchUser';
import styled from 'styled-components';
import { getImageUrl } from 'educoder';
const Img = styled.img`{
width:30px;
height:30px;
border-radius:50%;
}`
const demoData = [
{
img:"images/avatars/User/g",
name:"蔡世",
email:"1149225589@qq.com",
team:"caicaizi",
role:"管理者",
operation:"移除成员",
}
]
export default (()=>{
const [ choiceId , serChoiceId ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ limit , setLimit ] = useState(15);
const [ total , setTotal ] = useState(0);
const [ data , setData ] = useState(demoData);
// ID便
function getUser(id){
console.log(id);
serChoiceId(id);
}
//
function onSearch(value){
console.log(value);
}
//
function ChangePage(page){
setPage(page);
}
const menu=(
<Menu>
<Menu.Item key="all">全部</Menu.Item>
<Menu.Item key="Manager">管理员</Menu.Item>
<Menu.Item key="Developer">开发者</Menu.Item>
<Menu.Item key="Reporter">报告者</Menu.Item>
</Menu>
)
const roleTitle = (
<div><span className="mr3">角色</span>
<Tooltip placement='bottom' title=
{
<div>
<div className="mb3">管理员拥有仓库设置功能代码库读写操作</div>
<div className="mb3">开发人员只拥有代码库读写操作</div>
<div className="mb3">报告者只拥有代码库读操作</div>
</div>
}
>
<Icon type="question-circle"></Icon>
</Tooltip>
</div>
);
const columns = [
{
title: '头像',
dataIndex: 'Img',
width:"7%",
render:(value,item)=>{
return(
<Img src={getImageUrl(item.img)}></Img>
)
}
},
{
title: '用户名',
dataIndex: 'name',
width:"13%",
align:"center"
},
{
title: '邮箱',
dataIndex: 'email',
width:"25%",
},
{
title: '所属团队',
dataIndex: 'team',
width:"20%",
},
{
title: roleTitle,
dataIndex: 'role',
width:"20%",
render:(value,item)=>{
return(
item.role
)
}
},
{
title: '操作',
dataIndex: 'operation',
width:"15%",
render:(value,item)=>{
return <a className="color-grey-8">移除成员</a>
}
}
]
return(
<WhiteBack>
<Title>
<span>组织成员管理</span>
<AlignCenter>
<SearchUser getUser={getUser}/>
<Blueline className="ml30">+&nbsp;添加用户</Blueline>
</AlignCenter>
</Title>
<FlexAJ className="padding20-30">
<div style={{width:"580px"}}>
<Search placeholder="输入用户名或邮箱、团队名搜索" onSearch={onSearch}/>
</div>
<Sort menu={menu}>
<a className="color-blue">角色筛选<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
</Sort>
</FlexAJ>
<div className="pl30 pr30 pb30">
<Table
size="small"
columns={columns}
dataSource={data}
pagination={false}
className="teamMemberTable"
></Table>
{
total > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
</div>
:""
}
</div>
</WhiteBack>
)
})

View File

@ -95,6 +95,20 @@ ul,ol,dl{
font-size: 16px;
color: #999;
}
form.ant-form{
color:#333;
}
.required{
position: relative;
&::before{
content: "*";
color: red;
position: absolute;
left: -10px;
top: 0px;
line-height: 22px;
}
}
@media screen and (max-width: 1000px){
.main{
width: 750px;