feat:日历滑动
This commit is contained in:
parent
c2eb04b4b0
commit
55cfe79dab
|
@ -5,7 +5,7 @@ import {
|
||||||
Button,
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
TextArea,
|
TextArea,
|
||||||
Space, Tag, Radio
|
Space, Tag, Radio, Checkbox
|
||||||
} from 'antd-mobile'
|
} from 'antd-mobile'
|
||||||
import ParentTask from "../ParentTask";
|
import ParentTask from "../ParentTask";
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
|
@ -13,25 +13,34 @@ import {addTask, getPTask, getTaskById, updateTask} from "../../utils";
|
||||||
import {useLocation, useNavigate, useOutletContext, useSearchParams} from "react-router-dom";
|
import {useLocation, useNavigate, useOutletContext, useSearchParams} from "react-router-dom";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import DataPickItemPopup from "../DataPickItemPopup";
|
import DataPickItemPopup from "../DataPickItemPopup";
|
||||||
|
import {getDictionary} from "../../utils/dictUtil";
|
||||||
|
|
||||||
const DetailForm= () => {
|
const DetailForm = () => {
|
||||||
// 进入此页面的操作:添加,修改,详情(按钮为添加任务日志)
|
// 进入此页面的操作:添加,修改,详情(按钮为添加任务日志)
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
let [params] = useSearchParams();
|
let [params] = useSearchParams();
|
||||||
// 设置标题栏
|
// 设置标题栏
|
||||||
const {setTitle,setRightDesc} = useOutletContext();
|
const {setTitle, setRightDesc} = useOutletContext();
|
||||||
const [currentPath, setCurrentPath] = React.useState("");
|
const [currentPath, setCurrentPath] = React.useState("");
|
||||||
const [updateFiledDisabled, setUpdateFiledDisabled] = React.useState(true);
|
const [updateFiledDisabled, setUpdateFiledDisabled] = React.useState(true);
|
||||||
const [pName, setPName] = React.useState();
|
const [pName, setPName] = React.useState();
|
||||||
const [pidArray, setPidArray] = React.useState([]);
|
const [pidArray, setPidArray] = React.useState([]);
|
||||||
|
const [stateList, setStateList] = React.useState([]);
|
||||||
|
const [priorityList, setPriorityList] = React.useState([]);
|
||||||
// 路由
|
// 路由
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
// 获取form引用
|
// 获取form引用
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const addEditPName=(name)=>{
|
const addEditPName = (name) => {
|
||||||
setPName(name)
|
setPName(name)
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getDictionary("2").then(stateDictionary => {
|
||||||
|
setStateList(Array.from(stateDictionary.values()));
|
||||||
|
})
|
||||||
|
getDictionary("1").then(priorityDictionary => {
|
||||||
|
setPriorityList(Array.from(priorityDictionary.values()));
|
||||||
|
})
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
if (location.pathname.endsWith("addTask")) {
|
if (location.pathname.endsWith("addTask")) {
|
||||||
setTitle("添加任务");
|
setTitle("添加任务");
|
||||||
|
@ -50,7 +59,8 @@ const DetailForm= () => {
|
||||||
initData(params.get('id'));
|
initData(params.get('id'));
|
||||||
setUpdateFiledDisabled(true);
|
setUpdateFiledDisabled(true);
|
||||||
setRightDesc(<div>
|
setRightDesc(<div>
|
||||||
<Button type="button" color="danger" onClick={() => {Dialog.show({
|
<Button type="button" color="danger" onClick={() => {
|
||||||
|
Dialog.show({
|
||||||
content: `进入任务编辑`,
|
content: `进入任务编辑`,
|
||||||
closeOnAction: true,
|
closeOnAction: true,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -68,7 +78,8 @@ const DetailForm= () => {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
})}}>编辑</Button>
|
})
|
||||||
|
}}>编辑</Button>
|
||||||
</div>)
|
</div>)
|
||||||
} else {
|
} else {
|
||||||
// todo 异常处理
|
// todo 异常处理
|
||||||
|
@ -85,7 +96,7 @@ const DetailForm= () => {
|
||||||
console.log({res, parentMessageVOList});
|
console.log({res, parentMessageVOList});
|
||||||
setPName(parentMessageVOList[parentMessageVOList.length - 1].name);
|
setPName(parentMessageVOList[parentMessageVOList.length - 1].name);
|
||||||
setPidArray(parentMessageVOList.map(parent => parent.id))
|
setPidArray(parentMessageVOList.map(parent => parent.id))
|
||||||
form.setFieldValue("pidArray",parentMessageVOList.map(parent => parent.id))
|
form.setFieldValue("pidArray", parentMessageVOList.map(parent => parent.id))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,23 +229,41 @@ const DetailForm= () => {
|
||||||
showCount
|
showCount
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name='state' initialValue='8' label='任务状态' rules={[{required: true, message: '任务状态不能为空'}]} disabled={updateFiledDisabled}>
|
<Form.Item name='state' initialValue='8' label='任务状态'
|
||||||
|
rules={[{required: true, message: '任务状态不能为空'}]} disabled={updateFiledDisabled}>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Space direction='vertical'>
|
<Space direction='vertical'>
|
||||||
<Radio value='8'><Tag color='primary'>未开始</Tag></Radio>
|
{/*<Radio value='8'><Tag color='primary'>未开始</Tag></Radio>*/}
|
||||||
<Radio value='9'><Tag color='warning'>进行中</Tag></Radio>
|
{/*<Radio value='9'><Tag color='warning'>进行中</Tag></Radio>*/}
|
||||||
<Radio value='7'><Tag color='success'>已完成</Tag></Radio>
|
{/*<Radio value='7'><Tag color='success'>已完成</Tag></Radio>*/}
|
||||||
<Radio value='10'><Tag color='danger'>已逾期</Tag></Radio>
|
{/*<Radio value='10'><Tag color='danger'>已逾期</Tag></Radio>*/}
|
||||||
|
{
|
||||||
|
stateList.map(stateDict =>
|
||||||
|
<Radio key={stateDict.itemCode} value={stateDict.itemCode}>
|
||||||
|
<Tag key={stateDict.itemCode}
|
||||||
|
color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
|
||||||
|
</Radio>
|
||||||
|
)
|
||||||
|
}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name='priority' label='任务优先级' initialValue='2' rules={[{required: true, message: '任务优先级不能为空'}]} disabled={updateFiledDisabled}>
|
<Form.Item name='priority' label='任务优先级' initialValue='2'
|
||||||
|
rules={[{required: true, message: '任务优先级不能为空'}]} disabled={updateFiledDisabled}>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Space direction='vertical'>
|
<Space direction='vertical'>
|
||||||
<Radio value='3'><Tag color='danger'>紧急重要</Tag></Radio>
|
{/*<Radio value='3'><Tag color='danger'>紧急重要</Tag></Radio>*/}
|
||||||
<Radio value='2'><Tag color='warning'>不紧急重要</Tag></Radio>
|
{/*<Radio value='2'><Tag color='warning'>不紧急重要</Tag></Radio>*/}
|
||||||
<Radio value='1'><Tag>紧急不重要</Tag></Radio>
|
{/*<Radio value='1'><Tag>紧急不重要</Tag></Radio>*/}
|
||||||
<Radio value='0'><Tag color='success'>不紧急不重要</Tag></Radio>
|
{/*<Radio value='0'><Tag color='success'>不紧急不重要</Tag></Radio>*/}
|
||||||
|
{
|
||||||
|
priorityList.map(stateDict =>
|
||||||
|
<Radio key={stateDict.itemCode} value={stateDict.itemCode}>
|
||||||
|
<Tag key={stateDict.itemCode}
|
||||||
|
color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
|
||||||
|
</Radio>
|
||||||
|
)
|
||||||
|
}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -244,7 +273,8 @@ const DetailForm= () => {
|
||||||
labelName={"预计结束时间"}/>
|
labelName={"预计结束时间"}/>
|
||||||
<DataPickItemPopup disabled={updateFiledDisabled} fieldName={"actualStartTime"}
|
<DataPickItemPopup disabled={updateFiledDisabled} fieldName={"actualStartTime"}
|
||||||
labelName={"实际开始时间"}/>
|
labelName={"实际开始时间"}/>
|
||||||
<DataPickItemPopup disabled={updateFiledDisabled} fieldName={"actualEndTime"} labelName={"实际结束时间"}/>
|
<DataPickItemPopup disabled={updateFiledDisabled} fieldName={"actualEndTime"}
|
||||||
|
labelName={"实际结束时间"}/>
|
||||||
</Form>
|
</Form>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
.adm-cascader-header-title{
|
||||||
|
flex: 0.5;
|
||||||
|
}
|
|
@ -1,18 +1,27 @@
|
||||||
import {Cascader, Input, Toast} from "antd-mobile";
|
import {Cascader, Input, SearchBar, Toast} from "antd-mobile";
|
||||||
import React, {useEffect, useMemo, useState} from "react";
|
import React, {useEffect, useMemo, useState} from "react";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
} from 'antd-mobile'
|
} from 'antd-mobile'
|
||||||
import {getTaskByPid} from "../../utils";
|
import {getTaskByPid} from "../../utils";
|
||||||
|
import "./index.css"
|
||||||
|
import {CloseCircleFill} from "antd-mobile-icons";
|
||||||
|
|
||||||
const ParentTask = (props) => {
|
const ParentTask = (props) => {
|
||||||
const [valueToOptions, setValueToOptions] = useState([])
|
const [valueToOptions, setValueToOptions] = useState([])
|
||||||
const {form, disabled, pName, pidArray, addEditPName} = props;
|
const {form, disabled, pName, pidArray, addEditPName} = props;
|
||||||
const [parentValue, setParentValue] = useState(pidArray ?? [])
|
const [parentValue, setParentValue] = useState(pidArray ?? [])
|
||||||
const [visible, setVisible] = useState(false)
|
const [visible, setVisible] = useState(false)
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
const [currentLab, setCurrentLab] = useState(0);
|
||||||
|
const [selectValue, setSelectValue] = useState([]);
|
||||||
|
// 当前标签
|
||||||
|
// let currentLab=0;
|
||||||
|
// let selectValue=[];
|
||||||
|
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
|
console.log("useMemo")
|
||||||
|
|
||||||
function generate(v) {
|
function generate(v) {
|
||||||
const options = valueToOptions[v]
|
const options = valueToOptions[v]
|
||||||
if (options === null) {
|
if (options === null) {
|
||||||
|
@ -21,6 +30,27 @@ const ParentTask = (props) => {
|
||||||
if (options === undefined) {
|
if (options === undefined) {
|
||||||
return Cascader.optionSkeleton
|
return Cascader.optionSkeleton
|
||||||
}
|
}
|
||||||
|
// 如果有搜索有值,需要过滤,
|
||||||
|
// 根据currentLab查看需要过滤第几层,当前层可能没有值就会停留在上一层
|
||||||
|
if (searchValue && searchValue.length > 0) {
|
||||||
|
if (selectValue.length <= currentLab + 1) {
|
||||||
|
// 可能展示最新的,或没有停留在当前页面,正常是没有选择的时候搜索
|
||||||
|
console.log({searchValue}, {currentLab}, {selectValue})
|
||||||
|
if (currentLab === 0 && v === '0') {
|
||||||
|
return options.filter(option => option.label.includes(searchValue)).map(option => ({
|
||||||
|
...option,
|
||||||
|
children: generate(option.value),
|
||||||
|
}))
|
||||||
|
} else if (v === selectValue[currentLab - 1]) {
|
||||||
|
return options.filter(option => option.label.includes(searchValue)).map(option => ({
|
||||||
|
...option,
|
||||||
|
children: generate(option.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 用户切换回之前的标签,暂不处理
|
||||||
|
}
|
||||||
|
}
|
||||||
return options.map(option => ({
|
return options.map(option => ({
|
||||||
...option,
|
...option,
|
||||||
children: generate(option.value),
|
children: generate(option.value),
|
||||||
|
@ -28,7 +58,7 @@ const ParentTask = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return generate('0') ?? []
|
return generate('0') ?? []
|
||||||
}, [valueToOptions])
|
}, [valueToOptions, searchValue])
|
||||||
|
|
||||||
async function fetchOptionsForValue(v, level) {
|
async function fetchOptionsForValue(v, level) {
|
||||||
if (v in valueToOptions) return
|
if (v in valueToOptions) return
|
||||||
|
@ -72,13 +102,38 @@ const ParentTask = (props) => {
|
||||||
return <Form.Item
|
return <Form.Item
|
||||||
name='pidArray'
|
name='pidArray'
|
||||||
label='主线任务'
|
label='主线任务'
|
||||||
|
value={parentValue}
|
||||||
|
disabled={disabled}
|
||||||
|
arrow={
|
||||||
|
(form.getFieldValue('pidArray') && form.getFieldValue('pidArray').length > 0) ? (
|
||||||
|
<CloseCircleFill
|
||||||
|
style={{
|
||||||
|
color: 'var(--adm-color-light)',
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
onClick={e => {
|
||||||
|
form.setFieldsValue({pidArray: []})
|
||||||
|
setParentValue([])
|
||||||
|
// 阻止冒泡
|
||||||
|
e.stopPropagation()
|
||||||
|
// 阻止所有后续事件处理程序
|
||||||
|
// e.nativeEvent.stopImmediatePropagation();
|
||||||
|
}}
|
||||||
|
/>) : true
|
||||||
|
|
||||||
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setVisible(true)
|
setVisible(true)
|
||||||
}}
|
}}
|
||||||
value={parentValue}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
>
|
||||||
<Cascader
|
<Cascader
|
||||||
|
title={<SearchBar placeholder='搜索当前层相关标题' onChange={
|
||||||
|
// 获取当前选卡,过滤当前选项
|
||||||
|
(value) => {
|
||||||
|
console.log("搜索" + value)
|
||||||
|
setSearchValue(value);
|
||||||
|
}
|
||||||
|
}/>}
|
||||||
options={options}
|
options={options}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
defaultValue={pidArray}
|
defaultValue={pidArray}
|
||||||
|
@ -91,11 +146,13 @@ const ParentTask = (props) => {
|
||||||
setParentValue(val[val.length - 1])
|
setParentValue(val[val.length - 1])
|
||||||
form.setFieldValue('pidArray', val)
|
form.setFieldValue('pidArray', val)
|
||||||
}}
|
}}
|
||||||
// onSelect={(val, extend) => {
|
onTabsChange={index => {
|
||||||
// console.log('onSelect', val, extend.items)
|
console.log(index);
|
||||||
// }}
|
setCurrentLab(index)
|
||||||
|
}}
|
||||||
onSelect={value => {
|
onSelect={value => {
|
||||||
console.log("value", value)
|
console.log("value", value, currentLab)
|
||||||
|
setSelectValue(value)
|
||||||
value.forEach((v, index) => {
|
value.forEach((v, index) => {
|
||||||
fetchOptionsForValue(v, index + 1)
|
fetchOptionsForValue(v, index + 1)
|
||||||
})
|
})
|
||||||
|
@ -103,10 +160,11 @@ const ParentTask = (props) => {
|
||||||
>
|
>
|
||||||
{items => {
|
{items => {
|
||||||
if (items.every(item => item === null)) {
|
if (items.every(item => item === null)) {
|
||||||
return pName ? (<span>{pName}</span>) : disabled ?
|
return (pName && form.getFieldValue('pidArray') && form.getFieldValue('pidArray').length > 0) ? (
|
||||||
|
<span>{pName}</span>) : disabled ?
|
||||||
(<span>主线任务选填</span>) :
|
(<span>主线任务选填</span>) :
|
||||||
(<span style={{color: "#cccccc"}}>主线任务选填</span>)
|
(<span style={{color: "#cccccc"}}>主线任务选填</span>)
|
||||||
} else {
|
} else if (items) {
|
||||||
if (addEditPName) {
|
if (addEditPName) {
|
||||||
addEditPName(items[items.length - 1].label)
|
addEditPName(items[items.length - 1].label)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ export function DetailLogTask() {
|
||||||
const [currentTask, setCurrentTask] = useState({});
|
const [currentTask, setCurrentTask] = useState({});
|
||||||
const [actions,setActions] = useState([
|
const [actions,setActions] = useState([
|
||||||
{ text: '复制', key: 'copy' },
|
{ text: '复制', key: 'copy' },
|
||||||
{ text: '有效', key: 'edit' },
|
{ text: '有效', key: 'need' },
|
||||||
{ text: '创建任务', key: 'addTask'},
|
{ text: '创建任务', key: 'addTask'},
|
||||||
{
|
{
|
||||||
text: '删除',
|
text: '删除',
|
||||||
|
@ -48,7 +48,7 @@ export function DetailLogTask() {
|
||||||
map.get(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))?.push(taskLog);
|
map.get(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))?.push(taskLog);
|
||||||
return map;
|
return map;
|
||||||
}, new Map());
|
}, new Map());
|
||||||
}, [taskLogList])
|
}, [taskLogList,currentShow])
|
||||||
const handleSend = () => {
|
const handleSend = () => {
|
||||||
addTaskLog({
|
addTaskLog({
|
||||||
"description": sendValue,
|
"description": sendValue,
|
||||||
|
@ -110,7 +110,7 @@ export function DetailLogTask() {
|
||||||
{taskLogMapMemory.get(key).map(taskLog => {
|
{taskLogMapMemory.get(key).map(taskLog => {
|
||||||
return <div key={taskLog.id} style={{ display: 'flex', width: "80%", padding: "2px 20px"}}>
|
return <div key={taskLog.id} style={{ display: 'flex', width: "80%", padding: "2px 20px"}}>
|
||||||
<span className="detail-line" onClick={()=>{
|
<span className="detail-line" onClick={()=>{
|
||||||
actions[1]={ text: '失效', key: 'edit' }
|
actions[1]={ text: '失效', key: 'noneed' }
|
||||||
// setActions([...actions])
|
// setActions([...actions])
|
||||||
setCurrentTask(taskLog)
|
setCurrentTask(taskLog)
|
||||||
setActionSheetVisible(true)
|
setActionSheetVisible(true)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Calendar, Cascader, Tag} from "antd-mobile";
|
import {Calendar, Cascader, SwipeAction, Tag} from "antd-mobile";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {TaskCount} from "../TaskCount";
|
import {TaskCount} from "../TaskCount";
|
||||||
import React, {Fragment, useEffect, useLayoutEffect, useMemo, useRef, useState} from "react";
|
import React, {Fragment, useEffect, useLayoutEffect, useMemo, useRef, useState} from "react";
|
||||||
|
@ -12,6 +12,7 @@ import './index.css'
|
||||||
const ToDoCal = (props) => {
|
const ToDoCal = (props) => {
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
const calRef = useRef(null);
|
const calRef = useRef(null);
|
||||||
|
const refSwip = useRef(null);
|
||||||
const [currentDay, setCurrentDay] = React.useState(new Date())
|
const [currentDay, setCurrentDay] = React.useState(new Date())
|
||||||
const [currentMonth, setCurrentMonth] = React.useState(dayjs().set("date", 1).format('YYYY-MM-DD'));
|
const [currentMonth, setCurrentMonth] = React.useState(dayjs().set("date", 1).format('YYYY-MM-DD'));
|
||||||
// Map key为当前月value为当前月的向
|
// Map key为当前月value为当前月的向
|
||||||
|
@ -57,6 +58,36 @@ const ToDoCal = (props) => {
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
<SwipeAction
|
||||||
|
ref={refSwip}
|
||||||
|
rightActions={[
|
||||||
|
{
|
||||||
|
key: 'next',
|
||||||
|
text: '自送进入下一个月',
|
||||||
|
color: 'success',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
leftActions={[
|
||||||
|
{
|
||||||
|
key: 'last',
|
||||||
|
text: '自送进入上一个月',
|
||||||
|
color: 'success',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onActionsReveal={(sideType) => {
|
||||||
|
console.log(sideType,sideType === 'left',sideType === 'right',currentMonth)
|
||||||
|
if (sideType === 'left') {
|
||||||
|
const newMonth = dayjs(currentMonth).subtract(1, 'months')
|
||||||
|
calRef.current.jumpTo({year: newMonth.year(), month: newMonth.month()+1})
|
||||||
|
console.log(newMonth.year(),newMonth.month()+1)
|
||||||
|
} else if (sideType === 'right') {
|
||||||
|
const newMonth = dayjs(currentMonth).add(1, 'months')
|
||||||
|
calRef.current.jumpTo({year: newMonth.year(), month: newMonth.month()+1})
|
||||||
|
console.log(newMonth.year(),newMonth.month()+1)
|
||||||
|
}
|
||||||
|
refSwip.current?.close()
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Calendar
|
<Calendar
|
||||||
ref={calRef}
|
ref={calRef}
|
||||||
selectionMode='single'
|
selectionMode='single'
|
||||||
|
@ -121,6 +152,7 @@ const ToDoCal = (props) => {
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
</SwipeAction>
|
||||||
<TaskCount currentDay={currentDay} taskCount={listTaskMap?.get(currentMonth)} today={today}
|
<TaskCount currentDay={currentDay} taskCount={listTaskMap?.get(currentMonth)} today={today}
|
||||||
currentMonth={currentMonth}
|
currentMonth={currentMonth}
|
||||||
backToToday={backToToday}/>
|
backToToday={backToToday}/>
|
||||||
|
|
Loading…
Reference in New Issue