diff --git a/package.json b/package.json index 78b3ca92..34cfc943 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,7 @@ "@types/uuid": "^8.3.4", "@umijs/max": "^4.0.72", "@umijs/ssr-darkreader": "^4.9.45", + "ahooks": "^3.7.8", "ansi-to-react": "^6.1.6", "antd": "^4.24.8", "antd-img-crop": "^4.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d051739..ee1d5ee1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,6 +219,9 @@ devDependencies: '@umijs/ssr-darkreader': specifier: ^4.9.45 version: 4.9.45 + ahooks: + specifier: ^3.7.8 + version: 3.7.8(react@18.2.0) ansi-to-react: specifier: ^6.1.6 version: 6.1.6(react-dom@18.2.0)(react@18.2.0) @@ -4421,6 +4424,10 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: true + /@types/js-cookie@2.2.7: + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + dev: true + /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true @@ -5574,6 +5581,32 @@ packages: clean-stack: 2.2.0 indent-string: 4.0.0 + /ahooks-v3-count@1.0.0: + resolution: {integrity: sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==} + dev: true + + /ahooks@3.7.8(react@18.2.0): + resolution: {integrity: sha512-e/NMlQWoCjaUtncNFIZk3FG1ImSkV/JhScQSkTqnftakRwdfZWSw6zzoWSG9OMYqPNs2MguDYBUFFC6THelWXA==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || 18 + peerDependenciesMeta: + react: + optional: true + dependencies: + '@babel/runtime': 7.22.3 + '@types/js-cookie': 2.2.7 + ahooks-v3-count: 1.0.0 + dayjs: 1.11.8 + intersection-observer: 0.12.2 + js-cookie: 2.2.1 + lodash: 4.17.21 + react: 18.2.0 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + tslib: 2.5.3 + dev: true + /ajv-formats@2.1.1(ajv@8.12.0): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -9101,6 +9134,10 @@ packages: side-channel: 1.0.4 dev: true + /intersection-observer@0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + dev: true + /intl-format-cache@4.3.1: resolution: {integrity: sha512-OEUYNA7D06agqPOYhbTkl0T8HA3QKSuwWh1HiClEnpd9vw7N+3XsQt5iZ0GUEchp5CW1fQk/tary+NsbF3yQ1Q==} dev: true @@ -9578,6 +9615,10 @@ packages: '@sideway/pinpoint': 2.0.0 dev: false + /js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + dev: true + /js-sdsl@4.4.1: resolution: {integrity: sha512-6Gsx8R0RucyePbWqPssR8DyfuXmLBooYN5cZFZKjHGnQuaf7pEzhtpceagJxVu4LqhYY5EYA7nko3FmeHZ1KbA==} dev: true @@ -13626,6 +13667,11 @@ packages: ajv-keywords: 5.1.0(ajv@8.12.0) dev: true + /screenfull@5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + dev: true + /scroll-into-view-if-needed@2.2.31: resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} dependencies: diff --git a/src/components/name.tsx b/src/components/name.tsx new file mode 100644 index 00000000..7085e06f --- /dev/null +++ b/src/components/name.tsx @@ -0,0 +1,22 @@ +import { useRequest } from 'ahooks'; +import { Service, Options } from 'ahooks/lib/useRequest/src/types'; +import { Spin, Typography } from 'antd'; + +export default function Name< + TData extends { data?: { name: string } }, + TParams, +>({ + service, + options, +}: { + service: Service; + options: Options; +}) { + const { loading, data } = useRequest(service, options); + console.log(loading, data); + return ( + + {data?.data?.name} + + ); +} diff --git a/src/components/vlist.tsx b/src/components/vlist.tsx deleted file mode 100644 index 8d129360..00000000 --- a/src/components/vlist.tsx +++ /dev/null @@ -1,404 +0,0 @@ -import React, { - useRef, - useEffect, - useContext, - createContext, - useReducer, - useState, - useMemo, -} from 'react'; -import { throttle, isNumber, debounce } from 'lodash'; - -const initialState = { - // 行高度 - rowHeight: 0, - // 当前的scrollTop - curScrollTop: 0, - // 总行数 - totalLen: 0, -}; - -function reducer(state, action) { - const { curScrollTop, totalLen, ifScrollTopClear, scrollTop } = action; - - let stateScrollTop = state.curScrollTop; - switch (action.type) { - // 改变trs 即 改变渲染的列表trs - case 'changeTrs': - return { - ...state, - curScrollTop, - }; - // 更改totalLen - case 'changeTotalLen': - if (totalLen === 0) { - stateScrollTop = 0; - } - - return { - ...state, - totalLen, - curScrollTop: stateScrollTop, - }; - - case 'reset': - return { - ...state, - curScrollTop: ifScrollTopClear ? 0 : scrollTop ?? state.curScrollTop, - }; - default: - throw new Error(); - } -} - -// ==============全局常量 ================== // -const DEFAULT_VID = 'vtable'; -const vidMap = new Map(); -let preData = 0; - -// ===============context ============== // -const ScrollContext = createContext({ - dispatch: undefined, - renderLen: 1, - start: 0, - offsetStart: 0, - // ============= - rowHeight: initialState.rowHeight, - totalLen: 0, - vid: DEFAULT_VID, -}); - -// =============组件 =================== // - -function VCell(props: any): JSX.Element { - const { children, ...restProps } = props; - - return ( - -
{children[1]}
- - ); -} - -function VRow(props: any, ref: any): JSX.Element { - const { rowHeight } = useContext(ScrollContext); - - const { children, style, ...restProps } = props; - - const trRef = useRef(null); - - return ( - - {children} - - ); -} - -function VWrapper(props: any): JSX.Element { - const { children, ...restProps } = props; - - const { renderLen, start, dispatch, vid, totalLen } = - useContext(ScrollContext); - - const contents = useMemo(() => { - return children[1]; - }, [children]); - - const contentsLen = useMemo(() => { - return contents?.length ?? 0; - }, [contents]); - - useEffect(() => { - if (totalLen !== contentsLen) { - dispatch({ - type: 'changeTotalLen', - totalLen: contentsLen ?? 0, - }); - } - }, [contentsLen, dispatch, vid, totalLen]); - - let tempNode = null; - if (Array.isArray(contents) && contents.length) { - tempNode = [ - children[0], - contents.slice(start, start + (renderLen ?? 1)).map((item) => { - if (Array.isArray(item)) { - // 兼容antd v4.3.5 --- rc-table 7.8.1及以下 - return item[0]; - } - // 处理antd ^v4.4.0 --- rc-table ^7.8.2 - return item; - }), - ]; - } else { - tempNode = children; - } - - return {tempNode}; -} - -function VTable(props: any, otherParams): JSX.Element { - const { style, children, ...rest } = props; - const { width, ...rest_style } = style; - - const { vid, scrollY, resetScrollTopWhenDataChange, rowHeight, scrollTop } = - otherParams ?? {}; - - const [state, dispatch] = useReducer(reducer, { - ...initialState, - curScrollTop: scrollTop, - rowHeight, - }); - - const wrap_tableRef = useRef(null); - const tableRef = useRef(null); - - const ifChangeRef = useRef(false); - - // 数据的总条数 - const [totalLen, setTotalLen] = useState( - children[1]?.props?.data?.length ?? 0, - ); - - useEffect(() => { - setTotalLen(state.totalLen); - }, [state.totalLen]); - - // 组件卸载的清除操作 - useEffect(() => { - return () => { - vidMap.delete(vid); - }; - }, [vid]); - - // 数据变更 - useEffect(() => { - ifChangeRef.current = true; - // console.log('数据变更') - if (isNumber(children[1]?.props?.data?.length)) { - dispatch({ - type: 'changeTotalLen', - totalLen: children[1]?.props?.data?.length ?? 0, - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [children[1].props.data]); - - // table总高度 - const tableHeight = useMemo(() => { - let temp: string | number = 'auto'; - - if (rowHeight && totalLen) { - temp = rowHeight * totalLen; - } - return temp; - }, [totalLen]); - - // table的scrollY值 - const [tableScrollY, setTableScrollY] = useState(0); - - // tableScrollY 随scrollY / tableHeight 进行变更 - useEffect(() => { - let temp = 0; - - if (typeof scrollY === 'string') { - temp = - (wrap_tableRef.current?.parentNode as HTMLElement)?.offsetHeight ?? 0; - } else { - temp = scrollY; - } - - // if (isNumber(tableHeight) && tableHeight < temp) { - // temp = tableHeight; - // } - - // 处理tableScrollY <= 0的情况 - if (temp <= 0) { - temp = 0; - } - - setTableScrollY(temp); - }, [scrollY, tableHeight]); - - // 渲染的条数 - const renderLen = useMemo(() => { - let temp = 1; - if (rowHeight && totalLen && tableScrollY) { - if (tableScrollY <= 0) { - temp = 0; - } else { - const tempRenderLen = ((tableScrollY / rowHeight) | 0) + 10; - // console.log('tempRenderLen', tempRenderLen) - // temp = tempRenderLen > totalLen ? totalLen : tempRenderLen; - temp = tempRenderLen; - } - } - - return temp; - }, [totalLen, tableScrollY]); - - // 渲染中的第一条 - let start = rowHeight ? (state.curScrollTop / rowHeight) | 0 : 0; - - start = start < 5 ? 0 : start - 5 + 1; - - // 偏移量 - let offsetStart = state.curScrollTop % (rowHeight * 5); - - if (start > 0) { - offsetStart = offsetStart % rowHeight; - } - // console.log(offsetStart) - // offsetStart= offsetStart%rowHeight - // 用来优化向上滚动出现的空白 - if (state.curScrollTop && state.curScrollTop >= rowHeight * 5) { - // start -= 1 - // if (offsetStart >= rowHeight) { - // offsetStart += - // } else { - offsetStart += rowHeight * 4; - // } - } else { - start = 0; - } - - // console.log(state.curScrollTop, start, offsetStart) - - // 数据变更 操作scrollTop - useEffect(() => { - const scrollNode = wrap_tableRef.current?.parentNode as HTMLElement; - if (ifChangeRef?.current) { - // console.log(scrollNode) - ifChangeRef.current = false; - - if (resetScrollTopWhenDataChange) { - // 重置scrollTop - if (scrollNode) { - scrollNode.scrollTop = 0; - } - - dispatch({ type: 'reset', ifScrollTopClear: true }); - } else { - // console.log(preData) - // scrollNode.scrollTop = preData+53 - // 不重置scrollTop 不清空curScrollTop - dispatch({ type: 'reset', ifScrollTopClear: false }); - } - } - - if (vidMap.has(vid)) { - vidMap.set(vid, { - ...vidMap.get(vid), - scrollNode, - }); - } - }, [totalLen, resetScrollTopWhenDataChange, vid, children]); - - useEffect(() => { - const throttleScroll = throttle((e) => { - const scrollTop: number = e?.target?.scrollTop ?? 0; - // const scrollHeight: number = e?.target?.scrollHeight ?? 0 - // const clientHeight: number = e?.target?.clientHeight ?? 0 - if (scrollTop) { - preData = scrollTop; - } - // 到底了 没有滚动条就不会触发reachEnd. 建议设置scrolly高度少点或者数据量多点. - // 若renderLen大于totalLen, 置空curScrollTop. => table paddingTop会置空. - dispatch({ - type: 'changeTrs', - curScrollTop: renderLen <= totalLen ? scrollTop : 0, - }); - }, 60); - - const ref = wrap_tableRef?.current?.parentNode as HTMLElement; - - if (ref) { - ref.addEventListener('scroll', throttleScroll, { passive: true }); - } - - return () => { - ref.removeEventListener('scroll', throttleScroll); - }; - }, [renderLen, totalLen]); - - return ( -
- - - {children} -
-
-
- ); -} - -// ================导出=================== -export function VList(props: { - height: number; - // 唯一标识 - vid?: string; - rowHeight: number | string; - reset?: boolean; - scrollTop?: number | string; -}): any { - const { vid = DEFAULT_VID, rowHeight, height, reset, scrollTop } = props; - - const resetScrollTopWhenDataChange = reset ?? true; - - if (!vidMap.has(vid)) { - vidMap.set(vid, { _id: vid }); - } - - return { - table: (p) => - VTable(p, { - vid, - scrollY: height, - rowHeight, - resetScrollTopWhenDataChange, - scrollTop, - }), - body: { - wrapper: VWrapper, - row: VRow, - cell: VCell, - }, - }; -} diff --git a/src/layouts/index.less b/src/layouts/index.less index 2bb91c06..c4f7caec 100644 --- a/src/layouts/index.less +++ b/src/layouts/index.less @@ -420,3 +420,12 @@ body[data-mode='phone'] header { box-shadow: none; border-right: 1px solid #eee; } + +.ant-table.ant-table-middle .ant-table-title, +.ant-table.ant-table-middle .ant-table-footer, +.ant-table.ant-table-middle .ant-table-thead > tr > th, +.ant-table.ant-table-middle .ant-table-tbody > tr > td, +.ant-table.ant-table-middle tfoot > tr > th, +.ant-table.ant-table-middle tfoot > tr > td { + padding: 12px 16px; +} diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 3d05e4df..24ef6e37 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -392,5 +392,7 @@ "个人": "Personal", "重新安装": "Reinstall", "强制删除": "Force Delete", - "全部任务": "All Tasks" + "全部任务": "All Tasks", + "关联订阅": "Associate Subscription", + "订阅": "Subscription" } diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index 497c4851..08559f23 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -392,5 +392,7 @@ "个人": "个人", "重新安装": "重新安装", "强制删除": "强制删除", - "全部任务": "全部任务" + "全部任务": "全部任务", + "关联订阅": "关联订阅", + "订阅": "订阅" } diff --git a/src/pages/crontab/index.tsx b/src/pages/crontab/index.tsx index 88230b49..8257e3ba 100644 --- a/src/pages/crontab/index.tsx +++ b/src/pages/crontab/index.tsx @@ -56,6 +56,7 @@ import { getCommandScript, parseCrontab } from '@/utils'; import { ColumnProps } from 'antd/lib/table'; import { useVT } from 'virtualizedtableforantd4'; import { ICrontab, OperationName, OperationPath, CrontabStatus } from './type'; +import Name from '@/components/name'; const { Text, Paragraph } = Typography; const { Search } = Input; @@ -67,6 +68,7 @@ const Crontab = () => { title: intl.get('名称'), dataIndex: 'name', key: 'name', + fixed: isPhone ? undefined : 'left', width: 120, render: (text: string, record: any) => ( <> @@ -122,7 +124,7 @@ const Crontab = () => { title: intl.get('命令/脚本'), dataIndex: 'command', key: 'command', - width: 240, + width: 200, render: (text, record) => { return ( { compare: (a: any, b: any) => a.command.localeCompare(b.command), }, }, - { - title: intl.get('定时规则'), - dataIndex: 'schedule', - key: 'schedule', - width: 140, - sorter: { - compare: (a, b) => a.schedule.localeCompare(b.schedule), - }, - }, - { - title: intl.get('最后运行时长'), - width: 150, - dataIndex: 'last_running_time', - key: 'last_running_time', - sorter: { - compare: (a: any, b: any) => { - return a.last_running_time - b.last_running_time; - }, - }, - render: (text, record) => { - return record.last_running_time - ? diffTime(record.last_running_time) - : '-'; - }, - }, - { - title: intl.get('最后运行时间'), - dataIndex: 'last_execution_time', - key: 'last_execution_time', - width: 120, - sorter: { - compare: (a, b) => { - return (a.last_execution_time || 0) - (b.last_execution_time || 0); - }, - }, - render: (text, record) => { - const language = navigator.language || navigator.languages[0]; - return ( - - {record.last_execution_time - ? new Date(record.last_execution_time * 1000) - .toLocaleString(language, { - hour12: false, - }) - .replace(' 24:', ' 00:') - : '-'} - - ); - }, - }, - { - title: intl.get('下次运行时间'), - width: 120, - sorter: { - compare: (a: any, b: any) => { - return a.nextRunTime - b.nextRunTime; - }, - }, - render: (text, record) => { - const language = navigator.language || navigator.languages[0]; - return record.nextRunTime - .toLocaleString(language, { - hour12: false, - }) - .replace(' 24:', ' 00:'); - }, - }, { title: intl.get('状态'), key: 'status', dataIndex: 'status', - width: 88, + width: 100, filters: [ { text: intl.get('运行中'), @@ -272,10 +203,97 @@ const Crontab = () => { ), }, + { + title: intl.get('定时规则'), + dataIndex: 'schedule', + key: 'schedule', + width: 150, + sorter: { + compare: (a, b) => a.schedule.localeCompare(b.schedule), + }, + }, + { + title: intl.get('最后运行时长'), + width: 180, + dataIndex: 'last_running_time', + key: 'last_running_time', + sorter: { + compare: (a: any, b: any) => { + return a.last_running_time - b.last_running_time; + }, + }, + render: (text, record) => { + return record.last_running_time + ? diffTime(record.last_running_time) + : '-'; + }, + }, + { + title: intl.get('最后运行时间'), + dataIndex: 'last_execution_time', + key: 'last_execution_time', + width: 150, + sorter: { + compare: (a, b) => { + return (a.last_execution_time || 0) - (b.last_execution_time || 0); + }, + }, + render: (text, record) => { + const language = navigator.language || navigator.languages[0]; + return ( + + {record.last_execution_time + ? new Date(record.last_execution_time * 1000) + .toLocaleString(language, { + hour12: false, + }) + .replace(' 24:', ' 00:') + : '-'} + + ); + }, + }, + { + title: intl.get('下次运行时间'), + width: 150, + sorter: { + compare: (a: any, b: any) => { + return a.nextRunTime - b.nextRunTime; + }, + }, + render: (text, record) => { + const language = navigator.language || navigator.languages[0]; + return record.nextRunTime + .toLocaleString(language, { + hour12: false, + }) + .replace(' 24:', ' 00:'); + }, + }, + { + title: intl.get('关联订阅'), + width: 190, + render: (text, record: any) => + record.sub_id ? ( + + request.get(`${config.apiPrefix}subscriptions/${record.sub_id}`) + } + options={{ ready: record?.sub_id, cacheKey: record.sub_id }} + /> + ) : ( + '-' + ), + }, { title: intl.get('操作'), key: 'action', width: 130, + fixed: isPhone ? undefined : 'right', render: (text, record, index) => { const isPc = !isPhone; return ( @@ -350,6 +368,7 @@ const Crontab = () => { const [moreMenuActive, setMoreMenuActive] = useState(false); const tableRef = useRef(null); const tableScrollHeight = useTableScrollHeight(tableRef); + const [activeKey, setActiveKey] = useState(''); const goToScriptManager = (record: any) => { const result = getCommandScript(record.command); @@ -784,6 +803,9 @@ const Crontab = () => { if (pageConf.page && pageConf.size) { getCrons(); } + if (viewConf && viewConf.id) { + setActiveKey(viewConf.id); + } }, [pageConf, viewConf]); useEffect(() => { @@ -883,11 +905,6 @@ const Crontab = () => { setViewConf(view ? view : null); }; - const [vt] = useVT( - () => ({ scroll: { y: tableScrollHeight } }), - [tableScrollHeight], - ); - return ( { { rowSelection={rowSelection} rowClassName={getRowClassName} onChange={onPageChange} - // components={isPhone ? undefined : vt} /> { handleCancel={(data) => { setIsCreateViewModalVisible(false); getCronViews(); - if (data && data.id === viewConf.id) { - setViewConf({ ...viewConf, ...data }); - } }} /> { }} cronViewChange={(data) => { getCronViews(); - if (data && data.id === viewConf.id) { - setViewConf({ ...viewConf, ...data }); - } }} /> diff --git a/src/pages/crontab/viewCreateModal.tsx b/src/pages/crontab/viewCreateModal.tsx index 3423ea65..d5d4687d 100644 --- a/src/pages/crontab/viewCreateModal.tsx +++ b/src/pages/crontab/viewCreateModal.tsx @@ -14,15 +14,16 @@ import { request } from '@/utils/http'; import config from '@/utils/config'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import IconFont from '@/components/iconfont'; -import get from 'lodash/get'; import { CrontabStatus } from './type'; +import { useRequest } from 'ahooks'; const PROPERTIES = [ { name: intl.get('命令'), value: 'command' }, { name: intl.get('名称'), value: 'name' }, { name: intl.get('定时规则'), value: 'schedule' }, - { name: intl.get('状态'), value: 'status' }, + { name: intl.get('状态'), value: 'status', onlySelect: true }, { name: intl.get('标签'), value: 'labels' }, + { name: intl.get('订阅'), value: 'sub_id', onlySelect: true }, ]; const EOperation: any = { @@ -47,14 +48,6 @@ const SORTTYPES = [ { name: intl.get('倒序'), value: 'DESC' }, ]; -const STATUS_MAP = { - status: [ - { name: intl.get('运行中'), value: CrontabStatus.running }, - { name: intl.get('空闲中'), value: CrontabStatus.idle }, - { name: intl.get('已禁用'), value: CrontabStatus.disabled }, - ], -}; - enum ViewFilterRelation { 'and' = '且', 'or' = '或', @@ -73,6 +66,21 @@ const ViewCreateModal = ({ const [loading, setLoading] = useState(false); const [filterRelation, setFilterRelation] = useState<'and' | 'or'>('and'); const filtersValue = Form.useWatch('filters', form); + const { data } = useRequest( + () => request.get(`${config.apiPrefix}subscriptions`), + { + cacheKey: 'subscriptions', + }, + ); + + const STATUS_MAP = { + status: [ + { name: intl.get('运行中'), value: CrontabStatus.running }, + { name: intl.get('空闲中'), value: CrontabStatus.idle }, + { name: intl.get('已禁用'), value: CrontabStatus.disabled }, + ], + sub_id: data?.data.map((x) => ({ name: x.name, value: x.id })), + }; const handleOk = async (values: any) => { setLoading(true); @@ -105,7 +113,7 @@ const ViewCreateModal = ({ }, [view, visible]); const operationElement = ( - {OPERATIONS.map((x) => ( {x.name} @@ -243,7 +251,7 @@ const ViewCreateModal = ({ name={[name, 'property']} rules={[{ required: true }]} > - {propertyElement(PROPERTIES, { width: 90 })} + {propertyElement(PROPERTIES, { width: 120 })} (v === '全部任务' ? intl.get('全部任务') : v) }, { title: intl.get('类型'),