feat:团队列表
This commit is contained in:
parent
cf68c5e915
commit
55ffba0953
|
@ -29,6 +29,7 @@ export default function Layout({children}: { children: React.ReactNode }) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
token: {
|
token: {
|
||||||
|
controlItemBgHover:"#4096ff",
|
||||||
controlItemBgActiveHover:"#4096ff",
|
controlItemBgActiveHover:"#4096ff",
|
||||||
controlItemBgActive:"#4096ff"
|
controlItemBgActive:"#4096ff"
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
updateStepItemIndexAPI
|
updateStepItemIndexAPI
|
||||||
} from "@/components/service/StepSort";
|
} from "@/components/service/StepSort";
|
||||||
import {QuestionCircleOutlined} from "@ant-design/icons";
|
import {QuestionCircleOutlined} from "@ant-design/icons";
|
||||||
|
import {copyToClipboard} from "@/lib/copyToClipboard";
|
||||||
|
|
||||||
const reorder = (list: TaskStepSortVO[], startIndex: number, endIndex: number) => {
|
const reorder = (list: TaskStepSortVO[], startIndex: number, endIndex: number) => {
|
||||||
const result = Array.from(list);
|
const result = Array.from(list);
|
||||||
|
@ -42,7 +43,12 @@ const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
const [modalText, setModalText] = useState<TaskStepSortOperateVO>(initModalText);
|
const [modalText, setModalText] = useState<TaskStepSortOperateVO>(initModalText);
|
||||||
const items: MenuProps['items'] = [
|
const items: MenuProps['items'] = [
|
||||||
{
|
{
|
||||||
key: "0", label: "上方插入", onClick: () => {
|
key: "0", label: "复制", onClick: () => {
|
||||||
|
copyToClipboard(clickTaskSortItem?.stepDesc || "")
|
||||||
|
// copyToClipboard(clickTaskSortItem?.stepDesc ?? "")
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
key: "1", label: "上方插入", onClick: () => {
|
||||||
setDialogueOpen(true)
|
setDialogueOpen(true)
|
||||||
setModalText({
|
setModalText({
|
||||||
id: "",
|
id: "",
|
||||||
|
@ -56,7 +62,7 @@ const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "1", label: "下方插入", onClick: () => {
|
key: "2", label: "下方插入", onClick: () => {
|
||||||
setDialogueOpen(true)
|
setDialogueOpen(true)
|
||||||
setModalText({
|
setModalText({
|
||||||
id: "",
|
id: "",
|
||||||
|
@ -70,13 +76,13 @@ const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "2", label: "修改步骤", onClick: () => {
|
key: "3", label: "修改步骤", onClick: () => {
|
||||||
setDialogueOpen(true)
|
setDialogueOpen(true)
|
||||||
setModalText(clickTaskSortItem!)
|
setModalText(clickTaskSortItem!)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "3", label:
|
key: "4", label:
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="删除步骤"
|
title="删除步骤"
|
||||||
description="确认要删除步骤?"
|
description="确认要删除步骤?"
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import React, {Fragment, useEffect, useRef, useState} from "react";
|
||||||
|
import {Button, Modal, TablePaginationConfig} from "antd";
|
||||||
|
import {ActionType, ProColumns, ProTable} from "@ant-design/pro-components";
|
||||||
|
|
||||||
|
import {Params} from "next/dist/shared/lib/router/utils/route-matcher";
|
||||||
|
import {TeamMemberVO} from "@/components/type/Share.d";
|
||||||
|
import type {FilterValue, SorterResult, TableCurrentDataSource} from "antd/es/table/interface";
|
||||||
|
import {listTeamMemberAPI} from "@/components/service/Share";
|
||||||
|
|
||||||
|
const TeamMember = (props: { taskId: string }) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const onClose = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
const ref = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [userList, setUserList] = React.useState<TeamMemberVO[]>([]);
|
||||||
|
const [totalUserList, setTotalUserList] = React.useState<TeamMemberVO[]>([]);
|
||||||
|
const [totalElement, setTotalElement] = React.useState(0);
|
||||||
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (open){
|
||||||
|
setLoading(true);
|
||||||
|
listTeamMemberAPI(props.taskId).then((res)=>{
|
||||||
|
if (res.data.status.success){
|
||||||
|
setUserList(res.data.data.splice(0,10))
|
||||||
|
setTotalUserList(res.data.data)
|
||||||
|
setTotalElement(res.data.data.length)
|
||||||
|
setTimeout(()=>{ref.current?.reload()},100)
|
||||||
|
}
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},[open])
|
||||||
|
const columns: ProColumns<TeamMemberVO>[] = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
key: 'username',
|
||||||
|
dataIndex: 'username',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '昵称',
|
||||||
|
key: 'nickname',
|
||||||
|
dataIndex: 'nickname',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'operate',
|
||||||
|
width: 120,
|
||||||
|
valueType: 'option',
|
||||||
|
render: () => [<Button key="1">操作</Button>],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<Button type="primary" onClick={() => setOpen(!open)}>
|
||||||
|
查看团队
|
||||||
|
</Button>
|
||||||
|
<Modal
|
||||||
|
title="团队成员"
|
||||||
|
closable={{'aria-label': 'Custom Close Button'}}
|
||||||
|
open={open}
|
||||||
|
destroyOnClose={true}
|
||||||
|
footer={null}
|
||||||
|
onCancel={onClose}
|
||||||
|
>
|
||||||
|
<ProTable<TeamMemberVO, Params>
|
||||||
|
actionRef={ref}
|
||||||
|
search={false}
|
||||||
|
toolBarRender={false}
|
||||||
|
loading={loading}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={userList}
|
||||||
|
// request={(params, sorter, filter) => {
|
||||||
|
// // 表单搜索项会从 params 传入,传递给后端接口。
|
||||||
|
// console.log(params, sorter, filter);
|
||||||
|
// return Promise.resolve({
|
||||||
|
// data: userList,
|
||||||
|
// success: true,
|
||||||
|
// });
|
||||||
|
// }}
|
||||||
|
/* Pagination */
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize:10,
|
||||||
|
defaultCurrent:1,
|
||||||
|
total: totalElement,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total) => `总共 ${total} 条`
|
||||||
|
}}
|
||||||
|
onChange={(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>,
|
||||||
|
sorter: SorterResult<TeamMemberVO> | SorterResult<TeamMemberVO>[], extra:
|
||||||
|
TableCurrentDataSource<TeamMemberVO>) => {
|
||||||
|
setUserList(totalUserList.splice((pagination.current??1-1)*(pagination.pageSize??10),pagination.pageSize))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</Fragment>)
|
||||||
|
}
|
||||||
|
export default TeamMember;
|
|
@ -1,9 +1,12 @@
|
||||||
import {AxiosResponse} from "axios";
|
import {AxiosResponse} from "axios";
|
||||||
import {ResponseVO} from "@/lib/definitions";
|
import {ResponseVO} from "@/lib/definitions";
|
||||||
import {httpReq} from "@/utils/axiosReq";
|
import {httpReq} from "@/utils/axiosReq";
|
||||||
import {ShareVO} from "@/components/type/Share.d";
|
import {ShareVO, TeamMemberVO} from "@/components/type/Share.d";
|
||||||
|
|
||||||
export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<ShareVO>>> =>{
|
export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<ShareVO>>> =>{
|
||||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + "/task/pass",
|
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + "/task/pass",
|
||||||
data)
|
data)
|
||||||
}
|
}
|
||||||
|
export const listTeamMemberAPI = (taskId:string):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
|
||||||
|
return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/list?taskId=${taskId}`)
|
||||||
|
}
|
|
@ -1 +1,12 @@
|
||||||
export interface ShareVO { taskId: string, pass: string, joinCheck: string ,id?:string}
|
export interface ShareVO { taskId: string, pass: string, joinCheck: string ,id?:string}
|
||||||
|
|
||||||
|
export interface TeamMemberVO {
|
||||||
|
id:string,
|
||||||
|
userId:string,
|
||||||
|
username:string,
|
||||||
|
nickname:string,
|
||||||
|
userState:string,
|
||||||
|
userRole:string,
|
||||||
|
taskId:string,
|
||||||
|
fId:string,
|
||||||
|
}
|
|
@ -47,9 +47,10 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
render() {
|
render() {
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
this.setState({...this.state, openModal: false})
|
this.setState({...this.state, openModal: false})
|
||||||
if (this.state.operationId !== OPERATION_BUTTON_TYPE.DETAIL) {
|
|
||||||
this.props.refreshDate?.()
|
|
||||||
}
|
}
|
||||||
|
const closeAndReloadData = () => {
|
||||||
|
this.setState({...this.state, openModal: false})
|
||||||
|
this.props.refreshDate?.()
|
||||||
}
|
}
|
||||||
const onClick: MenuProps['onClick'] = ({key}) => {
|
const onClick: MenuProps['onClick'] = ({key}) => {
|
||||||
console.log(key)
|
console.log(key)
|
||||||
|
@ -156,6 +157,7 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
key: OPERATION_BUTTON_TYPE.UPDATE_PRIORITY,
|
key: OPERATION_BUTTON_TYPE.UPDATE_PRIORITY,
|
||||||
label: <a onClick={(e) => {
|
label: <a onClick={(e) => {
|
||||||
this.setState({updatePriority: true})
|
this.setState({updatePriority: true})
|
||||||
|
console.log("修改优先级",this.state.priority)
|
||||||
}}>修改优先级</a>,
|
}}>修改优先级</a>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -213,7 +215,8 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
|
||||||
this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? '添加支线任务' :
|
this.state.operationId === OPERATION_BUTTON_TYPE.ADD_CHILD ? '添加支线任务' :
|
||||||
this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE ? '修改任务' : '未知操作'}
|
this.state.operationId === OPERATION_BUTTON_TYPE.UPDATE ? '修改任务' : '未知操作'}
|
||||||
open={this.state.openModal}
|
open={this.state.openModal}
|
||||||
reloadData={handleCancel}/>}
|
closeOpen={handleCancel}
|
||||||
|
reloadData={closeAndReloadData}/>}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ClickRecord from "@/components/ClickRecord";
|
||||||
import onceConsumeList from "@/components/constant/onceConsumeList.json"
|
import onceConsumeList from "@/components/constant/onceConsumeList.json"
|
||||||
import {onceConsumerRead} from "@/utils/codeToReadName";
|
import {onceConsumerRead} from "@/utils/codeToReadName";
|
||||||
import style from "@/ui/task/project/DetailModelForm.module.css"
|
import style from "@/ui/task/project/DetailModelForm.module.css"
|
||||||
|
import TeamMember from "@/components/TeamMember";
|
||||||
export type DetailModelFormProps = {
|
export type DetailModelFormProps = {
|
||||||
// 当前内容id
|
// 当前内容id
|
||||||
itemId?: string,
|
itemId?: string,
|
||||||
|
@ -51,9 +52,10 @@ export type DetailModelFormProps = {
|
||||||
export type PidSelectTree = { label: string; value: string; pid: string; children?: PidSelectTree[] }
|
export type PidSelectTree = { label: string; value: string; pid: string; children?: PidSelectTree[] }
|
||||||
|
|
||||||
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
console.log("DetailModelForm:props:", props)
|
|
||||||
const [form] = Form.useForm<DataType>();
|
const [form] = Form.useForm<DataType>();
|
||||||
const [requestTask, setRequestTask] = useState<DataType>()
|
const [requestTask, setRequestTask] = useState<DataType>()
|
||||||
|
console.log("DetailModelForm:props:", props,requestTask)
|
||||||
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
const [editFormDisable, setEditFormDisable] = useState(props.operationId === OPERATION_BUTTON_TYPE.DETAIL)
|
||||||
// 团队第一层 pid必须为0
|
// 团队第一层 pid必须为0
|
||||||
const [taskType, setTaskType] = useState('0')
|
const [taskType, setTaskType] = useState('0')
|
||||||
|
@ -87,6 +89,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
console.log("form.setFieldsValue(task.data)" + JSON.stringify(task.data))
|
||||||
} else {
|
} else {
|
||||||
message.error(task.status.message);
|
message.error(task.status.message);
|
||||||
|
setRequestTask(undefined)
|
||||||
|
form.resetFields()
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
@ -141,6 +145,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
|
setRequestTask(undefined)
|
||||||
|
form.resetFields()
|
||||||
props.reloadData?.();
|
props.reloadData?.();
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
@ -170,6 +176,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
console.log('response', response)
|
console.log('response', response)
|
||||||
if (response.status.success) {
|
if (response.status.success) {
|
||||||
message.success("删除任务成功:" + response.data)
|
message.success("删除任务成功:" + response.data)
|
||||||
|
setRequestTask(undefined)
|
||||||
|
form.resetFields()
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -191,6 +199,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
} else {
|
} else {
|
||||||
if (editFormDisable && taskType == '1') {
|
if (editFormDisable && taskType == '1') {
|
||||||
result.push(<ShareOption taskId={props.itemId!}/>)
|
result.push(<ShareOption taskId={props.itemId!}/>)
|
||||||
|
result.push(<TeamMember taskId={props.itemId!}/> )
|
||||||
}
|
}
|
||||||
result.push(<Button type="primary" key="close"
|
result.push(<Button type="primary" key="close"
|
||||||
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
||||||
|
@ -269,6 +278,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
// 如果可以直接更新列表而不请求。。。。。。
|
// 如果可以直接更新列表而不请求。。。。。。
|
||||||
|
setRequestTask(undefined)
|
||||||
|
form.resetFields()
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
result = true
|
result = true
|
||||||
} else {
|
} else {
|
||||||
|
@ -289,6 +300,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// 如果可以直接更新列表而不请求。。。。。。
|
// 如果可以直接更新列表而不请求。。。。。。
|
||||||
console.log('props.reloadData?.()', props.reloadData)
|
console.log('props.reloadData?.()', props.reloadData)
|
||||||
result = (taskType != '1')
|
result = (taskType != '1')
|
||||||
|
setRequestTask(undefined)
|
||||||
|
form.resetFields()
|
||||||
props.reloadData?.()
|
props.reloadData?.()
|
||||||
} else {
|
} else {
|
||||||
message.error(response.data.status.message)
|
message.error(response.data.status.message)
|
||||||
|
|
|
@ -12,3 +12,23 @@
|
||||||
.ant-form-item .ant-form-item-label{
|
.ant-form-item .ant-form-item-label{
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-ellipsis {
|
||||||
|
/* 单行省略 */
|
||||||
|
/*width: 100%;*/
|
||||||
|
/*box-sizing: border-box;*/
|
||||||
|
/*white-space: nowrap;*/
|
||||||
|
/*overflow: hidden;*/
|
||||||
|
/*text-overflow: ellipsis;*/
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
line-height: 1.5em; /* 根据实际字体大小调整 */
|
||||||
|
max-height: 3em; /* 2行 x 1.5em */
|
||||||
|
word-break: break-word; /* 允许长单词换行 */
|
||||||
|
}
|
|
@ -5,11 +5,11 @@ import {
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import type {ActionType, FormInstance, ProColumns, ProFormInstance} from '@ant-design/pro-components';
|
import type {ActionType, FormInstance, ProColumns, ProFormInstance} from '@ant-design/pro-components';
|
||||||
import {ProTable, TableDropdown} from '@ant-design/pro-components';
|
import {ProTable, TableDropdown} from '@ant-design/pro-components';
|
||||||
import {Button, DatePicker, Dropdown, Space, Switch, Tag, Tooltip} from 'antd';
|
import { DatePicker, Dropdown, Space, Switch, Tag, Tooltip} from 'antd';
|
||||||
import React, {Fragment, useContext, useEffect, useRef} from 'react';
|
import React, {Fragment, useContext, useEffect, useRef} from 'react';
|
||||||
import {DataType} from "@/lib/definitions";
|
import {DataType} from "@/lib/definitions";
|
||||||
import {
|
import {
|
||||||
getTaskTreeResult, getTaskTreeResultAPI,
|
getTaskTreeResultAPI,
|
||||||
OPERATION_BUTTON_TYPE,
|
OPERATION_BUTTON_TYPE,
|
||||||
taskPriorityList,
|
taskPriorityList,
|
||||||
taskStateList,
|
taskStateList,
|
||||||
|
@ -63,6 +63,11 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
key: 'description',
|
key: 'description',
|
||||||
title: '任务描述',
|
title: '任务描述',
|
||||||
dataIndex: 'description',
|
dataIndex: 'description',
|
||||||
|
render: (_, record) => {
|
||||||
|
return <Tooltip placement="topLeft" title={record.description}>
|
||||||
|
<div className='text-ellipsis'>{record.description}</div>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'priority',
|
key: 'priority',
|
||||||
|
@ -152,6 +157,7 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
title: '操作',
|
title: '操作',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
render: (_, record) => <OperationButton itemId={record.id} itemName={record.name} pid={record.pid} pPid={record.pPid}
|
render: (_, record) => <OperationButton itemId={record.id} itemName={record.name} pid={record.pid} pPid={record.pPid}
|
||||||
|
priority={record.priority}
|
||||||
refreshDate={() => {
|
refreshDate={() => {
|
||||||
actionRef.current?.reload(false);
|
actionRef.current?.reload(false);
|
||||||
}}/>,
|
}}/>,
|
||||||
|
|
Loading…
Reference in New Issue