umi#useModel TypeScript Examples
The following examples show how to use
umi#useModel.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BaseConfig.tsx From scorpio-h5-design with MIT License | 6 votes |
App = () => {
const { pageSchema, selectComponent, setStateByObjectKeys } = useModel('bridge');
// @ts-expect-error
const form = useForm(selectComponent?.containerProps ?? {});
return (
<FormRender
form={form}
schema={componentBaseConfig}
displayType="row"
onFinish={() => { console.log(); }}
/>
);
}
Example #2
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function() {
const { setStateByObjectKeys, selectPage } = useModel('bridge');
useEffect(()=>{
const handshake = new Postmate.Model({
[childrenModel.SYNC_STATE]: (message: any)=>{
setStateByObjectKeys(message, false);
},
[childrenModel.CAPTURE]: async()=>{
const captureDom = window.document.getElementById('snapshot-container');
if(captureDom){
const canvas = await html2canvas(captureDom, {
useCORS: true,
scale: 1,
});
return canvas.toDataURL('image/png');
}
},
});
handshake.then((parent) => {
window.postmate_parent = parent;
});
}, []);
return (
<div
className="h5-canvas"
style={{backgroundColor: selectPage?.props?.backgroundColor}}
>
<div id="snapshot-container">
<DragContainer />
</div>
</div>
);
}
Example #3
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function() {
const { pageSchema, setStateByObjectKeys, selectComponent } = useModel('bridge');
const form = useForm();
useEffect(() => {
form.setValues(pageSchema[0].components[0].props || {});
}, [pageSchema[0].components[0].props]);
const watch = {
'#': (values: any) => {
pageSchema[0].components[0].props = values;
setStateByObjectKeys({
pageSchema: [...pageSchema],
});
},
};
return (
<div className="manage-component-detail-form">
<FormRenderWithWidgets
form={form}
watch={watch}
{...selectComponent.generatorSchema}
/>
</div>
);
}
Example #4
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function() {
const { selectComponent, selectPage } = useModel('bridge');
return (
<Tabs defaultActiveKey="componentConfig" type="card" className="config-tabs">
<TabPane tab="页面配置" key="pageConfig">
{selectPage ? <PageConfig /> : <Empty description="请新建一个页面后配置" /> }
</TabPane>
<TabPane tab="组件配置" key="componentConfig">
{selectComponent ? <ComponentConfig /> : <Empty description="请选取组件后配置组件" /> }
</TabPane>
<TabPane tab="外层容器配置" key="containerConfig">
{selectComponent ? <BaseLayoutConfig /> : <Empty description="请选取组件后配置外层容器" /> }
</TabPane>
<TabPane tab="事件" key="3">
开发中...
</TabPane>
</Tabs>
);
}
Example #5
Source File: PageConfig.tsx From scorpio-h5-design with MIT License | 6 votes |
App = () => {
const { pageSchema, setStateByObjectKeys, selectPage } = useModel('bridge');
const form = useForm();
const { generatorSchema, props } = selectPage;
useEffect(() => {
form.setValues(props);
}, [props]);
const watch = {
'#': (values: any) => {
selectPage.props = values;
setStateByObjectKeys({
pageSchema: [...pageSchema],
});
},
};
return (
<FormRenderWithWidgets
form={form}
watch={watch}
{...generatorSchema}
/>
);
}
Example #6
Source File: ComponentConfig.tsx From scorpio-h5-design with MIT License | 6 votes |
App = () => {
const { pageSchema, selectComponent, setStateByObjectKeys } = useModel('bridge');
const component = selectComponent as IComponentSchema;
const { generatorSchema, props } = component;
const form = useForm();
useEffect(() => {
form.setValues(props);
}, [props]);
const watch = {
'#': (values: any) => {
component.props = values;
setStateByObjectKeys({
pageSchema: [...pageSchema],
});
},
};
return (
// @ts-expect-error
<FormRenderWithWidgets
form={form}
watch={watch}
{...generatorSchema}
/>
);
}
Example #7
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function() {
const { openCreatePageDrawer } = useModel('page');
const { pageSchema, selectPageIndex } = useModel('bridge');
return (
<div className="page">
{
pageSchema.length === 0 ? (
<>
<div className="page-empty">
<div className="page-empty-center">
<Empty description="请先创建一个页面吧" />
<Button type="primary" className="page-empty-new-btn" onClick={openCreatePageDrawer}>新增页面</Button>
</div>
</div>
</>
) : (
pageSchema.map((item, index)=>(
<div
key={item.props.path}
className={classnames('page-card', {select: selectPageIndex === index})}
>
<img
className="page-card-cover"
src={item.coverSnapshot ?? item.cover ?? 'https://carpooling-1256959311.cos.ap-chengdu.myqcloud.com/d6bc039b-04ea-49ca-8ee9-a006aec7c443.png'}
/>
<div className="title">{item.props.title}</div>
</div>
))
)
}
<CreatePage />
<PageConfig />
</div>
);
}
Example #8
Source File: index.tsx From ant-design-pro-V5-multitab with MIT License | 6 votes |
SortableList = SortableContainer(() => {
const tabsRef = useRef<any>()
const { tabList, tarnslateX } = useModel("system");
return (
<div className={`${styles.tabList}`} ref={tabsRef} >
{/* <div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}> */}
<div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}>
{
tabList.map((value, index: number) => (
<Tab key={`item-${index}`} index={index} value={value} tabIndex={index} />
))
}
</div>
</div >
);
})
Example #9
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function(props:IProps) {
const ref = useRef<HTMLDivElement>(null);
const size = useSize(ref);
const { setStateByObjectKeys } = useModel('bridge');
useEffect(()=>{
if(history.location.pathname === '/manage/component/detail' && !props.loading){
setStateByObjectKeys({
showSelectComponentBorder: false,
});
}
}, [props.loading]);
return (
<div className="mobile-simulator-container">
{(history.location.pathname !== '/manage/component/detail' && !props.loading) && <SelectArea size={size} loading={props.loading}/>}
<div className="mobile-simulator">
<div className="mobile-head-bar"></div>
<div className="mobile-content" id="mobile-content" ref={ref} />
</div>
</div>
);
}
Example #10
Source File: index.tsx From scorpio-h5-design with MIT License | 6 votes |
export default function Font() {
const { selectComponent, changeContainerPropsState } = useModel('bridge');
const { color, fontSize, fontWeight } = selectComponent?.containerProps ?? {};
return (
<Descriptions column={1}>
<Descriptions.Item label="颜色">
<div className="font-color-input">
<ColorPicker onChange={(value: string) => { changeContainerPropsState('color', value); }} value={color ?? '#fff'} />
</div>
</Descriptions.Item>
<Descriptions.Item label="字号">
<div className="font-size-weight">
<Select
value={fontWeight ?? 100}
style={{ width: 120 }}
onChange={(value) => { changeContainerPropsState('fontWeight', value); }}
>
<Select.Option value={100}>普通</Select.Option>
<Select.Option value={800}>粗体</Select.Option>
</Select>
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => Number((value ?? '').replace('px', ''))}
value={fontSize ?? 30}
onChange={(value) => { changeContainerPropsState('fontSize', value); }}
/>
</div>
</Descriptions.Item>
</Descriptions>
);
}
Example #11
Source File: AvatarDropdown.tsx From anew-server with MIT License | 5 votes |
AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
const { initialState, setInitialState } = useModel('@@initialState');
const onMenuClick = useCallback(
(event: MenuInfo) => {
const { key } = event;
if (key === 'logout' && initialState) {
setInitialState({ ...initialState, currentUser: undefined });
loginOut();
return;
}
history.push('/account/settings');
},
[initialState, setInitialState],
);
const loading = (
<span className={`${styles.action} ${styles.account}`}>
<Spin
size="small"
style={{
marginLeft: 8,
marginRight: 8,
}}
/>
</span>
);
if (!initialState) {
return loading;
}
const { currentUser } = initialState;
if (!currentUser || !currentUser.name) {
return loading;
}
const menuHeaderDropdown = (
<Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
{menu && (
<Menu.Item key="settings">
<SettingOutlined />
个人设置
</Menu.Item>
)}
{menu && <Menu.Divider />}
<Menu.Item key="logout">
<LogoutOutlined />
退出登录
</Menu.Item>
</Menu>
);
return (
<HeaderDropdown overlay={menuHeaderDropdown}>
<span className={`${styles.action} ${styles.account}`}>
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
<span className={`${styles.name} anticon`}>{currentUser.name}</span>
</span>
</HeaderDropdown>
);
}
Example #12
Source File: index.tsx From anew-server with MIT License | 5 votes |
NoticeIconView = () => {
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || {};
const [notices, setNotices] = useState<API.NoticeIconItem[]>([]);
useEffect(() => {
getNotices().then(({ data }) => setNotices(data || []));
}, []);
const noticeData = getNoticeData(notices);
const unreadMsg = getUnreadData(noticeData || {});
const changeReadState = (id: string) => {
setNotices(
notices.map((item) => {
const notice = { ...item };
if (notice.id === id) {
notice.read = true;
}
return notice;
}),
);
};
const clearReadState = (title: string, key: string) => {
setNotices(
notices.map((item) => {
const notice = { ...item };
if (notice.type === key) {
notice.read = true;
}
return notice;
}),
);
message.success(`${'清空了'} ${title}`);
};
return (
<NoticeIcon
className={styles.action}
count={currentUser && currentUser.unreadCount}
onItemClick={(item) => {
changeReadState(item.id!);
}}
onClear={(title: string, key: string) => clearReadState(title, key)}
loading={false}
clearText="清空"
viewMoreText="查看更多"
onViewMore={() => message.info('Click on view more')}
clearClose
>
<NoticeIcon.Tab
tabKey="notification"
count={unreadMsg.notification}
list={noticeData.notification}
title="通知"
emptyText="你已查看所有通知"
showViewMore
/>
<NoticeIcon.Tab
tabKey="message"
count={unreadMsg.message}
list={noticeData.message}
title="消息"
emptyText="您已读完所有消息"
showViewMore
/>
<NoticeIcon.Tab
tabKey="event"
title="待办"
emptyText="你已完成所有待办"
count={unreadMsg.event}
list={noticeData.event}
showViewMore
/>
</NoticeIcon>
);
}
Example #13
Source File: index.tsx From ant-design-pro-V5-multitab with MIT License | 5 votes |
GlobalHeaderRight: React.FC = () => {
const { initialState } = useModel('@@initialState');
if (!initialState || !initialState.settings) {
return null;
}
const { navTheme, layout } = initialState.settings;
let className = styles.right;
if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
className = `${styles.right} ${styles.dark}`;
}
return (
<Space className={className}>
<HeaderSearch
className={`${styles.action} ${styles.search}`}
placeholder="站内搜索"
defaultValue="umi ui"
options={[
{ label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
{
label: <a href="next.ant.design">Ant Design</a>,
value: 'Ant Design',
},
{
label: <a href="https://protable.ant.design/">Pro Table</a>,
value: 'Pro Table',
},
{
label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
value: 'Pro Layout',
},
]}
// onSearch={value => {
// console.log('input', value);
// }}
/>
<HeaderDropdown
overlay={
<Menu>
<Menu.Item
onClick={() => {
window.open('/~docs');
}}
>
组件文档
</Menu.Item>
<Menu.Item
onClick={() => {
window.open('https://pro.ant.design/docs/getting-started');
}}
>
Ant Design Pro 文档
</Menu.Item>
</Menu>
}
>
<span className={styles.action}>
<QuestionCircleOutlined />
</span>
</HeaderDropdown>
<Avatar />
{REACT_APP_ENV && (
<span>
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
</span>
)}
<SelectLang className={styles.action} />
</Space>
);
}
Example #14
Source File: index.tsx From anew-server with MIT License | 5 votes |
GlobalHeaderRight: React.FC = () => {
const { initialState } = useModel('@@initialState');
if (!initialState || !initialState.settings) {
return null;
}
const { navTheme, layout } = initialState.settings;
let className = styles.right;
if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
className = `${styles.right} ${styles.dark}`;
}
return (
<Space className={className}>
<HeaderSearch
className={`${styles.action} ${styles.search}`}
placeholder="站内搜索"
defaultValue="umi ui"
options={[
{
label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>,
value: 'umi ui',
},
{
label: <a href="next.ant.design">Ant Design</a>,
value: 'Ant Design',
},
{
label: <a href="https://protable.ant.design/">Pro Table</a>,
value: 'Pro Table',
},
{
label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
value: 'Pro Layout',
},
]} // onSearch={value => {
// console.log('input', value);
// }}
/>
<span
className={styles.action}
onClick={() => {
window.open('https://pro.ant.design/docs/getting-started');
}}
>
<QuestionCircleOutlined />
</span>
{/* <NoticeIconView /> */}
<Avatar menu />
</Space>
);
}
Example #15
Source File: AvatarDropdown.tsx From ant-design-pro-V5-multitab with MIT License | 5 votes |
AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
const { initialState, setInitialState } = useModel('@@initialState');
const onMenuClick = useCallback(
(event: {
key: React.Key;
keyPath: React.Key[];
item: React.ReactInstance;
domEvent: React.MouseEvent<HTMLElement>;
}) => {
const { key } = event;
if (key === 'logout' && initialState) {
setInitialState({ ...initialState, currentUser: undefined });
loginOut();
return;
}
history.push(`/account/${key}`);
},
[initialState, setInitialState],
);
const loading = (
<span className={`${styles.action} ${styles.account}`}>
<Spin
size="small"
style={{
marginLeft: 8,
marginRight: 8,
}}
/>
</span>
);
if (!initialState) {
return loading;
}
const { currentUser } = initialState;
if (!currentUser || !currentUser.name) {
return loading;
}
const menuHeaderDropdown = (
<Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
{menu && (
<Menu.Item key="center">
<UserOutlined />
个人中心
</Menu.Item>
)}
{menu && (
<Menu.Item key="settings">
<SettingOutlined />
个人设置
</Menu.Item>
)}
{menu && <Menu.Divider />}
<Menu.Item key="logout">
<LogoutOutlined />
退出登录
</Menu.Item>
</Menu>
);
return (
<HeaderDropdown overlay={menuHeaderDropdown}>
<span className={`${styles.action} ${styles.account}`}>
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
<span className={`${styles.name} anticon`}>{currentUser.name}</span>
</span>
</HeaderDropdown>
);
}
Example #16
Source File: BaseForm.tsx From anew-server with MIT License | 5 votes |
BaseForm: React.FC<BaseFormProps> = (props) => {
const { values } = props;
const { initialState, setInitialState } = useModel('@@initialState');
return (
<ProForm
onFinish={async (v: API.UserInfo) => {
await updateUserInfo(v, values?.id).then((res) => {
if (res.code === 200 && res.status === true) {
message.success(res.message);
let userInfo = {};
Object.assign(userInfo, initialState?.currentUser);
(userInfo as API.UserInfo).name = v.name;
(userInfo as API.UserInfo).mobile = v.mobile;
(userInfo as API.UserInfo).email = v.email
setInitialState({ ...initialState, currentUser: userInfo as API.UserInfo });
}
});
}}
>
<ProForm.Group>
<ProFormText
name="name"
label="姓名"
width="md"
rules={[{ required: true }]}
initialValue={values?.name}
/>
<ProFormText
name="mobile"
label="手机"
width="md"
rules={[
{
pattern: /^1(?:70\d|(?:9[89]|8[0-24-9]|7[135-8]|66|5[0-35-9])\d|3(?:4[0-8]|[0-35-9]\d))\d{7}$/,
message: '请输入正确的手机号码',
},
]}
initialValue={values?.mobile}
/>
<ProFormText
name="email"
label="邮箱"
width="md"
rules={[
{
type: 'email',
message: '请输入正确的邮箱地址',
},
]}
initialValue={values?.email}
/>
</ProForm.Group>
</ProForm>
);
}
Example #17
Source File: CreateForm.tsx From anew-server with MIT License | 5 votes |
CreateForm: React.FC<CreateFormProps> = (props) => {
const { actionRef, modalVisible, handleChange } = props;
const [treeData, setTreeData] = useState<API.DictList[]>([]);
const { initialState, setInitialState } = useModel('@@initialState');
useEffect(() => {
queryDicts().then((res) => {
const top: API.DictList = { id: 0, dict_value: '暂无所属', dict_key: '' };
res.data.unshift(top)
const dicts = loopTreeItem(res.data);
setTreeData(dicts);
});
}, []);
return (
<ModalForm
title="新建字典"
visible={modalVisible}
onVisibleChange={handleChange}
onFinish={async (v) => {
createDict(v as API.DictParams).then((res) => {
if (res.code === 200 && res.status === true) {
message.success(res.message);
queryDictsByAllType().then((res) => setInitialState({ ...initialState, DictObj: res.data }));
if (actionRef.current) {
actionRef.current.reload();
}
}
});
return true;
}}
>
<ProForm.Group>
<ProFormText name="dict_key" label="字典标签" width="md" rules={[{ required: true }]} />
<ProFormText name="dict_value" label="字典键值" width="md" rules={[{ required: true }]} />
</ProForm.Group>
<ProForm.Group>
<ProFormDigit name="sort" label="排序" width="md" fieldProps={{ precision: 0 }} />
<ProFormText name="desc" label="说明" width="md" />
</ProForm.Group>
<ProForm.Group>
<Form.Item label="上级字典" name="parent_id">
<TreeSelect
style={{ width: 330 }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={treeData}
placeholder="请选择字典"
/>
</Form.Item>
</ProForm.Group>
</ModalForm >
);
}
Example #18
Source File: index.tsx From ant-design-pro-V5-multitab with MIT License | 5 votes |
NoticeIconView = () => {
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || {};
const [notices, setNotices] = useState<API.NoticeIconData[]>([]);
useEffect(() => {
queryNotices().then(({ data }) => setNotices(data));
}, []);
const noticeData = getNoticeData(notices);
const unreadMsg = getUnreadData(noticeData || {});
const changeReadState = (id: string) => {
setNotices(
notices.map((item) => {
const notice = { ...item };
if (notice.id === id) {
notice.read = true;
}
return notice;
}),
);
};
const clearReadState = (title: string, key: string) => {
setNotices(
notices.map((item) => {
const notice = { ...item };
if (notice.type === key) {
notice.read = true;
}
return notice;
}),
);
message.success(`${'清空了'} ${title}`);
};
return (
<NoticeIcon
className={styles.action}
count={currentUser && currentUser.unreadCount}
onItemClick={(item) => {
changeReadState(item.id);
}}
onClear={(title: string, key: string) => clearReadState(title, key)}
loading={false}
clearText="清空"
viewMoreText="查看更多"
onViewMore={() => message.info('Click on view more')}
clearClose
>
<NoticeIcon.Tab
tabKey="notification"
count={unreadMsg.notification}
list={noticeData.notification}
title="通知"
emptyText="你已查看所有通知"
showViewMore
/>
<NoticeIcon.Tab
tabKey="message"
count={unreadMsg.message}
list={noticeData.message}
title="消息"
emptyText="您已读完所有消息"
showViewMore
/>
<NoticeIcon.Tab
tabKey="event"
title="待办"
emptyText="你已完成所有待办"
count={unreadMsg.event}
list={noticeData.event}
showViewMore
/>
</NoticeIcon>
);
}
Example #19
Source File: index.tsx From ant-design-pro-V5-multitab with MIT License | 5 votes |
export default function KeepAlivePage(props: any) {
const intl = useIntl()
const { dispatch, tabList, showTabs, tarnslateX, tabsWidth, tabWidth } = useModel("system")
useEffect(() => {
// 去重
const localTablist = JSON.parse(JSON.stringify(tabList));
const isExit = localTablist.findIndex((item: any) => item.pathname === props.location.pathname);
// 需要计算translateX
if (isExit < 0) {
const obj = { ...props.location, title: intl.formatMessage({ id: props.route.keepAliveName }), keepAliveName: props.route.keepAliveName }
localTablist.push(obj);
let x = 0;
if (localTablist.length >= showTabs) {
const isBeyondDistance = ((showTabs as number) * (tabWidth as number)) - (tabsWidth as number) + 100;
x = isBeyondDistance + (localTablist.length - showTabs) * tabWidth
}
dispatch({ type: 'CHANGESTATE', payload: { tabList: localTablist, active: localTablist.length - 1, tarnslateX: x } });
} else {
const isBeyondDistance = ((showTabs as number) * (tabWidth as number)) - (tabsWidth as number) + 100;
const curClickIndex = tabList.findIndex(item => item.pathname === props.location.pathname) as number;
// 能展示多少个
const totalShowIndex = (showTabs as number) - 1;
if (curClickIndex > totalShowIndex) {
// 计算移动的距离
const x = (curClickIndex - totalShowIndex) * (tabWidth as number) + isBeyondDistance
dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: x, active: isExit } })
} else {
// 计算隐藏了多少个
const transNum = Math.ceil(tarnslateX / tabWidth);
if (isExit < transNum) {
dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: tabWidth * curClickIndex, active: isExit } })
} else {
dispatch({ type: 'CHANGESTATE', payload: { active: isExit } })
}
}
}
}, [])
if (props.route.keppAlive) {
return (
<KeepAlive saveScrollPosition={props.route.saveScrollPosition ?? "screen"} name={props.route.keepAliveName}>
{props.children}
</KeepAlive>
)
}
return props.children
}
Example #20
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function Background() {
const { selectComponent, changeContainerPropsState } = useModel('bridge');
const { backgroundImage, backgroundColor, backgroundSize, backgroundRepeat } = selectComponent?.containerProps ?? {};
const [backgroundFillType, setBackgroundFillType] = useState(FILL_TYPE.color);
return (
<Descriptions column={1}>
<Descriptions.Item label="填充">
<div className="background">
<Radio.Group
size="small"
options={[
{ label: '颜色填充', value: FILL_TYPE.color },
{ label: '背景图片', value: FILL_TYPE.image },
]}
onChange={(e) => { setBackgroundFillType(e.target.value); }}
value={backgroundFillType}
optionType="button"
buttonStyle="solid"
/>
</div>
</Descriptions.Item>
{backgroundFillType === FILL_TYPE.color && (
<Descriptions.Item label="填充颜色">
<ColorPicker
className="background-color"
onChange={(value: string) => { changeContainerPropsState('backgroundColor', value); }}
value={backgroundColor}
/>
</Descriptions.Item>
)}
{backgroundFillType === FILL_TYPE.image && (
<>
<Descriptions.Item label="图片">
<ImageUpload
value={backgroundImage}
onChange={(value) => { changeContainerPropsState('backgroundImage', value); }}
/>
</Descriptions.Item>
<Descriptions.Item label="尺寸">
<Radio.Group
style={{ marginTop: 4 }}
size="small"
options={[
{ label: '默认', value: 'initial' },
{ label: '充满', value: '100% 100%' },
{ label: '等比填充', value: 'contain' },
{ label: '等比覆盖', value: 'cover' },
]}
onChange={(e) => { changeContainerPropsState('backgroundSize', e.target.value); }}
value={backgroundSize ?? 'initial'}
optionType="button"
buttonStyle="solid"
/>
</Descriptions.Item>
<Descriptions.Item label="重复">
<Radio.Group
style={{ marginTop: 4 }}
size="small"
options={[
{ label: '默认', value: 'initial' },
{ label: '水平重复', value: 'repeat-x' },
{ label: '垂直重复', value: 'repeat-y' },
{ label: '不重复', value: 'no-repeat' },
]}
onChange={(e) => { changeContainerPropsState('backgroundRepeat', e.target.value); }}
value={backgroundRepeat ?? 'initial'}
optionType="button"
buttonStyle="solid"
/>
</Descriptions.Item>
</>
)}
</Descriptions>
);
}
Example #21
Source File: index.tsx From plugin-layout with MIT License | 5 votes |
BasicLayout = (props: any) => {
const { children, userConfig, location } = props;
const { initialState, loading } = (useModel && useModel('@@initialState')) || {
initialState: undefined,
loading: false,
}; // plugin-initial-state 未开启
const _routes = require('@@/router').routes;
const rightContentRender = useRightContent(userConfig, loading, initialState);
const layoutConfig = getLayoutConfigFromRoute(_routes);
const patchMenus: (ms: MenuItem[]) => MenuItem[] =
userConfig.patchMenus || ((ms: MenuItem[]): MenuItem[] => ms);
const menus = patchMenus(getMenuDataFromRoutes(_routes[0].routes));
// layout 是否渲染相关
const pathName = location.pathname;
const layoutRender: any = {};
// 动态路由匹配
const currentMatchPaths = Object.keys(layoutConfig).filter(item =>
pathToRegexp(`${item}(.*)`).test(pathName),
);
const currentPathConfig = currentMatchPaths.length
? layoutConfig[currentMatchPaths[currentMatchPaths.length - 1]]
: undefined;
if (currentPathConfig && currentPathConfig.hideMenu) {
layoutRender.menuRender = false;
}
if (currentPathConfig && currentPathConfig.hideNav) {
layoutRender.headerRender = false;
}
return (
<ProLayout
title={userConfig.name || userConfig.title}
className="umi-plugin-layout-main"
navTheme="dark"
siderWidth={256}
onMenuHeaderClick={e => {
e.stopPropagation();
e.preventDefault();
history.push('/');
}}
menu={{ locale: userConfig.locale }}
menuDataRender={() => menus}
formatMessage={formatMessage}
logo={initialState?.avatar || logo}
menuItemRender={(menuItemProps, defaultDom) => {
if (menuItemProps.isUrl || menuItemProps.children) {
return defaultDom;
}
return <Link to={menuItemProps.path || ''}>{defaultDom}</Link>;
}}
disableContentMargin
rightContentRender={rightContentRender}
fixSiderbar
fixedHeader
{...userConfig}
{...props}
{...layoutRender}
>
<ErrorBoundary>
<WithExceptionOpChildren currentPathConfig={currentPathConfig}>
{userConfig.childrenRender
? userConfig.childrenRender(children)
: children}
</WithExceptionOpChildren>
</ErrorBoundary>
</ProLayout>
);
}
Example #22
Source File: UpdateForm.tsx From anew-server with MIT License | 5 votes |
UpdateForm: React.FC<UpdateFormProps> = (props) => {
const { actionRef, modalVisible, handleChange, values } = props;
const [treeData, setTreeData] = useState<API.DictList[]>([]);
const { initialState, setInitialState } = useModel('@@initialState');
useEffect(() => {
queryDicts().then((res) => {
const top: API.DictList = { id: 0, dict_value: '暂无所属', dict_key: '' };
res.data.unshift(top)
const dicts = loopTreeItem(res.data);
setTreeData(dicts);
});
}, []);
return (
<ModalForm
title="更新字典"
visible={modalVisible}
onVisibleChange={handleChange}
onFinish={async (v) => {
updateDict(v as API.DictParams, values?.id).then((res) => {
if (res.code === 200 && res.status === true) {
message.success(res.message);
queryDictsByAllType().then((res) => setInitialState({ ...initialState, DictObj: res.data }));
if (actionRef.current) {
actionRef.current.reload();
}
}
});
return true;
}}
>
<ProForm.Group>
<ProFormText
name="dict_key"
label="字典标签"
width="md"
rules={[{ required: true }]}
initialValue={values?.dict_key}
/>
<ProFormText
name="dict_value"
label="字典键值"
width="md"
rules={[{ required: true }]}
initialValue={values?.dict_value}
/>
</ProForm.Group>
<ProForm.Group>
<ProFormDigit name="sort" label="排序" width="md" initialValue={values?.sort} fieldProps={{ precision: 0 }} />
<ProFormText name="desc" label="说明" initialValue={values?.desc} width="md" />
</ProForm.Group>
<ProForm.Group>
<Form.Item label="上级字典" name="parent_id" initialValue={values?.parent_id}>
<TreeSelect
style={{ width: 330 }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={treeData}
placeholder="请选择字典"
/>
</Form.Item>
</ProForm.Group>
</ModalForm>
);
}
Example #23
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
Components = function() {
const { onDragStart, onDragEnd, pageSchema } = useModel('bridge');
const { queryAllWithComponent } = Model.useContainer();
const dragStart = function(item: IComponentSchema) {
if (pageSchema.length === 0) {
notification.error({
message: '请先创建一个页面',
description: '创建页面后再进行组件拖拽操作!',
});
} else {
onDragStart(item);
}
};
const componentTree = queryAllWithComponent.data;
return (
<div className="components">
<Tabs tabPosition="left">
{
componentTree && componentTree.map((category: any) => (
<TabPane tab={category.name} key={category._id}>
<Row gutter={10}>
{
category.components.map((component: any) => (
<Col span={12} key={component._id}>
<div
className="components-item"
draggable
onDragStart={() => { dragStart(component); }}
onDragEnd={onDragEnd}
>
<div className="components-item-img">
<img src={component.cover} />
</div>
<div className="components-name">{component.name}</div>
</div>
</Col>
))
}
</Row>
</TabPane>
))
}
</Tabs>
</div>
);
}
Example #24
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function Border() {
const { selectComponent, changeContainerPropsState } = useModel('bridge');
const { borderColor, borderWidth, borderStyle, borderRadius } = selectComponent?.containerProps ?? {};
return (
<Descriptions column={1}>
<Descriptions.Item label="圆角">
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => Number((value ?? '').replace('px', ''))}
value={borderRadius ?? 0}
onChange={(value) => { changeContainerPropsState('borderRadius', value); }}
/>
</Descriptions.Item>
<Descriptions.Item label="样式">
<Radio.Group
size="small"
options={[
{ label: '无边框', value: 'none' },
{ label: '实线', value: 'solid' },
{ label: '虚线', value: 'dashed' },
{ label: '点线', value: 'dotted' },
]}
onChange={(e) => { changeContainerPropsState('borderStyle', e.target.value); }}
value={borderStyle ?? 'none'}
optionType="button"
buttonStyle="solid"
/>
</Descriptions.Item>
<Descriptions.Item label="宽度">
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => (value ?? '').replace('px', '')}
value={borderWidth ?? 0}
onChange={(value) => { changeContainerPropsState('borderWidth', value); }}
/>
</Descriptions.Item>
<Descriptions.Item label="颜色">
<ColorPicker
onChange={(value: string) => { changeContainerPropsState('borderColor', value); }}
value={borderColor}
/>
</Descriptions.Item>
</Descriptions>
);
}
Example #25
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function() {
const { selectComponent, pageSchema, setStateByObjectKeys} = useModel('bridge');
const { containerProps } = selectComponent || {};
const handleChange = function(value: string, key1: 'margin' | 'padding', key2: 'top' | 'right' | 'bottom' | 'left') {
if(!selectComponent)return;
if(!selectComponent.containerProps){
selectComponent.containerProps = {
margin: {},
padding: {},
};
}
if(!selectComponent.containerProps.margin){
selectComponent.containerProps.margin = {};
}
if(!selectComponent.containerProps.padding){
selectComponent.containerProps.padding = {};
}
// @ts-expect-error
selectComponent.containerProps[key1][key2] = value;
setStateByObjectKeys({
pageSchema: [...pageSchema],
});
};
return (
<div className="layout-config">
<div className="margin-top">
<input value={containerProps?.margin?.top} onChange={(e) => { handleChange(e.target.value, 'margin', 'top'); }} />
</div>
<div className="margin-right">
<input value={containerProps?.margin?.right} onChange={(e) => { handleChange(e.target.value, 'margin', 'right'); }} />
</div>
<div className="margin-bottom">
<input value={containerProps?.margin?.bottom} onChange={(e) => { handleChange(e.target.value, 'margin', 'bottom'); }} />
</div>
<div className="margin-left">
<input value={containerProps?.margin?.left} onChange={(e) => { handleChange(e.target.value, 'margin', 'left'); }} />
</div>
<div className="padding-top">
<input value={containerProps?.padding?.top} onChange={(e) => { handleChange(e.target.value, 'padding', 'top'); }} />
</div>
<div className="padding-right">
<input value={containerProps?.padding?.right} onChange={(e) => { handleChange(e.target.value, 'padding', 'right'); }} />
</div>
<div className="padding-bottom">
<input value={containerProps?.padding?.bottom} onChange={(e) => { handleChange(e.target.value, 'padding', 'bottom'); }} />
</div>
<div className="padding-left">
<input value={containerProps?.padding?.left} onChange={(e) => { handleChange(e.target.value, 'padding', 'left'); }} />
</div>
</div>
);
}
Example #26
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function Shadow() {
const { selectComponent, changeContainerPropsState } = useModel('bridge');
const { containerProps } = selectComponent || {};
const { boxShadow } = containerProps ?? {};
let computedBoxShadow = boxShadow as string;
if (!boxShadow) {
computedBoxShadow = 'rgba(255,255,255,0) 0px 0px 0px 0px';
}
const arrayBoxShadow = computedBoxShadow.split(' ') as string[];
const boxShadowType = /inset/.test(boxShadow as string) ? BOX_SHADOW_TYPE.inset : BOX_SHADOW_TYPE.outside;
const [color, boxShadowX, boxShadowY, boxShadowRadius] = arrayBoxShadow;
const onBoxShadowTypeChange = function(type: BOX_SHADOW_TYPE) {
let changedBoxShadow;
if (type === BOX_SHADOW_TYPE.outside) {
changedBoxShadow = arrayBoxShadow.slice(0, 4).join(' ');
}
if (type === BOX_SHADOW_TYPE.inset) {
changedBoxShadow = `${arrayBoxShadow.slice(0, 4).join(' ')} inset`;
}
changeContainerPropsState('boxShadow', changedBoxShadow);
};
const changeShadowState = function(index: number, value: string | number | undefined) {
// @ts-expect-error
arrayBoxShadow[index] = index === 0 ? value : `${value ?? 0}px`;
changeContainerPropsState('boxShadow', arrayBoxShadow.join(' '));
};
return (
<Descriptions column={1}>
<Descriptions.Item label="类型">
<Radio.Group
size="small"
options={[
{ label: '外阴影', value: BOX_SHADOW_TYPE.outside },
{ label: '内阴影', value: BOX_SHADOW_TYPE.inset },
]}
onChange={(e) => { onBoxShadowTypeChange(e.target.value); }}
value={boxShadowType}
optionType="button"
buttonStyle="solid"
/>
</Descriptions.Item>
<Descriptions.Item label="颜色">
<ColorPicker
className="background-color"
onChange={(value: string) => { changeShadowState(0, value); }}
value={color}
/>
</Descriptions.Item>
<Descriptions.Item label="X轴">
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => (value ?? '').replace('px', '')}
value={boxShadowX.replace('px', '')}
onChange={(value) => { changeShadowState(1, value); }}
/>
</Descriptions.Item>
<Descriptions.Item label="Y轴">
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => (value ?? '').replace('px', '')}
value={boxShadowY.replace('px', '')}
onChange={(value) => { changeShadowState(2, value); }}
/>
</Descriptions.Item>
<Descriptions.Item label="半径">
<InputNumber
formatter={(value) => `${value}px`}
parser={(value) => (value ?? '').replace('px', '')}
value={boxShadowRadius.replace('px', '')}
onChange={(value) => { changeShadowState(3, value); }}
/>
</Descriptions.Item>
</Descriptions>
);
}
Example #27
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function() {
const { page, closeCreatePageDrawer, openConfigPageDrawer, onCreatePage } = useModel('page');
const { queryPageListReq } = Model.useContainer();
const templateList = queryPageListReq.data;
const useTemplate = function(template:any){
onCreatePage({
...template.pageSchema[0],
});
};
return (
<Drawer
className="page-add"
title="新增页面-选择页面模板"
placement="left"
onClose={closeCreatePageDrawer}
visible={page.createModalVisible}
getContainer={false}
style={{ position: 'absolute' }}
width={430}
>
<Row gutter={16}>
<Col
className="gutter-row"
span={12}
onClick={()=>{
// onCreatePage(pageSchema);
openConfigPageDrawer();
}}
>
<Card
className="page-add-card"
cover={
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description=""/>
}
>
<div className="title">空白页面</div>
</Card>
</Col>
{
templateList && templateList.list.map((template: any) => (
<Col className="gutter-row" span={12} key={template._id}>
<Card
className="page-add-card"
cover={
<img
className="page-add-card-img"
alt="example"
src={template.pageSchema[0].cover}
/>
}
onClick={()=>{useTemplate(template);}}
>
<div className="title">{template.pageSchema[0].config.title}</div>
</Card>
</Col>
))
}
</Row>
</Drawer>
);
}
Example #28
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function() {
const { pageSchema } = useModel('bridge');
const { page, closeConfigPageDrawer, onCreatePage } = useModel('page');
useEffect(() => {
if (page.configModalVisible) {
form.setValues({
title: `页面-${pageSchema.length + 1}`,
path: uuidv4(),
});
}
}, [page.configModalVisible]);
const form = useForm();
const onFinish = function(formData: Record<string, unknown>, errors:any[]) {
if (errors.length === 0) {
onCreatePage({
config: formData,
generatorSchema: page_generatorSchema,
props: {
...formData,
isHome: true,
backgroundColor: '#fff',
},
components: [],
});
}
};
return (
<Drawer
className="page-config"
title="页面配置"
placement="left"
onClose={closeConfigPageDrawer}
visible={page.configModalVisible}
getContainer={false}
style={{ position: 'absolute' }}
width={420}
footer={
<div
style={{
textAlign: 'right',
}}
>
<Button onClick={closeConfigPageDrawer} style={{ marginRight: 8 }}>
取消
</Button>
<Button onClick={form.submit} type="primary">
确定
</Button>
</div>
}
>
<FormRenderWithWidgets
form={form}
schema={schema}
onFinish={onFinish}
/>
</Drawer>
);
}
Example #29
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
SlideLeft = function() {
const { side, setSide } = useModel('layout');
const menus = [{
title: '页面',
menuType: SIDES_MENU.page,
component: Pages,
icon: 'icon-yemian1',
}, {
title: '组件',
menuType: SIDES_MENU.component,
component: Components,
icon: 'icon-zujian',
}, {
title: '结构',
menuType: SIDES_MENU.structure,
component: Construct,
icon: 'icon-shuxingjiegou',
}];
const currentMenu = menus.find((item)=>item.menuType === side.menu);
return (
<>
<div className="side-left-nav">
<ul className="side-left-nav-list">
{
menus.map((item) => (
<li
className={classnames({ active: side.menu === item.menuType })}
onClick={() => { setSide({ menu: item.menuType }); }}
key={item.menuType}
>
<i className={`iconfont ${item.icon}`} />
<div className="title">{item.title}</div>
</li>
))
}
</ul>
</div>
<div className="side-left-content">
{currentMenu && <currentMenu.component/ >}
</div>
</>
);
}