diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3f5c9cf5..eeb81862 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,11 +2,16 @@ - [ ] 新功能 Feat - [ ] 缺陷修复 Bug -- [ ] 文档改进 Docs +- [ ] 文档改进 Doc - [ ] 重构和项目优化 Refactor or Perfs - [ ] 添加测试用例 Test ### ❗️ 请务必确保: - [ ] 代码经历过不少于 1 遍`书写-构建-使用`的自测流程 -- [ ] TS 类型定义完整且没有 any +- [ ] 有全面的组件文档 +- [ ] TS 类型定义完整且没有恶意 any + +### ⚠️ 请尽量保证: + +- [ ] 有完善的组件测试,覆盖率不低于 80% diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..fe250ebd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "monthly" diff --git a/.gitignore b/.gitignore index c2e363cf..78d7e3bc 100755 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ /node_modules /npm-debug.log* /yarn-error.log +package-lock.json +yarn.lock # production /dist diff --git a/docs/components/affix.md b/docs/components/affix.md deleted file mode 100755 index 76c0b15c..00000000 --- a/docs/components/affix.md +++ /dev/null @@ -1,12 +0,0 @@ -# Affix - -> 🔥 测试用的 - -## 1. 基本使用 - -```tsx -/** - * title: 测试一下 - * desc: 测试一下 - */ -``` diff --git a/docs/components/button.md b/docs/components/button.md index 732f193a..8d0b2269 100644 --- a/docs/components/button.md +++ b/docs/components/button.md @@ -160,13 +160,13 @@ const menuComponents = ( onClick={(e) => { message.success(`哦呵?`, e); }}> - }> + }> 毛血旺 - }> + }> 水煮鱼 - }> + }> 红烧肉 @@ -176,19 +176,19 @@ const pureMenuList = [ key: 1, text: '毛血旺', value: '毛血旺', - iconType: 'i-add', + iconType: 'gutline_add', }, { key: 2, text: '水煮鱼', value: '水煮鱼', - iconType: 'i-add', + iconType: 'gutline_add', }, { key: 3, text: '红烧肉', value: '红烧肉', - iconType: 'i-add', + iconType: 'gutline_add', }, ]; const App = () => { @@ -200,7 +200,7 @@ const App = () => { @@ -214,7 +214,7 @@ const App = () => { onChange={(value) => { message.success(`来一份${value}`); }}> - 减脂 + 减脂 @@ -241,7 +241,7 @@ const group = [ key: 1, text: '菜单1', value: 1, - leftIconType: 'i-play', + leftIconType: 'round_left_g', }, { key: 2, @@ -253,7 +253,7 @@ const group = [ key: 3, text: '菜单3', value: 3, - rightIconType: 'i-danmu', + rightIconType: 'round_right_g', }, ]; const App = () => { @@ -261,15 +261,16 @@ const App = () => { <>

使用Button.Group组件的方式:

- +

使用group属性的方式:

