mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 21:49:25 +08:00
Merge branch 'main' into next
This commit is contained in:
commit
d2bd8cdf48
@ -7,22 +7,52 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { connect, mapReadPretty } from '@formily/react';
|
import { connect, mapReadPretty, useField } from '@formily/react';
|
||||||
import React from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { DatePicker } from '../date-picker';
|
import { DatePicker } from '../date-picker';
|
||||||
|
|
||||||
|
const toValue = (value: any, accuracy) => {
|
||||||
|
if (value) {
|
||||||
|
return convertTimestampToDate(value, accuracy);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function convertTimestampToDate(timestamp, accuracy = 'second') {
|
||||||
|
// 如果是秒级时间戳,乘以1000转换为毫秒
|
||||||
|
const timeInMilliseconds = accuracy === 'second' ? timestamp * 1000 : timestamp;
|
||||||
|
|
||||||
|
// 创建Date对象并转为UTC时间
|
||||||
|
const date = new Date(timeInMilliseconds);
|
||||||
|
|
||||||
|
// 检查日期是否有效
|
||||||
|
if (isNaN(date.getTime())) {
|
||||||
|
return 'Invalid timestamp';
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.toUTCString(); // 返回 UTC 格式的日期
|
||||||
|
}
|
||||||
interface UnixTimestampProps {
|
interface UnixTimestampProps {
|
||||||
value?: any;
|
value?: any;
|
||||||
onChange?: (value: number) => void;
|
onChange?: (value: number) => void;
|
||||||
|
accuracy?: 'millisecond' | 'second';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UnixTimestamp = connect(
|
export const UnixTimestamp = connect(
|
||||||
(props: UnixTimestampProps) => {
|
(props: UnixTimestampProps) => {
|
||||||
const { value, onChange } = props;
|
const { value, onChange, accuracy } = props;
|
||||||
|
const targetValue = useMemo(() => {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
const v = toValue(value, accuracy);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DatePicker
|
<DatePicker
|
||||||
{...props}
|
{...props}
|
||||||
value={value}
|
value={targetValue}
|
||||||
onChange={(v: any) => {
|
onChange={(v: any) => {
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(v);
|
onChange(v);
|
||||||
|
@ -68,6 +68,29 @@ describe('unix timestamp field', () => {
|
|||||||
expect(date).toBe('2021-01-01 00:00:00');
|
expect(date).toBe('2021-01-01 00:00:00');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('number as second input should be kept as same', async () => {
|
||||||
|
const c1 = db.collection({
|
||||||
|
name: 'test13',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'date1',
|
||||||
|
type: 'unixTimestamp',
|
||||||
|
accuracy: 'second',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sync();
|
||||||
|
|
||||||
|
const d = new Date();
|
||||||
|
const second = Math.floor(d.getTime() / 1000);
|
||||||
|
|
||||||
|
const instance = await c1.repository.create({ values: { date1: second } });
|
||||||
|
const date1 = instance.get('date1');
|
||||||
|
expect(date1 instanceof Date).toBe(true);
|
||||||
|
expect(date1.getTime()).toBe(second * 1000);
|
||||||
|
});
|
||||||
|
|
||||||
describe('timezone', () => {
|
describe('timezone', () => {
|
||||||
test('custom', async () => {
|
test('custom', async () => {
|
||||||
db.collection({
|
db.collection({
|
@ -37,7 +37,7 @@ export class UnixTimestampField extends DateField {
|
|||||||
rationalNumber = 1;
|
rationalNumber = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.floor(new Date(val).getTime() / rationalNumber);
|
return Math.floor(typeof val === 'number' ? val : new Date(val).getTime() / rationalNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalSequelizeOptions() {
|
additionalSequelizeOptions() {
|
||||||
@ -61,18 +61,21 @@ export class UnixTimestampField extends DateField {
|
|||||||
return {
|
return {
|
||||||
get() {
|
get() {
|
||||||
const value = this.getDataValue(name);
|
const value = this.getDataValue(name);
|
||||||
if (value === null || value === undefined) {
|
if (value == null) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Date(value * rationalNumber);
|
return new Date(value * rationalNumber);
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value === null || value === undefined) {
|
if (value == null) {
|
||||||
this.setDataValue(name, value);
|
this.setDataValue(name, value);
|
||||||
} else {
|
} else {
|
||||||
// date to unix timestamp
|
// date to unix timestamp
|
||||||
this.setDataValue(name, Math.floor(new Date(value).getTime() / rationalNumber));
|
this.setDataValue(
|
||||||
|
name,
|
||||||
|
Math.floor(typeof value === 'number' ? value : new Date(value).getTime() / rationalNumber),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Database, { Collection, MagicAttributeModel, SyncOptions, Transactionable } from '@nocobase/database';
|
import Database, { Collection, MagicAttributeModel, SyncOptions, Transactionable } from '@nocobase/database';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
interface LoadOptions extends Transactionable {
|
interface LoadOptions extends Transactionable {
|
||||||
// TODO
|
// TODO
|
||||||
@ -42,7 +43,7 @@ export class FieldModel extends MagicAttributeModel {
|
|||||||
return collection.getField(name);
|
return collection.getField(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = this.get();
|
const options = this.toJSON();
|
||||||
|
|
||||||
const field = await (async () => {
|
const field = await (async () => {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
@ -202,4 +203,12 @@ export class FieldModel extends MagicAttributeModel {
|
|||||||
|
|
||||||
return this.db.getCollection(collectionName);
|
return this.db.getCollection(collectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJSON() {
|
||||||
|
const json = super.toJSON();
|
||||||
|
if (json.interface === 'unixTimestamp' && json.accuracy) {
|
||||||
|
_.set(json, 'uiSchema.x-component-props.accuracy', json.accuracy);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import { MagicAttributeModel } from '@nocobase/database';
|
import { MagicAttributeModel } from '@nocobase/database';
|
||||||
import { Application } from '@nocobase/server';
|
import { Application } from '@nocobase/server';
|
||||||
|
import _ from 'lodash';
|
||||||
import { mergeOptions } from '../utils';
|
import { mergeOptions } from '../utils';
|
||||||
|
|
||||||
type LoadOptions = {
|
type LoadOptions = {
|
||||||
@ -19,7 +20,7 @@ export class DataSourcesFieldModel extends MagicAttributeModel {
|
|||||||
load(loadOptions: LoadOptions) {
|
load(loadOptions: LoadOptions) {
|
||||||
const { app } = loadOptions;
|
const { app } = loadOptions;
|
||||||
|
|
||||||
const options = this.get();
|
const options = this.toJSON();
|
||||||
const { collectionName, name, dataSourceKey, field } = options;
|
const { collectionName, name, dataSourceKey, field } = options;
|
||||||
const dataSource = app.dataSourceManager.dataSources.get(dataSourceKey);
|
const dataSource = app.dataSourceManager.dataSources.get(dataSourceKey);
|
||||||
const collection = dataSource.collectionManager.getCollection(collectionName);
|
const collection = dataSource.collectionManager.getCollection(collectionName);
|
||||||
@ -45,7 +46,7 @@ export class DataSourcesFieldModel extends MagicAttributeModel {
|
|||||||
|
|
||||||
unload(loadOptions: LoadOptions) {
|
unload(loadOptions: LoadOptions) {
|
||||||
const { app } = loadOptions;
|
const { app } = loadOptions;
|
||||||
const options = this.get();
|
const options = this.toJSON();
|
||||||
const { collectionName, name, dataSourceKey } = options;
|
const { collectionName, name, dataSourceKey } = options;
|
||||||
const dataSource = app.dataSourceManager.dataSources.get(dataSourceKey);
|
const dataSource = app.dataSourceManager.dataSources.get(dataSourceKey);
|
||||||
if (!dataSource) {
|
if (!dataSource) {
|
||||||
@ -58,4 +59,12 @@ export class DataSourcesFieldModel extends MagicAttributeModel {
|
|||||||
|
|
||||||
collection.removeField(name);
|
collection.removeField(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJSON() {
|
||||||
|
const json = super.toJSON();
|
||||||
|
if (json.interface === 'unixTimestamp' && json.accuracy) {
|
||||||
|
_.set(json, 'uiSchema.x-component-props.accuracy', json.accuracy);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user