feat: support task

This commit is contained in:
liufree 2025-05-07 22:53:54 +08:00
parent 2a1324d130
commit da991daa6a
3 changed files with 281 additions and 32 deletions

View file

@ -1,7 +1,7 @@
{
"id": "querydash",
"name": "QueryDash",
"version": "1.0.4",
"version": "1.0.6",
"minAppVersion": "1.8.0",
"description": "Refer to Dataview and add search, sorting, and pagination functions, just like Notion.",
"author": "lwx",

View file

@ -0,0 +1,244 @@
import {PlusOutlined} from '@ant-design/icons';
import type {ActionType, ProColumns} from '@ant-design/pro-components';
import {
EditableProTable,
ProCard,
ProFormField,
} from '@ant-design/pro-components';
import type {InputRef} from 'antd';
import {Button, Form, Input, Space, Tag} from 'antd';
import React, {useRef, useState} from 'react';
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
const TagList: React.FC<{
value?: {
key: string;
label: string;
}[];
onChange?: (
value: {
key: string;
label: string;
}[],
) => void;
}> = ({value, onChange}) => {
const ref = useRef<InputRef | null>(null);
const [newTags, setNewTags] = useState<
{
key: string;
label: string;
}[]
>([]);
const [inputValue, setInputValue] = useState<string>('');
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
};
const handleInputConfirm = () => {
let tempsTags = [...(value || [])];
if (
inputValue &&
tempsTags.filter((tag) => tag.label === inputValue).length === 0
) {
tempsTags = [
...tempsTags,
{key: `new-${tempsTags.length}`, label: inputValue},
];
}
onChange?.(tempsTags);
setNewTags([]);
setInputValue('');
};
return (
<Space>
{(value || []).concat(newTags).map((item) => (
<Tag key={item.key}>{item.label}</Tag>
))}
<Input
ref={ref}
type="text"
size="small"
style={{width: 78}}
value={inputValue}
onChange={handleInputChange}
onBlur={handleInputConfirm}
onPressEnter={handleInputConfirm}
/>
</Space>
);
};
type DataSourceType = {
id: React.Key;
title?: string;
labels?: {
key: string;
label: string;
}[];
state?: string;
created_at?: number;
children?: DataSourceType[];
};
const defaultData: DataSourceType[] = [
{
id: 624748504,
title: '活动名称一',
labels: [{key: 'woman', label: '川妹子'}],
state: 'open',
created_at: 1590486176000,
},
{
id: 624691229,
title: '活动名称二',
labels: [{key: 'man', label: '西北汉子'}],
state: 'closed',
created_at: 1590481162000,
},
];
const columns: ProColumns<DataSourceType>[] = [
{
title: '活动名称',
dataIndex: 'title',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
width: '30%',
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
valueType: 'select',
valueEnum: {
all: {text: '全部', status: 'Default'},
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
},
},
},
{
title: '标签',
dataIndex: 'labels',
width: '20%',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
renderFormItem: (_, {isEditable}) => {
return isEditable ? <TagList/> : <Input/>;
},
render: (_, row) =>
row?.labels?.map((item) => <Tag key={item.key}>{item.label}</Tag>),
},
{
title: '操作',
valueType: 'option',
width: 250,
render: (text, record, _, action) => [
<a
key="editable"
onClick={() => {
action?.startEditable?.(record.id);
}}
>
</a>,
<EditableProTable.RecordCreator
key="copy"
record={{
...record,
id: (Math.random() * 1000000).toFixed(0),
}}
>
<a></a>
</EditableProTable.RecordCreator>,
],
},
];
export default () => {
const actionRef = useRef<ActionType>();
const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]);
const [form] = Form.useForm();
return (
<>
<EditableProTable<DataSourceType>
rowKey="id"
scroll={{
x: 960,
}}
actionRef={actionRef}
headerTitle="可编辑表格"
maxLength={5}
// 关闭默认的新建按钮
recordCreatorProps={{
position: 'top',
record: () => ({id: (Math.random() * 1000000).toFixed(0)}),
}}
columns={columns}
request={async () => ({
data: defaultData,
total: 3,
success: true,
})}
value={dataSource}
onChange={setDataSource}
search={{
labelWidth: 'auto',
}}
pagination={{
pageSize: 5,
onChange: (page) => console.log(page),
}}
editable={{
form,
editableKeys,
onSave: async () => {
await waitTime(2000);
},
onChange: setEditableRowKeys,
actionRender: (row, config, dom) => [dom.save, dom.cancel],
}}
/>
<ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
<ProFormField
ignoreFormItem
fieldProps={{
style: {
width: '100%',
},
}}
mode="read"
valueType="jsonCode"
text={JSON.stringify(dataSource)}
/>
</ProCard>
</>
);
};

View file

@ -5,6 +5,7 @@ import {getAPI, STask} from "obsidian-dataview";
import {ViewProps} from "../../models/ViewProps";
import {TFile, Vault} from "obsidian";
import EditableText from "./EditableText";
import EditableTable from "../../components/EditableTable";
const {Text, Link} = Typography;
@ -22,7 +23,7 @@ const KanbanView: React.FC<ViewProps> = ({app, source}) => {
leaf.openFile(file);
}
}}
>
>
<Text
style={display ? {maxWidth: 200, color: '#1890ff', cursor: 'pointer'} : {
color: '#1890ff',
@ -172,36 +173,40 @@ const KanbanView: React.FC<ViewProps> = ({app, source}) => {
}, [app]);
return (
<ProCard ghost gutter={8}>
{columns.map((column) => (
<ProCard key={column.title} title={column.title} bordered>
{column.items.map((item: any, index: number) => (
<>
<ProCard key={index} bordered>
<Row>
<Col span={1}>
<Checkbox
onChange={(e) => onChange(e.target.checked, item.text, item)}
checked={item.checked}
/>
</Col>
<Col span={18}>
<EditableText
app={app}
item={item}
onSave={(newText) => {
console.log("保存的新文本:", newText);
onChange(item.checked, newText, item);
}}
/>
</Col>
</Row>
</ProCard>
</>
))}
</ProCard>
))}
</ProCard>
<>
<EditableTable></EditableTable>
<ProCard ghost gutter={8}>
{columns.map((column) => (
<ProCard key={column.title} title={column.title} bordered>
{column.items.map((item: any, index: number) => (
<>
<ProCard key={index} bordered>
<Row>
<Col span={1}>
<Checkbox
onChange={(e) => onChange(e.target.checked, item.text, item)}
checked={item.checked}
/>
</Col>
<Col span={18}>
<EditableText
app={app}
item={item}
onSave={(newText) => {
console.log("保存的新文本:", newText);
onChange(item.checked, newText, item);
}}
/>
</Col>
</Row>
</ProCard>
</>
))}
</ProCard>
))}
</ProCard>
</>
);
};