feat:排序处理,添加计划名称前缀组件
This commit is contained in:
parent
88777b39be
commit
b90b63853f
|
@ -1,16 +1,9 @@
|
||||||
import React, {CSSProperties, Fragment, useState} from "react";
|
import React, {CSSProperties, Fragment, useEffect, useState} from "react";
|
||||||
import {DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDraggingStyle} from "react-beautiful-dnd";
|
import {DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDraggingStyle} from "react-beautiful-dnd";
|
||||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
||||||
import {Button, Drawer, Modal} from "antd";
|
import {Button, Drawer, message, Modal} from "antd";
|
||||||
import TextArea from "antd/es/input/TextArea";
|
import TextArea from "antd/es/input/TextArea";
|
||||||
|
import {addStepItemAPI} from "@/components/service/StepSort";
|
||||||
// fake data generator
|
|
||||||
const getItems = (count: number, offset = 0) =>
|
|
||||||
Array.from({length: count}, (v, k) => k).map(k => ({
|
|
||||||
id: `item-${k + offset}-${new Date().getTime()}`,
|
|
||||||
stepDesc: `item ${k + offset}`,
|
|
||||||
sortIndex: k + offset,
|
|
||||||
}));
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -34,11 +27,23 @@ const getListStyle = (isDraggingOver: boolean) => ({
|
||||||
width: "100%"
|
width: "100%"
|
||||||
});
|
});
|
||||||
|
|
||||||
const StepSort = (props: { taskId: string }) => {
|
const StepSort = (props: { taskId: string, stepList: TaskStepSortVO[] }) => {
|
||||||
const [state, setState] = useState<TaskStepSortVO[]>(getItems(5, 10));
|
const [state, setState] = useState<TaskStepSortVO[]>(props.stepList);
|
||||||
// 抽屉 start
|
// 抽屉 start
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [dialogueOpen, setDialogueOpen] = useState(false);
|
const [dialogueOpen, setDialogueOpen] = useState(false);
|
||||||
|
const [sortItemList, setSortItemList] = useState<TaskStepSortVO[]>([]);
|
||||||
|
const [modalText, setModalText] = useState<TaskStepSortVO>({
|
||||||
|
id: "",
|
||||||
|
stepDesc: undefined,
|
||||||
|
sortIndex: undefined,
|
||||||
|
taskId: props.taskId,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 根据任务id查找步骤
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
function onDragEnd(result: DropResult) {
|
function onDragEnd(result: DropResult) {
|
||||||
const {source, destination} = result;
|
const {source, destination} = result;
|
||||||
|
@ -50,16 +55,64 @@ const StepSort = (props: { taskId: string }) => {
|
||||||
let newState = [...state];
|
let newState = [...state];
|
||||||
newState = items;
|
newState = items;
|
||||||
setState(newState);
|
setState(newState);
|
||||||
|
props.stepList.length=0
|
||||||
|
props.stepList.push(...newState)
|
||||||
|
}
|
||||||
|
|
||||||
|
const [confirmButtonLoading, setConfirmButtonLoading] = useState(false);
|
||||||
|
const confirmModalTextArea = () => {
|
||||||
|
setConfirmButtonLoading(true)
|
||||||
|
addStepItemAPI(modalText).then(res => {
|
||||||
|
if (res.data.status.success) {
|
||||||
|
message.info("添加步骤成功")
|
||||||
|
setModalText(
|
||||||
|
{...modalText, stepDesc: undefined})
|
||||||
|
setState([...state, res.data.data])
|
||||||
|
props.stepList.length=0
|
||||||
|
props.stepList.push(...state, res.data.data)
|
||||||
|
setDialogueOpen(false);
|
||||||
|
} else {
|
||||||
|
message.error(res.data.status.message)
|
||||||
|
}
|
||||||
|
}).finally(()=>{
|
||||||
|
setConfirmButtonLoading(false)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
|
title={`步骤`}
|
||||||
closable={false}
|
closable={false}
|
||||||
open={dialogueOpen}
|
open={dialogueOpen}
|
||||||
|
confirmLoading={confirmButtonLoading}
|
||||||
|
onCancel={
|
||||||
|
() => {
|
||||||
|
setDialogueOpen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroyOnClose={true}
|
||||||
|
onOk={confirmModalTextArea}
|
||||||
>
|
>
|
||||||
<TextArea autoSize={{ minRows: 4, maxRows: 20 }} placeholder="最大长度255" maxLength={255} autoFocus />
|
<TextArea autoSize={{minRows: 4, maxRows: 20}}
|
||||||
|
placeholder="最大长度255"
|
||||||
|
showCount
|
||||||
|
styles={{
|
||||||
|
count: {
|
||||||
|
// color:"red",
|
||||||
|
bottom: "0px"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={modalText.sortIndex}
|
||||||
|
maxLength={255} autoFocus
|
||||||
|
onChange={(e) => setModalText(
|
||||||
|
{...modalText, stepDesc: e.target.value})}
|
||||||
|
onKeyDown={event => {
|
||||||
|
if (event.ctrlKey && event.key === 'Enter') {
|
||||||
|
confirmModalTextArea();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Button type={open ? "primary" : "default"} onClick={() => setOpen(!open)}>
|
<Button type={open ? "primary" : "default"} onClick={() => setOpen(!open)}>
|
||||||
|
@ -107,16 +160,13 @@ const StepSort = (props: { taskId: string }) => {
|
||||||
{`步骤${index + 1}`}
|
{`步骤${index + 1}`}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-around",
|
|
||||||
border: "solid",
|
|
||||||
borderRadius: grid * 2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
|
<div style={{whiteSpace: 'pre-line',border: "solid",
|
||||||
|
borderRadius: grid,}}>
|
||||||
{item.stepDesc}
|
{item.stepDesc}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import {TaskMessage} from "@/lib/definitions";
|
||||||
|
import React, {Fragment} from "react";
|
||||||
|
|
||||||
|
const TaskNameAndIcon = (props: {task:TaskMessage}) => {
|
||||||
|
return (<Fragment>
|
||||||
|
{props.task.fId &&
|
||||||
|
<svg className="icon" aria-hidden="true">
|
||||||
|
<use xlinkHref="#icon-tuandui"></use>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
{props.task.taskType == '2' &&
|
||||||
|
<svg className="icon" aria-hidden="true">
|
||||||
|
<use xlinkHref="#icon-youxuliebiao"></use>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
{props.task.taskType == '3' &&
|
||||||
|
<svg className="icon" aria-hidden="true">
|
||||||
|
<use xlinkHref="#icon-dingshi"></use>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
<text>{props.task.name}</text>
|
||||||
|
</Fragment>)
|
||||||
|
}
|
||||||
|
export default TaskNameAndIcon;
|
|
@ -0,0 +1,9 @@
|
||||||
|
import {AxiosResponse} from "axios";
|
||||||
|
import {ResponseVO} from "@/lib/definitions";
|
||||||
|
import {httpReq} from "@/utils/axiosReq";
|
||||||
|
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
||||||
|
|
||||||
|
export const addStepItemAPI= (data:TaskStepSortVO):Promise<AxiosResponse<ResponseVO<TaskStepSortVO>>> =>{
|
||||||
|
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/step/sort/item`,
|
||||||
|
data)
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
export type TaskStepSortVO = {
|
export type TaskStepSortVO = {
|
||||||
id: string,
|
id: string,
|
||||||
sortIndex: number,
|
sortIndex: number|undefined,
|
||||||
stepDesc: string
|
stepDesc: string|undefined,
|
||||||
|
taskId:string
|
||||||
}
|
}
|
|
@ -1,5 +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";
|
||||||
|
|
||||||
export type Request<T>={
|
export type Request<T>={
|
||||||
data:T,
|
data:T,
|
||||||
|
@ -36,6 +37,7 @@ export type TaskMessage ={
|
||||||
fId?:string;
|
fId?:string;
|
||||||
fName?:string;
|
fName?:string;
|
||||||
taskType?:string;
|
taskType?:string;
|
||||||
|
stepList?:TaskStepSortVO[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +53,7 @@ export type DataType = TaskMessage&{
|
||||||
actualTimeRange?:(string|Dayjs|undefined)[]
|
actualTimeRange?:(string|Dayjs|undefined)[]
|
||||||
children: DataType[]|undefined;
|
children: DataType[]|undefined;
|
||||||
sortNo?:number;
|
sortNo?:number;
|
||||||
|
|
||||||
}
|
}
|
||||||
export type DictType={
|
export type DictType={
|
||||||
id:number;
|
id:number;
|
||||||
|
|
|
@ -52,7 +52,7 @@ export async function getTask(id: string): Promise<ResponseVO<DataType>> {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<TaskMessage>>> {
|
export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<DataType>>> {
|
||||||
noStore();
|
noStore();
|
||||||
// 使用 Axios 发送 POST 请求添加数据
|
// 使用 Axios 发送 POST 请求添加数据
|
||||||
switch(task.taskType){
|
switch(task.taskType){
|
||||||
|
|
|
@ -24,7 +24,7 @@ html {
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
/* em 当前元素的 font-size 值,如果元素没有显式设置 font-size,则继承父元素的 font-size。 控制与字体大小相关的属性*/
|
/* em 当前元素的 font-size 值,如果元素没有显式设置 font-size,则继承父元素的 font-size。 控制与字体大小相关的属性*/
|
||||||
width: 1em;
|
width: 2em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
vertical-align: -0.15em;
|
vertical-align: -0.15em;
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'use client'
|
'use client'
|
||||||
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
|
import React, {Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
|
||||||
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
|
||||||
import dayjs, {Dayjs} from 'dayjs'
|
import dayjs, {Dayjs} from 'dayjs'
|
||||||
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
import 'react-big-calendar/lib/css/react-big-calendar.css'
|
||||||
|
@ -14,6 +14,8 @@ import LocalContext from "@/ui/LocalContent";
|
||||||
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
|
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
|
||||||
import {TaskEvent} from "@/lib/task/calendar/data";
|
import {TaskEvent} from "@/lib/task/calendar/data";
|
||||||
import {editExpectAPI} from "@/lib/task/calendar/service";
|
import {editExpectAPI} from "@/lib/task/calendar/service";
|
||||||
|
import TaskNamePrefixIcon from "@/components/TaskNameAndIcon";
|
||||||
|
import TaskNameAndIcon from "@/components/TaskNameAndIcon";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
* https://github.com/jquense/react-big-calendar?tab=readme-ov-file
|
||||||
|
@ -116,7 +118,7 @@ const CalShow: React.FC = () => {
|
||||||
return {
|
return {
|
||||||
start: dayjs(taskState.expectedStartTime).toDate(),
|
start: dayjs(taskState.expectedStartTime).toDate(),
|
||||||
end: dayjs(taskState.expectedEndTime).toDate(),
|
end: dayjs(taskState.expectedEndTime).toDate(),
|
||||||
title: taskState.name,
|
title: <TaskNameAndIcon task={taskState}/>,
|
||||||
resource: taskState.id,
|
resource: taskState.id,
|
||||||
id: taskState.id,
|
id: taskState.id,
|
||||||
state: taskState.state,
|
state: taskState.state,
|
||||||
|
@ -271,7 +273,7 @@ const CalShow: React.FC = () => {
|
||||||
haveButton={false}
|
haveButton={false}
|
||||||
itemId={itemId}
|
itemId={itemId}
|
||||||
reloadData={reloadData} expectedStartTime={expectedStartTime}
|
reloadData={reloadData} expectedStartTime={expectedStartTime}
|
||||||
closeOpen={()=>setOpen(false)}
|
closeOpen={() => setOpen(false)}
|
||||||
expectedEndTime={expectedEndTime}/>}
|
expectedEndTime={expectedEndTime}/>}
|
||||||
<DragAndDropCalendar
|
<DragAndDropCalendar
|
||||||
// 本地设置
|
// 本地设置
|
||||||
|
|
|
@ -189,7 +189,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
||||||
}
|
}
|
||||||
if (taskType == '2') {
|
if (taskType == '2') {
|
||||||
result.push(<StepSort taskId={props.itemId!}/>)
|
result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList||[]}/>)
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -205,9 +205,9 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
// }
|
// }
|
||||||
// return defaultDoms;
|
// return defaultDoms;
|
||||||
const result = defaultDoms.filter(defaultButton => defaultButton.key == 'rest');
|
const result = defaultDoms.filter(defaultButton => defaultButton.key == 'rest');
|
||||||
if (taskType == '2') {
|
// if (taskType == '2') {
|
||||||
result.push(<StepSort taskId={props.itemId!}/>)
|
// result.push(<StepSort taskId={props.itemId!} stepList={requestTask?.stepList||[]}/>)
|
||||||
}
|
// }
|
||||||
result.push(<Button type="primary" key="create-team" loading={operationRequest}
|
result.push(<Button type="primary" key="create-team" loading={operationRequest}
|
||||||
onClick={() => form.submit()}>{taskType == '1' ? "创建团队" : "确认"}
|
onClick={() => form.submit()}>{taskType == '1' ? "创建团队" : "确认"}
|
||||||
</Button>)
|
</Button>)
|
||||||
|
@ -270,6 +270,8 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
||||||
await addTask(values).then(response => {
|
await addTask(values).then(response => {
|
||||||
console.log('response', response)
|
console.log('response', response)
|
||||||
if (response.data.status.success) {
|
if (response.data.status.success) {
|
||||||
|
setRequestTask(response.data.data)
|
||||||
|
|
||||||
message.success(`添加计划${response.data.data.name}成功`)
|
message.success(`添加计划${response.data.data.name}成功`)
|
||||||
// 树任务重新刷新
|
// 树任务重新刷新
|
||||||
// 四象限任务重新刷新
|
// 四象限任务重新刷新
|
||||||
|
|
|
@ -20,6 +20,7 @@ import dayjs from "dayjs";
|
||||||
import '@/ui/task/project/TreeTablePro.modules.css'
|
import '@/ui/task/project/TreeTablePro.modules.css'
|
||||||
import {useSearchParams} from "next/navigation";
|
import {useSearchParams} from "next/navigation";
|
||||||
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
||||||
|
import TaskNameAndIcon from "@/components/TaskNameAndIcon";
|
||||||
|
|
||||||
const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
// 刷新表格
|
// 刷新表格
|
||||||
|
@ -55,12 +56,7 @@ const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return <Fragment>
|
return <TaskNameAndIcon task={record}/>
|
||||||
{record.fId && <svg className="icon" aria-hidden="true">
|
|
||||||
<use xlinkHref="#icon-tuandui"></use>
|
|
||||||
</svg>}
|
|
||||||
<text>{record.name}</text>
|
|
||||||
</Fragment>
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue