diff --git a/packages/core/client/src/locale/zh-CN.json b/packages/core/client/src/locale/zh-CN.json index 8e27dc701d..37ee3c0f57 100644 --- a/packages/core/client/src/locale/zh-CN.json +++ b/packages/core/client/src/locale/zh-CN.json @@ -821,6 +821,7 @@ "File size should not exceed {{size}}.": "文件大小不能超过 {{size}}", "File size exceeds the limit": "文件大小超过限制", "File type is not allowed": "文件类型不允许", + "Uploading": "上传中", "Incomplete uploading files need to be resolved": "未完成上传的文件需要处理", "Default title for each record": "用作数据的默认标题", "If collection inherits, choose inherited collections as templates": "当前表有继承关系时,可选择继承链路上的表作为模板来源", diff --git a/packages/core/client/src/schema-component/antd/input/Input.tsx b/packages/core/client/src/schema-component/antd/input/Input.tsx index 2870f7abf9..537d7bb95a 100644 --- a/packages/core/client/src/schema-component/antd/input/Input.tsx +++ b/packages/core/client/src/schema-component/antd/input/Input.tsx @@ -42,6 +42,8 @@ function InputInner(props: NocoBaseInputProps) { return ; } +InputInner.Password = AntdInput.Password; + export const Input: ComposedInput = Object.assign( connect( InputInner, diff --git a/packages/core/client/src/schema-component/hooks/useDesignable.tsx b/packages/core/client/src/schema-component/hooks/useDesignable.tsx index ed5e7f82d4..8fc4fddec1 100644 --- a/packages/core/client/src/schema-component/hooks/useDesignable.tsx +++ b/packages/core/client/src/schema-component/hooks/useDesignable.tsx @@ -799,7 +799,7 @@ export function useDesignable() { return component; } const c = get(components, component); - return c[LAZY_COMPONENT_KEY] ?? c; + return c?.[LAZY_COMPONENT_KEY] ?? c; }, [get], ), diff --git a/packages/core/database/src/interfaces/index.ts b/packages/core/database/src/interfaces/index.ts index 038ada52cc..aebd38d8d1 100644 --- a/packages/core/database/src/interfaces/index.ts +++ b/packages/core/database/src/interfaces/index.ts @@ -15,3 +15,4 @@ export * from './datetime-interface'; export * from './datetime-no-tz-interface'; export * from './boolean-interface'; export * from './date-interface'; +export * from './time-interface'; diff --git a/packages/core/database/src/interfaces/time-interface.ts b/packages/core/database/src/interfaces/time-interface.ts new file mode 100644 index 0000000000..95385b4eee --- /dev/null +++ b/packages/core/database/src/interfaces/time-interface.ts @@ -0,0 +1,26 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import dayjs from 'dayjs'; +import { BaseInterface } from './base-interface'; + +export class TimeInterface extends BaseInterface { + toValue(value: any, ctx?: any) { + if (this.validate(value)) { + const result = dayjs.utc(value).format('HH:mm:ss'); + return result; + } + return value; + } + + validate(value) { + const result = dayjs(value).isValid(); + return result; + } +} diff --git a/packages/core/database/src/interfaces/utils.ts b/packages/core/database/src/interfaces/utils.ts index 170687f6e5..cc10790ad0 100644 --- a/packages/core/database/src/interfaces/utils.ts +++ b/packages/core/database/src/interfaces/utils.ts @@ -16,6 +16,7 @@ import { MultipleSelectInterface, PercentInterface, SelectInterface, + TimeInterface, } from './index'; import { ManyToOneInterface } from './many-to-one-interface'; import { ManyToManyInterface } from './many-to-many-interface'; @@ -50,6 +51,7 @@ const interfaces = { o2m: OneToManyInterface, m2o: ManyToOneInterface, m2m: ManyToManyInterface, + time: TimeInterface, }; export function registerInterfaces(db: Database) { diff --git a/packages/plugins/@nocobase/plugin-action-import/src/server/__tests__/xlsx-importer.test.ts b/packages/plugins/@nocobase/plugin-action-import/src/server/__tests__/xlsx-importer.test.ts index 85cb90ca9a..21153d3760 100644 --- a/packages/plugins/@nocobase/plugin-action-import/src/server/__tests__/xlsx-importer.test.ts +++ b/packages/plugins/@nocobase/plugin-action-import/src/server/__tests__/xlsx-importer.test.ts @@ -2155,4 +2155,53 @@ describe('xlsx importer', () => { expect(await Post.repository.count()).toBe(1); }); + + it('should import time field successfully', async () => { + const TimeCollection = app.db.collection({ + name: 'time_tests', + fields: [ + { + type: 'time', + name: 'brithtime', + }, + ], + }); + + await app.db.sync(); + const templateCreator = new TemplateCreator({ + collection: TimeCollection, + explain: 'test', + columns: [ + { + dataIndex: ['birthtime'], + defaultTitle: '出生时间', + }, + ], + }); + + const template = (await templateCreator.run({ returnXLSXWorkbook: true })) as XLSX.WorkBook; + + const worksheet = template.Sheets[template.SheetNames[0]]; + + XLSX.utils.sheet_add_aoa(worksheet, [['12:12:12']], { + origin: 'A3', + }); + + const importer = new XlsxImporter({ + collectionManager: app.mainDataSource.collectionManager, + collection: TimeCollection, + explain: 'test', + columns: [ + { + dataIndex: ['brithtime'], + defaultTitle: '出生时间', + }, + ], + workbook: template, + }); + + await importer.run(); + const count = await TimeCollection.repository.count(); + expect(count).toBe(1); + }); }); diff --git a/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts b/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts index 8f8b75516f..9d63a78935 100644 --- a/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts +++ b/packages/plugins/@nocobase/plugin-action-import/src/server/actions/import-xlsx.ts @@ -36,6 +36,7 @@ async function importXlsxAction(ctx: Context, next: Next) { const workbook = XLSX.read(ctx.file.buffer, { type: 'buffer', sheetRows: readLimit, + cellDates: true, }); const repository = ctx.getCurrentRepository() as Repository; diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/WorkflowTodo.tsx b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/WorkflowTodo.tsx index 491a82d89c..628dceaab3 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/WorkflowTodo.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/WorkflowTodo.tsx @@ -8,6 +8,7 @@ */ import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; import { useField, useFieldSchema, useForm } from '@formily/react'; import { FormLayout } from '@formily/antd-v5'; import { Button, Card, ConfigProvider, Descriptions, Space, Spin, Tag } from 'antd'; @@ -47,7 +48,6 @@ import WorkflowPlugin, { useAvailableUpstreams, useFlowContext, EXECUTION_STATUS, - JOB_STATUS, WorkflowTitle, TASK_STATUS, usePopupRecordContext, @@ -56,8 +56,7 @@ import WorkflowPlugin, { import { NAMESPACE, useLang } from '../locale'; import { FormBlockProvider } from './instruction/FormBlockProvider'; import { ManualFormType, manualFormTypes } from './instruction/SchemaConfig'; -import { TaskStatusOptionsMap } from '../common/constants'; -import { useNavigate, useParams } from 'react-router-dom'; +import { TaskStatusOptionsMap, TASK_STATUS } from '../common/constants'; function TaskStatusColumn(props) { const recordData = useCollectionRecordData(); @@ -654,11 +653,11 @@ function TaskItem() { const StatusFilterMap = { pending: { - status: JOB_STATUS.PENDING, + status: TASK_STATUS.PENDING, 'execution.status': EXECUTION_STATUS.STARTED, }, completed: { - status: JOB_STATUS.RESOLVED, + status: [TASK_STATUS.RESOLVED, TASK_STATUS.REJECTED], }, }; diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/common/constants.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/common/constants.ts index dd4acc5d20..a59b843700 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/common/constants.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/common/constants.ts @@ -14,7 +14,7 @@ export const MANUAL_TASK_TYPE = 'manual'; export const TASK_STATUS = { PENDING: 0, RESOLVED: 1, - REJECTED: -1, + REJECTED: -5, }; export const TaskStatusOptions = [