mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 05:36:05 +00:00
feat: add support for filter action
This commit is contained in:
parent
a44bab62fc
commit
0d3d30e0c2
59
packages/app/src/components/actions/Filter.tsx
Normal file
59
packages/app/src/components/actions/Filter.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Button, Popover } from 'antd';
|
||||
import ViewFactory from '@/components/views';
|
||||
|
||||
export function Filter(props) {
|
||||
console.log(props);
|
||||
const drawerRef = useRef<any>();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { title, viewName, collection_name } = props.schema;
|
||||
const { activeTab = {}, item = {}, associatedName, associatedKey } = props;
|
||||
const { association } = activeTab;
|
||||
|
||||
const params = {};
|
||||
|
||||
if (association) {
|
||||
params['resourceName'] = association;
|
||||
params['associatedName'] = associatedName;
|
||||
params['associatedKey'] = associatedKey;
|
||||
} else {
|
||||
params['resourceName'] = collection_name;
|
||||
params['resourceKey'] = item.itemId;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Popover
|
||||
title="设置筛选"
|
||||
trigger="click"
|
||||
visible={visible}
|
||||
placement={'bottomLeft'}
|
||||
onVisibleChange={(visible) => {
|
||||
setVisible(visible);
|
||||
}}
|
||||
className={'filters-popover'}
|
||||
style={{
|
||||
}}
|
||||
overlayStyle={{
|
||||
minWidth: 500
|
||||
}}
|
||||
content={(
|
||||
<>
|
||||
<div className={'popover-button-mask'} onClick={() => setVisible(false)}></div>
|
||||
<ViewFactory
|
||||
{...props}
|
||||
viewName={'filter'}
|
||||
{...params}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<Button type={'primary'} onClick={() => {
|
||||
setVisible(true);
|
||||
}}>{title}</Button>
|
||||
</Popover>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Filter;
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||
import Create from './Create';
|
||||
import Update from './Update';
|
||||
import Destroy from './Destroy';
|
||||
import Filter from './Filter';
|
||||
import { Space } from 'antd';
|
||||
|
||||
const ACTIONS = new Map<string, any>();
|
||||
@ -14,6 +15,7 @@ export function registerAction(type: string, Action: any) {
|
||||
registerAction('update', Update);
|
||||
registerAction('create', Create);
|
||||
registerAction('destroy', Destroy);
|
||||
registerAction('filter', Filter);
|
||||
|
||||
export function getAction(type: string) {
|
||||
return ACTIONS.get(type);
|
||||
|
263
packages/app/src/components/form.fields/filter/index.tsx
Normal file
263
packages/app/src/components/form.fields/filter/index.tsx
Normal file
@ -0,0 +1,263 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Select, Input, Space, Form, InputNumber, DatePicker } from 'antd';
|
||||
import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
|
||||
import useDynamicList from './useDynamicList';
|
||||
import { connect } from '@formily/react-schema-renderer'
|
||||
import { mapStyledProps } from '../shared'
|
||||
import moment from 'moment';
|
||||
|
||||
export function FilterGroup(props: any) {
|
||||
const { showDeleteButton = false, fields = [], onDelete, onChange, onAdd, dataSource = {} } = props;
|
||||
const { list, getKey, push, remove, replace } = useDynamicList<any>(dataSource.list || [
|
||||
{
|
||||
type: 'item',
|
||||
},
|
||||
]);
|
||||
return (
|
||||
<div style={{marginBottom: 14, padding: 14, border: '1px dashed #dedede'}}>
|
||||
<div style={{marginBottom: 14}}>
|
||||
满足组内
|
||||
{' '}
|
||||
<Select style={{width: 80}} onChange={(value) => {
|
||||
onChange({...dataSource, andor: value});
|
||||
}} defaultValue={'and'}>
|
||||
<Select.Option value={'and'}>全部</Select.Option>
|
||||
<Select.Option value={'or'}>任意</Select.Option>
|
||||
</Select>
|
||||
{' '}
|
||||
条件
|
||||
</div>
|
||||
<div>
|
||||
{list.map((item, index) => {
|
||||
// console.log(item);
|
||||
const Component = item.type === 'group' ? FilterGroup : FilterItem;
|
||||
return (
|
||||
<div style={{marginBottom: 14}}>
|
||||
{<Component
|
||||
fields={fields}
|
||||
dataSource={item}
|
||||
showDeleteButton={list.length > 1}
|
||||
onChange={(value) => {
|
||||
replace(index, value);
|
||||
const newList = [...list];
|
||||
newList[index] = value;
|
||||
onChange({...dataSource, list: newList});
|
||||
// console.log(list, value, index);
|
||||
}}
|
||||
onDelete={() => {
|
||||
remove(index);
|
||||
const newList = [...list];
|
||||
newList.splice(index, 1);
|
||||
onChange({...dataSource, list: newList});
|
||||
// console.log(list, index);
|
||||
}}
|
||||
/>}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<Space>
|
||||
<Button onClick={() => {
|
||||
const data = {
|
||||
type: 'item'
|
||||
};
|
||||
push(data);
|
||||
const newList = [...list];
|
||||
newList.push(data);
|
||||
onChange({...dataSource, list: newList});
|
||||
}}>
|
||||
添加条件
|
||||
</Button>
|
||||
<Button onClick={() => {
|
||||
const data = {
|
||||
type: 'group',
|
||||
list: [
|
||||
{
|
||||
type: 'item',
|
||||
},
|
||||
],
|
||||
};
|
||||
push(data);
|
||||
const newList = [...list];
|
||||
newList.push(data);
|
||||
onChange({...dataSource, list: newList});
|
||||
}}>
|
||||
添加条件组
|
||||
</Button>
|
||||
{showDeleteButton && <Button onClick={(e) => {
|
||||
onDelete && onDelete(e);
|
||||
}}>
|
||||
删除组
|
||||
</Button>}
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface FieldOptions {
|
||||
name: string;
|
||||
title: string;
|
||||
interface: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface FilterItemProps {
|
||||
fields: FieldOptions[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const OP_MAP = {
|
||||
string: [
|
||||
{label: '等于', value: 'eq'},
|
||||
{label: '不等于', value: 'neq'},
|
||||
{label: '包含', value: 'cont'},
|
||||
{label: '不包含', value: 'ncont'},
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
],
|
||||
number: [
|
||||
{label: '等于', value: 'eq'},
|
||||
{label: '不等于', value: 'neq'},
|
||||
{label: '大于', value: 'gt'},
|
||||
{label: '大于等于', value: 'gte'},
|
||||
{label: '小于', value: 'lt'},
|
||||
{label: '小于等于', value: 'lte'},
|
||||
{label: '介于', value: 'between'},
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
],
|
||||
file: [
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
],
|
||||
boolean: [
|
||||
{label: '等于', value: 'eq'},
|
||||
],
|
||||
choices: [
|
||||
{label: '等于', value: 'eq'},
|
||||
{label: '不等于', value: 'neq'},
|
||||
{label: '包含', value: 'cont'},
|
||||
{label: '不包含', value: 'ncont'},
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
],
|
||||
datetime: [
|
||||
{label: '等于', value: 'eq'},
|
||||
{label: '不等于', value: 'neq'},
|
||||
{label: '大于', value: 'gt'},
|
||||
{label: '大于等于', value: 'gte'},
|
||||
{label: '小于', value: 'lt'},
|
||||
{label: '小于等于', value: 'lte'},
|
||||
{label: '介于', value: 'between'},
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
{label: '是今天', value: 'now'},
|
||||
{label: '在今天之前', value: 'before_today'},
|
||||
{label: '在今天之后', value: 'after_today'},
|
||||
],
|
||||
linkTo: [
|
||||
{label: '包含', value: 'cont'},
|
||||
{label: '不包含', value: 'ncont'},
|
||||
{label: '非空', value: 'notnull'},
|
||||
{label: '为空', value: 'null'},
|
||||
],
|
||||
};
|
||||
|
||||
const op = {
|
||||
string: OP_MAP.string,
|
||||
textarea: OP_MAP.string,
|
||||
number: OP_MAP.number,
|
||||
datetime: OP_MAP.datetime,
|
||||
};
|
||||
|
||||
const StringInput = (props) => {
|
||||
const { onChange, ...restProps } = props;
|
||||
return (
|
||||
<Input {...restProps} onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}/>
|
||||
);
|
||||
}
|
||||
|
||||
const controls = {
|
||||
string: StringInput,
|
||||
textarea: StringInput,
|
||||
number: InputNumber,
|
||||
// datetime: DatePicker,
|
||||
datetime: (props) => {
|
||||
const { value, onChange, ...restProps } = props;
|
||||
const m = moment(value, 'YYYY-MM-DD HH:mm:ss');
|
||||
return (
|
||||
<DatePicker value={m.isValid() ? m : null} onChange={(value) => {
|
||||
onChange(value ? value.format('YYYY-MM-DD HH:mm:ss') : null)
|
||||
console.log(value.format('YYYY-MM-DD HH:mm:ss'));
|
||||
}}/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export function FilterItem(props: FilterItemProps) {
|
||||
const { index, fields = [], showDeleteButton = false, onDelete, onChange, dataSource = {} } = props;
|
||||
const [type, setType] = useState('string');
|
||||
useEffect(() => {
|
||||
const field = fields.find(field => field.name === dataSource.column);
|
||||
if (field) {
|
||||
setType(field.interface);
|
||||
}
|
||||
}, [
|
||||
dataSource,
|
||||
]);
|
||||
const ValueControl = controls[type]||controls.string;
|
||||
return (
|
||||
<Input.Group compact>
|
||||
<Select value={dataSource.column}
|
||||
onChange={(value) => {
|
||||
const field = fields.find(field => field.name === value);
|
||||
if (field) {
|
||||
setType(field.interface);
|
||||
}
|
||||
onChange({...dataSource, column: value});
|
||||
}}
|
||||
style={{ width: '30%' }} placeholder={'选择字段'}>
|
||||
{fields.map(field => (
|
||||
<Select.Option value={field.name}>{field.title}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
<Select value={dataSource.op} style={{ minWidth: 100 }}
|
||||
onChange={(value) => {
|
||||
onChange({...dataSource, op: value});
|
||||
}}
|
||||
>
|
||||
{(op[type]||op.string).map(option => (
|
||||
<Select.Option value={option.value}>{option.label}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
<ValueControl value={dataSource.value} onChange={(value) => {
|
||||
onChange({...dataSource, value: value});
|
||||
}} style={{ width: '30%' }}/>
|
||||
{showDeleteButton && (
|
||||
<Button onClick={(e) => {
|
||||
onDelete && onDelete(e);
|
||||
}}>删除</Button>
|
||||
)}
|
||||
</Input.Group>
|
||||
);
|
||||
}
|
||||
|
||||
export const Filter = connect({
|
||||
getProps: mapStyledProps,
|
||||
})((props) => {
|
||||
const dataSource = {
|
||||
type: 'group',
|
||||
list: [
|
||||
{
|
||||
type: 'item',
|
||||
}
|
||||
],
|
||||
};
|
||||
return <FilterGroup dataSource={dataSource} {...props}/>
|
||||
});
|
||||
|
||||
export default Filter;
|
160
packages/app/src/components/form.fields/filter/useDynamicList.ts
Normal file
160
packages/app/src/components/form.fields/filter/useDynamicList.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
|
||||
export default <T>(initialValue: T[]) => {
|
||||
const counterRef = useRef(-1);
|
||||
// key 存储器
|
||||
const keyList = useRef<number[]>([]);
|
||||
|
||||
// 内部方法
|
||||
const setKey = useCallback((index: number) => {
|
||||
counterRef.current += 1;
|
||||
keyList.current.splice(index, 0, counterRef.current);
|
||||
}, []);
|
||||
|
||||
const [list, setList] = useState(() => {
|
||||
(initialValue || []).forEach((_, index) => {
|
||||
setKey(index);
|
||||
});
|
||||
return initialValue || [];
|
||||
});
|
||||
|
||||
const resetList = (newList: T[] = []) => {
|
||||
keyList.current = [];
|
||||
counterRef.current = -1;
|
||||
setList(() => {
|
||||
(newList || []).forEach((_, index) => {
|
||||
setKey(index);
|
||||
});
|
||||
return newList || [];
|
||||
});
|
||||
};
|
||||
|
||||
const insert = (index: number, obj: T) => {
|
||||
setList((l) => {
|
||||
const temp = [...l];
|
||||
temp.splice(index, 0, obj);
|
||||
setKey(index);
|
||||
return temp;
|
||||
});
|
||||
};
|
||||
|
||||
const getAll = () => list;
|
||||
const getKey = (index: number) => keyList.current[index];
|
||||
const getIndex = (index: number) => keyList.current.findIndex((ele) => ele === index);
|
||||
|
||||
const merge = (index: number, obj: T[]) => {
|
||||
setList((l) => {
|
||||
const temp = [...l];
|
||||
obj.forEach((_, i) => {
|
||||
setKey(index + i);
|
||||
});
|
||||
temp.splice(index, 0, ...obj);
|
||||
return temp;
|
||||
});
|
||||
};
|
||||
|
||||
const replace = (index: number, obj: T) => {
|
||||
setList((l) => {
|
||||
const temp = [...l];
|
||||
temp[index] = obj;
|
||||
return temp;
|
||||
});
|
||||
};
|
||||
|
||||
const remove = (index: number) => {
|
||||
setList((l) => {
|
||||
const temp = [...l];
|
||||
temp.splice(index, 1);
|
||||
|
||||
// remove keys if necessary
|
||||
try {
|
||||
keyList.current.splice(index, 1);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
return temp;
|
||||
});
|
||||
};
|
||||
|
||||
const move = (oldIndex: number, newIndex: number) => {
|
||||
if (oldIndex === newIndex) {
|
||||
return;
|
||||
}
|
||||
setList((l) => {
|
||||
const newList = [...l];
|
||||
const temp = newList.filter((_: {}, index: number) => index !== oldIndex);
|
||||
temp.splice(newIndex, 0, newList[oldIndex]);
|
||||
|
||||
// move keys if necessary
|
||||
try {
|
||||
const keyTemp = keyList.current.filter((_: {}, index: number) => index !== oldIndex);
|
||||
keyTemp.splice(newIndex, 0, keyList.current[oldIndex]);
|
||||
keyList.current = keyTemp;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return temp;
|
||||
});
|
||||
};
|
||||
|
||||
const push = (obj: T) => {
|
||||
setList((l) => {
|
||||
setKey(l.length);
|
||||
return l.concat([obj]);
|
||||
});
|
||||
};
|
||||
|
||||
const pop = () => {
|
||||
// remove keys if necessary
|
||||
try {
|
||||
keyList.current = keyList.current.slice(0, keyList.current.length - 1);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
setList((l) => l.slice(0, l.length - 1));
|
||||
};
|
||||
|
||||
const unshift = (obj: T) => {
|
||||
setList((l) => {
|
||||
setKey(0);
|
||||
return [obj].concat(l);
|
||||
});
|
||||
};
|
||||
|
||||
const sortForm = (result: unknown[]) =>
|
||||
result
|
||||
.map((item, index) => ({ key: index, item })) // add index into obj
|
||||
.sort((a, b) => getIndex(a.key) - getIndex(b.key)) // sort based on the index of table
|
||||
.filter((item) => !!item.item) // remove undefined(s)
|
||||
.map((item) => item.item); // retrive the data
|
||||
|
||||
const shift = () => {
|
||||
// remove keys if necessary
|
||||
try {
|
||||
keyList.current = keyList.current.slice(1, keyList.current.length);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
setList((l) => l.slice(1, l.length));
|
||||
};
|
||||
|
||||
return {
|
||||
list,
|
||||
insert,
|
||||
merge,
|
||||
replace,
|
||||
remove,
|
||||
getAll,
|
||||
getKey,
|
||||
getIndex,
|
||||
move,
|
||||
push,
|
||||
pop,
|
||||
unshift,
|
||||
shift,
|
||||
sortForm,
|
||||
resetList,
|
||||
};
|
||||
};
|
@ -13,6 +13,7 @@ import { Radio } from './radio'
|
||||
import { Range } from './range'
|
||||
import { Rating } from './rating'
|
||||
import { Upload } from './upload'
|
||||
import { Filter } from './filter'
|
||||
|
||||
export const setup = () => {
|
||||
registerFormFields({
|
||||
@ -37,6 +38,7 @@ export const setup = () => {
|
||||
radio: Radio.Group,
|
||||
range: Range,
|
||||
rating: Rating,
|
||||
upload: Upload
|
||||
upload: Upload,
|
||||
filter: Filter,
|
||||
})
|
||||
}
|
||||
|
54
packages/app/src/components/views/Form/FilterForm.tsx
Normal file
54
packages/app/src/components/views/Form/FilterForm.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { Tooltip, Card } from 'antd';
|
||||
import {
|
||||
SchemaForm,
|
||||
SchemaMarkupField as Field,
|
||||
createFormActions,
|
||||
createAsyncFormActions,
|
||||
Submit,
|
||||
Reset,
|
||||
FormButtonGroup,
|
||||
registerFormFields,
|
||||
FormValidator,
|
||||
setValidationLanguage,
|
||||
} from '@formily/antd';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
export function FilterForm(props: any) {
|
||||
const actions = createAsyncFormActions();
|
||||
const { title, fields: properties ={} } = props.schema||{};
|
||||
return (
|
||||
<SchemaForm
|
||||
colon={true}
|
||||
layout={'vertical'}
|
||||
initialValues={{}}
|
||||
actions={actions}
|
||||
schema={{
|
||||
type: 'object',
|
||||
properties,
|
||||
}}
|
||||
expressionScope={{
|
||||
text(...args: any[]) {
|
||||
return React.createElement('span', {}, ...args)
|
||||
},
|
||||
tooltip(title: string, offset = 3) {
|
||||
return (
|
||||
<Tooltip title={title}>
|
||||
<QuestionCircleOutlined
|
||||
style={{ margin: '0 3px', cursor: 'default', marginLeft: offset }}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
}}
|
||||
>
|
||||
<FormButtonGroup>
|
||||
<Reset>取消</Reset>
|
||||
<Submit onClick={async () => {
|
||||
const { values = {} } = await actions.submit();
|
||||
console.log(values);
|
||||
}}>确定</Submit>
|
||||
</FormButtonGroup>
|
||||
</SchemaForm>
|
||||
);
|
||||
}
|
@ -19,3 +19,4 @@ setValidationLanguage('zh-CN');
|
||||
|
||||
export { Form } from './Form';
|
||||
export { DrawerForm } from './DrawerForm';
|
||||
export { FilterForm } from './FilterForm';
|
||||
|
@ -5,7 +5,7 @@ import { useRequest } from 'umi';
|
||||
import { Spin } from '@nocobase/client';
|
||||
import { SimpleTable } from './SimpleTable';
|
||||
import { Table } from './Table';
|
||||
import { Form, DrawerForm } from './Form/index';
|
||||
import { Form, DrawerForm, FilterForm } from './Form/index';
|
||||
import { Details } from './Details';
|
||||
import './style.less';
|
||||
import { Login } from './Form/Login';
|
||||
@ -21,6 +21,7 @@ export function getViewTemplate(template: string) {
|
||||
return TEMPLATES.get(template);
|
||||
}
|
||||
|
||||
registerView('FilterForm', FilterForm)
|
||||
registerView('DrawerForm', DrawerForm);
|
||||
registerView('PermissionForm', DrawerForm);
|
||||
registerView('Form', Form);
|
||||
|
@ -21,10 +21,11 @@ const transforms = {
|
||||
const mode = get(ctx.action.params, ['values', 'mode'], ctx.action.params.mode);
|
||||
const schema = {};
|
||||
for (const field of fields) {
|
||||
if (!get(field.component, 'showInForm')) {
|
||||
if (!field.get('component.showInForm')) {
|
||||
continue;
|
||||
}
|
||||
const type = get(field.component, 'type', 'string');
|
||||
const interfaceType = field.get('interface');
|
||||
const type = field.get('component.type') || 'string';
|
||||
const prop: any = {
|
||||
type,
|
||||
title: field.title||field.name,
|
||||
@ -40,7 +41,7 @@ const transforms = {
|
||||
if (defaultValue) {
|
||||
prop.default = defaultValue;
|
||||
}
|
||||
if (['radio', 'select', 'checkboxes'].includes(type)) {
|
||||
if (['radio', 'select', 'checkboxes'].includes(interfaceType)) {
|
||||
prop.enum = get(field.options, 'dataSource', []);
|
||||
}
|
||||
schema[field.name] = {
|
||||
@ -62,12 +63,23 @@ const transforms = {
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
filter: async (fields: Model[], ctx?: any) => {
|
||||
const properties = {
|
||||
filter: {
|
||||
type: 'filter',
|
||||
'x-component-props': {
|
||||
fields,
|
||||
},
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
},
|
||||
};
|
||||
|
||||
export default async (ctx, next) => {
|
||||
const { resourceName, resourceKey } = ctx.action.params;
|
||||
const [View, Field, Action] = ctx.db.getModels(['views', 'fields', 'actions']) as ModelCtor<Model>[];
|
||||
const view = await View.findOne(View.parseApiJson({
|
||||
const [View, Collection, Field, Action] = ctx.db.getModels(['views', 'collections', 'fields', 'actions']) as ModelCtor<Model>[];
|
||||
let view = await View.findOne(View.parseApiJson({
|
||||
filter: {
|
||||
collection_name: resourceName,
|
||||
name: resourceKey,
|
||||
@ -76,8 +88,15 @@ export default async (ctx, next) => {
|
||||
// appends: ['actions', 'fields'],
|
||||
// },
|
||||
}));
|
||||
// console.log('getView', ctx.action.params, mode);
|
||||
const collection = await view.getCollection();
|
||||
if (!view) {
|
||||
// 如果不存在 view,新建一个
|
||||
view = new View({type: resourceKey, template: 'FilterForm'});
|
||||
}
|
||||
const collection = await Collection.findOne({
|
||||
where: {
|
||||
name: resourceName,
|
||||
},
|
||||
});
|
||||
const fields = await collection.getFields({
|
||||
where: {
|
||||
developerMode: ctx.state.developerMode,
|
||||
@ -94,9 +113,8 @@ export default async (ctx, next) => {
|
||||
['sort', 'asc'],
|
||||
]
|
||||
});
|
||||
const actionNames = view.options.actionNames||[];
|
||||
console.log(view.options);
|
||||
if (view.type === 'table') {
|
||||
const actionNames = view.get('actionNames') || [];
|
||||
if (view.get('type') === 'table') {
|
||||
const defaultTabs = await collection.getTabs({
|
||||
where: {
|
||||
default: true,
|
||||
@ -104,14 +122,21 @@ export default async (ctx, next) => {
|
||||
});
|
||||
view.setDataValue('defaultTabName', get(defaultTabs, [0, 'name']));
|
||||
}
|
||||
if (view.options.updateViewName) {
|
||||
view.setDataValue('rowViewName', view.options.updateViewName);
|
||||
if (view.get('updateViewName')) {
|
||||
view.setDataValue('rowViewName', view.get('updateViewName'));
|
||||
}
|
||||
view.setDataValue('viewCollectionName', view.collection_name);
|
||||
let title = collection.get('title');
|
||||
const mode = get(ctx.action.params, ['values', 'mode'], ctx.action.params.mode);
|
||||
if (mode === 'update') {
|
||||
title = `编辑${title}`;
|
||||
} else {
|
||||
title = `创建${title}`;
|
||||
}
|
||||
ctx.body = {
|
||||
...view.toJSON(),
|
||||
...(view.options||{}),
|
||||
ofs: fields,
|
||||
...view.get(),
|
||||
title,
|
||||
original: fields,
|
||||
fields: await (transforms[view.type]||transforms.table)(fields, ctx),
|
||||
actions: actions.filter(action => actionNames.includes(action.name)).map(action => ({
|
||||
...action.toJSON(),
|
||||
|
Loading…
Reference in New Issue
Block a user