Commit b54b794264ecb513567b841c5a12856965d02754
1 parent
8a14069e
fix(table): make sure the editing line is working, fix #439
Showing
12 changed files
with
172 additions
and
29 deletions
CHANGELOG.zh_CN.md
@@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
4 | 4 | ||
5 | - 新增`headerTitle` slot | 5 | - 新增`headerTitle` slot |
6 | - 新增打印示例 | 6 | - 新增打印示例 |
7 | +- 新增关于界面 | ||
7 | 8 | ||
8 | ### ✨ Refactor | 9 | ### ✨ Refactor |
9 | 10 | ||
@@ -15,6 +16,7 @@ | @@ -15,6 +16,7 @@ | ||
15 | 16 | ||
16 | - 确保面包屑正确的显示图标 | 17 | - 确保面包屑正确的显示图标 |
17 | - 修复 tinymce 上传按钮全屏模式下消失问题 | 18 | - 修复 tinymce 上传按钮全屏模式下消失问题 |
19 | +- 确保 title 在重新登录后正常改变 | ||
18 | 20 | ||
19 | ## 2.1.1 (2021-03-26) | 21 | ## 2.1.1 (2021-03-26) |
20 | 22 |
src/components/Table/src/BasicTable.vue
@@ -185,7 +185,7 @@ | @@ -185,7 +185,7 @@ | ||
185 | } = useTableForm(getProps, slots, fetch); | 185 | } = useTableForm(getProps, slots, fetch); |
186 | 186 | ||
187 | const getBindValues = computed(() => { | 187 | const getBindValues = computed(() => { |
188 | - const dataSource = toRaw(unref(getDataSourceRef)); | 188 | + const dataSource = unref(getDataSourceRef); |
189 | let propsData: Recordable = { | 189 | let propsData: Recordable = { |
190 | size: 'middle', | 190 | size: 'middle', |
191 | // ...(dataSource.length === 0 ? { getPopupContainer: () => document.body } : {}), | 191 | // ...(dataSource.length === 0 ? { getPopupContainer: () => document.body } : {}), |
src/components/Table/src/hooks/useTable.ts
@@ -17,7 +17,12 @@ type UseTableMethod = TableActionType & { | @@ -17,7 +17,12 @@ type UseTableMethod = TableActionType & { | ||
17 | 17 | ||
18 | export function useTable( | 18 | export function useTable( |
19 | tableProps?: Props | 19 | tableProps?: Props |
20 | -): [(instance: TableActionType, formInstance: UseTableMethod) => void, TableActionType] { | 20 | +): [ |
21 | + (instance: TableActionType, formInstance: UseTableMethod) => void, | ||
22 | + TableActionType & { | ||
23 | + getForm: () => FormActionType; | ||
24 | + } | ||
25 | +] { | ||
21 | const tableRef = ref<Nullable<TableActionType>>(null); | 26 | const tableRef = ref<Nullable<TableActionType>>(null); |
22 | const loadedRef = ref<Nullable<boolean>>(false); | 27 | const loadedRef = ref<Nullable<boolean>>(false); |
23 | const formRef = ref<Nullable<UseTableMethod>>(null); | 28 | const formRef = ref<Nullable<UseTableMethod>>(null); |
src/hooks/web/useTitle.ts
1 | +import { watch, unref } from 'vue'; | ||
1 | import { useI18n } from '/@/hooks/web/useI18n'; | 2 | import { useI18n } from '/@/hooks/web/useI18n'; |
2 | import { useTitle as usePageTitle } from '@vueuse/core'; | 3 | import { useTitle as usePageTitle } from '@vueuse/core'; |
3 | import { useGlobSetting } from '/@/hooks/setting'; | 4 | import { useGlobSetting } from '/@/hooks/setting'; |
5 | +import { useRouter } from 'vue-router'; | ||
4 | 6 | ||
5 | import { REDIRECT_NAME } from '/@/router/constant'; | 7 | import { REDIRECT_NAME } from '/@/router/constant'; |
6 | -import { listenerRouteChange } from '/@/logics/mitt/routeChange'; | ||
7 | 8 | ||
8 | export function useTitle() { | 9 | export function useTitle() { |
9 | const { title } = useGlobSetting(); | 10 | const { title } = useGlobSetting(); |
10 | const { t } = useI18n(); | 11 | const { t } = useI18n(); |
12 | + const { currentRoute } = useRouter(); | ||
11 | 13 | ||
12 | const pageTitle = usePageTitle(); | 14 | const pageTitle = usePageTitle(); |
13 | 15 | ||
14 | - listenerRouteChange((route) => { | ||
15 | - if (route.name === REDIRECT_NAME) { | ||
16 | - return; | ||
17 | - } | 16 | + watch( |
17 | + () => currentRoute.value.path, | ||
18 | + () => { | ||
19 | + const route = unref(currentRoute); | ||
20 | + if (route.name === REDIRECT_NAME) { | ||
21 | + return; | ||
22 | + } | ||
18 | 23 | ||
19 | - const tTitle = t(route?.meta?.title as string); | ||
20 | - pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`; | ||
21 | - }); | 24 | + const tTitle = t(route?.meta?.title as string); |
25 | + pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`; | ||
26 | + }, | ||
27 | + { immediate: true } | ||
28 | + ); | ||
22 | } | 29 | } |
src/locales/lang/en/routes/dashboard.ts
src/locales/lang/zh_CN/routes/dashboard.ts
src/router/menus/modules/home.ts renamed to src/router/menus/modules/about.ts
1 | import type { MenuModule } from '/@/router/types'; | 1 | import type { MenuModule } from '/@/router/types'; |
2 | import { t } from '/@/hooks/web/useI18n'; | 2 | import { t } from '/@/hooks/web/useI18n'; |
3 | 3 | ||
4 | -const menu: MenuModule = { | ||
5 | - orderNo: 0, | 4 | +const about: MenuModule = { |
5 | + orderNo: 100000, | ||
6 | menu: { | 6 | menu: { |
7 | - path: '/home/welcome', | ||
8 | - name: t('routes.dashboard.welcome'), | 7 | + path: '/about/index', |
8 | + name: t('routes.dashboard.about'), | ||
9 | }, | 9 | }, |
10 | }; | 10 | }; |
11 | -export default menu; | 11 | +export default about; |
src/router/routes/modules/home.ts renamed to src/router/routes/modules/about.ts
@@ -4,23 +4,22 @@ import { LAYOUT } from '/@/router/constant'; | @@ -4,23 +4,22 @@ import { LAYOUT } from '/@/router/constant'; | ||
4 | import { t } from '/@/hooks/web/useI18n'; | 4 | import { t } from '/@/hooks/web/useI18n'; |
5 | 5 | ||
6 | const dashboard: AppRouteModule = { | 6 | const dashboard: AppRouteModule = { |
7 | - path: '/home', | ||
8 | - name: 'Home', | 7 | + path: '/about', |
8 | + name: 'About', | ||
9 | component: LAYOUT, | 9 | component: LAYOUT, |
10 | - redirect: '/home/welcome', | 10 | + redirect: '/about/index', |
11 | meta: { | 11 | meta: { |
12 | - icon: 'ion:home-outline', | ||
13 | - title: t('routes.dashboard.welcome'), | 12 | + icon: 'simple-icons:about-dot-me', |
13 | + title: t('routes.dashboard.about'), | ||
14 | }, | 14 | }, |
15 | children: [ | 15 | children: [ |
16 | { | 16 | { |
17 | - path: 'welcome', | ||
18 | - name: 'Welcome', | ||
19 | - component: () => import('/@/views/dashboard/welcome/index.vue'), | 17 | + path: 'index', |
18 | + name: 'AboutPage', | ||
19 | + component: () => import('/@/views/sys/about/index.vue'), | ||
20 | meta: { | 20 | meta: { |
21 | - title: t('routes.dashboard.welcome'), | ||
22 | - affix: true, | ||
23 | - icon: 'bx:bx-home', | 21 | + title: t('routes.dashboard.about'), |
22 | + icon: 'simple-icons:about-dot-me', | ||
24 | }, | 23 | }, |
25 | }, | 24 | }, |
26 | ], | 25 | ], |
src/views/demo/table/FormTable.vue
1 | <template> | 1 | <template> |
2 | <BasicTable @register="registerTable"> | 2 | <BasicTable @register="registerTable"> |
3 | <template #form-custom> custom-slot </template> | 3 | <template #form-custom> custom-slot </template> |
4 | + | ||
5 | + <template #toolbar> | ||
6 | + <a-button type="primary" @click="getFormValues">获取表单数据</a-button> | ||
7 | + </template> | ||
4 | </BasicTable> | 8 | </BasicTable> |
5 | </template> | 9 | </template> |
6 | <script lang="ts"> | 10 | <script lang="ts"> |
@@ -13,7 +17,7 @@ | @@ -13,7 +17,7 @@ | ||
13 | export default defineComponent({ | 17 | export default defineComponent({ |
14 | components: { BasicTable }, | 18 | components: { BasicTable }, |
15 | setup() { | 19 | setup() { |
16 | - const [registerTable] = useTable({ | 20 | + const [registerTable, { getForm }] = useTable({ |
17 | title: '开启搜索区域', | 21 | title: '开启搜索区域', |
18 | api: demoListApi, | 22 | api: demoListApi, |
19 | columns: getBasicColumns(), | 23 | columns: getBasicColumns(), |
@@ -23,8 +27,13 @@ | @@ -23,8 +27,13 @@ | ||
23 | rowSelection: { type: 'checkbox' }, | 27 | rowSelection: { type: 'checkbox' }, |
24 | }); | 28 | }); |
25 | 29 | ||
30 | + function getFormValues() { | ||
31 | + console.log(getForm().getFieldsValue()); | ||
32 | + } | ||
33 | + | ||
26 | return { | 34 | return { |
27 | registerTable, | 35 | registerTable, |
36 | + getFormValues, | ||
28 | }; | 37 | }; |
29 | }, | 38 | }, |
30 | }); | 39 | }); |
src/views/sys/about/index.vue
0 → 100644
1 | +<template> | ||
2 | + <PageWrapper title="关于"> | ||
3 | + <template #headerContent> | ||
4 | + <div class="flex justify-between items-center"> | ||
5 | + <span class="flex-1"> | ||
6 | + <a :href="GITHUB_URL" target="_blank">{{ name }}</a> | ||
7 | + 是一个基于Vue3.0、Vite、 Ant-Design-Vue 、TypeScript | ||
8 | + 的后台解决方案,目标是为中大型项目开发,提供现成的开箱解决方案及丰富的示例,原则上不会限制任何代码用于商用。 | ||
9 | + </span> | ||
10 | + </div> | ||
11 | + </template> | ||
12 | + <Description @register="infoRegister" /> | ||
13 | + <Description @register="register" class="my-4" /> | ||
14 | + <Description @register="registerDev" /> | ||
15 | + </PageWrapper> | ||
16 | +</template> | ||
17 | +<script lang="ts"> | ||
18 | + import { defineComponent, h } from 'vue'; | ||
19 | + | ||
20 | + import { Tag } from 'ant-design-vue'; | ||
21 | + import { PageWrapper } from '/@/components/Page'; | ||
22 | + import { Description, DescItem, useDescription } from '/@/components/Description/index'; | ||
23 | + | ||
24 | + import { GITHUB_URL, SITE_URL, DOC_URL } from '/@/settings/siteSetting'; | ||
25 | + export default defineComponent({ | ||
26 | + name: 'AboutPage', | ||
27 | + components: { Description, PageWrapper }, | ||
28 | + setup() { | ||
29 | + const { pkg, lastBuildTime } = window.__APP_INFO__; | ||
30 | + | ||
31 | + const { dependencies, devDependencies, name, version } = pkg; | ||
32 | + | ||
33 | + const schema: DescItem[] = []; | ||
34 | + const devSchema: DescItem[] = []; | ||
35 | + const commonTagRender = (color: string) => (curVal) => h(Tag, { color }, () => curVal); | ||
36 | + const commonLinkRender = (text: string) => (href) => h('a', { href, target: '_blank' }, text); | ||
37 | + const infoSchema: DescItem[] = [ | ||
38 | + { | ||
39 | + label: '版本', | ||
40 | + field: 'version', | ||
41 | + render: commonTagRender('blue'), | ||
42 | + }, | ||
43 | + { | ||
44 | + label: '最后编译时间', | ||
45 | + field: 'lastBuildTime', | ||
46 | + render: commonTagRender('blue'), | ||
47 | + }, | ||
48 | + { | ||
49 | + label: '文档地址', | ||
50 | + field: 'doc', | ||
51 | + render: commonLinkRender('文档地址'), | ||
52 | + }, | ||
53 | + { | ||
54 | + label: '预览地址', | ||
55 | + field: 'preview', | ||
56 | + render: commonLinkRender('预览地址'), | ||
57 | + }, | ||
58 | + { | ||
59 | + label: 'Github', | ||
60 | + field: 'github', | ||
61 | + render: commonLinkRender('Github'), | ||
62 | + }, | ||
63 | + ]; | ||
64 | + | ||
65 | + const infoData = { | ||
66 | + version, | ||
67 | + lastBuildTime, | ||
68 | + doc: DOC_URL, | ||
69 | + preview: SITE_URL, | ||
70 | + github: GITHUB_URL, | ||
71 | + }; | ||
72 | + | ||
73 | + Object.keys(dependencies).forEach((key) => { | ||
74 | + schema.push({ field: key, label: key }); | ||
75 | + }); | ||
76 | + | ||
77 | + Object.keys(devDependencies).forEach((key) => { | ||
78 | + devSchema.push({ field: key, label: key }); | ||
79 | + }); | ||
80 | + const [register] = useDescription({ | ||
81 | + title: '生产环境依赖', | ||
82 | + data: dependencies, | ||
83 | + schema: schema, | ||
84 | + column: 3, | ||
85 | + }); | ||
86 | + const [registerDev] = useDescription({ | ||
87 | + title: '开发环境依赖', | ||
88 | + data: devDependencies, | ||
89 | + schema: devSchema, | ||
90 | + column: 3, | ||
91 | + }); | ||
92 | + const [infoRegister] = useDescription({ | ||
93 | + title: '项目信息', | ||
94 | + data: infoData, | ||
95 | + schema: infoSchema, | ||
96 | + column: 2, | ||
97 | + }); | ||
98 | + | ||
99 | + return { register, registerDev, infoRegister, name, GITHUB_URL }; | ||
100 | + }, | ||
101 | + }); | ||
102 | +</script> |
types/global.d.ts
@@ -10,6 +10,16 @@ declare global { | @@ -10,6 +10,16 @@ declare global { | ||
10 | declare interface Window { | 10 | declare interface Window { |
11 | // Global vue app instance | 11 | // Global vue app instance |
12 | __APP__: App<Element>; | 12 | __APP__: App<Element>; |
13 | + | ||
14 | + __APP_INFO__: { | ||
15 | + pkg: { | ||
16 | + name: string; | ||
17 | + version: string; | ||
18 | + dependencies: Recordable<string>; | ||
19 | + devDependencies: Recordable<string>; | ||
20 | + }; | ||
21 | + lastBuildTime: string; | ||
22 | + }; | ||
13 | } | 23 | } |
14 | 24 | ||
15 | // vue | 25 | // vue |
vite.config.ts
@@ -9,6 +9,13 @@ import { createAlias } from './build/vite/alias'; | @@ -9,6 +9,13 @@ import { createAlias } from './build/vite/alias'; | ||
9 | import { wrapperEnv } from './build/utils'; | 9 | import { wrapperEnv } from './build/utils'; |
10 | import { createVitePlugins } from './build/vite/plugin'; | 10 | import { createVitePlugins } from './build/vite/plugin'; |
11 | import { OUTPUT_DIR } from './build/constant'; | 11 | import { OUTPUT_DIR } from './build/constant'; |
12 | +import pkg from './package.json'; | ||
13 | +import moment from 'moment'; | ||
14 | + | ||
15 | +const APP_INFO = { | ||
16 | + pkg, | ||
17 | + lastBuildTime: moment().format('YYYY-MM-DD HH:mm:ss'), | ||
18 | +}; | ||
12 | 19 | ||
13 | export default ({ command, mode }: ConfigEnv): UserConfig => { | 20 | export default ({ command, mode }: ConfigEnv): UserConfig => { |
14 | const root = process.cwd(); | 21 | const root = process.cwd(); |
@@ -58,6 +65,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { | @@ -58,6 +65,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { | ||
58 | __VUE_I18N_LEGACY_API__: false, | 65 | __VUE_I18N_LEGACY_API__: false, |
59 | __VUE_I18N_FULL_INSTALL__: false, | 66 | __VUE_I18N_FULL_INSTALL__: false, |
60 | __INTLIFY_PROD_DEVTOOLS__: false, | 67 | __INTLIFY_PROD_DEVTOOLS__: false, |
68 | + | ||
69 | + __APP_INFO__: JSON.stringify(APP_INFO), | ||
61 | }, | 70 | }, |
62 | css: { | 71 | css: { |
63 | preprocessorOptions: { | 72 | preprocessorOptions: { |