diff --git a/packages/tdesign-uniapp/example/script/pages/index.js b/packages/tdesign-uniapp/example/script/pages/index.js index 535b74dd24..59ba7138ef 100644 --- a/packages/tdesign-uniapp/example/script/pages/index.js +++ b/packages/tdesign-uniapp/example/script/pages/index.js @@ -42,7 +42,6 @@ function main() { const list = [ base, nav, - form, display, other, ]; @@ -86,6 +85,7 @@ function main() { }; }); rawData.subPackages = [ + ...getSubPackages(form), ...getSubPackages(ux), ...getSubPackages(chat), ]; @@ -111,6 +111,7 @@ function main() { 'pages/home/home': { network: 'all', packages: [ + ...getSubPackages(form), ...getSubPackages(ux), ...getSubPackages(chat), ].map(item => item.root), diff --git a/packages/tdesign-uniapp/example/script/release/core.js b/packages/tdesign-uniapp/example/script/release/core.js index 102ff04e01..982675dd3f 100644 --- a/packages/tdesign-uniapp/example/script/release/core.js +++ b/packages/tdesign-uniapp/example/script/release/core.js @@ -1,6 +1,7 @@ const fs = require('fs'); const path = require('path'); const { processLess } = require('./less'); +const { processTs } = require('./typescript'); async function copy({ @@ -25,7 +26,13 @@ async function copy({ lessResult = await processLess(filePath, targetPath); } + // 对 .ts 文件进行编译(排除 .d.ts) + let tsResult = false; if (!lessResult) { + tsResult = processTs(filePath, targetPath); + } + + if (!lessResult && !tsResult) { fs.copyFileSync(filePath, targetPath); } diff --git a/packages/tdesign-uniapp/example/script/release/prepare.js b/packages/tdesign-uniapp/example/script/release/prepare.js index dface5956f..6e51ab1878 100644 --- a/packages/tdesign-uniapp/example/script/release/prepare.js +++ b/packages/tdesign-uniapp/example/script/release/prepare.js @@ -4,6 +4,7 @@ const { deleteFolder } = require('t-comm'); const { config, DIST_BLACK_LIST } = require('./config'); const { copy } = require('./core.js'); +const { generateDts } = require('./typescript'); async function main() { const { @@ -54,6 +55,9 @@ async function prepareOne({ targetDir, sourceGlob, sourceDir }) { } console.log(`[Wrote] done! Length is ${list.length}!`); + + // 批量生成 .d.ts 声明文件 + generateDts(sourceDir, targetDir); } main(); diff --git a/packages/tdesign-uniapp/example/script/release/typescript.js b/packages/tdesign-uniapp/example/script/release/typescript.js new file mode 100644 index 0000000000..915e16028d --- /dev/null +++ b/packages/tdesign-uniapp/example/script/release/typescript.js @@ -0,0 +1,163 @@ +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); +const ts = require('typescript'); +const { PROJECT_ROOT } = require('./config'); + +const COMPILE_TS = false; +const GENERATE_DTS = false; + + +/** 编译选项,与根目录 tsconfig.json 中的 compilerOptions 保持一致 */ +const COMPILER_OPTIONS = { + target: ts.ScriptTarget.ES2015, + module: ts.ModuleKind.ESNext, + moduleResolution: ts.ModuleResolutionKind.NodeJs, + esModuleInterop: true, + allowSyntheticDefaultImports: true, + experimentalDecorators: true, + declaration: false, + skipLibCheck: true, + resolveJsonModule: true, + allowJs: true, + removeComments: false, +}; + +/** + * 将单个 .ts 文件编译为 .js 文件 + * @param {string} inputFile 源 .ts 文件的绝对路径 + * @param {string} rawOutputFile 目标文件的绝对路径(仍是 .ts 后缀,函数内部会改为 .js) + * @returns {boolean|undefined} 成功返回 true,非 .ts 文件返回 undefined + */ +function processTs(inputFile, rawOutputFile) { + if (!COMPILE_TS) return; + + // 只处理 .ts 文件(排除 .d.ts) + if (!inputFile.endsWith('.ts') || inputFile.endsWith('.d.ts')) { + return; + } + + // 跳过纯类型定义文件(props.ts / type.ts / common.ts),这些文件仅提供类型声明,不需要编译为 JS + const basename = path.basename(inputFile); + if (basename === 'props.ts' || basename === 'type.ts' || basename === 'common.ts') { + return; + } + + try { + const tsCode = fs.readFileSync(inputFile, 'utf8'); + + const result = ts.transpileModule(tsCode, { + compilerOptions: COMPILER_OPTIONS, + fileName: path.basename(inputFile), + }); + + // 将 4 空格缩进转换为 2 空格缩进 + const outputText = result.outputText.replace(/^( {4})+/gm, match => ' '.repeat(match.length / 4)); + + // 输出文件后缀改为 .js + const outputFile = rawOutputFile.replace(/\.ts$/, '.js'); + fs.mkdirSync(path.dirname(outputFile), { recursive: true }); + fs.writeFileSync(outputFile, outputText); + console.log(`✅ TS 编译完成: ${path.relative(PROJECT_ROOT, outputFile)}`); + return true; + } catch (err) { + console.error(`❌ TS 编译失败: ${inputFile}`, err); + return false; + } +} + +/** + * 使用 tsc 命令行批量生成 .d.ts 声明文件 + * @param {string} sourceDir 源码根目录(如 uniapp-components) + * @param {string} targetDir 输出目录(如 dist) + */ +function generateDts(sourceDir, targetDir) { + if (!GENERATE_DTS) return; + // 收集 sourceDir 下所有 .ts 文件(排除 .d.ts、node_modules、_example) + const tsFiles = collectTsFiles(sourceDir); + + if (tsFiles.length === 0) { + console.log('⚠️ 未找到需要生成 .d.ts 的 .ts 文件'); + return; + } + + console.log(`\n📝 开始生成 .d.ts 声明文件,共 ${tsFiles.length} 个 .ts 文件...`); + + // 创建临时 tsconfig 文件,避免命令行参数过长 + const tmpTsConfig = path.join(sourceDir, '.tsconfig.dts.tmp.json'); + const tsconfigContent = { + compilerOptions: { + declaration: true, + emitDeclarationOnly: true, + skipLibCheck: true, + target: 'ES2015', + lib: ['ES2015', 'ES2016', 'ES2017', 'DOM'], + module: 'ESNext', + moduleResolution: 'node', + experimentalDecorators: true, + types: ['miniprogram-api-typings', '@dcloudio/types'], + baseUrl: sourceDir, + paths: { + './superComponent': ['./superComponent.placeholder'], + }, + outDir: targetDir, + rootDir: sourceDir, + }, + files: tsFiles, + }; + + fs.writeFileSync(tmpTsConfig, JSON.stringify(tsconfigContent, null, 2)); + + const tscBin = path.resolve(PROJECT_ROOT, 'node_modules/.bin/tsc'); + + try { + execSync(`"${tscBin}" --project "${tmpTsConfig}"`, { + cwd: PROJECT_ROOT, + stdio: 'pipe', + }); + console.log(`✅ .d.ts 声明文件生成完成,输出到 ${path.relative(PROJECT_ROOT, targetDir)}`); + } catch (err) { + const stdout = err.stdout ? err.stdout.toString() : ''; + const stderr = err.stderr ? err.stderr.toString() : ''; + const errorOutput = stdout || stderr; + // tsc 有类型错误但默认 noEmitOnError=false,.d.ts 仍然会生成 + // 仅打印警告,不中断流程 + if (errorOutput) { + console.warn(`⚠️ tsc 生成 .d.ts 时存在类型警告(不影响产物生成):\n${errorOutput}`); + } + console.log(`✅ .d.ts 声明文件生成完成(含警告),输出到 ${path.relative(PROJECT_ROOT, targetDir)}`); + } finally { + // 清理临时文件 + try { + fs.unlinkSync(tmpTsConfig); + } catch (e) { /* ignore */ } + } +} + +/** + * 递归收集目录下的所有 .ts 文件(排除 .d.ts、node_modules、_example) + */ +function collectTsFiles(dir) { + const results = []; + + function walk(currentDir) { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name); + if (entry.isDirectory()) { + if (entry.name === 'node_modules' || entry.name === '_example') continue; + walk(fullPath); + } else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) { + results.push(fullPath); + } + } + } + + walk(dir); + return results; +} + +module.exports = { + processTs, + generateDts, +}; diff --git a/packages/tdesign-uniapp/example/script/watch/init.js b/packages/tdesign-uniapp/example/script/watch/init.js index 21c0b9f217..4649870b44 100644 --- a/packages/tdesign-uniapp/example/script/watch/init.js +++ b/packages/tdesign-uniapp/example/script/watch/init.js @@ -5,6 +5,7 @@ const { deleteFolder } = require('t-comm'); const { config } = require('./config'); const { copyComponents, checkVue2CliExist, checkVue2HxExist, checkVue3HxExist } = require('./helper'); +const { generateDts } = require('../release/typescript'); async function copyOneProject({ @@ -43,11 +44,13 @@ function clearTargetDir() { if (checkVue2HxExist()) { deleteFolder(config.componentTargetDirInVue2Hx); + deleteFolder(config.componentChatTargetDirInVue2Hx); deleteFolder(config.pagesMoreDirInVue2Hx); } if (checkVue3HxExist()) { deleteFolder(config.componentTargetDirInVue3Hx); + deleteFolder(config.componentChatTargetDirInVue3Hx); deleteFolder(config.pagesMoreDirInVue3Hx); } } @@ -84,11 +87,17 @@ async function main() { isChat: false, }); + // 为主包生成 .d.ts 声明文件 + generateDts(config.sourceDir, config.componentTargetDirInVue3Cli); + await copyOneProject({ globMode: config.chatSourceGlob, sourceDir: config.chatSourceDir, isChat: true, }); + + // 为 chat 包生成 .d.ts 声明文件 + generateDts(config.chatSourceDir, config.componentTargetDirInVue3Cli); } diff --git a/packages/tdesign-uniapp/example/src/pages.json b/packages/tdesign-uniapp/example/src/pages.json index fd67adb3f0..7854d37cf6 100644 --- a/packages/tdesign-uniapp/example/src/pages.json +++ b/packages/tdesign-uniapp/example/src/pages.json @@ -70,115 +70,200 @@ "path": "pages-more/tabs/tabs" }, { - "path": "pages-more/calendar/calendar" + "path": "pages-more/avatar/avatar" }, { - "path": "pages-more/cascader/cascader" + "path": "pages-more/badge/badge" }, { - "path": "pages-more/checkbox/checkbox" + "path": "pages-more/cell/cell" }, { - "path": "pages-more/color-picker/color-picker" + "path": "pages-more/collapse/collapse" }, { - "path": "pages-more/date-time-picker/date-time-picker" + "path": "pages-more/count-down/count-down" }, { - "path": "pages-more/form/form" + "path": "pages-more/empty/empty" }, { - "path": "pages-more/input/input" + "path": "pages-more/footer/footer" }, { - "path": "pages-more/picker/picker" + "path": "pages-more/grid/grid" }, { - "path": "pages-more/radio/radio" + "path": "pages-more/image/image" }, { - "path": "pages-more/rate/rate" + "path": "pages-more/image-viewer/image-viewer" }, { - "path": "pages-more/search/search" + "path": "pages-more/progress/progress" }, { - "path": "pages-more/slider/slider" + "path": "pages-more/qrcode/qrcode" }, { - "path": "pages-more/stepper/stepper" + "path": "pages-more/result/result" }, { - "path": "pages-more/switch/switch" + "path": "pages-more/skeleton/skeleton" }, { - "path": "pages-more/textarea/textarea" + "path": "pages-more/sticky/sticky" }, { - "path": "pages-more/tree-select/tree-select" + "path": "pages-more/swiper/swiper" }, { - "path": "pages-more/upload/upload" + "path": "pages-more/tag/tag" }, { - "path": "pages-more/avatar/avatar" + "path": "pages-more/watermark/watermark" }, { - "path": "pages-more/badge/badge" - }, + "path": "pages-more/config-provider/config-provider" + } + ], + "subPackages": [ { - "path": "pages-more/cell/cell" + "root": "pages-more/calendar", + "pages": [ + { + "path": "calendar" + } + ] }, { - "path": "pages-more/collapse/collapse" + "root": "pages-more/cascader", + "pages": [ + { + "path": "cascader" + } + ] }, { - "path": "pages-more/count-down/count-down" + "root": "pages-more/checkbox", + "pages": [ + { + "path": "checkbox" + } + ] }, { - "path": "pages-more/empty/empty" + "root": "pages-more/color-picker", + "pages": [ + { + "path": "color-picker" + } + ] }, { - "path": "pages-more/footer/footer" + "root": "pages-more/date-time-picker", + "pages": [ + { + "path": "date-time-picker" + } + ] }, { - "path": "pages-more/grid/grid" + "root": "pages-more/form", + "pages": [ + { + "path": "form" + } + ] }, { - "path": "pages-more/image/image" + "root": "pages-more/input", + "pages": [ + { + "path": "input" + } + ] }, { - "path": "pages-more/image-viewer/image-viewer" + "root": "pages-more/picker", + "pages": [ + { + "path": "picker" + } + ] }, { - "path": "pages-more/progress/progress" + "root": "pages-more/radio", + "pages": [ + { + "path": "radio" + } + ] }, { - "path": "pages-more/qrcode/qrcode" + "root": "pages-more/rate", + "pages": [ + { + "path": "rate" + } + ] }, { - "path": "pages-more/result/result" + "root": "pages-more/search", + "pages": [ + { + "path": "search" + } + ] }, { - "path": "pages-more/skeleton/skeleton" + "root": "pages-more/slider", + "pages": [ + { + "path": "slider" + } + ] }, { - "path": "pages-more/sticky/sticky" + "root": "pages-more/stepper", + "pages": [ + { + "path": "stepper" + } + ] }, { - "path": "pages-more/swiper/swiper" + "root": "pages-more/switch", + "pages": [ + { + "path": "switch" + } + ] }, { - "path": "pages-more/tag/tag" + "root": "pages-more/textarea", + "pages": [ + { + "path": "textarea" + } + ] }, { - "path": "pages-more/watermark/watermark" + "root": "pages-more/tree-select", + "pages": [ + { + "path": "tree-select" + } + ] }, { - "path": "pages-more/config-provider/config-provider" - } - ], - "subPackages": [ + "root": "pages-more/upload", + "pages": [ + { + "path": "upload" + } + ] + }, { "root": "pages-more/action-sheet", "pages": [ @@ -422,74 +507,6 @@ "name": "tabs", "pathName": "pages-more/tabs/tabs" }, - { - "name": "calendar", - "pathName": "pages-more/calendar/calendar" - }, - { - "name": "cascader", - "pathName": "pages-more/cascader/cascader" - }, - { - "name": "checkbox", - "pathName": "pages-more/checkbox/checkbox" - }, - { - "name": "color-picker", - "pathName": "pages-more/color-picker/color-picker" - }, - { - "name": "date-time-picker", - "pathName": "pages-more/date-time-picker/date-time-picker" - }, - { - "name": "form", - "pathName": "pages-more/form/form" - }, - { - "name": "input", - "pathName": "pages-more/input/input" - }, - { - "name": "picker", - "pathName": "pages-more/picker/picker" - }, - { - "name": "radio", - "pathName": "pages-more/radio/radio" - }, - { - "name": "rate", - "pathName": "pages-more/rate/rate" - }, - { - "name": "search", - "pathName": "pages-more/search/search" - }, - { - "name": "slider", - "pathName": "pages-more/slider/slider" - }, - { - "name": "stepper", - "pathName": "pages-more/stepper/stepper" - }, - { - "name": "switch", - "pathName": "pages-more/switch/switch" - }, - { - "name": "textarea", - "pathName": "pages-more/textarea/textarea" - }, - { - "name": "tree-select", - "pathName": "pages-more/tree-select/tree-select" - }, - { - "name": "upload", - "pathName": "pages-more/upload/upload" - }, { "name": "avatar", "pathName": "pages-more/avatar/avatar" @@ -566,6 +583,74 @@ "name": "config-provider", "pathName": "pages-more/config-provider/config-provider" }, + { + "name": "calendar", + "pathName": "pages-more/calendar/calendar" + }, + { + "name": "cascader", + "pathName": "pages-more/cascader/cascader" + }, + { + "name": "checkbox", + "pathName": "pages-more/checkbox/checkbox" + }, + { + "name": "color-picker", + "pathName": "pages-more/color-picker/color-picker" + }, + { + "name": "date-time-picker", + "pathName": "pages-more/date-time-picker/date-time-picker" + }, + { + "name": "form", + "pathName": "pages-more/form/form" + }, + { + "name": "input", + "pathName": "pages-more/input/input" + }, + { + "name": "picker", + "pathName": "pages-more/picker/picker" + }, + { + "name": "radio", + "pathName": "pages-more/radio/radio" + }, + { + "name": "rate", + "pathName": "pages-more/rate/rate" + }, + { + "name": "search", + "pathName": "pages-more/search/search" + }, + { + "name": "slider", + "pathName": "pages-more/slider/slider" + }, + { + "name": "stepper", + "pathName": "pages-more/stepper/stepper" + }, + { + "name": "switch", + "pathName": "pages-more/switch/switch" + }, + { + "name": "textarea", + "pathName": "pages-more/textarea/textarea" + }, + { + "name": "tree-select", + "pathName": "pages-more/tree-select/tree-select" + }, + { + "name": "upload", + "pathName": "pages-more/upload/upload" + }, { "name": "action-sheet", "pathName": "pages-more/action-sheet/action-sheet" @@ -660,6 +745,23 @@ "pages/home/home": { "network": "all", "packages": [ + "pages-more/calendar", + "pages-more/cascader", + "pages-more/checkbox", + "pages-more/color-picker", + "pages-more/date-time-picker", + "pages-more/form", + "pages-more/input", + "pages-more/picker", + "pages-more/radio", + "pages-more/rate", + "pages-more/search", + "pages-more/slider", + "pages-more/stepper", + "pages-more/switch", + "pages-more/textarea", + "pages-more/tree-select", + "pages-more/upload", "pages-more/action-sheet", "pages-more/dialog", "pages-more/dropdown-menu", diff --git a/packages/tdesign-uniapp/example/src/pages/home/home.less b/packages/tdesign-uniapp/example/src/pages/home/home.less index 749107967e..90e4be1b55 100644 --- a/packages/tdesign-uniapp/example/src/pages/home/home.less +++ b/packages/tdesign-uniapp/example/src/pages/home/home.less @@ -1,5 +1,6 @@ @import '@tdesign/uniapp/common/style/_variables.less'; + .main { width: 100%; box-sizing: border-box; diff --git a/packages/tdesign-uniapp/example/src/style/app.less b/packages/tdesign-uniapp/example/src/style/app.less index 67758006f8..b3e79e53cb 100644 --- a/packages/tdesign-uniapp/example/src/style/app.less +++ b/packages/tdesign-uniapp/example/src/style/app.less @@ -1,6 +1,7 @@ @import '@tdesign/uniapp/common/style/_variables.less'; @import '@tdesign/uniapp/common/style/theme/index.less'; + @font-face { font-family: 'TCloudNumber'; src: url('data:font/ttf;charset=utf-8;base64,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NSEB0/5wAZD+cAGQ/nABkAIAgmiC/pSCaIL+/GgAAAAAAwBDAGAB0wJoAAMABwALAAABFSU1BRUFNQUVITUB0/5wAZD+cAGQ/nAB5miCaIJogmicaGgAAAAAABoBPgABAAAAAAAAACIARgABAAAAAAABAAwAgwABAAAAAAACAAcAoAABAAAAAAADAB8A6AABAAAAAAAEABQBMgABAAAAAAAFACEBiwABAAAAAAAGABQB1wABAAAAAAAIABUCGAABAAAAAAALABoCZAABAAAAAAANAJADoQABAAAAAAAOABoEaAABAAAAAAAQAAwEnQABAAAAAAARAAcEugADAAEECQAAAEQAAAADAAEECQABABgAaQADAAEECQACAA4AkAADAAEECQADAD4AqAADAAEECQAEACgBCAADAAEECQAFAEIBRwADAAEECQAGACgBrQADAAEECQAIACoB7AADAAEECQALADQCLgADAAEECQANASACfwADAAEECQAOADQEMgADAAEECQAQABgEgwADAAEECQARAA4EqgBDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADIAMQAtAHAAcgBlAHMAZQBuAHQAIABUAEQAZQBzAGkAZwBuAABDb3B5cmlnaHQgKGMpIDIwMjEtcHJlc2VudCBURGVzaWduAABUAEMAbABvAHUAZABOAHUAbQBiAGUAcgAAVENsb3VkTnVtYmVyAABSAGUAZwB1AGwAYQByAABSZWd1bGFyAAAxAC4AMAAxADAAOwBVAEsAVwBOADsAVABDAGwAbwB1AGQATgB1AG0AYgBlAHIALQBSAGUAZwB1AGwAYQByAAAxLjAxMDtVS1dOO1RDbG91ZE51bWJlci1SZWd1bGFyAABUAEMAbABvAHUAZABOAHUAbQBiAGUAcgAgAFIAZQBnAHUAbABhAHIAAFRDbG91ZE51bWJlciBSZWd1bGFyAABWAGUAcgBzAGkAbwBuACAAMQAuADAAMQAwADsARwBsAHkAcABoAHMAIAAzAC4AMQAuADEAIAAoADMAMQAzADUAKQAAVmVyc2lvbiAxLjAxMDtHbHlwaHMgMy4xLjEgKDMxMzUpAABUAEMAbABvAHUAZABOAHUAbQBiAGUAcgAtAFIAZQBnAHUAbABhAHIAAFRDbG91ZE51bWJlci1SZWd1bGFyAABUAGUAbgBjAGUAbgB0ACAAVABEAGUAcwBpAGcAbgAgAE8AdABlAGEAbQAAVGVuY2VudCBURGVzaWduIE90ZWFtAABoAHQAdABwADoALwAvAHQAZABlAHMAaQBnAG4ALgB0AGUAbgBjAGUAbgB0AC4AYwBvAG0AAGh0dHA6Ly90ZGVzaWduLnRlbmNlbnQuY29tAABUAGgAaQBzACAARgBvAG4AdAAgAFMAbwBmAHQAdwBhAHIAZQAgAGkAcwAgAGwAaQBjAGUAbgBzAGUAZAAgAHUAbgBkAGUAcgAgAHQAaABlACAAUwBJAEwAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUALAAgAFYAZQByAHMAaQBvAG4AIAAxAC4AMQAuACAAVABoAGkAcwAgAGwAaQBjAGUAbgBzAGUAIABpAHMAIABhAHYAYQBpAGwAYQBiAGwAZQAgAHcAaQB0AGgAIABhACAARgBBAFEAIABhAHQAOgAgAGgAdAB0AHAAOgAvAC8AcwBjAHIAaQBwAHQAcwAuAHMAaQBsAC4AbwByAGcALwBPAEYATAAAVGhpcyBGb250IFNvZnR3YXJlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBTSUwgT3BlbiBGb250IExpY2Vuc2UsIFZlcnNpb24gMS4xLiBUaGlzIGxpY2Vuc2UgaXMgYXZhaWxhYmxlIHdpdGggYSBGQVEgYXQ6IGh0dHA6Ly9zY3JpcHRzLnNpbC5vcmcvT0ZMAABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAGh0dHA6Ly9zY3JpcHRzLnNpbC5vcmcvT0ZMAABUAEMAbABvAHUAZABOAHUAbQBiAGUAcgAAVENsb3VkTnVtYmVyAABSAGUAZwB1AGwAYQByAABSZWd1bGFyAAACAAAAAAAA/5wAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAEsAAAABAAIAAwAEAAUABgAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjAD4APwBAAEEAQgBeAF8AYABhAKMAqQCkAJMAwwCqAKIA8AC4ALYAtwDEALQAtQDFAIcAqwDGAL4AvwCYAJoAmQDvAKUAkgCcAKcAjwCUAJUAAAAB//8AAgABAAAADAAAABYAAAACAAEAAwBKAAEABAAAAAIAAAAAAAAAAQAAAADeBipuAAAAANeCVUMAAAAA4YOP8w==') diff --git a/packages/uniapp-components/common/src/index.js b/packages/uniapp-components/common/src/index.js index 94e7ce1257..2055d5fbf9 100644 --- a/packages/uniapp-components/common/src/index.js +++ b/packages/uniapp-components/common/src/index.js @@ -1,4 +1,3 @@ -export * from './superComponent'; export * from './flatTool'; export * from './instantiationDecorator'; export * from './control'; diff --git a/packages/uniapp-components/common/src/superComponent.js b/packages/uniapp-components/common/src/superComponent.js deleted file mode 100644 index 3f85068495..0000000000 --- a/packages/uniapp-components/common/src/superComponent.js +++ /dev/null @@ -1,5 +0,0 @@ -export class SuperComponent { - constructor() { - this.app = getApp(); - } -} diff --git a/packages/uniapp-components/common/validator.js b/packages/uniapp-components/common/validator.ts similarity index 77% rename from packages/uniapp-components/common/validator.js rename to packages/uniapp-components/common/validator.ts index 7a9e050e70..bc97d25851 100644 --- a/packages/uniapp-components/common/validator.js +++ b/packages/uniapp-components/common/validator.ts @@ -1,43 +1,45 @@ -export function isFunction(val) { +import type { IsEmailOptions, IsURLOptions } from './common'; + +export function isFunction(val: unknown): val is (...args: unknown[]) => unknown { return typeof val === 'function'; } -export const isString = val => typeof val === 'string'; +export const isString = (val: unknown): val is string => typeof val === 'string'; -export const isNull = value => value === null; +export const isNull = (value: unknown): value is null => value === null; -export const isUndefined = value => value === undefined; +export const isUndefined = (value: unknown): value is undefined => value === undefined; -export function isDef(value) { +export function isDef(value: T | undefined | null): value is T { return !isUndefined(value) && !isNull(value); } -export function isInteger(value) { +export function isInteger(value: unknown): boolean { return Number.isInteger(value); } -export function isNumeric(value) { +export function isNumeric(value: unknown): boolean { return !Number.isNaN(Number(value)); } -export function isNumber(value) { +export function isNumber(value: unknown): value is number { return typeof value === 'number'; } -export function isBoolean(value) { +export function isBoolean(value: unknown): value is boolean { return typeof value === 'boolean'; } -export function isObject(x) { +export function isObject(x: unknown): x is Record { const type = typeof x; return x !== null && (type === 'object' || type === 'function'); } -export function isPlainObject(val) { +export function isPlainObject(val: unknown): val is Record { return val !== null && typeof val === 'object' && Object.prototype.toString.call(val) === '[object Object]'; } -export function isEmpty(val) { +export function isEmpty(val: unknown): boolean { if (val === null || val === undefined) return true; if (typeof val === 'string' || Array.isArray(val)) return val.length === 0; if (val instanceof Map || val instanceof Set) return val.size === 0; @@ -45,12 +47,33 @@ export function isEmpty(val) { return true; } +/** + * 日期校验选项 + */ +export interface IsDateOptions { + /** + * 日期格式 + * @default 'YYYY/MM/DD' + */ + format?: string; + /** + * 日期分隔符 + * @default ['/', '-'] + */ + delimiters?: string[]; + /** + * 是否启用严格模式 + * @default false + */ + strictMode?: boolean; +} + /** * 验证是否为有效日期 * 支持字符串格式(YYYY/MM/DD、YYYY-MM-DD 等)和 Date 对象 */ -export function isDate(input, options) { - const defaultOptions = { +export function isDate(input: string | Date, options?: IsDateOptions): boolean { + const defaultOptions: Required = { format: 'YYYY/MM/DD', delimiters: ['/', '-'], strictMode: false, @@ -93,7 +116,7 @@ export function isDate(input, options) { } if (!opts.strictMode) { - if (Object.prototype.toString.call(input) === '[object Date]' && Number.isFinite(input.getTime())) { + if (Object.prototype.toString.call(input) === '[object Date]' && Number.isFinite((input as Date).getTime())) { return true; } } @@ -104,8 +127,8 @@ export function isDate(input, options) { /** * 检查主机名是否匹配黑/白名单 */ -function checkHost(host, list) { - if (!list || !list.length) return false; +function checkHost(host: string, list: Array): boolean { + if (!list?.length) return false; return list.some((item) => { if (item instanceof RegExp) return item.test(host); return host === item; @@ -115,15 +138,36 @@ function checkHost(host, list) { /** * 计算字符串的字节长度(UTF-8 编码) */ -function byteLength(str) { +function byteLength(str: string): number { return encodeURI(str).split(/%..|./).length - 1; } +/** + * FQDN 校验选项 + */ +interface IsFQDNOptions { + /** + * 是否要求顶级域名 + * @default true + */ + require_tld?: boolean; + /** + * 是否允许下划线 + * @default false + */ + allow_underscores?: boolean; + /** + * 是否允许末尾的点 + * @default false + */ + allow_trailing_dot?: boolean; +} + /** * 检查是否为 FQDN(完全限定域名) */ -function isFQDN(str, options = {}) { - const opts = { +function isFQDN(str: string, options: IsFQDNOptions = {}): boolean { + const opts: Required = { require_tld: true, allow_underscores: false, allow_trailing_dot: false, @@ -163,7 +207,7 @@ function isFQDN(str, options = {}) { /** * 检查是否为有效的 IPv4 或 IPv6 地址 */ -function isIP(ipAddress, version) { +function isIP(ipAddress: string, version?: number): boolean { const IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; const IPv4AddressFormat = `(${IPv4SegmentFormat}[.]){3}${IPv4SegmentFormat}`; const IPv4AddressRegExp = new RegExp(`^${IPv4AddressFormat}$`); @@ -191,26 +235,13 @@ function isIP(ipAddress, version) { /** * 验证是否为有效邮箱地址 * 参考 validator.js 的 isEmail 实现,支持 options 参数 - * @param {string} str - 待校验字符串 - * @param {object} [options] - 校验选项 - * @param {boolean} [options.allow_display_name=false] - 是否允许显示名称格式 - * @param {boolean} [options.require_display_name=false] - 是否要求必须包含显示名称 - * @param {boolean} [options.allow_utf8_local_part=true] - 是否允许 UTF8 本地部分 - * @param {boolean} [options.require_tld=true] - 是否要求顶级域名 - * @param {boolean} [options.ignore_max_length=false] - 是否忽略最大长度限制 - * @param {boolean} [options.allow_ip_domain=false] - 是否允许 IP 地址作为域名 - * @param {boolean} [options.domain_specific_validation=false] - 是否启用域名特定校验(如 Gmail) - * @param {boolean} [options.allow_underscores=false] - 是否允许下划线 - * @param {Array} [options.host_blacklist] - 域名黑名单 - * @param {Array} [options.host_whitelist] - 域名白名单 - * @param {string} [options.blacklisted_chars] - 拒绝包含的字符 */ -export function isEmail(str, options) { +export function isEmail(str: string, options?: IsEmailOptions): boolean { if (typeof str !== 'string') return false; let email = str; - const defaultOpts = { + const defaultOpts: Required = { allow_display_name: false, allow_underscores: false, require_display_name: false, @@ -220,6 +251,8 @@ export function isEmail(str, options) { ignore_max_length: false, host_blacklist: [], host_whitelist: [], + allow_ip_domain: false, + domain_specific_validation: false, }; const opts = { ...defaultOpts, ...options }; @@ -246,7 +279,7 @@ export function isEmail(str, options) { if (!opts.ignore_max_length && email.length > 254) return false; const parts = email.split('@'); - const domain = parts.pop(); + const domain = parts.pop()!; const user = parts.join('@'); if (!user || !domain) return false; @@ -323,31 +356,13 @@ export function isEmail(str, options) { /** * 验证是否为有效 URL * 参考 validator.js 的 isURL 实现,支持完整 options 参数 - * @param {string} str - 待校验字符串 - * @param {object} [options] - 校验选项 - * @param {string[]} [options.protocols=['http','https','ftp']] - 允许的协议 - * @param {boolean} [options.require_tld=true] - 是否要求顶级域名 - * @param {boolean} [options.require_protocol=false] - 是否要求协议 - * @param {boolean} [options.require_host=true] - 是否要求主机名 - * @param {boolean} [options.require_port=false] - 是否要求端口 - * @param {boolean} [options.require_valid_protocol=true] - 是否要求有效协议 - * @param {boolean} [options.allow_underscores=false] - 是否允许下划线 - * @param {Array} [options.host_whitelist] - 主机名白名单 - * @param {Array} [options.host_blacklist] - 主机名黑名单 - * @param {boolean} [options.allow_trailing_dot=false] - 是否允许末尾的点 - * @param {boolean} [options.allow_protocol_relative_urls=false] - 是否允许协议相对 URL - * @param {boolean} [options.disallow_auth=false] - 是否禁止认证信息 - * @param {boolean} [options.allow_fragments=true] - 是否允许片段(hash) - * @param {boolean} [options.allow_query_components=true] - 是否允许查询参数 - * @param {boolean} [options.validate_length=true] - 是否校验长度 - * @param {number|false} [options.max_allowed_length=2084] - 最大允许长度 */ -export function isURL(str, options) { +export function isURL(str: string, options?: IsURLOptions): boolean { if (typeof str !== 'string') return false; if (!str || /[\s<>]/.test(str)) return false; if (str.indexOf('mailto:') === 0) return false; - const defaultOpts = { + const defaultOpts: Required = { protocols: ['http', 'https', 'ftp'], require_tld: true, require_protocol: false, @@ -362,6 +377,8 @@ export function isURL(str, options) { disallow_auth: false, validate_length: true, max_allowed_length: 2084, + host_whitelist: [], + host_blacklist: [], }; const opts = { ...defaultOpts, ...options }; @@ -378,7 +395,7 @@ export function isURL(str, options) { } let url = str; - let protocol; + let protocol: string | undefined; // 协议解析 const protocolRegex = /^([a-z][a-z0-9+\-.]*):\/\//i; @@ -401,14 +418,14 @@ export function isURL(str, options) { if (url === '') return false; // 分离片段和查询参数 - let split = url.split('#'); - url = split.shift(); + let split: string[] = url.split('#'); + url = split.shift()!; split = url.split('?'); - url = split.shift(); + url = split.shift()!; // 分离路径 split = url.split('/'); - url = split.shift(); + url = split.shift()!; if (url === '' && !opts.require_host) return true; @@ -416,7 +433,7 @@ export function isURL(str, options) { split = url.split('@'); if (split.length > 1) { if (opts.disallow_auth) return false; - const auth = split.shift(); + const auth = split.shift()!; if (auth === '') return false; if (auth.indexOf(':') >= 0 && auth.split(':').length > 2) return false; const [authUser, authPassword] = auth.split(':'); @@ -424,9 +441,9 @@ export function isURL(str, options) { } const hostname = split.join('@'); - let portStr = null; - let ipv6 = null; - let host; + let portStr: string | null = null; + let ipv6: string | null = null; + let host: string; // IPv6 包裹格式 [::1]:port const wrappedIpv6 = /^\[([^\]]+)\](?::([0-9]+))?$/; @@ -453,7 +470,7 @@ export function isURL(str, options) { } // 白名单优先 - if (opts.host_whitelist && opts.host_whitelist.length) { + if (opts?.host_whitelist?.length) { return checkHost(host, opts.host_whitelist); } @@ -468,10 +485,10 @@ export function isURL(str, options) { return false; } - host = host || ipv6; + host = host || ipv6!; // 黑名单 - if (opts.host_blacklist && opts.host_blacklist.length && checkHost(host, opts.host_blacklist)) { + if (opts?.host_blacklist?.length && checkHost(host, opts.host_blacklist)) { return false; } diff --git a/packages/uniapp-components/input/input.vue b/packages/uniapp-components/input/input.vue index ab467befed..b4f1d98327 100644 --- a/packages/uniapp-components/input/input.vue +++ b/packages/uniapp-components/input/input.vue @@ -151,7 +151,7 @@ import { getCharacterLength, calcIcon, coalesce, nextTick } from '../common/util import { isDef } from '../common/validator'; import { getInputClass } from './computed.js'; import tools from '../common/utils.wxs'; -import { RELATION_MAP } from '../common/relation/parent-map.js'; +import { RELATION_MAP } from '../common/relation/parent-map'; const name = `${prefix}-input`; @@ -205,9 +205,6 @@ export default { tools, dataValue: coalesce(this.value, this.defaultValue), - - // rawValue: '', - // innerMaxLen: -1, }; }, watch: { @@ -282,30 +279,7 @@ export default { this.dataValue = value; this.count = isDef(value) ? String(value).length : 0; } - - // this.updateInnerMaxLen(); }, - // updateInnerMaxLen() { - // this.innerMaxLen = this.getInnerMaxLen(); - // }, - // getInnerMaxLen() { - // const { - // allowInputOverMax, - // maxcharacter, - // maxlength, - // dataValue, - // rawValue, - // count, - // } = this; - // return getInnerMaxLen({ - // allowInputOverMax, - // maxcharacter, - // maxlength, - // dataValue, - // rawValue, - // count, - // }); - // }, updateClearIconVisible(value = false) { const { clearTrigger, disabled, readonly } = this; diff --git a/packages/uniapp-components/mixins/skyline.js b/packages/uniapp-components/mixins/skyline.js index d3d7567cff..7012933025 100644 --- a/packages/uniapp-components/mixins/skyline.js +++ b/packages/uniapp-components/mixins/skyline.js @@ -1,4 +1,4 @@ -import { getCurrentPage } from '../common/utils.js'; +import { getCurrentPage } from '../common/utils'; export default { data() { diff --git a/packages/uniapp-components/textarea/textarea.vue b/packages/uniapp-components/textarea/textarea.vue index 0334364dfa..65ef3a4802 100644 --- a/packages/uniapp-components/textarea/textarea.vue +++ b/packages/uniapp-components/textarea/textarea.vue @@ -56,8 +56,7 @@ import props from './props'; import { getCharacterLength, coalesce, nextTick } from '../common/utils'; import tools from '../common/utils.wxs'; import { textareaStyle } from './computed.js'; -// import { getInnerMaxLen } from '../input/utils'; -import { RELATION_MAP } from '../common/relation/parent-map.js'; +import { RELATION_MAP } from '../common/relation/parent-map'; const name = `${prefix}-textarea`; @@ -129,7 +128,6 @@ export default { this.dataValue = value; this.count = count; }); - // this.updateInnerMaxLen(); }, calculateValue(value, maxcharacter, maxlength) { @@ -197,28 +195,6 @@ export default { onKeyboardHeightChange(e) { this.$emit('keyboardheightchange', e.detail); }, - - // updateInnerMaxLen() { - // this.innerMaxLen = this.getInnerMaxLen(); - // }, - // getInnerMaxLen() { - // const { - // allowInputOverMax, - // maxcharacter, - // maxlength, - // dataValue, - // rawValue, - // count, - // } = this; - // return getInnerMaxLen({ - // allowInputOverMax, - // maxcharacter, - // maxlength, - // dataValue, - // rawValue, - // count, - // }); - // }, }, }), };