Commit 7101587b9676c91e9079044a096df08848f1f602
1 parent
c0692b0f
feat: add error handle
Showing
32 changed files
with
674 additions
and
116 deletions
.env.production
@@ -7,7 +7,7 @@ VITE_PUBLIC_PATH = ./ | @@ -7,7 +7,7 @@ VITE_PUBLIC_PATH = ./ | ||
7 | # Delete console | 7 | # Delete console |
8 | VITE_DROP_CONSOLE = true | 8 | VITE_DROP_CONSOLE = true |
9 | 9 | ||
10 | -# Delete console | 10 | +# Whether to output gz file for packaging |
11 | VITE_BUILD_GZIP = false | 11 | VITE_BUILD_GZIP = false |
12 | 12 | ||
13 | # Basic interface address SPA | 13 | # Basic interface address SPA |
README.en-US.md
@@ -225,17 +225,17 @@ yarn clean:lib # Delete node_modules, supported window | @@ -225,17 +225,17 @@ yarn clean:lib # Delete node_modules, supported window | ||
225 | - [x] First screen loading waiting animation | 225 | - [x] First screen loading waiting animation |
226 | - [x] Extract the production environment profile | 226 | - [x] Extract the production environment profile |
227 | - [x] Build Gzip | 227 | - [x] Build Gzip |
228 | +- [x] System performance optimization | ||
229 | +- [x] Data import and export | ||
230 | +- [x] Global error handling | ||
228 | 231 | ||
229 | ## Developing features | 232 | ## Developing features |
230 | 233 | ||
231 | - [ ] Upload component | 234 | - [ ] Upload component |
232 | - [ ] Rich text component | 235 | - [ ] Rich text component |
233 | -- [ ] Data import and export | ||
234 | -- [ ] Global error handling | ||
235 | - [ ] Theme configuration | 236 | - [ ] Theme configuration |
236 | - [ ] Dark theme | 237 | - [ ] Dark theme |
237 | - [ ] Build CDN | 238 | - [ ] Build CDN |
238 | -- [ ] System performance optimization | ||
239 | 239 | ||
240 | If you have more components/functions/suggestions/bugs/, welcome to submit pr or issue. | 240 | If you have more components/functions/suggestions/bugs/, welcome to submit pr or issue. |
241 | 241 |
README.md
@@ -223,17 +223,17 @@ yarn clean:lib # 删除node_modules,兼容window系统 | @@ -223,17 +223,17 @@ yarn clean:lib # 删除node_modules,兼容window系统 | ||
223 | - [x] 首屏加载等待动画 | 223 | - [x] 首屏加载等待动画 |
224 | - [x] 抽取生产环境配置文件 | 224 | - [x] 抽取生产环境配置文件 |
225 | - [x] 打包 Gzip | 225 | - [x] 打包 Gzip |
226 | +- [x] 数据导入导出 | ||
227 | +- [x] 系统性能优化 | ||
228 | +- [x] 全局错误处理 | ||
226 | 229 | ||
227 | ## 正在开发的功能 | 230 | ## 正在开发的功能 |
228 | 231 | ||
229 | - [ ] 上传组件 | 232 | - [ ] 上传组件 |
230 | - [ ] 富文本组件 | 233 | - [ ] 富文本组件 |
231 | -- [ ] 数据导入导出 | ||
232 | -- [ ] 全局错误处理 | ||
233 | - [ ] 主题配置 | 234 | - [ ] 主题配置 |
234 | - [ ] 黑暗主题 | 235 | - [ ] 黑暗主题 |
235 | - [ ] 打包 CDN | 236 | - [ ] 打包 CDN |
236 | -- [ ] 系统性能优化 | ||
237 | 237 | ||
238 | 更多组件/功能/建议/bug/欢迎提交 pr 或者 issue | 238 | 更多组件/功能/建议/bug/欢迎提交 pr 或者 issue |
239 | 239 |
build/config/vite/proxy.ts
@@ -2,13 +2,17 @@ type ProxyItem = [string, string]; | @@ -2,13 +2,17 @@ type ProxyItem = [string, string]; | ||
2 | 2 | ||
3 | type ProxyList = ProxyItem[]; | 3 | type ProxyList = ProxyItem[]; |
4 | 4 | ||
5 | +const reg = /^https:\/\//; | ||
5 | export function createProxy(list: ProxyList = []) { | 6 | export function createProxy(list: ProxyList = []) { |
6 | const ret: any = {}; | 7 | const ret: any = {}; |
7 | for (const [prefix, target] of list) { | 8 | for (const [prefix, target] of list) { |
9 | + const isHttps = reg.test(target); | ||
10 | + | ||
8 | ret[prefix] = { | 11 | ret[prefix] = { |
9 | target: target, | 12 | target: target, |
10 | changeOrigin: true, | 13 | changeOrigin: true, |
11 | rewrite: (path: string) => path.replace(new RegExp(`^${prefix}`), ''), | 14 | rewrite: (path: string) => path.replace(new RegExp(`^${prefix}`), ''), |
15 | + ...(isHttps ? { secure: false } : {}), | ||
12 | }; | 16 | }; |
13 | } | 17 | } |
14 | return ret; | 18 | return ret; |
build/plugin/vite-plugin-context-plugin/transform.ts renamed to build/plugin/vite-plugin-context/transform.ts
package.json
@@ -41,10 +41,10 @@ | @@ -41,10 +41,10 @@ | ||
41 | "devDependencies": { | 41 | "devDependencies": { |
42 | "@commitlint/cli": "^11.0.0", | 42 | "@commitlint/cli": "^11.0.0", |
43 | "@commitlint/config-conventional": "^11.0.0", | 43 | "@commitlint/config-conventional": "^11.0.0", |
44 | - "@iconify/json": "^1.1.242", | 44 | + "@iconify/json": "^1.1.243", |
45 | "@ls-lint/ls-lint": "^1.9.2", | 45 | "@ls-lint/ls-lint": "^1.9.2", |
46 | "@purge-icons/generated": "^0.4.1", | 46 | "@purge-icons/generated": "^0.4.1", |
47 | - "@types/echarts": "^4.8.1", | 47 | + "@types/echarts": "^4.8.3", |
48 | "@types/fs-extra": "^9.0.2", | 48 | "@types/fs-extra": "^9.0.2", |
49 | "@types/html-minifier": "^4.0.0", | 49 | "@types/html-minifier": "^4.0.0", |
50 | "@types/inquirer": "^7.3.1", | 50 | "@types/inquirer": "^7.3.1", |
@@ -55,7 +55,7 @@ | @@ -55,7 +55,7 @@ | ||
55 | "@types/qrcode": "^1.3.5", | 55 | "@types/qrcode": "^1.3.5", |
56 | "@types/rollup-plugin-visualizer": "^2.6.0", | 56 | "@types/rollup-plugin-visualizer": "^2.6.0", |
57 | "@types/shelljs": "^0.8.8", | 57 | "@types/shelljs": "^0.8.8", |
58 | - "@types/yargs": "^15.0.8", | 58 | + "@types/yargs": "^15.0.9", |
59 | "@types/zxcvbn": "^4.4.0", | 59 | "@types/zxcvbn": "^4.4.0", |
60 | "@typescript-eslint/eslint-plugin": "^4.4.1", | 60 | "@typescript-eslint/eslint-plugin": "^4.4.1", |
61 | "@typescript-eslint/parser": "^4.4.1", | 61 | "@typescript-eslint/parser": "^4.4.1", |
@@ -67,7 +67,7 @@ | @@ -67,7 +67,7 @@ | ||
67 | "cross-env": "^7.0.2", | 67 | "cross-env": "^7.0.2", |
68 | "dotenv": "^8.2.0", | 68 | "dotenv": "^8.2.0", |
69 | "eslint": "^7.10.0", | 69 | "eslint": "^7.10.0", |
70 | - "eslint-config-prettier": "^6.12.0", | 70 | + "eslint-config-prettier": "^6.13.0", |
71 | "eslint-plugin-prettier": "^3.1.4", | 71 | "eslint-plugin-prettier": "^3.1.4", |
72 | "eslint-plugin-vue": "^7.0.1", | 72 | "eslint-plugin-vue": "^7.0.1", |
73 | "fs-extra": "^9.0.1", | 73 | "fs-extra": "^9.0.1", |
@@ -76,7 +76,7 @@ | @@ -76,7 +76,7 @@ | ||
76 | "inquirer": "^7.3.3", | 76 | "inquirer": "^7.3.3", |
77 | "koa-static": "^5.0.0", | 77 | "koa-static": "^5.0.0", |
78 | "less": "^3.12.2", | 78 | "less": "^3.12.2", |
79 | - "lint-staged": "^10.4.0", | 79 | + "lint-staged": "^10.4.2", |
80 | "portfinder": "^1.0.28", | 80 | "portfinder": "^1.0.28", |
81 | "postcss-import": "^12.0.1", | 81 | "postcss-import": "^12.0.1", |
82 | "prettier": "^2.1.2", | 82 | "prettier": "^2.1.2", |
@@ -95,7 +95,7 @@ | @@ -95,7 +95,7 @@ | ||
95 | "vite-plugin-mock": "^1.0.2", | 95 | "vite-plugin-mock": "^1.0.2", |
96 | "vite-plugin-purge-icons": "^0.4.4", | 96 | "vite-plugin-purge-icons": "^0.4.4", |
97 | "vue-eslint-parser": "^7.1.1", | 97 | "vue-eslint-parser": "^7.1.1", |
98 | - "yargs": "^16.0.3" | 98 | + "yargs": "^16.1.0" |
99 | }, | 99 | }, |
100 | "repository": { | 100 | "repository": { |
101 | "type": "git", | 101 | "type": "git", |
src/App.vue
src/api/demo/error.ts
0 → 100644
src/components/Table/src/BasicTable.vue
@@ -146,7 +146,7 @@ | @@ -146,7 +146,7 @@ | ||
146 | } | 146 | } |
147 | if (showSummary) { | 147 | if (showSummary) { |
148 | propsData.footer = renderFooter.bind(null, { | 148 | propsData.footer = renderFooter.bind(null, { |
149 | - scroll, | 149 | + scroll: scroll as any, |
150 | columnsRef: getColumnsRef, | 150 | columnsRef: getColumnsRef, |
151 | summaryFunc: unref(getMergeProps).summaryFunc, | 151 | summaryFunc: unref(getMergeProps).summaryFunc, |
152 | dataSourceRef: getDataSourceRef, | 152 | dataSourceRef: getDataSourceRef, |
src/components/Table/src/components/TableAction.tsx
@@ -29,7 +29,6 @@ export default defineComponent({ | @@ -29,7 +29,6 @@ export default defineComponent({ | ||
29 | const { | 29 | const { |
30 | disabled = false, | 30 | disabled = false, |
31 | label, | 31 | label, |
32 | - props, | ||
33 | icon, | 32 | icon, |
34 | color = '', | 33 | color = '', |
35 | type = 'link', | 34 | type = 'link', |
@@ -41,7 +40,7 @@ export default defineComponent({ | @@ -41,7 +40,7 @@ export default defineComponent({ | ||
41 | size="small" | 40 | size="small" |
42 | disabled={disabled} | 41 | disabled={disabled} |
43 | color={color} | 42 | color={color} |
44 | - {...props} | 43 | + {...action} |
45 | key={index} | 44 | key={index} |
46 | > | 45 | > |
47 | {() => ( | 46 | {() => ( |
@@ -101,7 +100,6 @@ export default defineComponent({ | @@ -101,7 +100,6 @@ export default defineComponent({ | ||
101 | const { | 100 | const { |
102 | disabled = false, | 101 | disabled = false, |
103 | label, | 102 | label, |
104 | - props, | ||
105 | icon, | 103 | icon, |
106 | color = '', | 104 | color = '', |
107 | type = 'link', | 105 | type = 'link', |
@@ -112,7 +110,7 @@ export default defineComponent({ | @@ -112,7 +110,7 @@ export default defineComponent({ | ||
112 | <Button | 110 | <Button |
113 | type={type} | 111 | type={type} |
114 | size="small" | 112 | size="small" |
115 | - {...props} | 113 | + {...action} |
116 | disabled={disabled} | 114 | disabled={disabled} |
117 | color={color} | 115 | color={color} |
118 | > | 116 | > |
src/enums/exceptionEnum.ts
@@ -23,3 +23,11 @@ export enum ExceptionEnum { | @@ -23,3 +23,11 @@ export enum ExceptionEnum { | ||
23 | // No data on the page. In fact, it is not an exception page | 23 | // No data on the page. In fact, it is not an exception page |
24 | PAGE_NOT_DATA = 10400, | 24 | PAGE_NOT_DATA = 10400, |
25 | } | 25 | } |
26 | + | ||
27 | +export enum ErrorTypeEnum { | ||
28 | + VUE = 'vue', | ||
29 | + SCRIPT = 'script', | ||
30 | + RESOURCE = 'resource', | ||
31 | + AJAX = 'ajax', | ||
32 | + PROMISE = 'promise', | ||
33 | +} |
src/hooks/web/usePage.ts
@@ -19,7 +19,7 @@ function handleError(e: Error) { | @@ -19,7 +19,7 @@ function handleError(e: Error) { | ||
19 | // page switch | 19 | // page switch |
20 | export function useGo() { | 20 | export function useGo() { |
21 | const { push, replace } = useRouter(); | 21 | const { push, replace } = useRouter(); |
22 | - function go(opt: PageEnum | RouteLocationRawEx = PageEnum.BASE_HOME, isReplace = false) { | 22 | + function go(opt: PageEnum | RouteLocationRawEx | string = PageEnum.BASE_HOME, isReplace = false) { |
23 | if (isString(opt)) { | 23 | if (isString(opt)) { |
24 | isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError); | 24 | isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError); |
25 | } else { | 25 | } else { |
src/layouts/default/LayoutHeader.tsx
1 | import { defineComponent, unref, computed } from 'vue'; | 1 | import { defineComponent, unref, computed } from 'vue'; |
2 | -import { Layout, Tooltip } from 'ant-design-vue'; | 2 | +import { Layout, Tooltip, Badge } from 'ant-design-vue'; |
3 | import Logo from '/@/layouts/Logo.vue'; | 3 | import Logo from '/@/layouts/Logo.vue'; |
4 | import UserDropdown from './UserDropdown'; | 4 | import UserDropdown from './UserDropdown'; |
5 | import LayoutMenu from './LayoutMenu'; | 5 | import LayoutMenu from './LayoutMenu'; |
@@ -12,12 +12,15 @@ import { | @@ -12,12 +12,15 @@ import { | ||
12 | FullscreenOutlined, | 12 | FullscreenOutlined, |
13 | GithubFilled, | 13 | GithubFilled, |
14 | LockOutlined, | 14 | LockOutlined, |
15 | + BugOutlined, | ||
15 | } from '@ant-design/icons-vue'; | 16 | } from '@ant-design/icons-vue'; |
16 | import { useFullscreen } from '/@/hooks/web/useFullScreen'; | 17 | import { useFullscreen } from '/@/hooks/web/useFullScreen'; |
17 | import { useTabs } from '/@/hooks/web/useTabs'; | 18 | import { useTabs } from '/@/hooks/web/useTabs'; |
18 | import { GITHUB_URL } from '/@/settings/siteSetting'; | 19 | import { GITHUB_URL } from '/@/settings/siteSetting'; |
19 | import LockAction from './actions/LockActionItem'; | 20 | import LockAction from './actions/LockActionItem'; |
20 | import { useModal } from '/@/components/Modal/index'; | 21 | import { useModal } from '/@/components/Modal/index'; |
22 | +import { errorStore } from '/@/store/modules/error'; | ||
23 | +import { useGo } from '/@/hooks/web/usePage'; | ||
21 | 24 | ||
22 | export default defineComponent({ | 25 | export default defineComponent({ |
23 | name: 'DefaultLayoutHeader', | 26 | name: 'DefaultLayoutHeader', |
@@ -25,6 +28,7 @@ export default defineComponent({ | @@ -25,6 +28,7 @@ export default defineComponent({ | ||
25 | const { refreshPage } = useTabs(); | 28 | const { refreshPage } = useTabs(); |
26 | const [register, { openModal }] = useModal(); | 29 | const [register, { openModal }] = useModal(); |
27 | const { toggleFullscreen, isFullscreenRef } = useFullscreen(); | 30 | const { toggleFullscreen, isFullscreenRef } = useFullscreen(); |
31 | + const go = useGo(); | ||
28 | const getProjectConfigRef = computed(() => { | 32 | const getProjectConfigRef = computed(() => { |
29 | return appStore.getProjectConfig; | 33 | return appStore.getProjectConfig; |
30 | }); | 34 | }); |
@@ -37,6 +41,12 @@ export default defineComponent({ | @@ -37,6 +41,12 @@ export default defineComponent({ | ||
37 | const theme = unref(getProjectConfigRef).headerSetting.theme; | 41 | const theme = unref(getProjectConfigRef).headerSetting.theme; |
38 | return theme ? `layout-header__header--${theme}` : ''; | 42 | return theme ? `layout-header__header--${theme}` : ''; |
39 | }); | 43 | }); |
44 | + | ||
45 | + function handleToErrorList() { | ||
46 | + errorStore.commitErrorListCountState(0); | ||
47 | + go('/exception/error-log'); | ||
48 | + } | ||
49 | + | ||
40 | /** | 50 | /** |
41 | * @description: 锁定屏幕 | 51 | * @description: 锁定屏幕 |
42 | */ | 52 | */ |
@@ -46,9 +56,9 @@ export default defineComponent({ | @@ -46,9 +56,9 @@ export default defineComponent({ | ||
46 | return () => { | 56 | return () => { |
47 | const getProjectConfig = unref(getProjectConfigRef); | 57 | const getProjectConfig = unref(getProjectConfigRef); |
48 | const { | 58 | const { |
49 | - // useErrorHandle, | 59 | + useErrorHandle, |
50 | showLogo, | 60 | showLogo, |
51 | - headerSetting: { theme: headerTheme, showRedo, showGithub, showFullScreen }, | 61 | + headerSetting: { theme: headerTheme, useLockPage, showRedo, showGithub, showFullScreen }, |
52 | menuSetting: { mode, type: menuType, split: splitMenu, topMenuAlign }, | 62 | menuSetting: { mode, type: menuType, split: splitMenu, topMenuAlign }, |
53 | showBreadCrumb, | 63 | showBreadCrumb, |
54 | } = getProjectConfig; | 64 | } = getProjectConfig; |
@@ -77,8 +87,28 @@ export default defineComponent({ | @@ -77,8 +87,28 @@ export default defineComponent({ | ||
77 | </div> | 87 | </div> |
78 | 88 | ||
79 | <div class={`layout-header__action`}> | 89 | <div class={`layout-header__action`}> |
90 | + {useErrorHandle && ( | ||
91 | + <Tooltip> | ||
92 | + {{ | ||
93 | + title: () => '错误日志', | ||
94 | + default: () => ( | ||
95 | + <Badge | ||
96 | + count={errorStore.getErrorListCountState} | ||
97 | + offset={[0, 10]} | ||
98 | + overflowCount={99} | ||
99 | + > | ||
100 | + {() => ( | ||
101 | + <div class={`layout-header__action-item`} onClick={handleToErrorList}> | ||
102 | + <BugOutlined class={`layout-header__action-icon`} /> | ||
103 | + </div> | ||
104 | + )} | ||
105 | + </Badge> | ||
106 | + ), | ||
107 | + }} | ||
108 | + </Tooltip> | ||
109 | + )} | ||
110 | + | ||
80 | {showGithub && ( | 111 | {showGithub && ( |
81 | - // @ts-ignore | ||
82 | <Tooltip> | 112 | <Tooltip> |
83 | {{ | 113 | {{ |
84 | title: () => 'github', | 114 | title: () => 'github', |
@@ -90,8 +120,7 @@ export default defineComponent({ | @@ -90,8 +120,7 @@ export default defineComponent({ | ||
90 | }} | 120 | }} |
91 | </Tooltip> | 121 | </Tooltip> |
92 | )} | 122 | )} |
93 | - {showGithub && ( | ||
94 | - // @ts-ignore | 123 | + {useLockPage && ( |
95 | <Tooltip> | 124 | <Tooltip> |
96 | {{ | 125 | {{ |
97 | title: () => '锁定屏幕', | 126 | title: () => '锁定屏幕', |
@@ -104,7 +133,6 @@ export default defineComponent({ | @@ -104,7 +133,6 @@ export default defineComponent({ | ||
104 | </Tooltip> | 133 | </Tooltip> |
105 | )} | 134 | )} |
106 | {showRedo && ( | 135 | {showRedo && ( |
107 | - // @ts-ignore | ||
108 | <Tooltip> | 136 | <Tooltip> |
109 | {{ | 137 | {{ |
110 | title: () => '刷新', | 138 | title: () => '刷新', |
@@ -117,7 +145,6 @@ export default defineComponent({ | @@ -117,7 +145,6 @@ export default defineComponent({ | ||
117 | </Tooltip> | 145 | </Tooltip> |
118 | )} | 146 | )} |
119 | {showFullScreen && ( | 147 | {showFullScreen && ( |
120 | - // @ts-ignore | ||
121 | <Tooltip> | 148 | <Tooltip> |
122 | {{ | 149 | {{ |
123 | title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'), | 150 | title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'), |
src/layouts/default/actions/LockActionItem.tsx
@@ -40,10 +40,11 @@ export default defineComponent({ | @@ -40,10 +40,11 @@ export default defineComponent({ | ||
40 | let password: string | undefined = ''; | 40 | let password: string | undefined = ''; |
41 | 41 | ||
42 | try { | 42 | try { |
43 | - const values = (await validateFields()) as any; | ||
44 | - password = values.password; | ||
45 | if (!valid) { | 43 | if (!valid) { |
46 | password = undefined; | 44 | password = undefined; |
45 | + } else { | ||
46 | + const values = (await validateFields()) as any; | ||
47 | + password = values.password; | ||
47 | } | 48 | } |
48 | setModalProps({ | 49 | setModalProps({ |
49 | visible: false, | 50 | visible: false, |
src/layouts/default/actions/notice/NoticeActionItem.tsx
0 → 100644
1 | +import { defineComponent } from 'vue'; | ||
2 | +import { Popover, Tabs } from 'ant-design-vue'; | ||
3 | + | ||
4 | +import NoticeList from './NoticeList'; | ||
5 | +import { NoticeTabItem, NoticeListItem, noticeTabListData, noticeListData } from './data'; | ||
6 | +import './index.less'; | ||
7 | + | ||
8 | +const prefixCls = 'notice-popover'; | ||
9 | +export default defineComponent({ | ||
10 | + name: 'NoticePopover', | ||
11 | + props: { | ||
12 | + visible: { | ||
13 | + type: Boolean, | ||
14 | + default: false, | ||
15 | + }, | ||
16 | + }, | ||
17 | + setup(props, { attrs }) { | ||
18 | + // 渲染卡片内容 | ||
19 | + function renderContent() { | ||
20 | + return ( | ||
21 | + <Tabs class={`${prefixCls}__tabs`}> | ||
22 | + {() => { | ||
23 | + return noticeTabListData.map((item: NoticeTabItem) => { | ||
24 | + const { key, name } = item; | ||
25 | + return ( | ||
26 | + <Tabs.TabPane key={key} tab={renderTab(key, name)}> | ||
27 | + {() => <NoticeList list={getListData(key)} />} | ||
28 | + </Tabs.TabPane> | ||
29 | + ); | ||
30 | + }); | ||
31 | + }} | ||
32 | + </Tabs> | ||
33 | + ); | ||
34 | + } | ||
35 | + | ||
36 | + // tab标题渲染 | ||
37 | + function renderTab(key: string, name: string) { | ||
38 | + const list = getListData(key); | ||
39 | + const unreadlist = list.filter((item: NoticeListItem) => !item.read); | ||
40 | + return ( | ||
41 | + <div> | ||
42 | + {name} | ||
43 | + {unreadlist.length > 0 && <span>({unreadlist.length})</span>} | ||
44 | + </div> | ||
45 | + ); | ||
46 | + } | ||
47 | + | ||
48 | + // 获取数据 | ||
49 | + function getListData(type: string) { | ||
50 | + return noticeListData.filter((item: NoticeListItem) => item.type === type); | ||
51 | + } | ||
52 | + | ||
53 | + return () => { | ||
54 | + const { visible } = props; | ||
55 | + return ( | ||
56 | + <Popover | ||
57 | + title="" | ||
58 | + {...{ | ||
59 | + ...attrs, | ||
60 | + visible, | ||
61 | + }} | ||
62 | + content={renderContent} | ||
63 | + class={prefixCls} | ||
64 | + /> | ||
65 | + ); | ||
66 | + }; | ||
67 | + }, | ||
68 | +}); |
src/layouts/default/actions/notice/NoticeList.tsx
0 → 100644
1 | +import { defineComponent } from 'vue'; | ||
2 | +import { List, Avatar, Tag } from 'ant-design-vue'; | ||
3 | + | ||
4 | +import { NoticeListItem } from './data'; | ||
5 | +import './index.less'; | ||
6 | + | ||
7 | +const prefixCls = 'notice-popover'; | ||
8 | +export default defineComponent({ | ||
9 | + name: 'NoticeList', | ||
10 | + props: { | ||
11 | + list: { | ||
12 | + type: Array, | ||
13 | + default: () => [], | ||
14 | + }, | ||
15 | + }, | ||
16 | + setup(props) { | ||
17 | + // 头像渲染 | ||
18 | + function renderAvatar(avatar: string) { | ||
19 | + return avatar ? <Avatar class="avatar" src={avatar} /> : <span>{avatar}</span>; | ||
20 | + } | ||
21 | + | ||
22 | + // 描述渲染 | ||
23 | + function renderDescription(description: string, datetime: string) { | ||
24 | + return ( | ||
25 | + <div> | ||
26 | + <div class="description">{description}</div> | ||
27 | + <div class="datetime">{datetime}</div> | ||
28 | + </div> | ||
29 | + ); | ||
30 | + } | ||
31 | + | ||
32 | + // 标题渲染 | ||
33 | + function renderTitle(title: string, extra?: string, color?: string) { | ||
34 | + return ( | ||
35 | + <div class="title"> | ||
36 | + {title} | ||
37 | + {extra && ( | ||
38 | + <div class="extra"> | ||
39 | + <Tag class="tag" color={color}> | ||
40 | + {() => extra} | ||
41 | + </Tag> | ||
42 | + </div> | ||
43 | + )} | ||
44 | + </div> | ||
45 | + ); | ||
46 | + } | ||
47 | + | ||
48 | + return () => { | ||
49 | + const { list } = props; | ||
50 | + return ( | ||
51 | + <List dataSource={list} class={`${prefixCls}__list`}> | ||
52 | + {() => { | ||
53 | + return list.map((item: NoticeListItem) => { | ||
54 | + const { id, avatar, title, description, datetime, extra, read, color } = item; | ||
55 | + return ( | ||
56 | + <List.Item key={id} class={`${prefixCls}__list-item ${read ? 'read' : ''}`}> | ||
57 | + {() => ( | ||
58 | + <List.Item.Meta | ||
59 | + class="meta" | ||
60 | + avatar={renderAvatar(avatar)} | ||
61 | + title={renderTitle(title, extra, color)} | ||
62 | + description={renderDescription(description, datetime)} | ||
63 | + /> | ||
64 | + )} | ||
65 | + </List.Item> | ||
66 | + ); | ||
67 | + }); | ||
68 | + }} | ||
69 | + </List> | ||
70 | + ); | ||
71 | + }; | ||
72 | + }, | ||
73 | +}); |
src/layouts/default/index.less
@@ -102,12 +102,12 @@ | @@ -102,12 +102,12 @@ | ||
102 | .setting-button { | 102 | .setting-button { |
103 | top: 45%; | 103 | top: 45%; |
104 | right: 0; | 104 | right: 0; |
105 | - padding: 14px; | 105 | + padding: 8px; |
106 | border-radius: 6px 0 0 6px; | 106 | border-radius: 6px 0 0 6px; |
107 | 107 | ||
108 | svg { | 108 | svg { |
109 | - width: 1.2em; | ||
110 | - height: 1.2em; | 109 | + width: 1em; |
110 | + height: 1em; | ||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 |
src/layouts/default/setting/index.vue
@@ -30,7 +30,7 @@ | @@ -30,7 +30,7 @@ | ||
30 | position: absolute; | 30 | position: absolute; |
31 | z-index: 10; | 31 | z-index: 10; |
32 | display: flex; | 32 | display: flex; |
33 | - padding: 10px; | 33 | + // padding: 10px; |
34 | color: @white; | 34 | color: @white; |
35 | cursor: pointer; | 35 | cursor: pointer; |
36 | background: @primary-color; | 36 | background: @primary-color; |
src/layouts/page/index.tsx
@@ -54,6 +54,7 @@ export default defineComponent({ | @@ -54,6 +54,7 @@ export default defineComponent({ | ||
54 | {...on} | 54 | {...on} |
55 | name={name || route.meta.transitionName || routerTransition} | 55 | name={name || route.meta.transitionName || routerTransition} |
56 | mode="out-in" | 56 | mode="out-in" |
57 | + appear={true} | ||
57 | > | 58 | > |
58 | {() => Content} | 59 | {() => Content} |
59 | </Transition> | 60 | </Transition> |
src/main.ts
@@ -3,6 +3,7 @@ import { createApp } from 'vue'; | @@ -3,6 +3,7 @@ import { createApp } from 'vue'; | ||
3 | import router, { setupRouter } from '/@/router'; | 3 | import router, { setupRouter } from '/@/router'; |
4 | import { setupStore } from '/@/store'; | 4 | import { setupStore } from '/@/store'; |
5 | import { setupAntd } from '/@/setup/ant-design-vue'; | 5 | import { setupAntd } from '/@/setup/ant-design-vue'; |
6 | +import { setupErrorHandle } from '/@/setup/error-handle/index'; | ||
6 | import { setupDirectives } from '/@/setup/directives/index'; | 7 | import { setupDirectives } from '/@/setup/directives/index'; |
7 | 8 | ||
8 | import { registerGlobComp } from '/@/components/registerGlobComp'; | 9 | import { registerGlobComp } from '/@/components/registerGlobComp'; |
@@ -21,10 +22,12 @@ setupRouter(app); | @@ -21,10 +22,12 @@ setupRouter(app); | ||
21 | // store | 22 | // store |
22 | setupStore(app); | 23 | setupStore(app); |
23 | 24 | ||
24 | -registerGlobComp(app); | ||
25 | - | ||
26 | setupDirectives(app); | 25 | setupDirectives(app); |
27 | 26 | ||
27 | +setupErrorHandle(app); | ||
28 | + | ||
29 | +registerGlobComp(app); | ||
30 | + | ||
28 | router.isReady().then(() => { | 31 | router.isReady().then(() => { |
29 | app.mount('#app'); | 32 | app.mount('#app'); |
30 | }); | 33 | }); |
src/router/menus/modules/demo/exception.ts
src/router/routes/modules/demo/exception.ts
@@ -78,5 +78,13 @@ export default { | @@ -78,5 +78,13 @@ export default { | ||
78 | afterCloseLoading: true, | 78 | afterCloseLoading: true, |
79 | }, | 79 | }, |
80 | }, | 80 | }, |
81 | + { | ||
82 | + path: '/error-log', | ||
83 | + name: 'ErrorLog', | ||
84 | + component: () => import('/@/views/sys/error-log/index.vue'), | ||
85 | + meta: { | ||
86 | + title: '错误日志', | ||
87 | + }, | ||
88 | + }, | ||
81 | ], | 89 | ], |
82 | } as AppRouteModule; | 90 | } as AppRouteModule; |
src/settings/projectSetting.ts
@@ -30,7 +30,7 @@ const setting: ProjectConfig = { | @@ -30,7 +30,7 @@ const setting: ProjectConfig = { | ||
30 | // theme | 30 | // theme |
31 | theme: MenuThemeEnum.LIGHT, | 31 | theme: MenuThemeEnum.LIGHT, |
32 | // 开启锁屏功能 | 32 | // 开启锁屏功能 |
33 | - useLockPage: isProdMode(), | 33 | + useLockPage: true, |
34 | // 显示刷新按钮 | 34 | // 显示刷新按钮 |
35 | showRedo: true, | 35 | showRedo: true, |
36 | // 显示全屏按钮 | 36 | // 显示全屏按钮 |
@@ -86,7 +86,7 @@ const setting: ProjectConfig = { | @@ -86,7 +86,7 @@ const setting: ProjectConfig = { | ||
86 | // 是否开启KeepAlive缓存 开发时候最好关闭,不然每次都需要清除缓存 | 86 | // 是否开启KeepAlive缓存 开发时候最好关闭,不然每次都需要清除缓存 |
87 | openKeepAlive: true, | 87 | openKeepAlive: true, |
88 | 88 | ||
89 | - // 自动锁屏时间,为0不锁屏。 单位分钟 默认1个小时 | 89 | + // 自动锁屏时间,为0不锁屏。 单位分钟 默认0 |
90 | lockTime: 0, | 90 | lockTime: 0, |
91 | // 显示面包屑 | 91 | // 显示面包屑 |
92 | showBreadCrumb: true, | 92 | showBreadCrumb: true, |
@@ -96,6 +96,7 @@ const setting: ProjectConfig = { | @@ -96,6 +96,7 @@ const setting: ProjectConfig = { | ||
96 | 96 | ||
97 | // 开启页面切换动画 | 97 | // 开启页面切换动画 |
98 | openRouterTransition: true, | 98 | openRouterTransition: true, |
99 | + | ||
99 | // 路由切换动画 | 100 | // 路由切换动画 |
100 | routerTransition: RouterTransitionEnum.ZOOM_FADE, | 101 | routerTransition: RouterTransitionEnum.ZOOM_FADE, |
101 | 102 |
src/setup/error-handle/index.ts
0 → 100644
1 | +import { errorStore, ErrorInfo } from '/@/store/modules/error'; | ||
2 | +import { useSetting } from '/@/hooks/core/useSetting'; | ||
3 | +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; | ||
4 | +import { App } from 'vue'; | ||
5 | +function processStackMsg(error: Error) { | ||
6 | + if (!error.stack) { | ||
7 | + return ''; | ||
8 | + } | ||
9 | + let stack = error.stack | ||
10 | + .replace(/\n/gi, '') // 去掉换行,节省传输内容大小 | ||
11 | + .replace(/\bat\b/gi, '@') // chrome中是at,ff中是@ | ||
12 | + .split('@') // 以@分割信息 | ||
13 | + .slice(0, 9) // 最大堆栈长度(Error.stackTraceLimit = 10),所以只取前10条 | ||
14 | + .map((v) => v.replace(/^\s*|\s*$/g, '')) // 去除多余空格 | ||
15 | + .join('~') // 手动添加分隔符,便于后期展示 | ||
16 | + .replace(/\?[^:]+/gi, ''); // 去除js文件链接的多余参数(?x=1之类) | ||
17 | + const msg = error.toString(); | ||
18 | + if (stack.indexOf(msg) < 0) { | ||
19 | + stack = msg + '@' + stack; | ||
20 | + } | ||
21 | + return stack; | ||
22 | +} | ||
23 | + | ||
24 | +function formatComponentName(vm: any) { | ||
25 | + if (vm.$root === vm) { | ||
26 | + return { | ||
27 | + name: 'root', | ||
28 | + path: 'root', | ||
29 | + }; | ||
30 | + } | ||
31 | + | ||
32 | + const options = vm.$options as any; | ||
33 | + if (!options) { | ||
34 | + return { | ||
35 | + name: 'anonymous', | ||
36 | + path: 'anonymous', | ||
37 | + }; | ||
38 | + } | ||
39 | + const name = options.name || options._componentTag; | ||
40 | + return { | ||
41 | + name: name, | ||
42 | + path: options.__file, | ||
43 | + }; | ||
44 | +} | ||
45 | + | ||
46 | +function vueErrorHandler(err: Error, vm: any, info: string) { | ||
47 | + const { name, path } = formatComponentName(vm); | ||
48 | + errorStore.commitErrorInfoState({ | ||
49 | + type: ErrorTypeEnum.VUE, | ||
50 | + name, | ||
51 | + file: path, | ||
52 | + message: err.message, | ||
53 | + stack: processStackMsg(err), | ||
54 | + detail: info, | ||
55 | + url: window.location.href, | ||
56 | + }); | ||
57 | +} | ||
58 | + | ||
59 | +export function scriptErrorHandler( | ||
60 | + event: Event | string, | ||
61 | + source?: string, | ||
62 | + lineno?: number, | ||
63 | + colno?: number, | ||
64 | + error?: Error | ||
65 | +) { | ||
66 | + if (event === 'Script error.' && !source) { | ||
67 | + return false; | ||
68 | + } | ||
69 | + setTimeout(function () { | ||
70 | + const errorInfo: Partial<ErrorInfo> = {}; | ||
71 | + colno = colno || (window.event && (window.event as any).errorCharacter) || 0; | ||
72 | + errorInfo.message = event as string; | ||
73 | + if (error && error.stack) { | ||
74 | + errorInfo.stack = error.stack; | ||
75 | + } else { | ||
76 | + errorInfo.stack = ''; | ||
77 | + } | ||
78 | + const name = source ? source.substr(source.lastIndexOf('/') + 1) : 'script'; | ||
79 | + errorStore.commitErrorInfoState({ | ||
80 | + type: ErrorTypeEnum.SCRIPT, | ||
81 | + name: name, | ||
82 | + file: source as string, | ||
83 | + detail: 'lineno' + lineno, | ||
84 | + url: window.location.href, | ||
85 | + ...(errorInfo as Pick<ErrorInfo, 'message' | 'stack'>), | ||
86 | + }); | ||
87 | + }, 0); | ||
88 | + return true; | ||
89 | +} | ||
90 | + | ||
91 | +function registerPromiseErrorHandler() { | ||
92 | + window.addEventListener( | ||
93 | + 'unhandledrejection', | ||
94 | + function (event: any) { | ||
95 | + errorStore.commitErrorInfoState({ | ||
96 | + type: ErrorTypeEnum.PROMISE, | ||
97 | + name: 'Promise Error!', | ||
98 | + file: 'none', | ||
99 | + detail: 'promise error!', | ||
100 | + url: window.location.href, | ||
101 | + stack: 'promise error!', | ||
102 | + message: event.reason, | ||
103 | + }); | ||
104 | + }, | ||
105 | + true | ||
106 | + ); | ||
107 | +} | ||
108 | + | ||
109 | +function registerResourceErrorHandler() { | ||
110 | + // 监控资源加载错误(img,script,css,以及jsonp) | ||
111 | + window.addEventListener( | ||
112 | + 'error', | ||
113 | + function (e: Event) { | ||
114 | + const target = e.target ? e.target : (e.srcElement as any); | ||
115 | + | ||
116 | + errorStore.commitErrorInfoState({ | ||
117 | + type: ErrorTypeEnum.RESOURCE, | ||
118 | + name: 'Resouce Error!', | ||
119 | + file: (e.target || ({} as any)).currentSrc, | ||
120 | + detail: JSON.stringify({ | ||
121 | + tagName: target.localName, | ||
122 | + html: target.outerHTML, | ||
123 | + type: e.type, | ||
124 | + }), | ||
125 | + url: window.location.href, | ||
126 | + stack: 'resouce is not found', | ||
127 | + message: (e.target || ({} as any)).localName + ' is load error', | ||
128 | + }); | ||
129 | + }, | ||
130 | + true | ||
131 | + ); | ||
132 | +} | ||
133 | + | ||
134 | +export function setupErrorHandle(app: App) { | ||
135 | + const { projectSetting } = useSetting(); | ||
136 | + const { useErrorHandle } = projectSetting; | ||
137 | + if (!useErrorHandle) { | ||
138 | + return; | ||
139 | + } | ||
140 | + // Vue异常监控; | ||
141 | + app.config.errorHandler = vueErrorHandler; | ||
142 | + // js错误 | ||
143 | + window.onerror = scriptErrorHandler; | ||
144 | + // promise 异常 | ||
145 | + registerPromiseErrorHandler(); | ||
146 | + | ||
147 | + // 静态资源异常 | ||
148 | + registerResourceErrorHandler(); | ||
149 | +} |
src/store/modules/error.ts
1 | import store from '/@/store'; | 1 | import store from '/@/store'; |
2 | import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper'; | 2 | import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper'; |
3 | -import { VuexModule, getModule, Module, Mutation } from 'vuex-module-decorators'; | 3 | +import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators'; |
4 | 4 | ||
5 | import { formatToDateTime } from '/@/utils/dateUtil'; | 5 | import { formatToDateTime } from '/@/utils/dateUtil'; |
6 | -export enum ErrorTypeEnum { | ||
7 | - VUE = 'vue', | ||
8 | - SCRIPT = 'script', | ||
9 | - RESOURCE = 'resource', | ||
10 | - AJAX = 'ajax', | ||
11 | - PROMISE = 'promise', | ||
12 | -} | 6 | +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; |
7 | +import { useSetting } from '/@/hooks/core/useSetting'; | ||
13 | 8 | ||
14 | export interface ErrorInfo { | 9 | export interface ErrorInfo { |
15 | type: ErrorTypeEnum; | 10 | type: ErrorTypeEnum; |
@@ -43,10 +38,11 @@ class Error extends VuexModule implements ErrorState { | @@ -43,10 +38,11 @@ class Error extends VuexModule implements ErrorState { | ||
43 | 38 | ||
44 | @Mutation | 39 | @Mutation |
45 | commitErrorInfoState(info: ErrorInfo): void { | 40 | commitErrorInfoState(info: ErrorInfo): void { |
46 | - this.errorInfoState.unshift({ | 41 | + const item = { |
47 | ...info, | 42 | ...info, |
48 | time: formatToDateTime(new Date()), | 43 | time: formatToDateTime(new Date()), |
49 | - }); | 44 | + }; |
45 | + this.errorInfoState = [item, ...this.errorInfoState]; | ||
50 | this.errorListCountState += 1; | 46 | this.errorListCountState += 1; |
51 | } | 47 | } |
52 | 48 | ||
@@ -54,6 +50,30 @@ class Error extends VuexModule implements ErrorState { | @@ -54,6 +50,30 @@ class Error extends VuexModule implements ErrorState { | ||
54 | commitErrorListCountState(count: number): void { | 50 | commitErrorListCountState(count: number): void { |
55 | this.errorListCountState = count; | 51 | this.errorListCountState = count; |
56 | } | 52 | } |
53 | + | ||
54 | + @Action | ||
55 | + setupErrorHandle(error: any) { | ||
56 | + const { projectSetting } = useSetting(); | ||
57 | + const { useErrorHandle } = projectSetting; | ||
58 | + if (!useErrorHandle) return; | ||
59 | + | ||
60 | + const errInfo: Partial<ErrorInfo> = { | ||
61 | + message: error.message, | ||
62 | + type: ErrorTypeEnum.AJAX, | ||
63 | + }; | ||
64 | + if (error.response) { | ||
65 | + const { | ||
66 | + config: { url = '', data: params = '', method = 'get', headers = {} } = {}, | ||
67 | + data = {}, | ||
68 | + } = error.response; | ||
69 | + errInfo.url = url; | ||
70 | + errInfo.name = 'Ajax Error!'; | ||
71 | + errInfo.file = '-'; | ||
72 | + errInfo.stack = JSON.stringify(data); | ||
73 | + errInfo.detail = JSON.stringify({ params, method, headers }); | ||
74 | + } | ||
75 | + this.commitErrorInfoState(errInfo as ErrorInfo); | ||
76 | + } | ||
57 | } | 77 | } |
58 | export { Error }; | 78 | export { Error }; |
59 | export const errorStore = getModule<Error>(Error); | 79 | export const errorStore = getModule<Error>(Error); |
src/utils/http/axios/index.ts
@@ -18,36 +18,13 @@ import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum'; | @@ -18,36 +18,13 @@ import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum'; | ||
18 | import { isString } from '/@/utils/is'; | 18 | import { isString } from '/@/utils/is'; |
19 | import { formatRequestDate } from '/@/utils/dateUtil'; | 19 | import { formatRequestDate } from '/@/utils/dateUtil'; |
20 | import { setObjToUrlParams, deepMerge } from '/@/utils'; | 20 | import { setObjToUrlParams, deepMerge } from '/@/utils'; |
21 | -import { errorStore, ErrorTypeEnum, ErrorInfo } from '/@/store/modules/error'; | ||
22 | -import { appStore } from '/@/store/modules/app'; | 21 | +import { errorStore } from '/@/store/modules/error'; |
23 | import { errorResult } from './const'; | 22 | import { errorResult } from './const'; |
24 | 23 | ||
25 | const { globSetting } = useSetting(); | 24 | const { globSetting } = useSetting(); |
26 | const prefix = globSetting.urlPrefix; | 25 | const prefix = globSetting.urlPrefix; |
27 | const { createMessage, createErrorModal } = useMessage(); | 26 | const { createMessage, createErrorModal } = useMessage(); |
28 | 27 | ||
29 | -function setupErrorHandle(error: any) { | ||
30 | - const { useErrorHandle } = appStore.getProjectConfig; | ||
31 | - if (!useErrorHandle) return; | ||
32 | - | ||
33 | - const errInfo: Partial<ErrorInfo> = { | ||
34 | - message: error.message, | ||
35 | - type: ErrorTypeEnum.AJAX, | ||
36 | - }; | ||
37 | - if (error.response) { | ||
38 | - const { | ||
39 | - config: { url = '', data: params = '', method = 'get', headers = {} } = {}, | ||
40 | - data = {}, | ||
41 | - } = error.response; | ||
42 | - errInfo.url = url; | ||
43 | - errInfo.name = 'Ajax Error!'; | ||
44 | - errInfo.file = '-'; | ||
45 | - errInfo.stack = JSON.stringify(data); | ||
46 | - errInfo.detail = JSON.stringify({ params, method, headers }); | ||
47 | - } | ||
48 | - errorStore.commitErrorInfoState(errInfo as ErrorInfo); | ||
49 | -} | ||
50 | - | ||
51 | /** | 28 | /** |
52 | * @description: 数据处理,方便区分多种处理方式 | 29 | * @description: 数据处理,方便区分多种处理方式 |
53 | */ | 30 | */ |
@@ -175,7 +152,7 @@ const transform: AxiosTransform = { | @@ -175,7 +152,7 @@ const transform: AxiosTransform = { | ||
175 | * @description: 响应错误处理 | 152 | * @description: 响应错误处理 |
176 | */ | 153 | */ |
177 | responseInterceptorsCatch: (error: any) => { | 154 | responseInterceptorsCatch: (error: any) => { |
178 | - setupErrorHandle(error); | 155 | + errorStore.setupErrorHandle(error); |
179 | const { response, code, message } = error || {}; | 156 | const { response, code, message } = error || {}; |
180 | const msg: string = | 157 | const msg: string = |
181 | response && response.data && response.data.error ? response.data.error.message : ''; | 158 | response && response.data && response.data.error ? response.data.error.message : ''; |
src/views/sys/error-log/DetailModal.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicModal :width="800" title="错误详情" v-bind="$attrs"> | ||
3 | + <Description :data="info" @register="register" /> | ||
4 | + </BasicModal> | ||
5 | +</template> | ||
6 | +<script lang="ts"> | ||
7 | + import { defineComponent, PropType } from 'vue'; | ||
8 | + import { BasicModal } from '/@/components/Modal/index'; | ||
9 | + import { ErrorInfo } from '/@/store/modules/error'; | ||
10 | + import { Description, useDescription } from '/@/components/Description/index'; | ||
11 | + import { getDescSchema } from './data'; | ||
12 | + | ||
13 | + export default defineComponent({ | ||
14 | + name: 'ErrorLogDetailModal', | ||
15 | + components: { BasicModal, Description }, | ||
16 | + props: { | ||
17 | + info: { | ||
18 | + type: Object as PropType<ErrorInfo>, | ||
19 | + default: null, | ||
20 | + }, | ||
21 | + }, | ||
22 | + setup() { | ||
23 | + const [register] = useDescription({ | ||
24 | + column: 2, | ||
25 | + schema: getDescSchema(), | ||
26 | + }); | ||
27 | + return { | ||
28 | + register, | ||
29 | + }; | ||
30 | + }, | ||
31 | + }); | ||
32 | +</script> |
src/views/sys/error-log/data.tsx
0 → 100644
1 | +import { Tag } from 'ant-design-vue'; | ||
2 | +import { BasicColumn } from '/@/components/Table/index'; | ||
3 | +import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; | ||
4 | + | ||
5 | +export function getColumns(): BasicColumn[] { | ||
6 | + return [ | ||
7 | + { | ||
8 | + dataIndex: 'type', | ||
9 | + title: '类型', | ||
10 | + width: 80, | ||
11 | + customRender: ({ text }) => { | ||
12 | + const color = | ||
13 | + text === ErrorTypeEnum.VUE | ||
14 | + ? 'green' | ||
15 | + : text === ErrorTypeEnum.RESOURCE | ||
16 | + ? 'cyan' | ||
17 | + : text === ErrorTypeEnum.PROMISE | ||
18 | + ? 'blue' | ||
19 | + : ErrorTypeEnum.AJAX | ||
20 | + ? 'red' | ||
21 | + : 'purple'; | ||
22 | + return <Tag color={color}>{() => text}</Tag>; | ||
23 | + }, | ||
24 | + }, | ||
25 | + { | ||
26 | + dataIndex: 'url', | ||
27 | + title: '地址', | ||
28 | + width: 200, | ||
29 | + }, | ||
30 | + { | ||
31 | + dataIndex: 'time', | ||
32 | + title: '时间', | ||
33 | + width: 160, | ||
34 | + }, | ||
35 | + { | ||
36 | + dataIndex: 'file', | ||
37 | + title: '文件', | ||
38 | + width: 200, | ||
39 | + }, | ||
40 | + { | ||
41 | + dataIndex: 'name', | ||
42 | + title: 'Name', | ||
43 | + width: 200, | ||
44 | + }, | ||
45 | + { | ||
46 | + dataIndex: 'message', | ||
47 | + title: '错误信息', | ||
48 | + width: 300, | ||
49 | + }, | ||
50 | + { | ||
51 | + dataIndex: 'stack', | ||
52 | + title: 'stack信息', | ||
53 | + width: 300, | ||
54 | + }, | ||
55 | + ]; | ||
56 | +} | ||
57 | + | ||
58 | +export function getDescSchema() { | ||
59 | + return getColumns().map((column) => { | ||
60 | + return { | ||
61 | + field: column.dataIndex!, | ||
62 | + label: column.title, | ||
63 | + }; | ||
64 | + }); | ||
65 | +} |
src/views/sys/error-log/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div class="p-4"> | ||
3 | + <template v-for="src in imgListRef" :key="src"> | ||
4 | + <img :src="src" v-show="false" /> | ||
5 | + </template> | ||
6 | + <DetailModal :info="rowInfoRef" @register="registerModal" /> | ||
7 | + <BasicTable @register="register" class="error-handle-table"> | ||
8 | + <template #toolbar> | ||
9 | + <a-button @click="fireVueError" type="primary"> 点击触发vue错误 </a-button> | ||
10 | + <a-button @click="fireResourceError" type="primary"> 点击触发resource错误 </a-button> | ||
11 | + <a-button @click="fireAjaxError" type="primary"> 点击触发ajax错误 </a-button> | ||
12 | + </template> | ||
13 | + <template #action="{ record }"> | ||
14 | + <TableAction :actions="[{ label: '详情', onClick: handleDetail.bind(null, record) }]" /> | ||
15 | + </template> | ||
16 | + </BasicTable> | ||
17 | + </div> | ||
18 | +</template> | ||
19 | + | ||
20 | +<script lang="ts"> | ||
21 | + import { defineComponent, watch, ref, nextTick } from 'vue'; | ||
22 | + | ||
23 | + import DetailModal from './DetailModal.vue'; | ||
24 | + import { useModal } from '/@/components/Modal/index'; | ||
25 | + | ||
26 | + import { BasicTable, useTable, TableAction } from '/@/components/Table/index'; | ||
27 | + | ||
28 | + import { errorStore, ErrorInfo } from '/@/store/modules/error'; | ||
29 | + | ||
30 | + import { fireErrorApi } from '/@/api/demo/error'; | ||
31 | + | ||
32 | + import { getColumns } from './data'; | ||
33 | + | ||
34 | + import { cloneDeep } from 'lodash-es'; | ||
35 | + | ||
36 | + export default defineComponent({ | ||
37 | + name: 'ErrorHandler', | ||
38 | + components: { DetailModal, BasicTable, TableAction }, | ||
39 | + setup() { | ||
40 | + const rowInfoRef = ref<ErrorInfo>(); | ||
41 | + const imgListRef = ref<string[]>([]); | ||
42 | + const [register, { setTableData }] = useTable({ | ||
43 | + titleHelpMessage: '只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效!', | ||
44 | + title: '错误日志列表', | ||
45 | + columns: getColumns(), | ||
46 | + actionColumn: { | ||
47 | + width: 80, | ||
48 | + title: '操作', | ||
49 | + dataIndex: 'action', | ||
50 | + slots: { customRender: 'action' }, | ||
51 | + }, | ||
52 | + }); | ||
53 | + | ||
54 | + const [registerModal, { openModal }] = useModal(); | ||
55 | + watch( | ||
56 | + () => errorStore.getErrorInfoState, | ||
57 | + (list) => { | ||
58 | + nextTick(() => { | ||
59 | + setTableData(cloneDeep(list)); | ||
60 | + }); | ||
61 | + }, | ||
62 | + { | ||
63 | + immediate: true, | ||
64 | + } | ||
65 | + ); | ||
66 | + | ||
67 | + // 查看详情 | ||
68 | + function handleDetail(row: ErrorInfo) { | ||
69 | + rowInfoRef.value = row; | ||
70 | + openModal(true); | ||
71 | + } | ||
72 | + | ||
73 | + function fireVueError() { | ||
74 | + throw new Error('fire vue error!'); | ||
75 | + } | ||
76 | + | ||
77 | + function fireResourceError() { | ||
78 | + imgListRef.value.push(`${new Date().getTime()}.png`); | ||
79 | + } | ||
80 | + | ||
81 | + async function fireAjaxError() { | ||
82 | + await fireErrorApi(); | ||
83 | + } | ||
84 | + | ||
85 | + return { | ||
86 | + register, | ||
87 | + registerModal, | ||
88 | + handleDetail, | ||
89 | + fireVueError, | ||
90 | + fireResourceError, | ||
91 | + fireAjaxError, | ||
92 | + imgListRef, | ||
93 | + rowInfoRef, | ||
94 | + }; | ||
95 | + }, | ||
96 | + }); | ||
97 | +</script> |
src/views/sys/lock/index.vue
@@ -118,8 +118,8 @@ | @@ -118,8 +118,8 @@ | ||
118 | &__entry { | 118 | &__entry { |
119 | position: relative; | 119 | position: relative; |
120 | width: 400px; | 120 | width: 400px; |
121 | - height: 260px; | ||
122 | - padding: 80px 50px 0 50px; | 121 | + // height: 260px; |
122 | + padding: 80px 50px 50px 50px; | ||
123 | margin-right: 50px; | 123 | margin-right: 50px; |
124 | background: #fff; | 124 | background: #fff; |
125 | border-radius: 6px; | 125 | border-radius: 6px; |
vite.config.ts
@@ -13,7 +13,7 @@ import { createProxy } from './build/config/vite/proxy'; | @@ -13,7 +13,7 @@ import { createProxy } from './build/config/vite/proxy'; | ||
13 | import { createMockServer } from 'vite-plugin-mock'; | 13 | import { createMockServer } from 'vite-plugin-mock'; |
14 | import PurgeIcons from 'vite-plugin-purge-icons'; | 14 | import PurgeIcons from 'vite-plugin-purge-icons'; |
15 | import gzipPlugin from './build/plugin/gzip/index'; | 15 | import gzipPlugin from './build/plugin/gzip/index'; |
16 | -import globbyTransform from './build/plugin/vite-plugin-context-plugin/transform'; | 16 | +import globbyTransform from './build/plugin/vite-plugin-context/transform'; |
17 | 17 | ||
18 | import { isDevFn, isReportMode, isProdFn, loadEnv, isBuildGzip, isSiteMode } from './build/utils'; | 18 | import { isDevFn, isReportMode, isProdFn, loadEnv, isBuildGzip, isSiteMode } from './build/utils'; |
19 | const pkg = require('./package.json'); | 19 | const pkg = require('./package.json'); |
yarn.lock
@@ -386,10 +386,10 @@ | @@ -386,10 +386,10 @@ | ||
386 | resolved "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.0.0-rc.1.tgz#a8bae29d71016d5af98c69f56a73c4a040217b3a" | 386 | resolved "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.0.0-rc.1.tgz#a8bae29d71016d5af98c69f56a73c4a040217b3a" |
387 | integrity sha512-ji5H04VjYtR4seIEgVVLPxg1KRhrFquOiyfPyLVS6vYPkuqV6bcWdssi05YSmf/OAzG4E7Qsg80/bOKyd5tYTw== | 387 | integrity sha512-ji5H04VjYtR4seIEgVVLPxg1KRhrFquOiyfPyLVS6vYPkuqV6bcWdssi05YSmf/OAzG4E7Qsg80/bOKyd5tYTw== |
388 | 388 | ||
389 | -"@iconify/json@^1.1.242": | ||
390 | - version "1.1.242" | ||
391 | - resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.242.tgz#f43b83acb7c3fe7906eb46cbe174a946aa17f9ff" | ||
392 | - integrity sha512-uxiUvrINyZlITzKxa2J/75AzReenah83XxQLyryVHjGCSqNWQjQICmBLlrCsch5PMr5nF9JeNMbIPDzxlS59Og== | 389 | +"@iconify/json@^1.1.243": |
390 | + version "1.1.243" | ||
391 | + resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.243.tgz#8013fc781621b2549e379aab4e3e945974ec8032" | ||
392 | + integrity sha512-vf8N+fUJysvCoJknS4XqorlvWLqjw/+Mid8CuzxQxMX8/RlWRU1yMFIgRpGAkMnCYe38KUtHqFVu0FlVNGP/Lw== | ||
393 | 393 | ||
394 | "@ls-lint/ls-lint@^1.9.2": | 394 | "@ls-lint/ls-lint@^1.9.2": |
395 | version "1.9.2" | 395 | version "1.9.2" |
@@ -577,10 +577,10 @@ | @@ -577,10 +577,10 @@ | ||
577 | "@types/keygrip" "*" | 577 | "@types/keygrip" "*" |
578 | "@types/node" "*" | 578 | "@types/node" "*" |
579 | 579 | ||
580 | -"@types/echarts@^4.8.1": | ||
581 | - version "4.8.1" | ||
582 | - resolved "https://registry.npmjs.org/@types/echarts/-/echarts-4.8.1.tgz#e03aed60bbf25b7629affab699175df2e980fbb2" | ||
583 | - integrity sha512-+kyP8TUkyJgmIBioPBJiTay9G7f/xcW7/8CYgh3iWa8kQ/SbGmAIpXyyCXtiWqPXT+tnsIONLC4hcNfmxVfxAg== | 580 | +"@types/echarts@^4.8.3": |
581 | + version "4.8.3" | ||
582 | + resolved "https://registry.npmjs.org/@types/echarts/-/echarts-4.8.3.tgz#78ef1ede01c3705b52342da997b3d54571d3604e" | ||
583 | + integrity sha512-5aFZ7/6f+SPonLh4Nuso6pEZWwX8VBMYh2e83x1GVEpGkcN3GC0HzxPoF6ZSZPwoe5Rg4bhNwD9f2TVYxgU/QQ== | ||
584 | dependencies: | 584 | dependencies: |
585 | "@types/zrender" "*" | 585 | "@types/zrender" "*" |
586 | 586 | ||
@@ -849,10 +849,10 @@ | @@ -849,10 +849,10 @@ | ||
849 | resolved "https://registry.npm.taobao.org/@types/yargs-parser/download/@types/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" | 849 | resolved "https://registry.npm.taobao.org/@types/yargs-parser/download/@types/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" |
850 | integrity sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= | 850 | integrity sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= |
851 | 851 | ||
852 | -"@types/yargs@^15.0.8": | ||
853 | - version "15.0.8" | ||
854 | - resolved "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-15.0.8.tgz?cache=0&sync_timestamp=1602182032636&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.8.tgz#7644904cad7427eb704331ea9bf1ee5499b82e23" | ||
855 | - integrity sha1-dkSQTK10J+twQzHqm/HuVJm4LiM= | 852 | +"@types/yargs@^15.0.9": |
853 | + version "15.0.9" | ||
854 | + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz#524cd7998fe810cdb02f26101b699cccd156ff19" | ||
855 | + integrity sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g== | ||
856 | dependencies: | 856 | dependencies: |
857 | "@types/yargs-parser" "*" | 857 | "@types/yargs-parser" "*" |
858 | 858 | ||
@@ -1735,10 +1735,10 @@ cliui@^6.0.0: | @@ -1735,10 +1735,10 @@ cliui@^6.0.0: | ||
1735 | strip-ansi "^6.0.0" | 1735 | strip-ansi "^6.0.0" |
1736 | wrap-ansi "^6.2.0" | 1736 | wrap-ansi "^6.2.0" |
1737 | 1737 | ||
1738 | -cliui@^7.0.0: | ||
1739 | - version "7.0.1" | ||
1740 | - resolved "https://registry.npm.taobao.org/cliui/download/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3" | ||
1741 | - integrity sha1-pMtnqtRc2D2NBRKPyfTY+7iH5rM= | 1738 | +cliui@^7.0.2: |
1739 | + version "7.0.3" | ||
1740 | + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz#ef180f26c8d9bff3927ee52428bfec2090427981" | ||
1741 | + integrity sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw== | ||
1742 | dependencies: | 1742 | dependencies: |
1743 | string-width "^4.2.0" | 1743 | string-width "^4.2.0" |
1744 | strip-ansi "^6.0.0" | 1744 | strip-ansi "^6.0.0" |
@@ -2537,11 +2537,16 @@ esbuild@^0.7.1: | @@ -2537,11 +2537,16 @@ esbuild@^0.7.1: | ||
2537 | resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.14.tgz#9de555e75669187c2315317fbf489b229b1a4cbb" | 2537 | resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.14.tgz#9de555e75669187c2315317fbf489b229b1a4cbb" |
2538 | integrity sha512-w2CEVeRcUhCGYMHnNNwb8q+9w42scL7RcNzJm85gZVzNBE3AF0sLq5YP/IdaTBJIFBphIKG3bGbwRH+zsgH/ig== | 2538 | integrity sha512-w2CEVeRcUhCGYMHnNNwb8q+9w42scL7RcNzJm85gZVzNBE3AF0sLq5YP/IdaTBJIFBphIKG3bGbwRH+zsgH/ig== |
2539 | 2539 | ||
2540 | -escalade@^3.0.2, escalade@^3.1.0: | 2540 | +escalade@^3.1.0: |
2541 | version "3.1.0" | 2541 | version "3.1.0" |
2542 | resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" | 2542 | resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" |
2543 | integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== | 2543 | integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== |
2544 | 2544 | ||
2545 | +escalade@^3.1.1: | ||
2546 | + version "3.1.1" | ||
2547 | + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" | ||
2548 | + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== | ||
2549 | + | ||
2545 | escape-goat@^2.0.0: | 2550 | escape-goat@^2.0.0: |
2546 | version "2.1.1" | 2551 | version "2.1.1" |
2547 | resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" | 2552 | resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" |
@@ -2557,10 +2562,10 @@ escape-string-regexp@^1.0.5: | @@ -2557,10 +2562,10 @@ escape-string-regexp@^1.0.5: | ||
2557 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" | 2562 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" |
2558 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= | 2563 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= |
2559 | 2564 | ||
2560 | -eslint-config-prettier@^6.12.0: | ||
2561 | - version "6.12.0" | ||
2562 | - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2" | ||
2563 | - integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw== | 2565 | +eslint-config-prettier@^6.13.0: |
2566 | + version "6.13.0" | ||
2567 | + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.13.0.tgz#207d88796b5624e5bb815bbbdfc5891ceb9ebffa" | ||
2568 | + integrity sha512-LcT0i0LSmnzqK2t764pyIt7kKH2AuuqKRTtJTdddWxOiUja9HdG5GXBVF2gmCTvVYWVsTu8J2MhJLVGRh+pj8w== | ||
2564 | dependencies: | 2569 | dependencies: |
2565 | get-stdin "^6.0.0" | 2570 | get-stdin "^6.0.0" |
2566 | 2571 | ||
@@ -4207,10 +4212,10 @@ lines-and-columns@^1.1.6: | @@ -4207,10 +4212,10 @@ lines-and-columns@^1.1.6: | ||
4207 | resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" | 4212 | resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" |
4208 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= | 4213 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= |
4209 | 4214 | ||
4210 | -lint-staged@^10.4.0: | ||
4211 | - version "10.4.0" | ||
4212 | - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.0.tgz#d18628f737328e0bbbf87d183f4020930e9a984e" | ||
4213 | - integrity sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg== | 4215 | +lint-staged@^10.4.2: |
4216 | + version "10.4.2" | ||
4217 | + resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.2.tgz#9fee4635c4b5ddb845746f237c6d43494ccd21c1" | ||
4218 | + integrity sha512-OLCA9K1hS+Sl179SO6kX0JtnsaKj/MZalEhUj5yAgXsb63qPI/Gfn6Ua1KuZdbfkZNEu3/n5C/obYCu70IMt9g== | ||
4214 | dependencies: | 4219 | dependencies: |
4215 | chalk "^4.1.0" | 4220 | chalk "^4.1.0" |
4216 | cli-truncate "^2.1.0" | 4221 | cli-truncate "^2.1.0" |
@@ -7268,10 +7273,10 @@ y18n@^4.0.0: | @@ -7268,10 +7273,10 @@ y18n@^4.0.0: | ||
7268 | resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" | 7273 | resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" |
7269 | integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== | 7274 | integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== |
7270 | 7275 | ||
7271 | -y18n@^5.0.1: | ||
7272 | - version "5.0.2" | ||
7273 | - resolved "https://registry.npm.taobao.org/y18n/download/y18n-5.0.2.tgz?cache=0&sync_timestamp=1601576683926&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fy18n%2Fdownload%2Fy18n-5.0.2.tgz#48218df5da2731b4403115c39a1af709c873f829" | ||
7274 | - integrity sha1-SCGN9donMbRAMRXDmhr3Cchz+Ck= | 7276 | +y18n@^5.0.2: |
7277 | + version "5.0.4" | ||
7278 | + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.4.tgz#0ab2db89dd5873b5ec4682d8e703e833373ea897" | ||
7279 | + integrity sha512-deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ== | ||
7275 | 7280 | ||
7276 | yallist@^3.0.2: | 7281 | yallist@^3.0.2: |
7277 | version "3.1.1" | 7282 | version "3.1.1" |
@@ -7304,10 +7309,10 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: | @@ -7304,10 +7309,10 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: | ||
7304 | camelcase "^5.0.0" | 7309 | camelcase "^5.0.0" |
7305 | decamelize "^1.2.0" | 7310 | decamelize "^1.2.0" |
7306 | 7311 | ||
7307 | -yargs-parser@^20.0.0: | ||
7308 | - version "20.2.1" | ||
7309 | - resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-20.2.1.tgz?cache=0&sync_timestamp=1601576684570&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-20.2.1.tgz#28f3773c546cdd8a69ddae68116b48a5da328e77" | ||
7310 | - integrity sha1-KPN3PFRs3Ypp3a5oEWtIpdoyjnc= | 7312 | +yargs-parser@^20.2.2: |
7313 | + version "20.2.3" | ||
7314 | + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26" | ||
7315 | + integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww== | ||
7311 | 7316 | ||
7312 | yargs@^13.2.4: | 7317 | yargs@^13.2.4: |
7313 | version "13.3.2" | 7318 | version "13.3.2" |
@@ -7342,18 +7347,18 @@ yargs@^15.0.0, yargs@^15.1.0: | @@ -7342,18 +7347,18 @@ yargs@^15.0.0, yargs@^15.1.0: | ||
7342 | y18n "^4.0.0" | 7347 | y18n "^4.0.0" |
7343 | yargs-parser "^18.1.2" | 7348 | yargs-parser "^18.1.2" |
7344 | 7349 | ||
7345 | -yargs@^16.0.3: | ||
7346 | - version "16.0.3" | ||
7347 | - resolved "https://registry.npm.taobao.org/yargs/download/yargs-16.0.3.tgz?cache=0&sync_timestamp=1600660006050&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c" | ||
7348 | - integrity sha1-epGbnkPJD4DUoUKol5XoU5mn5Uw= | 7350 | +yargs@^16.1.0: |
7351 | + version "16.1.0" | ||
7352 | + resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz#fc333fe4791660eace5a894b39d42f851cd48f2a" | ||
7353 | + integrity sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g== | ||
7349 | dependencies: | 7354 | dependencies: |
7350 | - cliui "^7.0.0" | ||
7351 | - escalade "^3.0.2" | 7355 | + cliui "^7.0.2" |
7356 | + escalade "^3.1.1" | ||
7352 | get-caller-file "^2.0.5" | 7357 | get-caller-file "^2.0.5" |
7353 | require-directory "^2.1.1" | 7358 | require-directory "^2.1.1" |
7354 | string-width "^4.2.0" | 7359 | string-width "^4.2.0" |
7355 | - y18n "^5.0.1" | ||
7356 | - yargs-parser "^20.0.0" | 7360 | + y18n "^5.0.2" |
7361 | + yargs-parser "^20.2.2" | ||
7357 | 7362 | ||
7358 | ylru@^1.2.0: | 7363 | ylru@^1.2.0: |
7359 | version "1.2.1" | 7364 | version "1.2.1" |