parent
dbdb1135bc
commit
65693d0359
@ -2,6 +2,7 @@ import { Plugin } from '@nocobase/client';
|
||||
import PluginBlock from './schma-block';
|
||||
import PluginTabSearch from './schma-component/tab-search';
|
||||
import './assets/svg/index';
|
||||
import PluginSwiper from './schma-component/swiper';
|
||||
|
||||
class PluginMobileClient extends Plugin {
|
||||
async beforeLoad() {}
|
||||
@ -11,6 +12,7 @@ class PluginMobileClient extends Plugin {
|
||||
async afterAdd() {
|
||||
this.pm.add(PluginBlock);
|
||||
this.pm.add(PluginTabSearch);
|
||||
this.pm.add(PluginSwiper);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,11 @@
|
||||
import { Plugin } from '@nocobase/client';
|
||||
import { NoticeBlock, NoticeBlockInitializer } from './schema-initializer/NoticeBlockInitializer';
|
||||
import { SwiperBlock, SwiperBlockInitializer } from './schema-initializer/SwiperBlockInitializer';
|
||||
|
||||
class PluginBlock extends Plugin {
|
||||
async load() {
|
||||
this.app.addComponents({
|
||||
NoticeBlock,
|
||||
NoticeBlockInitializer,
|
||||
SwiperBlock,
|
||||
SwiperBlockInitializer,
|
||||
});
|
||||
|
||||
this.app.schemaInitializerManager.addItem('MBlockInitializers', 'dataBlocks.swiper', {
|
||||
title: 'swiper',
|
||||
name: 'swiper',
|
||||
type: 'item',
|
||||
Component: 'SwiperBlockInitializer',
|
||||
});
|
||||
this.app.schemaInitializerManager.addItem('MBlockInitializers', 'dataBlocks.notice', {
|
||||
title: 'notice',
|
||||
|
@ -12,6 +12,8 @@ export const createGridCardBlockSchema = (options, componentName) => {
|
||||
template,
|
||||
dataSource,
|
||||
settings,
|
||||
value,
|
||||
childrenSettings,
|
||||
...others
|
||||
} = options;
|
||||
const resourceName = resource || association || collection;
|
||||
@ -42,6 +44,13 @@ export const createGridCardBlockSchema = (options, componentName) => {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': componentName,
|
||||
'x-settings': childrenSettings,
|
||||
'x-component-props': {
|
||||
resourceName,
|
||||
fieldName: {
|
||||
value,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1,71 +0,0 @@
|
||||
import {
|
||||
DataBlockInitializer,
|
||||
Icon,
|
||||
css,
|
||||
useCollectionManager,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { Swiper, Toast } from 'antd-mobile';
|
||||
import { createGridCardBlockSchema } from '../schema-create/createGridCardBlockSchma';
|
||||
import { SwiperIcon } from '../../assets/svg';
|
||||
|
||||
export const SwiperBlock = () => {
|
||||
const colors = ['#ace0ff', '#bcffbd', '#e4fabd', '#ffcfac'];
|
||||
const items = colors.map((color, index) => (
|
||||
<Swiper.Item key={index}>
|
||||
<div
|
||||
className={css`
|
||||
height: 120px;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 48px;
|
||||
user-select: none;
|
||||
`}
|
||||
style={{ background: color }}
|
||||
onClick={() => {
|
||||
Toast.show(`你点击了卡片 ${index + 1}`);
|
||||
}}
|
||||
>
|
||||
{index + 1}
|
||||
</div>
|
||||
</Swiper.Item>
|
||||
));
|
||||
return (
|
||||
<Swiper loop autoplay>
|
||||
{items}
|
||||
</Swiper>
|
||||
);
|
||||
};
|
||||
|
||||
export const SwiperBlockInitializer = () => {
|
||||
const { insert } = useSchemaInitializer();
|
||||
const cm = useCollectionManager();
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
|
||||
const onCreateBlockSchema = async ({ item }) => {
|
||||
const collection = cm.getCollection(item.name);
|
||||
const schema = createGridCardBlockSchema(
|
||||
{
|
||||
collection: item.name,
|
||||
dataSource: item.dataSource,
|
||||
rowKey: collection.filterTargetKey || 'id',
|
||||
settings: 'blockSettings:gridCard',
|
||||
},
|
||||
'SwiperBlock',
|
||||
);
|
||||
insert(schema);
|
||||
};
|
||||
|
||||
return (
|
||||
<DataBlockInitializer
|
||||
{...itemConfig}
|
||||
icon={<Icon type="swiper-block" />}
|
||||
componentType={'Swiper'}
|
||||
onCreateBlockSchema={onCreateBlockSchema}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1,44 @@
|
||||
import { BlockItem, css, useDesignable, useRequest, withDynamicSchemaProps } from '@nocobase/client';
|
||||
import { useFieldSchema } from '@nocobase/schema';
|
||||
import { Swiper } from 'antd-mobile';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export const SwiperBlock = withDynamicSchemaProps((props) => {
|
||||
const { fieldValue, data, changeNav } = props;
|
||||
if (!data) return;
|
||||
const items = data['data']
|
||||
?.map((imgItem, index) => {
|
||||
return imgItem[fieldValue] ? (
|
||||
<Swiper.Item key={index}>
|
||||
<div
|
||||
className={css`
|
||||
height: 20vh;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 48px;
|
||||
user-select: none;
|
||||
`}
|
||||
style={{
|
||||
backgroundImage: `url(${imgItem[fieldValue][0].url})`,
|
||||
backgroundSize: '100% 100%',
|
||||
backgroundAttachment: 'fixed',
|
||||
}}
|
||||
onClick={() => {
|
||||
changeNav(imgItem);
|
||||
}}
|
||||
></div>
|
||||
</Swiper.Item>
|
||||
) : null;
|
||||
})
|
||||
.filter(Boolean);
|
||||
return (
|
||||
<BlockItem>
|
||||
<Swiper loop autoplay>
|
||||
{items}
|
||||
</Swiper>
|
||||
</BlockItem>
|
||||
);
|
||||
});
|
@ -0,0 +1,50 @@
|
||||
import {
|
||||
DataBlockInitializer,
|
||||
Icon,
|
||||
useCollectionManager,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { createGridCardBlockSchema } from '../../schma-block/schema-create/createGridCardBlockSchma';
|
||||
import { ISchema } from '@nocobase/schema';
|
||||
|
||||
export const SwiperBlockInitializer = () => {
|
||||
const { insert } = useSchemaInitializer();
|
||||
const cm = useCollectionManager();
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
|
||||
const onCreateBlockSchema = async ({ item }) => {
|
||||
const collection = cm.getCollection(item.name);
|
||||
const value = collection.fields.find((field) => field.interface === 'attachment');
|
||||
if (!value) return;
|
||||
const schema: ISchema = {
|
||||
type: 'void',
|
||||
name: item.name,
|
||||
title: collection.title,
|
||||
'x-decorator': 'DataBlockProvider',
|
||||
'x-decorator-props': {
|
||||
collection: item.name,
|
||||
dataSource: 'main',
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'SwiperFieldSettings',
|
||||
'x-component': 'SwiperBlock',
|
||||
'x-use-component-props': 'useSwiperBlockProps',
|
||||
'x-component-props': {
|
||||
resourceName: item.name,
|
||||
fieldValue: value.name,
|
||||
},
|
||||
};
|
||||
insert(schema);
|
||||
};
|
||||
|
||||
return (
|
||||
<DataBlockInitializer
|
||||
{...itemConfig}
|
||||
icon="swiper-block"
|
||||
componentType={'Swiper'}
|
||||
onCreateBlockSchema={onCreateBlockSchema}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1,124 @@
|
||||
import {
|
||||
SchemaSettings,
|
||||
SchemaSettingsDataScope,
|
||||
useCollection,
|
||||
useCompile,
|
||||
useDesignable,
|
||||
useFormBlockContext,
|
||||
} from '@nocobase/client';
|
||||
import { useField, useFieldSchema } from '@nocobase/schema';
|
||||
import _ from 'lodash';
|
||||
import { useTranslation } from '../../locale';
|
||||
|
||||
export const SwiperFieldSettings = new SchemaSettings({
|
||||
name: 'SwiperFieldSettings',
|
||||
items: [
|
||||
{
|
||||
name: 'setTheDataScope',
|
||||
Component: SchemaSettingsDataScope,
|
||||
useComponentProps() {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { form } = useFormBlockContext();
|
||||
const field = useField();
|
||||
const c = useCollection();
|
||||
const { dn } = useDesignable();
|
||||
return {
|
||||
collectionName: c.getOptions().name,
|
||||
defaultFilter: fieldSchema?.['x-component-props']?.params?.filter || {},
|
||||
form: form,
|
||||
onSubmit: ({ filter }) => {
|
||||
_.set(field.componentProps, 'params', {
|
||||
...field.componentProps?.params,
|
||||
filter,
|
||||
});
|
||||
fieldSchema['x-component-props']['params'] = field.componentProps.params;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
'x-component-props': fieldSchema['x-component-props'],
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setShowField',
|
||||
type: 'select',
|
||||
useComponentProps() {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { t } = useTranslation();
|
||||
const c = useCollection();
|
||||
const compile = useCompile();
|
||||
const { dn } = useDesignable();
|
||||
const options = c.fields
|
||||
.map((field) => {
|
||||
if (field?.interface === 'attachment') {
|
||||
return {
|
||||
label: compile(field.uiSchema?.title) || field.name,
|
||||
value: field.name,
|
||||
};
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
const onChange = (label) => {
|
||||
const schema = {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
};
|
||||
fieldSchema['x-component-props']['fieldValue'] = label;
|
||||
schema['x-component-props'] = fieldSchema['x-component-props'];
|
||||
dn.emit('patch', {
|
||||
schema,
|
||||
});
|
||||
dn.refresh();
|
||||
};
|
||||
return {
|
||||
title: t('SetShowfield'),
|
||||
options,
|
||||
value: fieldSchema['x-component-props'].fieldValue,
|
||||
onChange,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setFieldCount',
|
||||
type: 'select',
|
||||
useComponentProps() {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { dn } = useDesignable();
|
||||
const options = [];
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
options.push({
|
||||
label: i,
|
||||
value: i,
|
||||
});
|
||||
}
|
||||
const onChange = (value) => {
|
||||
fieldSchema['x-component-props']['pageSize'] = value;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
['x-component-props']: fieldSchema['x-component-props'],
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
};
|
||||
return {
|
||||
title: 'setFieldCount',
|
||||
options,
|
||||
value: fieldSchema['x-component-props'].pageSize || 5,
|
||||
onChange,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
type: 'remove',
|
||||
sort: 100,
|
||||
},
|
||||
],
|
||||
});
|
@ -0,0 +1,22 @@
|
||||
import {
|
||||
CollectionRecordProvider,
|
||||
DataBlockProvider,
|
||||
RemoteSchemaComponent,
|
||||
useCollectionRecord,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
export const SwiperPage = () => {
|
||||
const params = useParams();
|
||||
const { name, collection, field, fieldParams } = params;
|
||||
const record = {};
|
||||
record[field] = fieldParams;
|
||||
return (
|
||||
<DataBlockProvider collection={collection} dataSource="main">
|
||||
<CollectionRecordProvider record={record} parentRecord={null}>
|
||||
<RemoteSchemaComponent uid={name} />
|
||||
</CollectionRecordProvider>
|
||||
</DataBlockProvider>
|
||||
);
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
import { Plugin } from '@nocobase/client';
|
||||
import { SwiperBlockInitializer } from './SwiperBlockInitializer';
|
||||
import { SwiperBlock } from './SwiperBlock';
|
||||
import { SwiperFieldSettings } from './SwiperFieldSettings';
|
||||
import { useSwiperBlockProps } from './useSwiperBlockProps';
|
||||
import { SwiperPage } from './SwiperPage';
|
||||
|
||||
class PluginSwiper extends Plugin {
|
||||
async load() {
|
||||
this.app.addScopes({
|
||||
useSwiperBlockProps,
|
||||
});
|
||||
this.app.addComponents({
|
||||
SwiperBlockInitializer,
|
||||
SwiperBlock,
|
||||
SwiperPage,
|
||||
});
|
||||
|
||||
this.app.schemaInitializerManager.addItem('mobilePage:addBlock', 'dataBlocks.swiper', {
|
||||
title: 'swiper',
|
||||
name: 'swiper',
|
||||
type: 'item',
|
||||
Component: 'SwiperBlockInitializer',
|
||||
});
|
||||
this.app.schemaSettingsManager.add(SwiperFieldSettings);
|
||||
this.app.router.add('mobile.swiper.page', {
|
||||
path: '/mobile/:name/image/:collection/:field/:fieldParams',
|
||||
Component: 'SwiperPage',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default PluginSwiper;
|
@ -0,0 +1,86 @@
|
||||
import { useFieldSchema } from '@nocobase/schema';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useCollection, useDesignable, useRequest } from '@nocobase/client';
|
||||
|
||||
export const useSwiperBlockProps = () => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const navigate = useNavigate();
|
||||
const properties = fieldSchema.properties ? Object.values(fieldSchema.properties) : null;
|
||||
const { insertAdjacent } = useDesignable();
|
||||
const collection = useCollection();
|
||||
const field = collection.targetKey || 'id';
|
||||
const { filter, pageSize, fieldValue, resourceName } = fieldSchema['x-component-props'];
|
||||
const { data, run } = useRequest({
|
||||
resource: resourceName + ':list',
|
||||
params: {
|
||||
filter,
|
||||
pageSize: pageSize || 5,
|
||||
appends: fieldValue ? [fieldValue] : [],
|
||||
},
|
||||
});
|
||||
useEffect(() => {
|
||||
run();
|
||||
}, [filter, pageSize, fieldValue]);
|
||||
const changeNav = (imgItem) => {
|
||||
if (imgItem['isIdentical']) {
|
||||
const existence = properties?.find((value) => value['x-component-props']['fixedComponent']);
|
||||
if (existence) {
|
||||
navigate(`/mobile/${existence['x-uid']}/image/${resourceName}/${field}/${imgItem[field]}`);
|
||||
} else {
|
||||
insertAdjacent('beforeEnd', swiperCustomPage(imgItem, 'fixedComponent'), {
|
||||
onSuccess(res) {
|
||||
if (res) {
|
||||
navigate(`/mobile/${res['x-uid']}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const existence = properties?.find((value) => value.name === String(imgItem.id));
|
||||
if (existence) {
|
||||
navigate(`/mobile/${existence['x-uid']}`);
|
||||
} else {
|
||||
insertAdjacent('beforeEnd', swiperCustomPage(imgItem), {
|
||||
onSuccess(res) {
|
||||
if (res) {
|
||||
navigate(`/mobile/${res['x-uid']}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
data,
|
||||
fieldValue,
|
||||
changeNav,
|
||||
};
|
||||
};
|
||||
|
||||
const swiperCustomPage = (imgItem, fixedComponent?) => {
|
||||
return {
|
||||
type: 'void',
|
||||
title: imgItem.title,
|
||||
name: imgItem.id,
|
||||
'x-component': 'MMenu.Item',
|
||||
'x-component-props': { imgItem, fixedComponent },
|
||||
'x-designer': 'MMenu.Item.Designer',
|
||||
properties: {
|
||||
page: {
|
||||
type: 'void',
|
||||
'x-component': 'MPage',
|
||||
'x-designer': 'MPage.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'mobilePage:addBlock',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
@ -16,7 +16,7 @@ const textFieldsItem: SchemaInitializerItemType<any> = {
|
||||
const itemComponent = isMobield ? 'TabSearchCollapsibleInputMItem' : 'TabSearchCollapsibleInputItem';
|
||||
const children = associatedFields
|
||||
.map((field) => {
|
||||
if (canBeSearchField(field.interface) && !field['isForeignKey']) {
|
||||
if (canBeSearchField(field.interface) || (canBeOptionalField(field.interface) && !field['isForeignKey'])) {
|
||||
const label = field.name;
|
||||
return createTabSearchItemSchema({ field, itemComponent, label });
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ const canBeSearchFields = [
|
||||
'color',
|
||||
'icon',
|
||||
'formula',
|
||||
'sequence',
|
||||
];
|
||||
|
||||
export const isTabSearchCollapsibleInputItem = (component: string) =>
|
||||
|
5319
pnpm-lock.yaml
5319
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user