+ + +); + +const { Header, Content, Footer, Sider } = Layout; +const { SubMenu } = Menu; +class App extends React.PureComponent { + state = { + collapsed: false, + }; + + onCollapse = (collapsed) => this.setState({ collapsed }); + + render() { + return ( +
+ + +
+ + {this.state.collapsed ? null : 统一交易管理系统} +
+ + }> + Option 1 + + }> + Option 2 + + } title="User"> + Tom + Bill + Alex + + } title="Team"> + Team 1 + Team 2 + + } /> + +
+ +
+ + +
+ +
+ View Contents +
+
+
后台管理系统设计规范组件库 © 2020
+
+
+
+ ); + } +} +export default App; +``` + +## 3. 组件概述 + +- Layout:布局容器,其下可嵌套 Header Sider Content Footer 或 Layout 本身,可以放在任何父容器中。 +- Header:顶部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。 +- Sider:侧边栏,自带默认样式及基本功能,其下可嵌套任何元素,只能放在 Layout 中。 +- Content:内容部分,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。 +- Footer:底部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。 + +## 说明 + +## APIs diff --git a/docs/components/menu.md b/docs/components/menu.md index 2c2cf658..7aeaea84 100755 --- a/docs/components/menu.md +++ b/docs/components/menu.md @@ -1,26 +1,18 @@ # Menu -**`📦菜单`用于展示整个网站的分页和区分业务区块** - -## 1. 基本使用 - -```tsx -/** - * title: 菜单按钮 - * desc: 按钮组合使用时,推荐使用 1 个主操作 + n 个次操作,3 个以上操作时把更多操作放到菜单按钮中组合使用。🚗可以通过两种方式使用`菜单按钮`功能,一种是使用Dropdown + Menu实现,另一种是为Button组件传入menu属性。 - */ -import React from 'react'; -import Icon from '@/Menu/Menu'; -``` - -## 2. 接入平台权限管理系统 - -```tsx -/** - * title: 权限管理系统 - * desc: 前提是必须接入了内部账号系统 - */ -``` +**`📦菜单`为页面和功能提供导航的菜单列表。** + +### 何时使用? + +导航菜单是一个网站的灵魂,用户依赖导航在各个页面中进行跳转。一般分为顶部导航和侧边导航,顶部导航提供全局性的类目和功能,侧边导航提供多级结构来收纳和排列网站架构。 + +## 1. 顶部导航 + + + +## 2. 垂直菜单 + + 参见: diff --git a/docs/components/page-header.md b/docs/components/page-header.md deleted file mode 100644 index 02d144dc..00000000 --- a/docs/components/page-header.md +++ /dev/null @@ -1,16 +0,0 @@ -# PageHeader - -**`📦页头`可用于声明页面主题、展示用户所关注的页面重要信息,以及承载与当前页相关的操作项(包含页面级操作,页面间导航等)。当需要使用户快速理解当前页是什么以及方便用户使用页面功能时使用,通常也可被用作页面间导航。** - -#### PageHeader - -```tsx -/** - * title: 标准样式 - * desc: 标准页头,适合使用在需要简单描述的场景。 - */ -import React from 'react'; -import PageHeader from '@/PageHeader/PageHeader'; - -export default () => null} title="Title" subTitle="This is a subtitle" />; -``` diff --git a/docs/demo/icon/normal-usage.demo.tsx b/docs/demo/icon/normal-usage.demo.tsx index 566c02c3..4bd79a2c 100644 --- a/docs/demo/icon/normal-usage.demo.tsx +++ b/docs/demo/icon/normal-usage.demo.tsx @@ -4,7 +4,7 @@ import { Space } from 'antd'; export default () => ( - + diff --git a/docs/demo/icon/used-in-others.demo.tsx b/docs/demo/icon/used-in-others.demo.tsx index ecc604f8..6b36efd4 100644 --- a/docs/demo/icon/used-in-others.demo.tsx +++ b/docs/demo/icon/used-in-others.demo.tsx @@ -5,10 +5,10 @@ import Button from '@/Button/Button'; export default () => ( - - } color="#cd201f"> + } color="#cd201f"> 朕是个Tag }> diff --git a/src/Menu/index.d.ts b/docs/demo/layout/aside-nav.demo.tsx similarity index 100% rename from src/Menu/index.d.ts rename to docs/demo/layout/aside-nav.demo.tsx diff --git a/docs/demo/layout/head-nav.demo.tsx b/docs/demo/layout/head-nav.demo.tsx new file mode 100644 index 00000000..9e80a7b3 --- /dev/null +++ b/docs/demo/layout/head-nav.demo.tsx @@ -0,0 +1,4 @@ +/** + * title: 顶部导航布局 + * desc: 最基本的『上-中-下』布局。网站路由由位于顶部的导航进行主控,没有侧边导航栏。 + */ diff --git a/docs/demo/menu/head-menu.demo.tsx b/docs/demo/menu/head-menu.demo.tsx new file mode 100644 index 00000000..c5fb2868 --- /dev/null +++ b/docs/demo/menu/head-menu.demo.tsx @@ -0,0 +1,48 @@ +/** + * title: 顶部导航 + * desc: 水平的顶部导航菜单。 + */ +import React from 'react'; +import Menu from '@/Menu/Menu'; +import Icon from '@/Icon/Icon'; + +const { SubMenu } = Menu; +class App extends React.PureComponent { + state = { + data: [], + loading: true, + }; + + render() { + return ( + + Navigation One + + Navigation Two + + } title="Navigation 3 - Submenu"> + + Option 1 + Option 2 + + + Option 3 + Option 4 + + + } title="Navigation 4 - Submenu"> + + Option 1 + Option 2 + + + Option 3 + Option 4 + + + + ); + } +} + +export default App; diff --git a/docs/demo/menu/side-menu.demo.tsx b/docs/demo/menu/side-menu.demo.tsx new file mode 100644 index 00000000..ae3856be --- /dev/null +++ b/docs/demo/menu/side-menu.demo.tsx @@ -0,0 +1,72 @@ +/** + * title: 侧边导航 + * desc: 垂直菜单,子菜单内嵌在菜单区域。 + */ +import React from 'react'; +import Menu from '@/Menu/Menu'; +import Icon from '@/Icon/Icon'; +import Button from '@/Button/Button'; + +const { SubMenu } = Menu; +class App extends React.PureComponent { + state = { collapsed: false, darken: false, mode: false }; + + toggleCollapsed = () => + this.setState({ + collapsed: !this.state.collapsed, + }); + + toggleDarkeness = () => + this.setState({ + darken: !this.state.darken, + }); + + toggleMode = () => + this.setState({ + mode: !this.state.mode, + }); + + render() { + return ( +
+ + + + + Navigation One + + Navigation Two + + } title="Navigation 3 - Submenu"> + + Option 1 + Option 2 + + + Option 3 + Option 4 + + + } title="Navigation 4 - Submenu"> + + Option 1 + Option 2 + + + Option 3 + Option 4 + + + +
+ ); + } +} + +export default App; diff --git a/docs/demo/table/normal-usage.demo.tsx b/docs/demo/table/normal-usage.demo.tsx index 6c3951aa..219a52b2 100755 --- a/docs/demo/table/normal-usage.demo.tsx +++ b/docs/demo/table/normal-usage.demo.tsx @@ -4,43 +4,63 @@ */ import React from 'react'; import Table from '@/Table/Table'; +import Button from '@/Button/Button'; import axios from 'axios'; const columns = [ { - title: '名称', + title: 'Normal', dataIndex: 'desc', ellipsis: true, - width: 350, primary: true, }, { - title: '状态', + title: 'Enum', dataIndex: 'status', - valueType: 'tag' as const, - valueEnum: { - all: { text: '全部', status: 'Default' }, - close: { text: '售罄', status: 'Error' }, - running: { text: '补货中', status: 'Processing' }, - online: { text: '正在销售', status: 'Success' }, - error: { text: '库存不足', status: 'Warning' }, - } as const, + type: 'enum', + enums: { + all: '全部', + close: '售罄', + running: '补货中', + online: '正在销售', + error: '库存不足', + }, }, { - title: '创建时间', - dataIndex: 'createdAt', - valueType: 'dateTime' as const, - }, - { - title: '更新时间', - dataIndex: 'createdAt', - valueType: 'date' as const, + title: 'Tag', + dataIndex: 'status', + type: 'tag', + enums: { + all: { text: '全部', color: 'magenta' }, + close: { text: '售罄', color: 'red' }, + running: { text: '补货中', color: 'volcano', desc: 'testDesc' }, + online: { text: '正在销售', color: 'orange' }, + error: { text: '库存不足', color: 'gold' }, + }, }, { title: '操作', - valueType: 'option' as const, - width: 120, - render: () => [设置, 下架], + render: () => [ + 检查, + , + ], }, ]; @@ -54,36 +74,23 @@ class App extends React.PureComponent { this.fetchData(); } - fetchData = (params?: { current: number; limit: number }) => { + fetchData = async (params?: { current: number; limit: number }) => { this.setState({ loading: true }); - axios - .get('http://rap2.taobao.org:38080/app/mock/252468/admini/table-demo', { - method: 'get', - params: params || { - current: 1, - limit: 10, - }, - }) - .then((res: any) => { - const { data } = res; - this.setState({ - data: data.items, - loading: false, - }); - }); + const { data } = await axios.get('http://rap2.taobao.org:38080/app/mock/252468/admini/table-demo', { + method: 'get', + params: params || { + current: 1, + limit: 10, + }, + }); + this.setState({ + data: data.items, + loading: false, + }); }; render() { - return ( - { - this.fetchData(pgn); - }} - /> - ); + return
this.fetchData(pgn)} />; } } diff --git a/package-lock.json b/package-lock.json index a261d906..663b9b73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@mlz/admin", - "version": "0.0.4", + "version": "0.0.11", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10092,6 +10092,11 @@ "integrity": "sha1-LnG/CxGRU9u0zE6I2epaz7UNwFw=", "dev": true }, + "dayjs": { + "version": "1.8.28", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.28.tgz", + "integrity": "sha512-ccnYgKC0/hPSGXxj7Ju6AV/BP4HUkXC2u15mikXT5mX9YorEaoi1bEKOmAqdkJHN4EEkmAf97SpH66Try5Mbeg==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", @@ -21164,6 +21169,15 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "mytils": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/mytils/-/mytils-1.2.8.tgz", + "integrity": "sha512-iTrp3IDX3tOKY7ccHJWP8+zzpEqK7ilN4tLXqXWvZhlyKqiR+Qs397U9HMxcd0vjV+k5NECo+RCnwUGhyC5QZw==", + "requires": { + "dayjs": "^1.8.28", + "lodash-es": "^4.17.15" + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz", diff --git a/package.json b/package.json index 9d980840..a6782d21 100755 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "compression": "^1.7.4", "express": "^4.17.1", "lodash-es": "^4.17.15", + "mytils": "^1.2.8", "react": "^16.12.0" }, "peerDependencies": { diff --git a/src/Affix/Affix.tsx b/src/Affix/Affix.tsx deleted file mode 100755 index 95e93463..00000000 --- a/src/Affix/Affix.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { default as AntdAffix } from 'antd/es/affix'; -import 'antd/es/affix/style/index.less'; - -const Affix = AntdAffix; - -export default Affix; diff --git a/src/Button/Button.tsx b/src/Button/Button.tsx index 9ca15ba3..a477c503 100644 --- a/src/Button/Button.tsx +++ b/src/Button/Button.tsx @@ -2,7 +2,7 @@ import React, { useState, useContext } from 'react'; import { Button as AntdButton, Dropdown, Menu } from 'antd'; import { ClickParam } from 'antd/lib/menu/index.d'; import { default as AntdButtonGroup } from 'antd/es/button/button-group'; -import { omitObject } from '../shared/utils'; +import { omitProps } from 'mytils'; import Icon from '../Icon/Icon'; import { MenuType, GroupType, ButtonTypes, ButtonGroupPropableValue } from './Button.type'; @@ -34,7 +34,10 @@ const Button = (props: ButtonTypes): React.ReactElement => { })} }> - + ) ) : ( @@ -43,7 +46,7 @@ const Button = (props: ButtonTypes): React.ReactElement => { return ( { item.onClick && item.onClick(e); props.onChange && props.onChange(item.value || undefined); diff --git a/src/Icon/Icon.tsx b/src/Icon/Icon.tsx index 36a6ac03..05e3ba8f 100644 --- a/src/Icon/Icon.tsx +++ b/src/Icon/Icon.tsx @@ -2,20 +2,21 @@ import React from 'react'; import { createFromIconfontCN as createFromIconfont } from '@ant-design/icons/es'; class IconFontScript { - public scriptUrl: string; + public scriptUrls: string[]; constructor($scriptUrl: URL['href']) { - this.scriptUrl = $scriptUrl; + this.scriptUrls = [$scriptUrl]; } - public replaceIconFontScript($scriptUrl: URL['href']) { - this.scriptUrl = $scriptUrl; + public addIconFontScript($scriptUrl: URL['href'] | URL['href'][]) { + const scripts = typeof $scriptUrl !== 'string' ? $scriptUrl : [$scriptUrl]; + this.scriptUrls = this.scriptUrls.concat(scripts as URL['href'][]); } } -const newScript = new IconFontScript('//at.alicdn.com/t/font_1545707_47fjy8om7mg.js'); +const newScript = new IconFontScript('//at.alicdn.com/t/font_1820833_zgnaif28led.js'); const Icon = createFromIconfont({ - scriptUrl: newScript.scriptUrl, + scriptUrl: [...newScript.scriptUrls], }); +export const createIconFontScript = newScript.addIconFontScript; export default Icon; -export const createIconFontScript = newScript.replaceIconFontScript; diff --git a/src/Layout/Layout.tsx b/src/Layout/Layout.tsx new file mode 100644 index 00000000..7d1bc2be --- /dev/null +++ b/src/Layout/Layout.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { Layout as AntdMLayout } from 'antd'; +import { BasicProps } from 'antd/lib/layout/layout.d'; + +const Layout = AntdMLayout; +export default Layout; diff --git a/src/Menu/Menu.tsx b/src/Menu/Menu.tsx index 72c6dc2f..b00b0033 100644 --- a/src/Menu/Menu.tsx +++ b/src/Menu/Menu.tsx @@ -1,7 +1,5 @@ import React from 'react'; import { Menu as AntdMenu } from 'antd'; -const Menu = () => { - return AntdMenu; -}; +const Menu: typeof AntdMenu = AntdMenu; export default Menu; diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx deleted file mode 100644 index 931fc4ae..00000000 --- a/src/PageHeader/PageHeader.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React, { useState, useContext } from 'react'; -import { PageHeader as AntdPageHeader } from 'antd'; - -const PageHeader = AntdPageHeader; - -export default PageHeader; diff --git a/src/Table/Table.tsx b/src/Table/Table.tsx index 2daf574e..b4eb7cb6 100644 --- a/src/Table/Table.tsx +++ b/src/Table/Table.tsx @@ -1,6 +1,6 @@ import React, { useState, useContext } from 'react'; -import { Table as AntdTable } from 'antd'; +import CommonTable from './commonTable'; -const Table = AntdTable; +const Table = CommonTable; export default Table; diff --git a/src/Table/commonSearch/index.tsx b/src/Table/commonSearch/index.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/Table/commonTable/index.less b/src/Table/commonTable/index.less new file mode 100644 index 00000000..362e3d82 --- /dev/null +++ b/src/Table/commonTable/index.less @@ -0,0 +1,3 @@ +.table-options-container > * { + margin-right: 8px; +} diff --git a/src/Table/commonTable/index.tsx b/src/Table/commonTable/index.tsx new file mode 100644 index 00000000..4773aebc --- /dev/null +++ b/src/Table/commonTable/index.tsx @@ -0,0 +1,43 @@ +import React, { useState, useContext } from 'react'; +import { Table, Tooltip, Tag } from 'antd'; +import { formatUnixTime, getDataType } from 'mytils'; +import { formatPrice } from '@/shared/utils'; +import { IColumnTypes, ITableTypes, recordedType, EnumsType, TagEnumsType, SupporttedColumnTypes } from './index.type'; +// import 'index.less'; + +export const typeFilter = { + normal: (value: any) => value || '--', + price: (value: number) => formatPrice(value), + date: (value: number) => formatUnixTime(value, 'YYYY/MM/DD'), + datetime: (value: number) => formatUnixTime(value), + enum: (value: number | string, enums?: TagEnumsType) => enums?.[value] || '--', + tag: (value: string, enums?: EnumsType) => { + const TagNode = {enums?.[value]?.text || '--'}; + return enums?.[value]?.desc ? {TagNode} : TagNode; + }, +}; + +const renderNode = (type: SupporttedColumnTypes = 'normal', value: any, column: IColumnTypes) => { + return ['enum', 'tag'].includes(type) ? typeFilter[type](value, column?.enums as Record) : typeFilter[type](value); +}; + +const formatColumns = ($columns: IColumnTypes[]) => { + return $columns.map((column) => { + const { type, ...others } = column; + let { render } = column; + if (!render) { + render = (value) => renderNode(type as SupporttedColumnTypes, value, column); + } + return { + ...others, + render, + }; + }); +}; + +const CommonTable = (props: ITableTypes) => { + const { columns, pagination, rowKey = 'id', ...others } = props; + return
; +}; + +export default CommonTable; diff --git a/src/Table/commonTable/index.type.ts b/src/Table/commonTable/index.type.ts new file mode 100644 index 00000000..f58bf560 --- /dev/null +++ b/src/Table/commonTable/index.type.ts @@ -0,0 +1,19 @@ +import { ColumnProps, TableProps, TablePaginationConfig } from 'antd/lib/table'; +import { PresetColorType, PresetStatusColorType } from 'antd/lib/_util/colors'; +import { LiteralUnion } from 'antd/lib/_util/type'; +import { typeFilter } from '.'; + +export interface ITableTypes extends TableProps { + columns: IColumnTypes[]; + onSearch?: () => void; +} +export type SupporttedColumnTypes = keyof typeof typeFilter; +export type ColorTypes = LiteralUnion; +export type EnumsType = Record; +export type TagEnumsType = { [key: string]: string }; +export interface IColumnTypes extends ColumnProps { + type?: string; + enums?: EnumsType | TagEnumsType; + primary?: number | boolean; +} +export type recordedType = unknown; diff --git a/src/Upload/Import/Import.tsx b/src/Upload/Import/Import.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/Upload/Upload.tsx b/src/Upload/Upload.tsx new file mode 100644 index 00000000..2482a771 --- /dev/null +++ b/src/Upload/Upload.tsx @@ -0,0 +1,6 @@ +import React, { useState, useContext } from 'react'; +import { Upload as AntdUpload } from 'antd'; + +const Upload = AntdUpload; + +export default Upload; diff --git a/src/index.tsx b/src/index.tsx index ea48a58b..16bb0f06 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,2 @@ export * from 'antd'; export { default as Button } from './Button/Button'; -export { default as PageHeader } from './PageHeader/PageHeader'; diff --git a/src/shared/components/keep-alive/index.tsx b/src/shared/keep-alive/index.tsx similarity index 100% rename from src/shared/components/keep-alive/index.tsx rename to src/shared/keep-alive/index.tsx diff --git a/src/shared/components/keep-alive/keep-alive.store.ts b/src/shared/keep-alive/keep-alive.store.ts similarity index 89% rename from src/shared/components/keep-alive/keep-alive.store.ts rename to src/shared/keep-alive/keep-alive.store.ts index a4ccc7ae..347d85f7 100755 --- a/src/shared/components/keep-alive/keep-alive.store.ts +++ b/src/shared/keep-alive/keep-alive.store.ts @@ -19,7 +19,7 @@ class AlivesStore { } const tnow = new Date().valueOf(); this.stackChecker(); - // TODO 暂时不支持历史功能 + // TODO 暂时不支持历史回溯功能 this.snapshots.set(name, { shootedTime: tnow, payload: $args.length === 1 ? $args[0] : $args, @@ -37,8 +37,7 @@ class AlivesStore { if ($key) { return this.snapshots.get($key); } else { - console.error('必须指定一个keep-alive的name索引'); - return undefined; + throw new Error('必须指定一个keep-alive的name索引'); } }; } diff --git a/src/shared/components/keep-alive/keep-alive.type.ts b/src/shared/keep-alive/keep-alive.type.ts similarity index 100% rename from src/shared/components/keep-alive/keep-alive.type.ts rename to src/shared/keep-alive/keep-alive.type.ts diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts index 32c77d3a..16d9c2f7 100755 --- a/src/shared/utils/index.ts +++ b/src/shared/utils/index.ts @@ -1,30 +1,6 @@ const __DEV__ = (window as any).__DEV__ !== 'false'; -// 🔧 判断对象非原型链上是否存在某一指定属性 -export const ifPropertyExited = ($key: PropertyKey, $targetObj: Record): boolean => Object.prototype.hasOwnProperty.call($targetObj, $key); - -// 🔧 清洗属性 -export const omitObject = , U extends string>($targetObj: T, $key: U | U[], $prototypable?: boolean): Omit => { - const keies: string[] = typeof $key === 'string' ? [$key] : $key; - const result = JSON.parse(JSON.stringify($targetObj)); - if ($prototypable === true) { - __DEV__ && console.warn(`[${omitObject.name}]开启prototypable后将影响到原型链上的属性,请确保你能hold住`); - for (const key in result) { - if (keies.includes(key)) { - delete result[key]; - } - } - return result; - } - keies.forEach((oneKey) => { - if (ifPropertyExited(oneKey, result)) { - delete result[oneKey]; - } - }); - return result; -}; - -// 🔧 预测columns可能的primary key +// 预测columns可能的primary key export const guessPrimaryKey = ($columns: any[]): string | undefined => { if (!$columns) { return; @@ -55,3 +31,8 @@ export const guessPrimaryKey = ($columns: any[]): string | undefined => { return $columns[indexa]?.dataIndex; } }; + +// 数字转金额 +export const formatPrice = (price: number) => { + return price && price.toString().includes('.') ? `¥ ${price}` : `¥ ${price}.00`; +};