mirror of
https://github.com/Tencent/tdesign-vue-next-starter.git
synced 2024-12-22 16:36:32 +08:00
feat: 将代码迁移至TS严格模式 (#684)
* feat: 将现有代码迁移至TS严格模式 - 禁止隐匿Any的This * feat: 将代码迁移至TS严格模式 - 启用JS严格模式 和 绑定类型检查 * feat: 移除无用钩子,修改为工具API * feat: 将代码迁移至TS严格模式 - 启用严格函数类型检查
This commit is contained in:
parent
944f03a064
commit
0f7096a167
|
@ -8,6 +8,7 @@
|
|||
"dev:linux": "vite --mode development",
|
||||
"build:test": "vite build --mode test",
|
||||
"build": "vue-tsc --noEmit && vite build --mode release",
|
||||
"build:type": "vue-tsc --noEmit",
|
||||
"build:site": "vue-tsc --noEmit && vite build --mode site",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0",
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import debounce from 'lodash/debounce';
|
||||
import { onMounted, onUnmounted } from 'vue';
|
||||
|
||||
interface WindowSizeOptions {
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
interface Fn<T = any, R = T> {
|
||||
(...arg: T[]): R;
|
||||
}
|
||||
|
||||
export function useWindowSizeFn<T>(fn: Fn<T>, options?: WindowSizeOptions, wait = 150) {
|
||||
const handleSize: () => void = debounce(fn, wait);
|
||||
|
||||
const start = () => {
|
||||
if (options && options.immediate) {
|
||||
fn();
|
||||
}
|
||||
window.addEventListener('resize', handleSize);
|
||||
};
|
||||
|
||||
const stop = () => {
|
||||
window.removeEventListener('resize', handleSize);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
start();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
stop();
|
||||
});
|
||||
return [start, stop];
|
||||
}
|
|
@ -6,17 +6,19 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useWindowSize } from '@vueuse/core';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { computed, CSSProperties, ref, unref, watch } from 'vue';
|
||||
|
||||
import { prefix } from '@/config/global';
|
||||
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn';
|
||||
import { useSettingStore } from '@/store';
|
||||
|
||||
defineProps({
|
||||
frameSrc: String,
|
||||
});
|
||||
|
||||
const { width, height } = useWindowSize();
|
||||
|
||||
const loading = ref(true);
|
||||
const heightRef = ref(window.innerHeight);
|
||||
const frameRef = ref<HTMLFrameElement>();
|
||||
|
@ -69,8 +71,8 @@ function hideLoading() {
|
|||
calcHeight();
|
||||
}
|
||||
|
||||
useWindowSizeFn(calcHeight, { immediate: true });
|
||||
|
||||
// 如果窗口大小发生变化
|
||||
watch([width, height], debounce(calcHeight, 250));
|
||||
watch(
|
||||
[() => settingStore.showFooter, () => settingStore.isUseTabsRouter, () => settingStore.showBreadcrumb],
|
||||
debounce(calcHeight, 250),
|
||||
|
|
|
@ -38,9 +38,13 @@
|
|||
<translate-icon />
|
||||
</t-button>
|
||||
<t-dropdown-menu>
|
||||
<t-dropdown-item v-for="(lang, index) in langList" :key="index" :value="lang.value" @click="changeLang">{{
|
||||
lang.content
|
||||
}}</t-dropdown-item></t-dropdown-menu
|
||||
<t-dropdown-item
|
||||
v-for="(lang, index) in langList"
|
||||
:key="index"
|
||||
:value="lang.value"
|
||||
@click="(options) => changeLang(options.value as string)"
|
||||
>{{ lang.content }}</t-dropdown-item
|
||||
></t-dropdown-menu
|
||||
>
|
||||
</t-dropdown>
|
||||
<t-dropdown :min-column-width="120" trigger="click">
|
||||
|
@ -85,7 +89,7 @@ import { langList } from '@/locales/index';
|
|||
import { useLocale } from '@/locales/useLocale';
|
||||
import { getActive } from '@/router';
|
||||
import { useSettingStore, useUserStore } from '@/store';
|
||||
import type { MenuRoute } from '@/types/interface';
|
||||
import type { MenuRoute, ModeType } from '@/types/interface';
|
||||
|
||||
import MenuContent from './MenuContent.vue';
|
||||
import Notice from './Notice.vue';
|
||||
|
@ -147,11 +151,11 @@ const menuCls = computed(() => {
|
|||
},
|
||||
];
|
||||
});
|
||||
const menuTheme = computed(() => props.theme as 'light' | 'dark');
|
||||
const menuTheme = computed(() => props.theme as ModeType);
|
||||
|
||||
// 切换语言
|
||||
const { changeLocale } = useLocale();
|
||||
const changeLang = ({ value: lang }: { value: string }) => {
|
||||
const changeLang = (lang: string) => {
|
||||
changeLocale(lang);
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:class="`${prefix}-layout-tabs-nav`"
|
||||
:value="$route.path"
|
||||
:style="{ position: 'sticky', top: 0, width: '100%' }"
|
||||
@change="handleChangeCurrentTab"
|
||||
@change="(value) => handleChangeCurrentTab(value as string)"
|
||||
@remove="handleRemove"
|
||||
@drag-sort="handleDragend"
|
||||
>
|
||||
|
|
|
@ -26,7 +26,7 @@ import AssetLogo from '@/assets/assets-t-logo.svg?component';
|
|||
import { prefix } from '@/config/global';
|
||||
import { getActive, getRoutesExpanded } from '@/router';
|
||||
import { useSettingStore } from '@/store';
|
||||
import type { MenuRoute } from '@/types/interface';
|
||||
import type { MenuRoute, ModeType } from '@/types/interface';
|
||||
|
||||
import pgk from '../../../package.json';
|
||||
import MenuContent from './MenuContent.vue';
|
||||
|
@ -55,7 +55,7 @@ const props = defineProps({
|
|||
default: '64px',
|
||||
},
|
||||
theme: {
|
||||
type: String as PropType<'light' | 'dark'>,
|
||||
type: String as PropType<ModeType>,
|
||||
default: 'light',
|
||||
},
|
||||
isCompact: {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
theme="primary"
|
||||
mode="date"
|
||||
:default-value="LAST_7_DAYS"
|
||||
@change="onCurrencyChange"
|
||||
@change="(value) => onCurrencyChange(value as string[])"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
theme="primary"
|
||||
mode="date"
|
||||
:default-value="LAST_7_DAYS"
|
||||
@change="onStokeDataChange"
|
||||
@change="(value) => onStokeDataChange(value as string[])"
|
||||
/>
|
||||
</template>
|
||||
<div id="stokeContainer" style="width: 100%; height: 351px" class="dashboard-chart-container"></div>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
theme="primary"
|
||||
mode="date"
|
||||
style="width: 248px"
|
||||
@change="onMaterialChange"
|
||||
@change="(value) => onMaterialChange(value as string[])"
|
||||
/>
|
||||
</template>
|
||||
<div id="lineContainer" style="width: 100%; height: 416px" />
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
:header-affixed-top="headerAffixedTop"
|
||||
@page-change="rehandlePageChange"
|
||||
@change="rehandleChange"
|
||||
@select-change="rehandleSelectChange"
|
||||
@select-change="(value) => rehandleSelectChange(value as number[])"
|
||||
>
|
||||
<template #status="{ row }">
|
||||
<t-tag v-if="row.status === CONTRACT_STATUS.FAIL" theme="danger" variant="light">
|
||||
|
|
|
@ -74,7 +74,7 @@ const formVisible = ref(false);
|
|||
const formData = ref({ ...INITIAL_DATA });
|
||||
const textareaValue = ref('');
|
||||
|
||||
const onSubmit = ({ validateResult, firstError }: SubmitContext<FormData>) => {
|
||||
const onSubmit = ({ validateResult, firstError }: SubmitContext) => {
|
||||
if (!firstError) {
|
||||
MessagePlugin.success('提交成功');
|
||||
formVisible.value = false;
|
||||
|
|
|
@ -2,15 +2,16 @@ import keys from 'lodash/keys';
|
|||
import { defineStore } from 'pinia';
|
||||
import { Color } from 'tvision-color';
|
||||
|
||||
import { DARK_CHART_COLORS, LIGHT_CHART_COLORS } from '@/config/color';
|
||||
import { DARK_CHART_COLORS, LIGHT_CHART_COLORS, TColorSeries } from '@/config/color';
|
||||
import STYLE_CONFIG from '@/config/style';
|
||||
import { store } from '@/store';
|
||||
import { ModeType } from '@/types/interface';
|
||||
import { generateColorMap, insertThemeStylesheet } from '@/utils/color';
|
||||
|
||||
const state = {
|
||||
const state: Record<string, any> = {
|
||||
...STYLE_CONFIG,
|
||||
showSettingPanel: false,
|
||||
colorList: {},
|
||||
colorList: {} as TColorSeries,
|
||||
chartColors: LIGHT_CHART_COLORS,
|
||||
};
|
||||
|
||||
|
@ -23,7 +24,7 @@ export const useSettingStore = defineStore('setting', {
|
|||
showSidebar: (state) => state.layout !== 'top',
|
||||
showSidebarLogo: (state) => state.layout === 'side',
|
||||
showHeaderLogo: (state) => state.layout !== 'side',
|
||||
displayMode: (state): 'dark' | 'light' => {
|
||||
displayMode: (state): ModeType => {
|
||||
if (state.mode === 'auto') {
|
||||
const media = window.matchMedia('(prefers-color-scheme:dark)');
|
||||
if (media.matches) {
|
||||
|
@ -31,14 +32,14 @@ export const useSettingStore = defineStore('setting', {
|
|||
}
|
||||
return 'light';
|
||||
}
|
||||
return state.mode as 'dark' | 'light';
|
||||
return state.mode as ModeType;
|
||||
},
|
||||
displaySideMode: (state): 'dark' | 'light' => {
|
||||
return state.sideMode as 'dark' | 'light';
|
||||
displaySideMode: (state): ModeType => {
|
||||
return state.sideMode as ModeType;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async changeMode(mode: 'dark' | 'light' | 'auto') {
|
||||
async changeMode(mode: ModeType | 'auto') {
|
||||
let theme = mode;
|
||||
|
||||
if (mode === 'auto') {
|
||||
|
@ -50,7 +51,7 @@ export const useSettingStore = defineStore('setting', {
|
|||
|
||||
this.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
|
||||
},
|
||||
async changeSideMode(mode: 'dark' | 'light') {
|
||||
async changeSideMode(mode: ModeType) {
|
||||
const isDarkMode = mode === 'dark';
|
||||
|
||||
document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : '');
|
||||
|
@ -75,23 +76,23 @@ export const useSettingStore = defineStore('setting', {
|
|||
step: 10,
|
||||
remainInput: false, // 是否保留输入 不保留会矫正不合适的主题色
|
||||
});
|
||||
colorMap = generateColorMap(brandTheme, newPalette, mode as 'light' | 'dark', brandColorIndex);
|
||||
colorMap = generateColorMap(brandTheme, newPalette, mode, brandColorIndex);
|
||||
this.colorList[colorKey] = colorMap;
|
||||
}
|
||||
// TODO 需要解决不停切换时有反复插入 style 的问题
|
||||
insertThemeStylesheet(brandTheme, colorMap, mode as 'light' | 'dark');
|
||||
insertThemeStylesheet(brandTheme, colorMap, mode);
|
||||
document.documentElement.setAttribute('theme-color', brandTheme);
|
||||
},
|
||||
updateConfig(payload: Partial<TState>) {
|
||||
for (const key in payload) {
|
||||
if (payload[key as TStateKey] !== undefined) {
|
||||
this[key] = payload[key as TStateKey];
|
||||
this[key as TStateKey] = payload[key as TStateKey];
|
||||
}
|
||||
if (key === 'mode') {
|
||||
this.changeMode(payload[key]);
|
||||
this.changeMode(payload[key] as ModeType);
|
||||
}
|
||||
if (key === 'sideMode') {
|
||||
this.changeSideMode(payload[key]);
|
||||
this.changeSideMode(payload[key] as ModeType);
|
||||
}
|
||||
if (key === 'brandTheme') {
|
||||
this.changeBrandTheme(payload[key]);
|
||||
|
|
10
src/types/interface.d.ts
vendored
10
src/types/interface.d.ts
vendored
|
@ -1,8 +1,6 @@
|
|||
import type { TabValue } from 'tdesign-vue-next';
|
||||
import { LocationQueryRaw, RouteRecordName } from 'vue-router';
|
||||
|
||||
import STYLE_CONFIG from '@/config/style';
|
||||
|
||||
export interface RouteMeta {
|
||||
title?: string | Record<string, string>;
|
||||
icon?: string;
|
||||
|
@ -32,14 +30,6 @@ export interface MenuRoute {
|
|||
|
||||
export type ModeType = 'dark' | 'light';
|
||||
|
||||
export type SettingType = typeof STYLE_CONFIG;
|
||||
|
||||
export type ClassName = { [className: string]: any } | ClassName[] | string;
|
||||
|
||||
export type CommonObjType = {
|
||||
[key: string]: string | number;
|
||||
};
|
||||
|
||||
export interface UserInfo {
|
||||
name: string;
|
||||
roles: string[];
|
||||
|
|
|
@ -3,6 +3,7 @@ import trim from 'lodash/trim';
|
|||
import { Color } from 'tvision-color';
|
||||
|
||||
import { TColorToken } from '@/config/color';
|
||||
import { ModeType } from '@/types/interface';
|
||||
|
||||
/**
|
||||
* 依据主题类型获取颜色
|
||||
|
@ -58,12 +59,7 @@ export function changeChartsTheme(chartsList: echarts.EChartsType[]): void {
|
|||
/**
|
||||
* 根据当前主题色、模式等情景 计算最后生成的色阶
|
||||
*/
|
||||
export function generateColorMap(
|
||||
theme: string,
|
||||
colorPalette: Array<string>,
|
||||
mode: 'light' | 'dark',
|
||||
brandColorIdx: number,
|
||||
) {
|
||||
export function generateColorMap(theme: string, colorPalette: Array<string>, mode: ModeType, brandColorIdx: number) {
|
||||
const isDarkMode = mode === 'dark';
|
||||
|
||||
if (isDarkMode) {
|
||||
|
@ -76,7 +72,7 @@ export function generateColorMap(
|
|||
colorPalette[0] = `${colorPalette[brandColorIdx]}20`;
|
||||
}
|
||||
|
||||
const colorMap = {
|
||||
const colorMap: TColorToken = {
|
||||
'--td-brand-color': colorPalette[brandColorIdx], // 主题色
|
||||
'--td-brand-color-1': colorPalette[0], // light
|
||||
'--td-brand-color-2': colorPalette[1], // focus
|
||||
|
@ -95,7 +91,7 @@ export function generateColorMap(
|
|||
/**
|
||||
* 将生成的样式嵌入头部
|
||||
*/
|
||||
export function insertThemeStylesheet(theme: string, colorMap: TColorToken, mode: 'light' | 'dark') {
|
||||
export function insertThemeStylesheet(theme: string, colorMap: TColorToken, mode: ModeType) {
|
||||
const isDarkMode = mode === 'dark';
|
||||
const root = !isDarkMode ? `:root[theme-color='${theme}']` : `:root[theme-color='${theme}'][theme-mode='dark']`;
|
||||
|
||||
|
|
|
@ -16,7 +16,11 @@
|
|||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"noImplicitAny": true
|
||||
"noImplicitAny": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictBindCallApply": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
|
|
Loading…
Reference in New Issue
Block a user