feat:取消pc链接分享
This commit is contained in:
parent
4e3bc8ddc2
commit
88777b39be
|
@ -1,17 +1,22 @@
|
|||
'use client'
|
||||
import { useRouter} from "next/navigation";
|
||||
import {usePathname,useSearchParams, useRouter} from "next/navigation";
|
||||
import dayjs from "dayjs";
|
||||
import {useEffect} from "react";
|
||||
import { isMobile } from 'react-device-detect';
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const {replace} = useRouter();
|
||||
useEffect(()=>{
|
||||
const pathName = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
console.log({pathName},{searchParams})
|
||||
if(localStorage.getItem('platform-security')){
|
||||
if (isMobile){
|
||||
replace('/mobile/')
|
||||
}else {
|
||||
replace("/task/project")
|
||||
if (!pathName){
|
||||
var callBack = searchParams.get("callBack");
|
||||
if (callBack){
|
||||
replace(decodeURI(callBack))
|
||||
}else {
|
||||
replace("/task/project")
|
||||
}
|
||||
}
|
||||
}else {
|
||||
replace("/login")
|
||||
|
|
|
@ -62,6 +62,7 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
const [diaryList, setDiaryList] = useState<ListDiary[]>([]);
|
||||
const [diaryReduceList, setDiaryReduceList] = useState<ListDiary[]>([])
|
||||
const [page, setPage] = useState(1);
|
||||
const [selectLoading,setSelectLoading]=useState<boolean>(false);
|
||||
const noMore = {
|
||||
id: '0',
|
||||
keyId: 'o0',
|
||||
|
@ -99,6 +100,7 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
if (!open) {
|
||||
return
|
||||
}
|
||||
setSendValueFlag(true)
|
||||
const fakeDataUrl = process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/message/diary/select`;
|
||||
fetch(fakeDataUrl, {
|
||||
method: 'POST', headers: {
|
||||
|
@ -121,6 +123,7 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
listRef.current.scrollTo({top: 9999999});
|
||||
}
|
||||
}
|
||||
setSendValueFlag(false)
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -134,9 +137,9 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
diaryList.filter(taskLog => {
|
||||
if (currentIndex === 0) {
|
||||
return true
|
||||
} else if (currentIndex === 1 && taskLog.enableFlag === "1") {
|
||||
} else if (currentIndex === 1 && taskLog.enableFlag !== "0") {
|
||||
return true
|
||||
} else if (currentIndex === 2 && taskLog.enableFlag === "0") {
|
||||
} else if (currentIndex === 2 && taskLog.enableFlag !== "1") {
|
||||
return true
|
||||
} else return false;
|
||||
}).reduce((map, taskLog) => {
|
||||
|
@ -288,7 +291,6 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
},
|
||||
})
|
||||
// 点击操作 end
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button type={open?"primary":"default"} onClick={() => setOpen(!open)}>
|
||||
|
@ -366,7 +368,7 @@ const DiaryOption = (props: SelectDiary) => {
|
|||
<Button style={{flexGrow: 1}} onClick={() => setCurrentIndex(2)}
|
||||
type={currentIndex == 2 ? "primary" : "default"}>失效</Button>
|
||||
</div>
|
||||
<List>
|
||||
<List loading={sendValueFlag}>
|
||||
<VirtualList
|
||||
data={diaryReduceList}
|
||||
height={containerHeight}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, {Fragment, useEffect, useState} from 'react';
|
||||
import {Button, Image, Input, Modal, QRCode, Space } from 'antd';
|
||||
import {Button, Image, Input, message, Modal, QRCode, Space} from 'antd';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {copyToClipboard} from "@/lib/copyToClipboard";
|
||||
import {addTaskPassAPI} from "@/components/service/Share";
|
||||
|
||||
const ShareOption = (props: { taskId: string }) => {
|
||||
// const [loading, setLoading] = useState(false);
|
||||
|
@ -9,7 +10,7 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
const [buttonIndex, setButtonIndex] = useState(1);
|
||||
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
||||
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>("loading");
|
||||
|
||||
const [joinId,setJoinId] = useState("");
|
||||
function doDownload(url: string, fileName: string) {
|
||||
const a = document.createElement('a');
|
||||
a.download = fileName;
|
||||
|
@ -37,7 +38,22 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
};
|
||||
|
||||
const generateQrcode = () => {
|
||||
|
||||
const clientId: string = uuidv4().substring(0,32);
|
||||
// 分享人必须有权限
|
||||
// 生成分享信息同时适用链接和二维码
|
||||
addTaskPassAPI({taskId:props.taskId,pass:clientId,joinCheck:'1'}).then(res=>{
|
||||
if (res.data.status.success){
|
||||
let qrCodeData = {
|
||||
taskId: props.taskId, pass: clientId,
|
||||
passId: res.data.data.id,
|
||||
local: "马上行计划管理",
|
||||
opType: "SHARE_OPTION"
|
||||
}
|
||||
setJoinId(res.data.data.id!)
|
||||
setQrCodeValue(JSON.stringify(qrCodeData))
|
||||
setQrCodeStatus("active")
|
||||
}
|
||||
});
|
||||
}
|
||||
const showModal = () => {
|
||||
setOpen(true);
|
||||
|
@ -47,14 +63,7 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
setOpen(false);
|
||||
};
|
||||
useEffect(() => {
|
||||
// 分享人必须有权限
|
||||
// 生成分享信息同时适用链接和二维码
|
||||
const clientId: string = uuidv4();
|
||||
let qrCodeData = {
|
||||
taskId: props.taskId, pass: clientId, local: "马上行计划管理", opType: "SHARE_OPTION"
|
||||
}
|
||||
setQrCodeValue(JSON.stringify(qrCodeData))
|
||||
setQrCodeStatus("active")
|
||||
generateQrcode()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
@ -72,22 +81,22 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
<Button key="back" onClick={handleCancel}>
|
||||
返回
|
||||
</Button>,
|
||||
<Button key="qrcode"
|
||||
type={buttonIndex == 1 ? "primary" : "default"}
|
||||
// loading={loading}
|
||||
onClick={() => setButtonIndex(1)}>
|
||||
使用二维码
|
||||
</Button>,
|
||||
<Button
|
||||
key="link"
|
||||
// href="https://google.com"
|
||||
// target="_blank"
|
||||
type={buttonIndex == 2 ? "primary" : "default"}
|
||||
// loading={loading}
|
||||
onClick={() => setButtonIndex(2)}
|
||||
>
|
||||
使用连接
|
||||
</Button>,
|
||||
// <Button key="qrcode"
|
||||
// type={buttonIndex == 1 ? "primary" : "default"}
|
||||
// // loading={loading}
|
||||
// onClick={() => setButtonIndex(1)}>
|
||||
// 使用二维码
|
||||
// </Button>,
|
||||
// <Button
|
||||
// key="link"
|
||||
// // href="https://google.com"
|
||||
// // target="_blank"
|
||||
// type={buttonIndex == 2 ? "primary" : "default"}
|
||||
// // loading={loading}
|
||||
// onClick={() => setButtonIndex(2)}
|
||||
// >
|
||||
// 使用连接
|
||||
// </Button>,
|
||||
]}
|
||||
>
|
||||
{buttonIndex == 1 && <div className="displayFlexRow">
|
||||
|
@ -109,7 +118,8 @@ const ShareOption = (props: { taskId: string }) => {
|
|||
<Space.Compact style={{width: '100%'}}>
|
||||
<Input defaultValue="https://www.huaruyu.com" readOnly/>
|
||||
<Button loading={qrCodeStatus=="loading"}
|
||||
onClick={()=>copyToClipboard("https://www.huaruyu.com")}
|
||||
onClick={()=>{copyToClipboard(`https://www.huaruyu.com/task/project?joinId=${joinId}`);
|
||||
message.info("复制链接成功过")}}
|
||||
type="primary">复制链接</Button>
|
||||
</Space.Compact>
|
||||
</div>}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, {CSSProperties, Fragment, useState} from "react";
|
||||
import {DragDropContext, Droppable, Draggable, DropResult, DraggingStyle, NotDraggingStyle} from "react-beautiful-dnd";
|
||||
import {TaskStepSortVO} from "@/components/type/TaskSort.d";
|
||||
import {Button, Drawer} from "antd";
|
||||
import {Button, Drawer, Modal} from "antd";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
|
||||
// fake data generator
|
||||
const getItems = (count: number, offset = 0) =>
|
||||
|
@ -23,25 +24,21 @@ const grid = 8;
|
|||
const getItemStyle = (isDragging: boolean, draggableStyle: DraggingStyle | NotDraggingStyle | undefined): CSSProperties => ({
|
||||
// some basic styles to make the items look a bit nicer
|
||||
userSelect: "none",
|
||||
padding: grid * 2,
|
||||
// padding: grid,
|
||||
margin: `0 0 ${grid}px 0`,
|
||||
|
||||
// change background colour if dragging
|
||||
background: isDragging ? "lightgreen" : "grey",
|
||||
|
||||
// styles we need to apply on draggables
|
||||
background: isDragging ? "lightgreen" : "white",
|
||||
...draggableStyle
|
||||
});
|
||||
const getListStyle = (isDraggingOver: boolean) => ({
|
||||
background: isDraggingOver ? "lightblue" : "lightgrey",
|
||||
padding: grid,
|
||||
width: 250
|
||||
background: isDraggingOver ? "lightblue" : "white",
|
||||
width: "100%"
|
||||
});
|
||||
|
||||
const StepSort = (props: { taskId: string }) => {
|
||||
const [state, setState] = useState<TaskStepSortVO[]>(getItems(5, 10));
|
||||
// 抽屉 start
|
||||
const [open, setOpen] = useState(false);
|
||||
const [dialogueOpen, setDialogueOpen] = useState(false);
|
||||
|
||||
function onDragEnd(result: DropResult) {
|
||||
const {source, destination} = result;
|
||||
|
@ -57,10 +54,30 @@ const StepSort = (props: { taskId: string }) => {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
|
||||
<Modal
|
||||
closable={false}
|
||||
open={dialogueOpen}
|
||||
>
|
||||
<TextArea autoSize={{ minRows: 4, maxRows: 20 }} placeholder="最大长度255" maxLength={255} autoFocus />
|
||||
</Modal>
|
||||
|
||||
<Button type={open ? "primary" : "default"} onClick={() => setOpen(!open)}>
|
||||
查看步骤
|
||||
</Button>
|
||||
<Drawer>
|
||||
<Drawer
|
||||
style={{boxSizing: "border-box"}}
|
||||
styles={{
|
||||
// body: {padding: "0 24px"}
|
||||
}}
|
||||
mask={false}
|
||||
maskClosable={false}
|
||||
title="步骤列表"
|
||||
closable={{'aria-label': 'Close Button'}}
|
||||
onClose={() => setOpen(false)}
|
||||
open={open}
|
||||
footer={<Button type={"primary"} onClick={() => setDialogueOpen(true)}>添加步骤</Button>}
|
||||
>
|
||||
<div style={{display: "flex"}}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable key="sortDroppable" droppableId="sortDroppableId">
|
||||
|
@ -86,10 +103,15 @@ const StepSort = (props: { taskId: string }) => {
|
|||
provided.draggableProps.style
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
{`步骤${index + 1}`}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-around"
|
||||
justifyContent: "space-around",
|
||||
border: "solid",
|
||||
borderRadius: grid * 2,
|
||||
}}
|
||||
>
|
||||
{item.stepDesc}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import {AxiosResponse} from "axios";
|
||||
import {ResponseVO} from "@/lib/definitions";
|
||||
import {httpReq} from "@/utils/axiosReq";
|
||||
import {ShareVO} from "@/components/type/Share.d";
|
||||
|
||||
export const addTaskPassAPI= (data:ShareVO):Promise<AxiosResponse<ResponseVO<ShareVO>>> =>{
|
||||
return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + "/task/pass",
|
||||
data)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export interface ShareVO { taskId: string, pass: string, joinCheck: string ,id?:string}
|
|
@ -68,12 +68,21 @@ export function addTask(task: DataType): Promise<AxiosResponse<ResponseVO<TaskMe
|
|||
}
|
||||
}
|
||||
|
||||
export async function updateTask(task: DataType): Promise<ResponseVO<string>> {
|
||||
export async function updateTask(task: DataType): Promise<AxiosResponse<ResponseVO<TaskMessage>>> {
|
||||
noStore();
|
||||
// 使用 Axios 发送 PUT 请求修改数据
|
||||
const response: AxiosResponse<ResponseVO<string>> = await httpReq.put(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task', task);
|
||||
// 从响应中提取数据并返回
|
||||
return response.data;
|
||||
// 使用 Axios 发送 POST 请求添加数据
|
||||
switch(task.taskType){
|
||||
// 常规任务
|
||||
case '0':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/V2/task', task);
|
||||
// 团队任务
|
||||
case '1':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/V2/task', task);
|
||||
// 顺序
|
||||
case '2':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task/step/sort', task);
|
||||
// 周期
|
||||
case '3':return httpReq.post(process.env.NEXT_PUBLIC_TODO_REQUEST_URL + '/task/schedule', task);
|
||||
default:throw new Error("创建任务必选任务类型");
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteTask(id: string): Promise<ResponseVO<string>> {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export interface TaskPassVO {
|
||||
taskId:string;
|
||||
pass:string;
|
||||
shareUser:string;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import {DataType, ResponseVO} from "@/lib/definitions";
|
||||
import {unstable_noStore as noStore} from "next/dist/server/web/spec-extension/unstable-no-store";
|
||||
import {AxiosResponse} from "axios";
|
||||
import {httpReq} from "@/utils/axiosReq";
|
||||
import {TaskPassVO} from "@/lib/task/project/team.d";
|
||||
|
||||
export async function getJoinMessageAPI(joinId: string): Promise<ResponseVO<TaskPassVO>> {
|
||||
noStore();
|
||||
// 使用 Axios 发送 PUT 请求获取数据
|
||||
const response: AxiosResponse<ResponseVO<TaskPassVO>> = await httpReq.get(
|
||||
process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/task/pass/${joinId}`);
|
||||
// 从响应中提取数据并返回
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getTaskInSecurityAPI(requestParam: TaskPassVO): Promise<ResponseVO<DataType>> {
|
||||
noStore();
|
||||
// 使用 Axios 发送 PUT 请求获取数据
|
||||
const response: AxiosResponse<ResponseVO<DataType>> = await httpReq.put(
|
||||
process.env.NEXT_PUBLIC_TODO_REQUEST_URL + `/inSecurity/task/${requestParam.taskId}/${requestParam.pass}`);
|
||||
// 从响应中提取数据并返回
|
||||
return response.data;
|
||||
}
|
|
@ -8,7 +8,7 @@ import React, {useLayoutEffect} from 'react';
|
|||
import {useState} from 'react';
|
||||
import {LoginObject} from "@/lib/login/definitions";
|
||||
import {useRouter} from 'next/navigation'
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {askLoginAPI, generateQrcodeAPI} from "@/lib/login/service";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
|
@ -22,33 +22,36 @@ export default function XcxLoginPage() {
|
|||
const [qrCodeStatus, setQrCodeStatus] = useState<'active' | 'expired' | 'loading' | 'scanned'>();
|
||||
const [qrCodeValue, setQrCodeValue] = useState<string>("-");
|
||||
const generateQrcode = () => {
|
||||
if (qrCodeStatus=='loading') {
|
||||
message.info({content:"请耐心等待"})
|
||||
}else if (qrCodeStatus=='expired') {
|
||||
if (qrCodeStatus == 'loading') {
|
||||
message.info({content: "请耐心等待"})
|
||||
} else if (qrCodeStatus == 'expired') {
|
||||
setQrCode()
|
||||
}else if (qrCodeStatus=='active') {
|
||||
} else if (qrCodeStatus == 'active') {
|
||||
|
||||
}else if (qrCodeStatus=='scanned') {
|
||||
} else if (qrCodeStatus == 'scanned') {
|
||||
|
||||
}else {
|
||||
} else {
|
||||
setQrCode()
|
||||
}
|
||||
}
|
||||
function setQrCode(){
|
||||
|
||||
function setQrCode() {
|
||||
// 生成唯一id
|
||||
setQrCodeStatus("loading")
|
||||
const clientId: string = uuidv4();
|
||||
generateQrcodeAPI({clientId}).then(res=>{
|
||||
let qrCodeData={
|
||||
clientId,serverId:res.data.data,local:"马上行计划管理",
|
||||
opType:"LOGIN_OPTION"
|
||||
generateQrcodeAPI({clientId}).then(res => {
|
||||
let qrCodeData = {
|
||||
clientId, serverId: res.data.data, local: "马上行计划管理",
|
||||
opType: "LOGIN_OPTION"
|
||||
}
|
||||
setQrCodeValue(JSON.stringify(qrCodeData))
|
||||
setQrCodeStatus("active")
|
||||
let timeout=undefined;
|
||||
let timeout: ReturnType<typeof setTimeout> | null = null;
|
||||
// 设置定时器,每2000毫秒(2秒)执行一次myFunction
|
||||
let timerId =undefined;
|
||||
timerId = setInterval(askLogin,2000,timeout,timerId,qrCodeData);
|
||||
let timerId: ReturnType<typeof setInterval> | null = null;
|
||||
timerId = setInterval(() => {
|
||||
askLogin(timeout, timerId, qrCodeData);
|
||||
}, 2000);
|
||||
// 如果需要停止定时器,可以调用 clearInterval(timerId);
|
||||
// 例如:1分钟后停止定时器
|
||||
timeout = setTimeout(() => {
|
||||
|
@ -56,16 +59,21 @@ export default function XcxLoginPage() {
|
|||
clearInterval(timerId);
|
||||
console.log("定时器已停止");
|
||||
}, 60000);
|
||||
}).catch(()=>{
|
||||
}).catch(() => {
|
||||
setQrCodeStatus("expired")
|
||||
})
|
||||
}
|
||||
function askLogin(timeout:any,timerId:any,qrCodeData:{}){
|
||||
askLoginAPI(qrCodeData).then(res=>{
|
||||
if (res.data.status.success&&res.data.data.length>0){
|
||||
|
||||
function askLogin(timeout: ReturnType<typeof setTimeout> | null, timerId: ReturnType<typeof setInterval> | null,
|
||||
qrCodeData: {}) {
|
||||
askLoginAPI(qrCodeData).then(res => {
|
||||
if (res.data.status.success && res.data.data.length > 0) {
|
||||
setQrCodeStatus("scanned")
|
||||
if(timeout){
|
||||
console.log({timerId}, {timeout})
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
if (timerId) {
|
||||
clearInterval(timerId);
|
||||
}
|
||||
// localStorage.removeItem("platform-security")
|
||||
|
@ -73,12 +81,28 @@ export default function XcxLoginPage() {
|
|||
// 删除名为 'platform-security' 的Cookie
|
||||
// Cookies.remove('platform-security');
|
||||
// 设置一个有效期为7天的Cookie
|
||||
Cookies.set('platform-security', res.data.data[0].token, { expires: 7 });
|
||||
router.push('/task/project')
|
||||
Cookies.set('platform-security', res.data.data[0].token, {expires: 7});
|
||||
// 获取路径名 (pathname) - 这通常是你所说的“请求路径”
|
||||
console.log(window.location.pathname); // 例如: "/path/to/page"
|
||||
if (window.location.pathname&&window.location.pathname.indexOf("/login")==-1) {
|
||||
return;
|
||||
}
|
||||
// 获取查询字符串(例如: "?name=John&age=30")
|
||||
const queryString = window.location.search;
|
||||
// 创建 URLSearchParams 对象
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
let callBack = urlParams.get("callBack")
|
||||
if (callBack) {
|
||||
console.log({queryString}, decodeURIComponent(callBack))
|
||||
router.push(decodeURIComponent(callBack))
|
||||
} else {
|
||||
router.push('/task/project')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 二维码 end
|
||||
const {token} = theme.useToken();
|
||||
const router = useRouter()
|
||||
|
@ -97,7 +121,7 @@ export default function XcxLoginPage() {
|
|||
{loaded ? <LoginFormPage
|
||||
backgroundImageUrl="/20-1733751222585.jpg"
|
||||
title="马上行计划管理"
|
||||
subTitle={qrCodeShow?undefined:"使用微信扫码打开小程序"}
|
||||
subTitle={qrCodeShow ? undefined : "使用微信扫码打开小程序"}
|
||||
containerStyle={{
|
||||
backgroundColor: 'rgba(0, 0, 0,0.65)',
|
||||
backdropFilter: 'blur(4px)',
|
||||
|
@ -110,11 +134,17 @@ export default function XcxLoginPage() {
|
|||
}
|
||||
setQrCodeShow(!qrCodeShow)
|
||||
}}
|
||||
submitter={{ searchConfig: { submitText: qrCodeShow?"在我的-PC扫码登录或者返回":"已打开微信小程序,生成登录码。",resetText: '重置2'}}}
|
||||
submitter={{
|
||||
searchConfig: {
|
||||
submitText: qrCodeShow ? "在我的-PC扫码登录或者返回" : "已打开微信小程序,生成登录码。",
|
||||
resetText: '重置2'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="displayFlexColumn" style={{margin:'20px'}}>
|
||||
<div className="displayFlexColumn" style={{margin: '20px'}}>
|
||||
{
|
||||
qrCodeShow?<QRCode value={qrCodeValue} size={300} status={qrCodeStatus} onRefresh={generateQrcode} />:
|
||||
qrCodeShow ?
|
||||
<QRCode value={qrCodeValue} size={300} status={qrCodeStatus} onRefresh={generateQrcode}/> :
|
||||
<Image width={300} src="/static/pc-Web.png"/>
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -132,6 +132,7 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
autoFocusFirstInput
|
||||
modalProps={{
|
||||
destroyOnClose: true,
|
||||
maskClosable:false,
|
||||
onCancel: () => {
|
||||
props.reloadData?.();
|
||||
},
|
||||
|
@ -184,12 +185,12 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
if (editFormDisable && taskType == '1') {
|
||||
result.push(<ShareOption taskId={props.itemId!}/>)
|
||||
}
|
||||
if (editFormDisable && taskType == '2') {
|
||||
result.push(<StepSort taskId={props.itemId!}/>)
|
||||
}
|
||||
result.push(<Button type="primary" key="close"
|
||||
onClick={() => props.closeOpen?.()}>关闭</Button>)
|
||||
}
|
||||
if (taskType == '2') {
|
||||
result.push(<StepSort taskId={props.itemId!}/>)
|
||||
}
|
||||
return result;
|
||||
},
|
||||
} : {
|
||||
|
@ -204,7 +205,10 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
// }
|
||||
// return defaultDoms;
|
||||
const result = defaultDoms.filter(defaultButton => defaultButton.key == 'rest');
|
||||
result.push(<Button type="primary" key="create-team"
|
||||
if (taskType == '2') {
|
||||
result.push(<StepSort taskId={props.itemId!}/>)
|
||||
}
|
||||
result.push(<Button type="primary" key="create-team" loading={operationRequest}
|
||||
onClick={() => form.submit()}>{taskType == '1' ? "创建团队" : "确认"}
|
||||
</Button>)
|
||||
return result;
|
||||
|
@ -249,16 +253,15 @@ export const DetailModelForm: React.FC<DetailModelFormProps> = (props) => {
|
|||
if (props.operationId === OPERATION_BUTTON_TYPE.UPDATE || (props.operationId === OPERATION_BUTTON_TYPE.DETAIL && !editFormDisable)) {
|
||||
await updateTask(values).then(response => {
|
||||
console.log('response', response)
|
||||
if (response.status.success) {
|
||||
message.success("修改任务成功:" + response.data)
|
||||
if (response.data.status.success) {
|
||||
message.success("修改任务成功:" + response.data.data.name)
|
||||
// 树任务重新刷新
|
||||
// 四象限任务重新刷新
|
||||
// 如果可以直接更新列表而不请求。。。。。。
|
||||
console.log('props.reloadData?.()', props.reloadData)
|
||||
props.reloadData?.()
|
||||
result = true
|
||||
} else {
|
||||
message.error(response.status.message)
|
||||
message.error(response.data.status.message)
|
||||
result = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
import {
|
||||
ModalForm,
|
||||
ProForm,
|
||||
ProFormDateTimeRangePicker,
|
||||
ProFormSelect,
|
||||
ProFormText, ProFormTextArea,
|
||||
} from '@ant-design/pro-components';
|
||||
import {Button, Form, message, Spin} from 'antd';
|
||||
import React, {Fragment, useEffect, useState} from "react";
|
||||
import {
|
||||
TASK_TYPE,
|
||||
taskPriorityList,
|
||||
taskStateList
|
||||
} from "@/lib/task/project/data";
|
||||
import {DataType} from "@/lib/definitions";
|
||||
import dayjs, {Dayjs} from "dayjs";
|
||||
import {getJoinMessageAPI, getTaskInSecurityAPI} from "@/lib/task/project/team";
|
||||
|
||||
export type JoinTeamPropsVO = {
|
||||
joinId: string, reloadData: () => void, open: boolean,
|
||||
closeOpen: () => void
|
||||
}
|
||||
|
||||
export const JoinTeam = (props: JoinTeamPropsVO) => {
|
||||
console.log("JoinTeam:props:", props)
|
||||
const [form] = Form.useForm<DataType>();
|
||||
const [requestTask, setRequestTask] = useState<DataType>()
|
||||
const [spinning, setSpinning] = useState(true)
|
||||
const [title, setTitle] = useState("");
|
||||
useEffect(() => {
|
||||
getJoinMessageAPI(props.joinId).then(teamRes => {
|
||||
if (!teamRes.status.success) {
|
||||
return
|
||||
}
|
||||
setTitle(`来自的${teamRes.data.shareUser}协作邀请`)
|
||||
getTaskInSecurityAPI(teamRes.data).then(task => {
|
||||
if (task.status.success) {
|
||||
setRequestTask(task.data)
|
||||
task.data.state = taskStateList.find(taskState => taskState.code === task.data.state?.toString())!.name;
|
||||
task.data.priority = taskPriorityList.find(taskPriority => taskPriority.code === task.data.priority?.toString())!.name;
|
||||
task.data.actualTimeRange = [task.data.actualStartTime ? dayjs(task.data.actualStartTime) : undefined,
|
||||
task.data.actualEndTime ? dayjs(task.data.actualEndTime) : undefined];
|
||||
task.data.expectedTimeRange = [task.data.expectedStartTime ? dayjs(task.data.expectedStartTime) : undefined,
|
||||
task.data.expectedEndTime ? dayjs(task.data.expectedEndTime) : undefined];
|
||||
form.setFieldsValue(task.data)
|
||||
} else {
|
||||
message.error(task.status.message);
|
||||
props.reloadData?.()
|
||||
}
|
||||
}).finally(() => {
|
||||
setSpinning(false)
|
||||
}
|
||||
)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Spin spinning={spinning} fullscreen/>
|
||||
<ModalForm<DataType>
|
||||
title={title}
|
||||
open={!spinning && props.open}
|
||||
form={form}
|
||||
autoFocusFirstInput
|
||||
modalProps={{
|
||||
destroyOnClose: true,
|
||||
onCancel: () => {
|
||||
props.reloadData?.();
|
||||
},
|
||||
}}
|
||||
readonly={true}
|
||||
submitter={{
|
||||
render: (prop, defaultDoms) => {
|
||||
console.log("submitter render: ", {prop})
|
||||
let result = [
|
||||
<Button type="primary" key="close"
|
||||
onClick={() => props.closeOpen?.()}>拒绝</Button>,
|
||||
<Button type="primary" key="close"
|
||||
onClick={() => props.closeOpen?.()}>关闭</Button>,
|
||||
<Button type="primary" key="close"
|
||||
onClick={() => props.closeOpen?.()}>加入</Button>,
|
||||
]
|
||||
return result;
|
||||
},
|
||||
}}
|
||||
onFinish={async (values) => {
|
||||
}}
|
||||
>
|
||||
<ProFormText width="sm" name="id" hidden={true} label="主键"/>
|
||||
<ProFormText width="sm" name="code" hidden={true} label="任务编码"/>
|
||||
<ProFormText width="sm" name="pPid" hidden={true} label="祖宗id"/>
|
||||
<ProForm.Group>
|
||||
<ProFormSelect
|
||||
required={true}
|
||||
options={TASK_TYPE}
|
||||
width="sm"
|
||||
name="taskType"
|
||||
label="任务类型"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请输入计划类型"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
required={true}
|
||||
width="sm"
|
||||
name="fName"
|
||||
label="团队名称"
|
||||
tooltip="最长为 10 位"
|
||||
placeholder="请输入团队名称"
|
||||
|
||||
/>
|
||||
<ProFormText
|
||||
required={true}
|
||||
width="sm"
|
||||
name="name"
|
||||
label="任务名称"
|
||||
tooltip="最长为 10 位"
|
||||
placeholder="请输入任务名称"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请输入计划名称"
|
||||
}, {
|
||||
max: 10,
|
||||
message: "名称长度不易超过10个字"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
<ProFormTextArea
|
||||
width="xl"
|
||||
name="description"
|
||||
label="任务描述"
|
||||
tooltip="最长255个字"
|
||||
placeholder="请输入任务描述"
|
||||
/>
|
||||
|
||||
<ProForm.Group>
|
||||
<ProFormSelect
|
||||
request={async () =>
|
||||
taskPriorityList.map
|
||||
(
|
||||
taskState => {
|
||||
return {'label': taskState.name, 'value': taskState.code}
|
||||
}
|
||||
)
|
||||
}
|
||||
width="sm"
|
||||
name="priority"
|
||||
label="任务优先级"
|
||||
initialValue='3'
|
||||
rules={[{required: true, message: "请选择计划优先级"}]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
width="sm"
|
||||
options={taskStateList.map(taskState => {
|
||||
return {'label': taskState.name, 'value': taskState.code}
|
||||
})}
|
||||
name="state"
|
||||
label="任务状态"
|
||||
initialValue='8'
|
||||
rules={
|
||||
[
|
||||
{
|
||||
required: true,
|
||||
message: "请选择计划状态"
|
||||
}
|
||||
]
|
||||
}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
|
||||
<ProForm.Group>
|
||||
<ProFormDateTimeRangePicker
|
||||
initialValue={[dayjs(), undefined]}
|
||||
name="expectedTimeRange"
|
||||
label="期望时间"
|
||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
||||
placeholder={['开始时间', '结束时间']}
|
||||
/>
|
||||
<ProFormDateTimeRangePicker
|
||||
name="actualTimeRange"
|
||||
label="实际时间"
|
||||
fieldProps={{allowEmpty: [true, true], showTime: true, needConfirm: true}}
|
||||
placeholder={['开始时间', '结束时间']}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</ModalForm>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
|
@ -21,7 +21,7 @@ import '@/ui/task/project/TreeTablePro.modules.css'
|
|||
import {useSearchParams} from "next/navigation";
|
||||
import {TaskWebSelectVO} from "@/lib/task/project/definitions";
|
||||
|
||||
const TreeTablePro: React.FC = () => {
|
||||
const TreeTablePro: React.FC = (props:{joinId?:string}) => {
|
||||
// 刷新表格
|
||||
const actionRef = useRef<ActionType>();
|
||||
// 列表和树切换
|
||||
|
@ -182,6 +182,12 @@ const TreeTablePro: React.FC = () => {
|
|||
}}/></>)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (props.joinId){
|
||||
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
actionRef.current?.reload(false)
|
||||
}, [useSearchParams()])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import axios, {Canceler, CancelToken, CancelTokenSource} from "axios";
|
||||
import {message} from "antd";
|
||||
import {usePathname, useSearchParams} from "next/navigation";
|
||||
|
||||
|
||||
export const httpReq = axios.create({
|
||||
|
@ -53,7 +54,7 @@ httpReq.interceptors.response.use(
|
|||
message.error('系统异常');
|
||||
} else if (error.response.status >= 400 && error.response.status <= 500) {
|
||||
message.warning('无权限');
|
||||
window.location.href = '/login';
|
||||
window.location.href = `/login?callBack=${encodeURIComponent(window.location.pathname+window.location.search)}`;
|
||||
}
|
||||
// switch (error.response.status) {
|
||||
// case 401:
|
||||
|
|
Loading…
Reference in New Issue