This commit is contained in:
2024-03-01 20:28:14 +08:00
commit 076c21dc36
491 changed files with 84482 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
import './ProjectCard.scss';
import React, { PureComponent as Component } from 'react';
import { Card, Icon, Tooltip, Modal, Alert, Input, message } from 'antd';
import { connect } from 'react-redux';
import { delFollow, addFollow } from '../../reducer/modules/follow';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router';
import { debounce } from '../../common';
import constants from '../../constants/variable.js';
import produce from 'immer';
import { getProject, checkProjectName, copyProjectMsg } from '../../reducer/modules/project';
import { trim } from '../../common.js';
const confirm = Modal.confirm;
@connect(
state => {
return {
uid: state.user.uid,
currPage: state.project.currPage
};
},
{
delFollow,
addFollow,
getProject,
checkProjectName,
copyProjectMsg
}
)
@withRouter
class ProjectCard extends Component {
constructor(props) {
super(props);
this.add = debounce(this.add, 400);
this.del = debounce(this.del, 400);
}
static propTypes = {
projectData: PropTypes.object,
uid: PropTypes.number,
inFollowPage: PropTypes.bool,
callbackResult: PropTypes.func,
history: PropTypes.object,
delFollow: PropTypes.func,
addFollow: PropTypes.func,
isShow: PropTypes.bool,
getProject: PropTypes.func,
checkProjectName: PropTypes.func,
copyProjectMsg: PropTypes.func,
currPage: PropTypes.number
};
copy = async projectName => {
const id = this.props.projectData._id;
let projectData = await this.props.getProject(id);
let data = projectData.payload.data.data;
let newData = produce(data, draftData => {
draftData.preName = draftData.name;
draftData.name = projectName;
});
await this.props.copyProjectMsg(newData);
message.success('项目复制成功');
this.props.callbackResult();
};
// 复制项目的二次确认
showConfirm = () => {
const that = this;
confirm({
title: '确认复制 ' + that.props.projectData.name + ' 项目吗?',
okText: '确认',
cancelText: '取消',
content: (
<div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
<Alert
message={`该操作将会复制 ${
that.props.projectData.name
} 下的所有接口集合,但不包括测试集合中的接口`}
type="info"
/>
<div style={{ marginTop: '16px' }}>
<p>
<b>项目名称:</b>
</p>
<Input id="project_name" placeholder="项目名称" />
</div>
</div>
),
async onOk() {
const projectName = trim(document.getElementById('project_name').value);
// 查询项目名称是否重复
const group_id = that.props.projectData.group_id;
await that.props.checkProjectName(projectName, group_id);
that.copy(projectName);
},
iconType: 'copy',
onCancel() {}
});
};
del = () => {
const id = this.props.projectData.projectid || this.props.projectData._id;
this.props.delFollow(id).then(res => {
if (res.payload.data.errcode === 0) {
this.props.callbackResult();
// message.success('已取消关注!'); // 星号已做出反馈 无需重复提醒用户
}
});
};
add = () => {
const { uid, projectData } = this.props;
const param = {
uid,
projectid: projectData._id,
projectname: projectData.name,
icon: projectData.icon || constants.PROJECT_ICON[0],
color: projectData.color || constants.PROJECT_COLOR.blue
};
this.props.addFollow(param).then(res => {
if (res.payload.data.errcode === 0) {
this.props.callbackResult();
// message.success('已添加关注!'); // 星号已做出反馈 无需重复提醒用户
}
});
};
render() {
const { projectData, inFollowPage, isShow } = this.props;
return (
<div className="card-container">
<Card
bordered={false}
className="m-card"
onClick={() =>
this.props.history.push('/project/' + (projectData.projectid || projectData._id))
}
>
<Icon
type={projectData.icon || 'star-o'}
className="ui-logo"
style={{
backgroundColor:
constants.PROJECT_COLOR[projectData.color] || constants.PROJECT_COLOR.blue
}}
/>
<h4 className="ui-title">{projectData.name || projectData.projectname}</h4>
</Card>
<div
className="card-btns"
onClick={projectData.follow || inFollowPage ? this.del : this.add}
>
<Tooltip
placement="rightTop"
title={projectData.follow || inFollowPage ? '取消关注' : '添加关注'}
>
<Icon
type={projectData.follow || inFollowPage ? 'star' : 'star-o'}
className={'icon ' + (projectData.follow || inFollowPage ? 'active' : '')}
/>
</Tooltip>
</div>
{isShow && (
<div className="copy-btns" onClick={this.showConfirm}>
<Tooltip placement="rightTop" title="复制项目">
<Icon type="copy" className="icon" />
</Tooltip>
</div>
)}
</div>
);
}
}
export default ProjectCard;

View File

@@ -0,0 +1,163 @@
@import '../../styles/mixin.scss';
.card-container {
position: relative;
user-select: none;
transition: all .2s;
.m-card, .card-btns {
transform: translateY(0);
transition: all .2s;
}
&:hover {
.m-card, .card-btns , .copy-btns {
transform: translateY(-4px);
}
.m-card .ant-card-body {
background-color: $color-bg-gray;
box-shadow: 0 4px 8px rgba(50, 50, 93, 0.11), 0 4px 6px rgba(0, 0, 0, 0.08);
}
.card-btns .icon {
color: rgba(39, 56, 72, 0.85);
}
.copy-btns .icon {
color: #2395f1
}
.card-btns .icon.active , .copy-btns .icon.active {
color: #fac200;
}
}
&:active {
.m-card, .card-btns, .copy-btns {
transform: translateY(4px);
}
}
// 覆盖 card 组件 hover 状态的默认阴影样式
.ant-card:not(.ant-card-no-hovering):hover {
box-shadow: none;
}
// 卡片右上角按钮
.card-btns {
position: absolute;
top: 0;
right: 0;
width: .48rem;
height: .48rem;
// background: linear-gradient(225deg, #ccc, #ccc 50%, transparent 0);
border-top-right-radius: 4px;
.icon {
cursor: pointer;
font-size: .16rem;
padding: .06rem;
position: absolute;
right: 0;
top: 0;
color: #fff;
}
.icon.active {
color: #fff;
}
}
// 卡片昨上角按钮
.copy-btns {
position: absolute;
top: 0;
left: 0;
width: .48rem;
height: .48rem;
// background: linear-gradient(225deg, #ccc, #ccc 50%, transparent 0);
border-top-right-radius: 4px;
.icon {
cursor: pointer;
font-size: .16rem;
padding: .06rem;
position: absolute;
right: 0;
top: 3px;
color: #fff;
}
.icon.active {
color: #fff;
}
}
}
.m-card {
cursor: pointer;
text-align: center;
margin-bottom: .16rem;
transition: all .4s;
position: relative;
.ant-card-body {
background-color: transparent;
border-radius: 4px;
padding-top: .24rem + .16rem + 1rem;
box-shadow: 0 4px 6px rgba(255,255,255,.11), 0 1px 3px rgba(255,255,255,.08);
// box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08);
transition: all .2s;
}
.ui-logo {
width: 1rem;
height: 1rem;
border-radius: 50%;
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%, .24rem);
font-size: .5rem;
color: #fff;
background-color: #2395f1;
line-height: 1rem;
box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08);
}
.ui-title {
font-size: .19rem;
font-weight: normal;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.m-card-body {
.icon {
font-size: .8rem;
}
.name {
font-size: .18rem;
margin-top: .16rem;
}
}
}
@media (max-width: 768px) {
.m-card {
.ui-logo {
width: .6rem;
height: .6rem;
line-height: .6rem;
font-size: .3rem;
transform: translate(-50%, 0.08rem);
}
.ant-card-body {
padding-top: .08rem + .08rem + .6rem;
padding-bottom: .08rem;
}
}
}
@media (min-width: 768px) and (max-width: 992px) {
.m-card {
.ui-logo {
width: .8rem;
height: .8rem;
line-height: .8rem;
font-size: .4rem;
transform: translate(-50%, 0.16rem);
}
.ant-card-body {
padding-top: .16rem + .16rem + .8rem;
padding-bottom: .16rem;
}
}
}