feat:1.根据路径展示2.设置主线任务

This commit is contained in:
1708-huayu 2025-08-07 19:27:37 +08:00
parent 55ffba0953
commit 09d4357719
16 changed files with 4556 additions and 105 deletions

View File

@ -107,7 +107,7 @@ const ShareOption = (props: { taskId: string }) => {
onClick={() => doDownload("/static/pc-Web.png", '微信小程序马上行计划管理.png')}></Button> onClick={() => doDownload("/static/pc-Web.png", '微信小程序马上行计划管理.png')}></Button>
</div> </div>
<div className="displayFlexColumn" id="myqrcode"> <div className="displayFlexColumn" id="myqrcode">
<div className="title">7</div> <div className="title">1</div>
<QRCode type="svg" value={qrCodeValue} size={300} status={qrCodeStatus} <QRCode type="svg" value={qrCodeValue} size={300} status={qrCodeStatus}
onRefresh={generateQrcode}/> onRefresh={generateQrcode}/>
<Button onClick={downloadSvgQRCode}></Button> <Button onClick={downloadSvgQRCode}></Button>

View File

@ -0,0 +1,3 @@
.localDiv{
margin-bottom: 24px;
}

View File

@ -0,0 +1,169 @@
import styles from "@/components/TaskRemind.module.css";
import {CascaderProps, ConfigProvider} from 'antd';
import {Cascader} from 'antd';
import React, {useState} from "react";
interface ITaskRemind {
remindTypeList: string[],
setRemindTypeList: (taskTypeList: string[]) => void,
readonly: boolean,
}
interface Option {
value?: string | number | null;
label: React.ReactNode;
children?: Option[];
isLeaf?: boolean;
}
const optionLists: Option[] = [
{
label: "期望开始",
value: "expect_start",
isLeaf: false,
},
{
label: "期望结束",
value: "expect_end",
isLeaf: false,
},
];
const TaskRemindComponent = (props: ITaskRemind) => {
const [options, setOptions] = useState<Option[]>(optionLists);
const cascaderOnChange: CascaderProps<Option>['onChange'] = (value: (string | number)[], selectedOptions: Option[]) => {
console.log(value, selectedOptions);
};
const cascaderLoadData = (selectedOptions: Option[]) => {
const targetOption = selectedOptions[selectedOptions.length - 1];
if (targetOption.value === "expect_start" || targetOption.value === "expect_end") {
targetOption.children = [
{
label: ``,
value: 'before',
isLeaf: false,
},
{
label: ``,
value: 'after',
isLeaf: false,
},
];
} else if (targetOption.value === "before" || targetOption.value === "after") {
targetOption.children = Array.from({length: 60}, (_, i) => ({
label: i.toString().padStart(2, '0'), // 显示为 "00", "01", ..., "59"
value: i,
isLeaf: false,
}))
} else {
targetOption.children = [
{
label: "分钟",
value: "m",
isLeaf: true,
},
{
label: "小时",
value: "h",
isLeaf: false,
},
{
label: "天",
value: "d",
isLeaf: false,
}
]
}
setOptions([...options]);
}
return (<div className={styles.localDiv}>
<div style={{marginBottom: "8px"}}></div>
{/*{props.readonly ?*/}
{/* (props.remindTypeList.length == 0 ? <div>-</div> : props.remindTypeList.map(remindType => {*/}
{/* <div>remindType.split(",")</div>*/}
{/* })) :*/}
{/* (props.remindTypeList.length == 0 ? <Space wrap>*/}
{/* <Select*/}
{/* style={{width: 120}}*/}
{/* allowClear*/}
{/* // defaultValue={onceConsumeChange[0]}*/}
{/* onChange={(value) => {*/}
{/* }}*/}
{/* options={[{*/}
{/* label: "期望开始",*/}
{/* value: "expect_start",*/}
{/* }, {*/}
{/* label: "期望结束",*/}
{/* value: "expect_end",*/}
{/* }*/}
{/* ]}*/}
{/* />*/}
{/* <Select*/}
{/* style={{width: 120}}*/}
{/* allowClear*/}
{/* // defaultValue={onceConsumeChange[0]}*/}
{/* onChange={(value) => {*/}
{/* }}*/}
{/* options={[{*/}
{/* label: "前",*/}
{/* value: "before",*/}
{/* }, {*/}
{/* label: "后",*/}
{/* value: "after",*/}
{/* }*/}
{/* ]}*/}
{/* />*/}
{/* <Select*/}
{/* style={{width: 120}}*/}
{/* allowClear*/}
{/* onChange={(value) => {*/}
{/* }}*/}
{/* options={onceConsumeList}*/}
{/* />*/}
{/* <Select*/}
{/* style={{width: 120}}*/}
{/* allowClear*/}
{/* // defaultValue={onceConsumeChange[1]}*/}
{/* onChange={(value) => {*/}
{/* }}*/}
{/* options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {*/}
{/* label: "天",*/}
{/* value: "d"*/}
{/* }]}*/}
{/* />*/}
{/* </Space>:props.remindTypeList.map(remindType => {*/}
{/* <div>remindType.split(",")</div>*/}
{/* }))}*/}
{props.readonly ? (
props.remindTypeList.length === 0 ? (
<div>-</div>
) : (
props.remindTypeList.map((remindType, index) => (
<div key={index}>{remindType.split(",").join(", ")}</div>
))
)
) : props.remindTypeList.length === 0 ? (
<ConfigProvider
theme={{
components: {
Cascader: {
/* 这里是你的组件 token */
controlWidth:300
},
},
}}
>
<Cascader options={options} loadData={cascaderLoadData} onChange={cascaderOnChange} changeOnSelect defaultValue={["expect_start","after","1","h"]} />
</ConfigProvider>
) : (
props.remindTypeList.map((remindType, index) => (
<div key={index}>{remindType.split(",").join(", ")}</div>
))
)}
</div>)
}
export default TaskRemindComponent

View File

@ -1,13 +1,13 @@
import React, {Fragment, useEffect, useRef, useState} from "react"; import React, {Fragment, useEffect, useRef, useState} from "react";
import {Button, Modal, TablePaginationConfig} from "antd"; import {Button, message, Modal, TablePaginationConfig} from "antd";
import {ActionType, ProColumns, ProTable} from "@ant-design/pro-components"; import {ActionType, ProColumns, ProTable} from "@ant-design/pro-components";
import {Params} from "next/dist/shared/lib/router/utils/route-matcher"; import {Params} from "next/dist/shared/lib/router/utils/route-matcher";
import {TeamMemberVO} from "@/components/type/Share.d"; import {TeamMemberVO} from "@/components/type/Share.d";
import type {FilterValue, SorterResult, TableCurrentDataSource} from "antd/es/table/interface"; import type {FilterValue, SorterResult, TableCurrentDataSource} from "antd/es/table/interface";
import {listTeamMemberAPI} from "@/components/service/Share"; import {allowAddTeamAPI, listTeamMemberAPI, quitTeamAPI, removeTeamAPI} from "@/components/service/Share";
const TeamMember = (props: { taskId: string }) => { const TeamMember = (props: { taskId: string,closeOpen?: () => void,reloadData?: () => void }) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
@ -18,20 +18,57 @@ const TeamMember = (props: { taskId: string }) => {
const [totalUserList, setTotalUserList] = React.useState<TeamMemberVO[]>([]); const [totalUserList, setTotalUserList] = React.useState<TeamMemberVO[]>([]);
const [totalElement, setTotalElement] = React.useState(0); const [totalElement, setTotalElement] = React.useState(0);
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [buttonLoading, setButtonLoading] = React.useState(false);
const [currentUser, setCurrentUser] =
React.useState<{ username: string, adminFlag: boolean }>();
const [page,setPage]=React.useState({pageSize:10, pageIndex:1});
useEffect(() => { useEffect(() => {
if (open){ if (open) {
setLoading(true); setLoading(true);
listTeamMemberAPI(props.taskId).then((res)=>{ listTeamMemberAPI(props.taskId).then((res) => {
if (res.data.status.success){ if (res.data.status.success) {
setUserList(res.data.data.splice(0,10)) setUserList(res.data.data.splice(0, 10))
setTotalUserList(res.data.data) setTotalUserList(res.data.data)
setTotalElement(res.data.data.length) setTotalElement(res.data.data.length)
setTimeout(()=>{ref.current?.reload()},100) setTimeout(() => {
ref.current?.reload()
}, 100)
} }
setLoading(false) setLoading(false)
}) })
} }
},[open]) }, [open])
const removeTeam = (teamMember: TeamMemberVO) => {
removeTeamAPI(teamMember).then(res => {
if (res.data.status.success) {
message.success("移除成功")
setTotalUserList(res.data.data)
setUserList(res.data.data.splice((page.pageIndex - 1) * (page.pageSize), page.pageSize))
}
})
}
const quitTeam = (teamMember: TeamMemberVO) => {
quitTeamAPI(teamMember).then(res => {
if (res.data.status.success) {
message.success('退出成功,随后返回首页')
props.reloadData?.()
setOpen(!open)
props.closeOpen?.()
}
})
}
const allowAddTeam = (teamMember: TeamMemberVO) => {
allowAddTeamAPI({
userId: [teamMember.userId],
taskId: props.taskId
}).then(res=>{
message.success("添加成功")
setTotalUserList(res.data.data)
setUserList(res.data.data.splice((page.pageIndex - 1) * (page.pageSize), page.pageSize))
})
}
const columns: ProColumns<TeamMemberVO>[] = [ const columns: ProColumns<TeamMemberVO>[] = [
{ {
title: 'ID', title: 'ID',
@ -50,7 +87,22 @@ const TeamMember = (props: { taskId: string }) => {
key: 'operate', key: 'operate',
width: 120, width: 120,
valueType: 'option', valueType: 'option',
render: () => [<Button key="1"></Button>], render: (node, entity) => {
// 管理员可展示提出,普通用户自己展示退出
if (currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser.username) {
return <Button key={`${entity.id}remove`} loading={buttonLoading} danger
onClick={(event) => removeTeam(entity)}></Button>
} else if (currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser.username) {
return <Button key={`${entity.id}myself`} loading={buttonLoading} color='default'></Button>
} else if (!currentUser?.adminFlag && entity.userState == '1' && entity.username != currentUser?.username) {
return <Button key={`${entity.id}team`} loading={buttonLoading} color='default'></Button>
} else if (!currentUser?.adminFlag && entity.userState == '1' && entity.username == currentUser?.username) {
return <Button key={`${entity.id}quit`} loading={buttonLoading} danger onClick={(event) => quitTeam(entity)}>退</Button>
} else if (entity.userState == '0') {
return <Button key={`${entity.id}allow`} loading={buttonLoading} color='primary' onClick={(event) => allowAddTeam(entity)}></Button>
}
return undefined;
},
}, },
]; ];
return ( return (
@ -83,8 +135,8 @@ const TeamMember = (props: { taskId: string }) => {
// }} // }}
/* Pagination */ /* Pagination */
pagination={{ pagination={{
defaultPageSize:10, defaultPageSize: page.pageSize,
defaultCurrent:1, defaultCurrent: page.pageIndex,
total: totalElement, total: totalElement,
showSizeChanger: true, showSizeChanger: true,
showQuickJumper: true, showQuickJumper: true,
@ -93,7 +145,11 @@ const TeamMember = (props: { taskId: string }) => {
onChange={(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>, onChange={(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>,
sorter: SorterResult<TeamMemberVO> | SorterResult<TeamMemberVO>[], extra: sorter: SorterResult<TeamMemberVO> | SorterResult<TeamMemberVO>[], extra:
TableCurrentDataSource<TeamMemberVO>) => { TableCurrentDataSource<TeamMemberVO>) => {
setUserList(totalUserList.splice((pagination.current??1-1)*(pagination.pageSize??10),pagination.pageSize)) setPage({
pageSize: pagination.pageSize||10,
pageIndex: pagination.current||1,
})
setUserList(totalUserList.splice((pagination.current ?? 1 - 1) * (pagination.pageSize ?? 10), pagination.pageSize))
}} }}
/> />
</Modal> </Modal>

File diff suppressed because it is too large Load Diff

View File

@ -10,3 +10,12 @@ export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<Sha
export const listTeamMemberAPI = (taskId:string):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{ 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}`) return httpReq.get(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/list?taskId=${taskId}`)
} }
export const removeTeamAPI = (teamMember: TeamMemberVO):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/remove`,teamMember)
}
export const quitTeamAPI = (teamMember: TeamMemberVO):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
return httpReq.delete(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/quite/${teamMember.id}`)
}
export const allowAddTeamAPI = (teamAllow:any):Promise<AxiosResponse<ResponseVO<TeamMemberVO[]>>> =>{
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/team/member/allow`,teamAllow)
}

View File

@ -1,7 +1,6 @@
import React from "react"; import React from "react";
import {Dayjs} from "dayjs"; import {Dayjs} from "dayjs";
import {TaskStepSortVO} from "@/components/type/TaskSort.d"; import {TaskStepSortVO} from "@/components/type/TaskSort.d";
import {Data} from "@dnd-kit/core";
export type Request<T>={ export type Request<T>={
data:T, data:T,
@ -58,7 +57,7 @@ export type DataType = TaskMessage&{
actualTimeRange?:(string|Dayjs|undefined)[] actualTimeRange?:(string|Dayjs|undefined)[]
children: DataType[]|undefined; children: DataType[]|undefined;
sortNo?:number; sortNo?:number;
remindType?:string[]
} }
export type DictType={ export type DictType={
id:number; id:number;

View File

@ -12,7 +12,9 @@ import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
export interface OperationButtonProps { export interface OperationButtonProps {
itemId: string, itemId: string,
fId:string|undefined,
itemName:string, itemName:string,
fName:string|undefined,
priority?:string, priority?:string,
pid: string, pid: string,
pPid: string, pPid: string,
@ -162,15 +164,15 @@ class OperationButton extends React.Component<OperationButtonProps, OperationMod
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_TREE, key: OPERATION_BUTTON_TYPE.SHOW_TREE,
label: <Link href={`/task/project?pid=${this.props.itemId}&pName=${this.props.itemName}`}></Link>, label: <Link href={`/task/project?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}></Link>,
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_FOUR, key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
label: <Link href={`/task/drag?pid=${this.props.itemId}&pName=${this.props.itemName}`}></Link>, label: <Link href={`/task/drag?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}></Link>,
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR, key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
label: <Link href={`/task/calendar?pid=${this.props.itemId}&pName=${this.props.itemName}`}></Link>, label: <Link href={`/task/calendar?pid=${this.props.itemId}&pName=${this.props.itemName}${this.props.fId?('&fId='+this.props.fId+"&fName="+this.props.fName):""}`}></Link>,
} }
]; ];
return <Fragment> return <Fragment>

View File

@ -7,8 +7,10 @@ import Link from "next/link";
import {DetailModelForm} from "@/ui/task/project/DetailModelForm"; import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
interface OperationButtonProps { interface OperationButtonProps {
itemId: string, itemId: string,
fId:string|undefined,
taskType?:string, taskType?:string,
itemName: string, itemName: string,
fName:string|undefined,
priority?:string, priority?:string,
pid: string, pid: string,
pPid: string, pPid: string,
@ -89,15 +91,15 @@ const RightOption: React.FC<OperationButtonProps> = (props) => {
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_TREE, key: OPERATION_BUTTON_TYPE.SHOW_TREE,
label: <Link href={`/task/project?pid=${props.itemId}&pName=${props.itemName}`}></Link>, label: <Link href={`/task/project?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}></Link>,
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_FOUR, key: OPERATION_BUTTON_TYPE.SHOW_FOUR,
label: <Link href={`/task/drag?pid=${props.itemId}&pName=${props.itemName}`}></Link>, label: <Link href={`/task/drag?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}></Link>,
}, },
{ {
key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR, key: OPERATION_BUTTON_TYPE.SHOW_CALENDAR,
label: <Link href={`/task/calendar?pid=${props.itemId}&pName=${props.itemName}`}></Link>, label: <Link href={`/task/calendar?pid=${props.itemId}&pName=${props.itemName}${props.fId?('&fId='+props.fId+"&fName="+props.fName):""}`}></Link>,
} }
]; ];
// 获取系统样式 // 获取系统样式

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import React, {Fragment, useContext, useEffect} from "react"; import React, {Fragment, useContext, useEffect, useState} from "react";
import {Button, Checkbox, CheckboxOptionType, DatePicker, Select, Space} from "antd"; import {Button, Checkbox, CheckboxOptionType, DatePicker, MenuProps, message, Select, Space} from "antd";
import {usePathname, useRouter} from "next/navigation"; import {usePathname, useRouter} from "next/navigation";
import {DetailModelForm} from "@/ui/task/project/DetailModelForm"; import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
import {OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data"; import {OPERATION_BUTTON_TYPE, taskStateList} from "@/lib/task/project/data";
@ -9,6 +9,7 @@ import LocalContext from "@/ui/LocalContent";
import {RequestDateType} from "@/ui/task/RequestDateType"; import {RequestDateType} from "@/ui/task/RequestDateType";
import dayjs, {Dayjs} from "dayjs"; import dayjs, {Dayjs} from "dayjs";
import {useSearchParams} from "next/dist/client/components/navigation"; import {useSearchParams} from "next/dist/client/components/navigation";
import Dropdown from "antd/es/dropdown/dropdown";
interface TitleOperationProps { interface TitleOperationProps {
setTaskState: (value: string) => void; setTaskState: (value: string) => void;
@ -22,8 +23,14 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
refreshData refreshData
}: TitleOperationProps) => { }: TitleOperationProps) => {
const {replace} = useRouter(); const {replace} = useRouter();
console.log('usePathname()', usePathname()); const searchParams = useSearchParams();
console.log('useSearchParams()', useSearchParams().get('pid')); const pathname = usePathname();
const [pathParam, setPathParam] = useState<string | undefined>(searchParams.toString());
const [pathName, setPathName] = useState(pathname);
console.log('usePathname()', pathname);
console.log('useSearchParams()',searchParams.toString(),searchParams.get('pName'), searchParams.get('pid'));
const data = useContext(LocalContext); const data = useContext(LocalContext);
const {RangePicker} = DatePicker; const {RangePicker} = DatePicker;
const expectStartTimeParseResult: RequestDateType[] = data.expectedStartTime.length > 0 ? JSON.parse(data.expectedStartTime) : [undefined, undefined] const expectStartTimeParseResult: RequestDateType[] = data.expectedStartTime.length > 0 ? JSON.parse(data.expectedStartTime) : [undefined, undefined]
@ -32,17 +39,48 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined, expectStartTimeParseResult[0] && expectStartTimeParseResult[0].value ? dayjs(expectStartTimeParseResult[0].value.toString()) : undefined,
expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined expectStartTimeParseResult[1] && expectStartTimeParseResult[1].value ? dayjs(expectStartTimeParseResult[1].value.toString()) : undefined
]; ];
const pName = useSearchParams().get("pName");
const typeList: CheckboxOptionType<string>[] = [ const typeList: CheckboxOptionType<string>[] = [
{ label: '计划', value: '0,1,2,3', }, { label: '计划', value: '0,1,2,3', },
{ label: '打卡', value: '4', }, { label: '打卡', value: '4', },
{ label: '事件', value: '5', }, { label: '事件', value: '5', },
]; ];
// ✅ 监听 searchParams 变化
useEffect(() => { useEffect(() => {
const pName = searchParams.get("pName");
if(pName&&pName!=document.title){ if(pName&&pName!=document.title){
document.title = pName; document.title = pName;
} }
}, [pName]); setPathParam(searchParams.toString());
}, [searchParams]); // searchParams 变化时触发
const onClick: MenuProps['onClick'] = ({ key }) => {
if (key == "1"){
}else if (key == "2"){
replace(pathName)
setPathParam(undefined)
}
};
const items: MenuProps['items'] = [
{
label: '退出登录',
key: '1',
},
];
const itemsPid: MenuProps['items'] = [
{
label: '退出登录',
key: '1',
},
{
label: '从顶级任务查看',
key: '2',
},
];
return <div className={style.container}> return <div className={style.container}>
<Space style={{marginTop: 0, "height": "42px", "alignContent": "center"}}> <Space style={{marginTop: 0, "height": "42px", "alignContent": "center"}}>
<DetailModelForm haveButton={true} open={false} operationId={OPERATION_BUTTON_TYPE.ADD} <DetailModelForm haveButton={true} open={false} operationId={OPERATION_BUTTON_TYPE.ADD}
@ -50,21 +88,21 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
{ {
!usePathname().startsWith("/task/project") && !usePathname().startsWith("/task/project") &&
<Button type="primary" onClick={() => { <Button type="primary" onClick={() => {
replace("/task/project"); replace(`/task/project${pathParam?('?'+pathParam):""}`);
// setCurrentPath("/task/project") // setCurrentPath("/task/project")
}}></Button> }}></Button>
} }
{ {
!usePathname().startsWith("/task/drag") && !usePathname().startsWith("/task/drag") &&
<Button type="primary" onClick={() => { <Button type="primary" onClick={() => {
replace("/task/drag"); replace(`/task/drag${pathParam?('?'+pathParam):""}`);
// setCurrentPath("/task/four"); // setCurrentPath("/task/four");
}}></Button> }}></Button>
} }
{ {
!usePathname().startsWith("/task/calendar") && !usePathname().startsWith("/task/calendar") &&
<Button type="primary" onClick={() => { <Button type="primary" onClick={() => {
replace("/task/calendar"); replace(`/task/calendar${pathParam?('?'+pathParam):""}`);
// setCurrentPath("/task/project") // setCurrentPath("/task/project")
}}></Button> }}></Button>
} }
@ -139,8 +177,10 @@ export const TitleOperation: React.FC<TitleOperationProps> = ({
</Fragment> </Fragment>
} }
</Space> </Space>
<Dropdown menu={{ items:pathParam?itemsPid:items, onClick }}>
<svg style={{height: "32px", width: "32px", alignItems: "center"}} className="icon" aria-hidden="true"> <svg style={{height: "32px", width: "32px", alignItems: "center"}} className="icon" aria-hidden="true">
<use xlinkHref="#icon-user__easyico"></use> <use xlinkHref="#icon-user__easyico"></use>
</svg> </svg>
</Dropdown>
</div> </div>
} }

View File

@ -9,7 +9,7 @@ import dayjs from "dayjs";
import {getTaskState, taskPriorityList} from "@/lib/task/project/data"; import {getTaskState, taskPriorityList} from "@/lib/task/project/data";
import 'react-virtualized/styles.css'; import 'react-virtualized/styles.css';
import RightOption from "@/ui/task/RightOption"; import RightOption from "@/ui/task/RightOption";
import {CopyOutlined} from "@ant-design/icons";
interface DroppableTableProps { interface DroppableTableProps {
tableCode: string, tableCode: string,
@ -83,6 +83,7 @@ export const DroppableTable = React.memo((props: DroppableTableProps) => {
{(provided, snapshot) => ( {(provided, snapshot) => (
<RightOption refreshDate={props.refreshDate} itemId={record.id} <RightOption refreshDate={props.refreshDate} itemId={record.id}
itemName={record.name} pid={record.pid} itemName={record.name} pid={record.pid}
fId={record.fId} fName={record.fName}
taskType={record.taskType} taskType={record.taskType}
pPid={record.pPid} children={<div pPid={record.pPid} children={<div
ref={provided.innerRef} ref={provided.innerRef}

View File

@ -152,7 +152,9 @@ const TreeTable: React.FC<TableSearchType> = (props) => {
columns={columns} columns={columns}
// rowSelection={{ ...rowSelection, checkStrictly}} // rowSelection={{ ...rowSelection, checkStrictly}}
dataSource={props.resultDataTypeList.filter(resultDataType=>{ dataSource={props.resultDataTypeList.filter(resultDataType=>{
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/> resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name}
fId={resultDataType.fId} fName={resultDataType.fName}
pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
if (dataLocalContext.expectedStartTime.length === 0) { if (dataLocalContext.expectedStartTime.length === 0) {
return true; return true;
} }

View File

@ -166,7 +166,9 @@ const TreeTable: React.FC<TableSearchType> = (props) => {
columns={columns} columns={columns}
// rowSelection={{ ...rowSelection, checkStrictly}} // rowSelection={{ ...rowSelection, checkStrictly}}
dataSource={props.resultDataTypeList.filter(resultDataType=>{ dataSource={props.resultDataTypeList.filter(resultDataType=>{
resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name} priority={resultDataType.priority} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/> resultDataType.action= <OperationButton itemId={resultDataType.id} itemName={resultDataType.name}
fId={resultDataType.fId} fName={resultDataType.fName}
priority={resultDataType.priority} pid={resultDataType.pid} pPid={resultDataType.pPid} refreshDate={props.refreshDate}/>
if (dataLocalContext.expectedStartTime.length === 0) { if (dataLocalContext.expectedStartTime.length === 0) {
return true; return true;
} }

View File

@ -26,6 +26,9 @@ 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"; import TeamMember from "@/components/TeamMember";
import {useSearchParams} from "next/dist/client/components/navigation";
import TaskRemindComponent from "@/components/TaskRemindComponent";
export type DetailModelFormProps = { export type DetailModelFormProps = {
// 当前内容id // 当前内容id
itemId?: string, itemId?: string,
@ -49,19 +52,71 @@ export type DetailModelFormProps = {
// 重新加载数据 // 重新加载数据
reloadData?: () => void reloadData?: () => void
} }
export type PidSelectTree = { label: string; value: string; pid: string; children?: PidSelectTree[] } export type PidSelectTree = {
label: string;
value: string;
pid: string;
fId: string | undefined,
fName: string | undefined,
children?: PidSelectTree[]
}
export type ParentTaskVO = {
pid: string,
pName: string | undefined,
fId: string | undefined,
fName: string | undefined,
}
export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => { export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
const [form] = Form.useForm<DataType>(); const [form] = Form.useForm<DataType>();
const searchParams = useSearchParams();
const [requestTask, setRequestTask] = useState<DataType>() const [requestTask, setRequestTask] = useState<DataType>()
console.log("DetailModelForm:props:", props,requestTask) 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')
const [spinning, setSpinning] = useState(true) const [spinning, setSpinning] = useState(true)
const [operationRequest, setOperationRequest] = useState(false) const [operationRequest, setOperationRequest] = useState(false)
const [onceConsumeChange, setOnceConsumeChange] = useState<string[]>(["1", "h"]) const [onceConsumeChange, setOnceConsumeChange] = useState<string[]>(["1", "h"])
const [defaultPTask, setDefaultPTask] = useState<ParentTaskVO>({
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
const [pTaskMap, setPTaskMap] = useState<Record<string, ParentTaskVO>>()
const [remindTypeList,setRemindTypeList] = useState<string[]>([])
function initData(){
form.resetFields()
setTaskType('0')
setOnceConsumeChange(["1", "h"])
setRequestTask(undefined);
setDefaultPTask({
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
}
useEffect(() => {
if (searchParams && searchParams.get("pid")) {
setDefaultPTask({
pid: searchParams.get("pid")!,
pName: searchParams.get("pName")!,
fId: searchParams.get("fId")!,
fName: searchParams.get("fName")!,
})
} else {
setDefaultPTask({
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
}
}, [searchParams]);
useEffect(() => { useEffect(() => {
if (props.itemId != undefined && ( if (props.itemId != undefined && (
props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) { props.operationId === OPERATION_BUTTON_TYPE.DETAIL || props.operationId === OPERATION_BUTTON_TYPE.UPDATE)) {
@ -78,19 +133,26 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
form.setFieldsValue(task.data) form.setFieldsValue(task.data)
if (task.data.pid == "0") { if (task.data.pid == "0") {
form.setFieldValue("pid", undefined) form.setFieldValue("pid", undefined)
}else if (searchParams){
form.setFieldValue("pid", task.data.pName)
} }
if (task.data.taskType) { if (task.data.taskType) {
setTaskType(task.data.taskType) setTaskType(task.data.taskType)
} }
setRequestTask(task.data) setRequestTask(task.data)
setDefaultPTask({
pid: task.data.pid,
pName: task.data.pName,
fId: task.data.fId,
fName: task.data.fName,
})
if (task.data.onceConsume) { if (task.data.onceConsume) {
setOnceConsumeChange(task.data.onceConsume.split(",")) setOnceConsumeChange(task.data.onceConsume.split(","))
} }
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) initData()
form.resetFields()
props.reloadData?.() props.reloadData?.()
} }
}).finally(() => { }).finally(() => {
@ -111,13 +173,19 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
function childReduce(child: DataType[]): PidSelectTree[] { function childReduce(child: DataType[]): PidSelectTree[] {
const result: PidSelectTree[] = []; const result: PidSelectTree[] = [];
const parentTaskMap: Record<string, ParentTaskVO> = {};
child.map(data => { child.map(data => {
const resultData: PidSelectTree = {label: data.name, value: data.id, pid: data.pid}; const resultData: PidSelectTree = {
label: data.name, value: data.id, pid: data.pid,
fId: data.fId, fName: data.fName
};
parentTaskMap[data.id] = {pid: data.pid, pName: data.pName, fId: data.fId, fName: data.fName};
if (data.children) { if (data.children) {
resultData.children = childReduce(data.children); resultData.children = childReduce(data.children);
} }
result.push(resultData); result.push(resultData);
}) })
setPTaskMap({...pTaskMap, ...parentTaskMap})
return result; return result;
} }
@ -145,8 +213,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
destroyOnClose: true, destroyOnClose: true,
maskClosable: false, maskClosable: false,
onCancel: () => { onCancel: () => {
setRequestTask(undefined) initData()
form.resetFields()
props.reloadData?.(); props.reloadData?.();
}, },
}} }}
@ -176,8 +243,7 @@ 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) initData()
form.resetFields()
props.reloadData?.() props.reloadData?.()
} }
})); }));
@ -199,7 +265,8 @@ 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(<TeamMember taskId={props.itemId!} closeOpen={props.closeOpen}
reloadData={props.reloadData}/>)
} }
result.push(<Button type="primary" key="close" result.push(<Button type="primary" key="close"
onClick={() => props.closeOpen?.()}></Button>) onClick={() => props.closeOpen?.()}></Button>)
@ -236,14 +303,15 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
} }
} }
onFinish={async (values) => { onFinish={async (values) => {
{/* onFinish 返回true关闭窗口范湖false不关闭窗口 */ console.log('Received values of form: ', values,defaultPTask, {...requestTask, ...values});
}
console.log('Received values of form: ', values, {...requestTask, ...values});
setOperationRequest(true) setOperationRequest(true)
if (requestTask) { if (requestTask) {
const {sortNo} = requestTask; const {sortNo} = requestTask;
values.sortNo = sortNo; values.sortNo = sortNo;
} }
values.pid = defaultPTask.pid;
values.fId = defaultPTask.fId;
values.fName = defaultPTask.fName;
if (values.pid === undefined) { if (values.pid === undefined) {
values.pid = '0' values.pid = '0'
} }
@ -260,6 +328,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
values.actualEndTime = dayjs(values.actualTimeRange[1]).toDate() values.actualEndTime = dayjs(values.actualTimeRange[1]).toDate()
} }
var result: boolean = false; var result: boolean = false;
values.remindType=remindTypeList;
let state = taskStateList.find(taskState => taskState.name === values.state?.toString()); let state = taskStateList.find(taskState => taskState.name === values.state?.toString());
if (state) { if (state) {
@ -278,8 +347,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
// 树任务重新刷新 // 树任务重新刷新
// 四象限任务重新刷新 // 四象限任务重新刷新
// 如果可以直接更新列表而不请求。。。。。。 // 如果可以直接更新列表而不请求。。。。。。
setRequestTask(undefined) initData()
form.resetFields()
props.reloadData?.() props.reloadData?.()
result = true result = true
} else { } else {
@ -293,15 +361,15 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
console.log('response', response) console.log('response', response)
if (response.data.status.success) { if (response.data.status.success) {
setRequestTask(response.data.data) setRequestTask(response.data.data)
message.success(`添加计划${response.data.data.name}成功`) message.success(`添加计划${response.data.data.name}成功`)
// 树任务重新刷新 // 树任务重新刷新
// 四象限任务重新刷新 // 四象限任务重新刷新
// 如果可以直接更新列表而不请求。。。。。。 // 如果可以直接更新列表而不请求。。。。。。
console.log('props.reloadData?.()', props.reloadData) console.log('props.reloadData?.()', props.reloadData)
result = (taskType != '1') result = (taskType != '1')
setRequestTask(undefined) if(result){
form.resetFields() initData()
}
props.reloadData?.() props.reloadData?.()
} else { } else {
message.error(response.data.status.message) message.error(response.data.status.message)
@ -310,6 +378,12 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
} }
); );
} }
setDefaultPTask({
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
setOperationRequest(false) setOperationRequest(false)
return result; return result;
}} }}
@ -322,7 +396,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
required={true} required={true}
options={TASK_TYPE.map(task => options={TASK_TYPE.map(task =>
(task.value == '1' && (requestTask?.id)) ? {...task, disabled: true} : task)} (task.value == '1' && (requestTask?.id)) ? {...task, disabled: true} : task)}
// (task.value == '1' ) ? {...task, disabled: true} : task)} // (task.value == '1' ) ? {...task, disabled: true} : task)}
width="sm" width="sm"
name="taskType" name="taskType"
label="任务类型" label="任务类型"
@ -353,12 +427,13 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
<ProFormTreeSelect <ProFormTreeSelect
hidden={taskType == '1'} hidden={taskType == '1'}
width="sm" width="sm"
initialValue={defaultPTask.pName}
request={() => { request={() => {
return getTaskTreeResult(JSON.stringify( return getTaskTreeResult(JSON.stringify(
{ {
pageSize: 1000, pageSize: 1000,
pageNumber: 1, pageNumber: 1,
data: [{code: 'pid', value: '0', operateType: '='}, data: [{code: 'pid', value: defaultPTask.pid, operateType: '='},
// 如果父任务完成会导致父任务不展示 // 如果父任务完成会导致父任务不展示
// { // {
// code: 'state', // code: 'state',
@ -374,8 +449,21 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
fieldProps={{ fieldProps={{
onSelect: (e, node) => { onSelect: (e, node) => {
console.log('onSelect', e, node); console.log('onSelect', e, node);
// setPid(e) setDefaultPTask(pTaskMap?.[e] || {
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
}, },
onClear: () => {
setDefaultPTask({
pid: '0',
pName: undefined,
fId: undefined,
fName: undefined,
})
}
}} }}
disabled={editFormDisable} disabled={editFormDisable}
/> />
@ -406,52 +494,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
placeholder="请输入任务描述" placeholder="请输入任务描述"
disabled={editFormDisable} disabled={editFormDisable}
/> />
<div className={style.localDiv}> <TaskRemindComponent remindTypeList={remindTypeList} setRemindTypeList={(a:string[])=>setRemindTypeList(a)} readonly={editFormDisable} />
<Space wrap>
<text>:</text>
<Select
style={{width: 120}}
allowClear
// defaultValue={onceConsumeChange[0]}
onChange={(value) => {
}}
options={[{label: "期望开始",
value: "expect_start",},{label: "期望结束",
value: "expect_end",}
]}
/>
<Select
style={{width: 120}}
allowClear
// defaultValue={onceConsumeChange[0]}
onChange={(value) => {
}}
options={[{label: "前",
value: "before",},{label: "后",
value: "after",}
]}
/>
<Select
style={{width: 120}}
allowClear
onChange={(value) => {
}}
options={onceConsumeList}
/>
<Select
style={{width: 120}}
allowClear
// defaultValue={onceConsumeChange[1]}
onChange={(value) => {
}}
options={[{label: "分钟", value: "m"}, {label: "小时", value: "h"}, {
label: "天",
value: "d"
}]}
/>
</Space>
</div>
<ProForm.Group> <ProForm.Group>
<ProFormSelect <ProFormSelect
request={async () => request={async () =>
@ -520,7 +563,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
{taskType == "3" && {taskType == "3" &&
<Fragment> <Fragment>
{editFormDisable ? {editFormDisable ?
<div className={style.localDiv} > <div className={style.localDiv}>
<text>:{onceConsumerRead(requestTask?.onceConsume)}</text> <text>:{onceConsumerRead(requestTask?.onceConsume)}</text>
</div> : </div> :
<div className={style.localDiv}> <div className={style.localDiv}>

View File

@ -156,7 +156,9 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
key: 'option', key: 'option',
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}
fId={record.fId} fName={record.fName}
pid={record.pid} pPid={record.pPid}
priority={record.priority} priority={record.priority}
refreshDate={() => { refreshDate={() => {
actionRef.current?.reload(false); actionRef.current?.reload(false);