diff --git a/packages/tdesign-uniapp-chat/package.json b/packages/tdesign-uniapp-chat/package.json index 5f85cfff0..c3dba1ef7 100644 --- a/packages/tdesign-uniapp-chat/package.json +++ b/packages/tdesign-uniapp-chat/package.json @@ -3,7 +3,7 @@ "version": "0.2.4", "id": "tdesign-uniapp-chat", "title": "tdesign-uniapp-chat", - "description": "TDesign Chat Component for UniApp", + "description": "TDesign Chat Component for Uniapp", "author": "tdesign", "license": "MIT", "keywords": [ @@ -145,4 +145,4 @@ "eslint --fix" ] } -} \ No newline at end of file +} diff --git a/packages/tdesign-uniapp-chat/script/postinstall.js b/packages/tdesign-uniapp-chat/script/postinstall.js index 91eed1a8f..4422bddbf 100644 --- a/packages/tdesign-uniapp-chat/script/postinstall.js +++ b/packages/tdesign-uniapp-chat/script/postinstall.js @@ -17,7 +17,7 @@ function isUserInstall() { function printVue2PostCSSWarning() { console.warn('\n'); - console.warn('⚠️ [TDesign UniApp Chat] 检测到当前使用 Vue2 环境'); + console.warn('⚠️ [TDesign Uniapp Chat] 检测到当前使用 Vue2 环境'); console.warn(' Vue2 项目需要在 postcss.config.js 中进行适配,否则样式可能无法正常工作。'); console.warn(''); console.warn(' 📖 适配指南: https://juejin.cn/post/7602901195154030644'); @@ -73,14 +73,14 @@ function main() { const version = detectVueVersion(); if (!version) { - console.warn('[TDesign UniApp Chat] Vue is not found. Please run "npm install vue" to install.'); + console.warn('[TDesign Uniapp Chat] Vue is not found. Please run "npm install vue" to install.'); return; } if (isVue2(version)) { printVue2PostCSSWarning(); } else if (!isVue3(version)) { - console.warn(`[TDesign UniApp Chat] Vue version ${version} is not supported.`); + console.warn(`[TDesign Uniapp Chat] Vue version ${version} is not supported.`); } } diff --git a/packages/tdesign-uniapp-chat/site/docs/custom-style.md b/packages/tdesign-uniapp-chat/site/docs/custom-style.md index 4f3df2fae..e14bbee2f 100644 --- a/packages/tdesign-uniapp-chat/site/docs/custom-style.md +++ b/packages/tdesign-uniapp-chat/site/docs/custom-style.md @@ -4,7 +4,7 @@ description: TDesign 提供了多种方式可以实现样式覆盖 spline: explain --- -TDesign UniApp 提供了 4 种方式用于样式覆盖 +TDesign Uniapp 提供了 4 种方式用于样式覆盖 ## 1 使用 Custom Style @@ -108,7 +108,7 @@ TDesign 在每个组件的内部都预置了许多外部样式类供开发者使 } ``` -**实现上,TDesign UniApp 将外部样式类都转成了 `props`** +**实现上,TDesign Uniapp 将外部样式类都转成了 `props`** ## 4 使用 CSS 变量 diff --git a/packages/tdesign-uniapp-chat/site/docs/custom-theme.md b/packages/tdesign-uniapp-chat/site/docs/custom-theme.md index c1c9390c6..abcf0fb74 100644 --- a/packages/tdesign-uniapp-chat/site/docs/custom-theme.md +++ b/packages/tdesign-uniapp-chat/site/docs/custom-theme.md @@ -8,7 +8,7 @@ spline: explain ## 全局自定义 -TDesign UniApp 的 CSS Variables 全部定义可以在这里看到: [_variables.less](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/style/_variables.less) +TDesign Uniapp 的 CSS Variables 全部定义可以在这里看到: [_variables.less](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/style/_variables.less) 如果你想改变主题色,主要改变这几个变量即可: @@ -31,7 +31,7 @@ page { ## 局部自定义 -在 TDesign UniApp 里,你也可以只给某个组件修改主题,下面以 `Rate` 举例: +在 TDesign Uniapp 里,你也可以只给某个组件修改主题,下面以 `Rate` 举例: ```css page { diff --git a/packages/tdesign-uniapp-chat/site/docs/dark-mode.md b/packages/tdesign-uniapp-chat/site/docs/dark-mode.md index b9723f5cd..faddc08db 100644 --- a/packages/tdesign-uniapp-chat/site/docs/dark-mode.md +++ b/packages/tdesign-uniapp-chat/site/docs/dark-mode.md @@ -17,7 +17,7 @@ spline: design-mode ## 实现方案 -TDesign UniApp 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 +TDesign Uniapp 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 ## 使用方式 diff --git a/packages/tdesign-uniapp-chat/site/docs/faq.md b/packages/tdesign-uniapp-chat/site/docs/faq.md index 911d40bfa..b120cf804 100644 --- a/packages/tdesign-uniapp-chat/site/docs/faq.md +++ b/packages/tdesign-uniapp-chat/site/docs/faq.md @@ -4,11 +4,11 @@ description: 看看有没有你想要的。 spline: explain --- -### 与 TDesign UniApp 库的关系 +### 与 TDesign Uniapp 库的关系 -[TDsign UniApp](https://www.npmjs.com/package/@tdesign/uniapp) 和 [TDesign UniApp Chat](https://www.npmjs.com/package/@tdesign/uniapp-chat) 是两个不同的包,后者依赖前者。 +[TDesign Uniapp](https://www.npmjs.com/package/@tdesign/uniapp) 和 [TDesign Uniapp Chat](https://www.npmjs.com/package/@tdesign/uniapp-chat) 是两个不同的包,后者依赖前者。 -样式文件从 TDesign UniApp 引入一份即可。 +样式文件从 TDesign Uniapp 引入一份即可。 ```js import '@tdesign/uniapp/theme.css'; diff --git a/packages/tdesign-uniapp-chat/site/docs/getting-started.en-US.md b/packages/tdesign-uniapp-chat/site/docs/getting-started.en-US.md index 7425fff09..3fbc1b098 100644 --- a/packages/tdesign-uniapp-chat/site/docs/getting-started.en-US.md +++ b/packages/tdesign-uniapp-chat/site/docs/getting-started.en-US.md @@ -1,6 +1,6 @@ --- title: Uni App Chat -description: TDesign UniApp Chat is a UI component library for Uni App. +description: TDesign Uniapp Chat is a UI component library for Uni App. spline: explain --- @@ -8,7 +8,7 @@ spline: explain - Starting from version 0.2.0, the npm package name for the TDesign UniApp Chat component library has changed from tdesign-uniapp-chat to @tdesign/uniapp-chat. + Starting from version 0.2.0, the npm package name for the TDesign Uniapp Chat component library has changed from tdesign-uniapp-chat to @tdesign/uniapp-chat. ## Preview diff --git a/packages/tdesign-uniapp-chat/site/docs/getting-started.md b/packages/tdesign-uniapp-chat/site/docs/getting-started.md index 9acdfdabb..39c4e9a30 100644 --- a/packages/tdesign-uniapp-chat/site/docs/getting-started.md +++ b/packages/tdesign-uniapp-chat/site/docs/getting-started.md @@ -1,6 +1,6 @@ --- title: Uni App Chat -description: TDesign UniApp Chat 组件库。 +description: TDesign Uniapp Chat 组件库。 spline: explain --- @@ -8,7 +8,7 @@ spline: explain - TDesign UniApp Chat 组件库 npm 包名自 0.2.0 版本开始,从 tdesign-uniapp-chat 变更为 @tdesign/uniapp-chat + TDesign Uniapp Chat 组件库 npm 包名自 0.2.0 版本开始,从 tdesign-uniapp-chat 变更为 @tdesign/uniapp-chat ## 预览 diff --git a/packages/tdesign-uniapp-chat/site/web/stackblitz/content.ts b/packages/tdesign-uniapp-chat/site/web/stackblitz/content.ts index 3a862aa0c..db4ea9288 100644 --- a/packages/tdesign-uniapp-chat/site/web/stackblitz/content.ts +++ b/packages/tdesign-uniapp-chat/site/web/stackblitz/content.ts @@ -42,7 +42,7 @@ export function createApp() { `; export const MANIFEST_JSON_CONTENT = JSON.stringify({ - name: 'TDesign UniApp', + name: 'TDesign Uniapp', appid: '', description: '', versionName: '1.0.0', @@ -111,7 +111,7 @@ export const PAGES_JSON_CONTENT = JSON.stringify({ { path: 'pages/index/index', style: { - navigationBarTitleText: 'TDesign UniApp', + navigationBarTitleText: 'TDesign Uniapp', }, }, ], diff --git a/packages/tdesign-uniapp/.changelog/pr-4511.md b/packages/tdesign-uniapp/.changelog/pr-4511.md new file mode 100644 index 000000000..aaae886a0 --- /dev/null +++ b/packages/tdesign-uniapp/.changelog/pr-4511.md @@ -0,0 +1,12 @@ +--- +pr_number: 4511 +contributor: novlan1 +--- + +- fix(Message): 修复连续点击时的报错问题 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- fix(Stepper): 调整手动输入逻辑,输入时仅过滤非法字符,范围校验&赋值移至失焦 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- fix(Search): 补全 `update:value` 事件声明,修复 `v-model:value` 语法糖告警 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- fix(Upload): 修复禁用态文件样式错误(禁用态下移除操作按钮) @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- fix(Image): 修复鸿蒙下图片无法显示问题 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- feat(Cascader): 新增 `filterable`、`filter` 和 `filter-placeholder` 属性,支持搜索功能 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) +- feat(Typography): 新增 `Typography` 排版组件 @novlan1 ([#4511](https://github.com/Tencent/tdesign-miniprogram/pull/4511)) diff --git a/packages/tdesign-uniapp/README.md b/packages/tdesign-uniapp/README.md index 8f090c808..e6c344a61 100644 --- a/packages/tdesign-uniapp/README.md +++ b/packages/tdesign-uniapp/README.md @@ -167,11 +167,11 @@ import TLoading from '@tdesign/uniapp/loading/loading.vue'; | 模板 | 描述 | 预览 | | --- | --- | --- | -| [TDesign UniApp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI 模式模板 - 通用类 | | -| [TDesign UniApp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI 模式模板 - 活动报名 | | -| [TDesign UniApp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX 模式模板 | | -| [TDesign UniApp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI 模式模板 | | -| [TDesign UniApp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX 模式模板 | | +| [TDesign Uniapp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI 模式模板 - 通用类 | | +| [TDesign Uniapp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI 模式模板 - 活动报名 | | +| [TDesign Uniapp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX 模式模板 | | +| [TDesign Uniapp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI 模式模板 | | +| [TDesign Uniapp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX 模式模板 | | ## 反馈 有任何问题,建议通过 [Github issues](https://github.com/Tencent/tdesign-miniprogram/issues) 反馈或扫码加入用户微信群。 diff --git a/packages/tdesign-uniapp/example/index.html b/packages/tdesign-uniapp/example/index.html index 0edcb8889..ddf7f982b 100644 --- a/packages/tdesign-uniapp/example/index.html +++ b/packages/tdesign-uniapp/example/index.html @@ -13,7 +13,7 @@ '" />', ); - TDesign UniApp + TDesign Uniapp diff --git a/packages/tdesign-uniapp/example/script/types/index.js b/packages/tdesign-uniapp/example/script/types/index.js index ff9c634e1..4cfb82121 100644 --- a/packages/tdesign-uniapp/example/script/types/index.js +++ b/packages/tdesign-uniapp/example/script/types/index.js @@ -1,3 +1,4 @@ +const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); @@ -117,6 +118,37 @@ function checkFileExists(filePath, label) { } } +function runEslintFix(targets, label) { + // 过滤掉不存在的路径,避免 eslint 直接报错退出 + const existing = targets.filter(p => fs.existsSync(p)); + if (existing.length === 0) { + console.warn(`[types][${label}] 跳过 eslint --fix: 无可处理的目标文件`); + return; + } + + const args = [ + 'eslint', + '--fix', + '--no-error-on-unmatched-pattern', + '--ext', + '.ts,.d.ts', + ...existing.map(p => `"${p}"`), + ].join(' '); + + console.log(`[types][${label}] 执行 eslint --fix 处理 ${existing.length} 个目标...`); + try { + execSync(`npx ${args}`, { + cwd: PROJECT_ROOT, + stdio: 'inherit', + }); + console.log(`[types][${label}] eslint --fix 完成 ✅`); + } catch (err) { + // eslint 在仅有 warning(或个别非 --fix 可处理的 error)时也会非零退出, + // 不应阻断生成流程,仅打印提示 + console.warn(`[types][${label}] eslint --fix 退出码非零(可能存在无法自动修复的问题,请手动检查)`); + } +} + async function genOnProject({ pkgGlob, pkgJsonPath, @@ -158,6 +190,9 @@ async function genOnProject({ genIndexContent(fileNames, indexPath, isChat, label); getGlobalDTS(fileNames, globalDTSPath, isChat, label); + // 对生成的文件自动执行 eslint --fix,避免再手动跑 lint + runEslintFix([dtsDir, globalDTSPath], label); + console.log(`[types][${label}] 生成完毕 ✅`); } diff --git a/packages/tdesign-uniapp/example/src/manifest.json b/packages/tdesign-uniapp/example/src/manifest.json index 89747bb91..c401325f4 100644 --- a/packages/tdesign-uniapp/example/src/manifest.json +++ b/packages/tdesign-uniapp/example/src/manifest.json @@ -1,5 +1,5 @@ { - "name": "TDesign UniApp", + "name": "TDesign Uniapp", "appid": "", "description": "", "versionName": "1.0.0", @@ -123,4 +123,4 @@ "enable": false }, "vueVersion": "3" -} +} \ No newline at end of file diff --git a/packages/tdesign-uniapp/example/src/pages.json b/packages/tdesign-uniapp/example/src/pages.json index 13723f139..6d58c839f 100644 --- a/packages/tdesign-uniapp/example/src/pages.json +++ b/packages/tdesign-uniapp/example/src/pages.json @@ -45,6 +45,9 @@ { "path": "pages-more/col/col" }, + { + "path": "pages-more/paragraph/paragraph" + }, { "path": "pages-more/back-top/back-top" }, @@ -450,7 +453,7 @@ "globalStyle": { "pageOrientation": "portrait", "navigationBarTextStyle": "black", - "navigationBarTitleText": "TDesign UniApp", + "navigationBarTitleText": "TDesign Uniapp", "backgroundColor": "#F8F8F8", "navigationStyle": "custom" }, @@ -481,6 +484,10 @@ "name": "layout", "pathName": "pages-more/col/col" }, + { + "name": "typography", + "pathName": "pages-more/paragraph/paragraph" + }, { "name": "back-top", "pathName": "pages-more/back-top/back-top" diff --git a/packages/tdesign-uniapp/example/src/pages/home/data/base.json b/packages/tdesign-uniapp/example/src/pages/home/data/base.json index fdc1fd38b..e8eddc953 100644 --- a/packages/tdesign-uniapp/example/src/pages/home/data/base.json +++ b/packages/tdesign-uniapp/example/src/pages/home/data/base.json @@ -27,6 +27,11 @@ "name": "Layout", "label": "布局", "path": "/pages-more/col/col" + }, + { + "name": "Typography", + "label": "排版", + "path": "/pages-more/paragraph/paragraph" } ] }, diff --git a/packages/tdesign-uniapp/global.d.ts b/packages/tdesign-uniapp/global.d.ts index 4aff571c7..6059de61e 100644 --- a/packages/tdesign-uniapp/global.d.ts +++ b/packages/tdesign-uniapp/global.d.ts @@ -45,6 +45,7 @@ declare module 'vue' { TNavbar: typeof import('@tdesign/uniapp/navbar/navbar.vue').default; TNoticeBar: typeof import('@tdesign/uniapp/notice-bar/notice-bar.vue').default; TOverlay: typeof import('@tdesign/uniapp/overlay/overlay.vue').default; + TParagraph: typeof import('@tdesign/uniapp/paragraph/paragraph.vue').default; TPicker: typeof import('@tdesign/uniapp/picker/picker.vue').default; TPickerItem: typeof import('@tdesign/uniapp/picker-item/picker-item.vue').default; TPopover: typeof import('@tdesign/uniapp/popover/popover.vue').default; @@ -77,7 +78,9 @@ declare module 'vue' { TTable: typeof import('@tdesign/uniapp/table/table.vue').default; TTabs: typeof import('@tdesign/uniapp/tabs/tabs.vue').default; TTag: typeof import('@tdesign/uniapp/tag/tag.vue').default; + TText: typeof import('@tdesign/uniapp/text/text.vue').default; TTextarea: typeof import('@tdesign/uniapp/textarea/textarea.vue').default; + TTitle: typeof import('@tdesign/uniapp/title/title.vue').default; TToast: typeof import('@tdesign/uniapp/toast/toast.vue').default; TTreeSelect: typeof import('@tdesign/uniapp/tree-select/tree-select.vue').default; TUpload: typeof import('@tdesign/uniapp/upload/upload.vue').default; diff --git a/packages/tdesign-uniapp/package.json b/packages/tdesign-uniapp/package.json index 01e746e3b..6436c8307 100644 --- a/packages/tdesign-uniapp/package.json +++ b/packages/tdesign-uniapp/package.json @@ -3,7 +3,7 @@ "version": "0.9.1", "id": "tdesign-uniapp", "title": "tdesign-uniapp", - "description": "TDesign Component for UniApp", + "description": "TDesign Component for Uniapp", "author": "tdesign", "license": "MIT", "keywords": [ @@ -309,6 +309,11 @@ "import": "./dist/overlay/overlay.vue", "default": "./dist/overlay/overlay.vue" }, + "./paragraph/paragraph.vue": { + "types": "./dist/types/paragraph.d.ts", + "import": "./dist/paragraph/paragraph.vue", + "default": "./dist/paragraph/paragraph.vue" + }, "./picker/picker.vue": { "types": "./dist/types/picker.d.ts", "import": "./dist/picker/picker.vue", @@ -469,11 +474,21 @@ "import": "./dist/tag/tag.vue", "default": "./dist/tag/tag.vue" }, + "./text/text.vue": { + "types": "./dist/types/text.d.ts", + "import": "./dist/text/text.vue", + "default": "./dist/text/text.vue" + }, "./textarea/textarea.vue": { "types": "./dist/types/textarea.d.ts", "import": "./dist/textarea/textarea.vue", "default": "./dist/textarea/textarea.vue" }, + "./title/title.vue": { + "types": "./dist/types/title.d.ts", + "import": "./dist/title/title.vue", + "default": "./dist/title/title.vue" + }, "./toast/toast.vue": { "types": "./dist/types/toast.d.ts", "import": "./dist/toast/toast.vue", @@ -582,4 +597,4 @@ "eslint --fix" ] } -} \ No newline at end of file +} diff --git a/packages/tdesign-uniapp/script/postinstall.js b/packages/tdesign-uniapp/script/postinstall.js index 15d214b06..b060f637c 100644 --- a/packages/tdesign-uniapp/script/postinstall.js +++ b/packages/tdesign-uniapp/script/postinstall.js @@ -17,7 +17,7 @@ function isUserInstall() { function printVue2PostCSSWarning() { console.warn('\n'); - console.warn('⚠️ [TDesign UniApp] 检测到当前使用 Vue2 环境'); + console.warn('⚠️ [TDesign Uniapp] 检测到当前使用 Vue2 环境'); console.warn(' Vue2 项目需要在 postcss.config.js 中进行适配,否则样式可能无法正常工作。'); console.warn(''); console.warn(' 📖 适配指南: https://juejin.cn/post/7602901195154030644'); @@ -73,14 +73,14 @@ function main() { const version = detectVueVersion(); if (!version) { - console.warn('[TDesign UniApp] Vue is not found. Please run "npm install vue" to install.'); + console.warn('[TDesign Uniapp] Vue is not found. Please run "npm install vue" to install.'); return; } if (isVue2(version)) { printVue2PostCSSWarning(); } else if (!isVue3(version)) { - console.warn(`[TDesign UniApp] Vue version ${version} is not supported.`); + console.warn(`[TDesign Uniapp] Vue version ${version} is not supported.`); } } diff --git a/packages/tdesign-uniapp/site/docs.config.js b/packages/tdesign-uniapp/site/docs.config.js index 4a9cdac97..e7f9707f8 100644 --- a/packages/tdesign-uniapp/site/docs.config.js +++ b/packages/tdesign-uniapp/site/docs.config.js @@ -160,6 +160,15 @@ export const docs = [ component: () => import('@/link/README.md'), componentEn: () => import('@/link/README.en-US.md'), }, + { + title: 'Typography 排版', + titleEn: 'Typography', + name: 'typography', + meta: { docType: 'base' }, + path: '/uniapp/components/typography', + component: () => import('@/paragraph/README.md'), + componentEn: () => import('@/paragraph/README.en-US.md'), + }, ], }, { diff --git a/packages/tdesign-uniapp/site/docs/custom-style.md b/packages/tdesign-uniapp/site/docs/custom-style.md index 4f3df2fae..e14bbee2f 100644 --- a/packages/tdesign-uniapp/site/docs/custom-style.md +++ b/packages/tdesign-uniapp/site/docs/custom-style.md @@ -4,7 +4,7 @@ description: TDesign 提供了多种方式可以实现样式覆盖 spline: explain --- -TDesign UniApp 提供了 4 种方式用于样式覆盖 +TDesign Uniapp 提供了 4 种方式用于样式覆盖 ## 1 使用 Custom Style @@ -108,7 +108,7 @@ TDesign 在每个组件的内部都预置了许多外部样式类供开发者使 } ``` -**实现上,TDesign UniApp 将外部样式类都转成了 `props`** +**实现上,TDesign Uniapp 将外部样式类都转成了 `props`** ## 4 使用 CSS 变量 diff --git a/packages/tdesign-uniapp/site/docs/custom-theme.md b/packages/tdesign-uniapp/site/docs/custom-theme.md index c1c9390c6..abcf0fb74 100644 --- a/packages/tdesign-uniapp/site/docs/custom-theme.md +++ b/packages/tdesign-uniapp/site/docs/custom-theme.md @@ -8,7 +8,7 @@ spline: explain ## 全局自定义 -TDesign UniApp 的 CSS Variables 全部定义可以在这里看到: [_variables.less](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/style/_variables.less) +TDesign Uniapp 的 CSS Variables 全部定义可以在这里看到: [_variables.less](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/style/_variables.less) 如果你想改变主题色,主要改变这几个变量即可: @@ -31,7 +31,7 @@ page { ## 局部自定义 -在 TDesign UniApp 里,你也可以只给某个组件修改主题,下面以 `Rate` 举例: +在 TDesign Uniapp 里,你也可以只给某个组件修改主题,下面以 `Rate` 举例: ```css page { diff --git a/packages/tdesign-uniapp/site/docs/dark-mode.md b/packages/tdesign-uniapp/site/docs/dark-mode.md index b9723f5cd..faddc08db 100644 --- a/packages/tdesign-uniapp/site/docs/dark-mode.md +++ b/packages/tdesign-uniapp/site/docs/dark-mode.md @@ -17,7 +17,7 @@ spline: design-mode ## 实现方案 -TDesign UniApp 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 +TDesign Uniapp 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 ## 使用方式 diff --git a/packages/tdesign-uniapp/site/docs/faq.md b/packages/tdesign-uniapp/site/docs/faq.md index c365f5cea..e44ef3e9f 100644 --- a/packages/tdesign-uniapp/site/docs/faq.md +++ b/packages/tdesign-uniapp/site/docs/faq.md @@ -6,7 +6,7 @@ spline: explain ## 写在前面 -TDesign UniApp 的实现原理,可以查看[这篇文章](https://juejin.cn/post/7571650164844068898)。 +TDesign Uniapp 的实现原理,可以查看[这篇文章](https://juejin.cn/post/7571650164844068898)。 ### 外部样式类 diff --git a/packages/tdesign-uniapp/site/docs/getting-started.en-US.md b/packages/tdesign-uniapp/site/docs/getting-started.en-US.md index 196b83e53..5f6992e55 100644 --- a/packages/tdesign-uniapp/site/docs/getting-started.en-US.md +++ b/packages/tdesign-uniapp/site/docs/getting-started.en-US.md @@ -1,6 +1,6 @@ --- title: Uni App -description: TDesign UniApp is a UI component library for Uni App. +description: TDesign Uniapp is a UI component library for Uni App. spline: explain --- @@ -8,7 +8,7 @@ spline: explain - Starting with version 0.7.0, the npm package name for the TDesign UniApp component library has changed from tdesign-uniapp to @tdesign/uniapp. + Starting with version 0.7.0, the npm package name for the TDesign Uniapp component library has changed from tdesign-uniapp to @tdesign/uniapp. ## Preview @@ -149,11 +149,11 @@ We provide a variety of out-of-the-box template projects to help you get started | Template | Description | Preview | | --- | --- | --- | -| [TDesign UniApp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI Mode - General | | -| [TDesign UniApp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI Mode - Event Registration | | -| [TDesign UniApp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX Mode | | -| [TDesign UniApp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI Mode | | -| [TDesign UniApp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX Mode | | +| [TDesign Uniapp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI Mode - General | | +| [TDesign Uniapp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI Mode - Event Registration | | +| [TDesign Uniapp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX Mode | | +| [TDesign Uniapp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI Mode | | +| [TDesign Uniapp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX Mode | | ## Development diff --git a/packages/tdesign-uniapp/site/docs/getting-started.md b/packages/tdesign-uniapp/site/docs/getting-started.md index 5bcadd4e8..29a8678e3 100644 --- a/packages/tdesign-uniapp/site/docs/getting-started.md +++ b/packages/tdesign-uniapp/site/docs/getting-started.md @@ -1,6 +1,6 @@ --- title: Uni App -description: TDesign UniApp 组件库。 +description: TDesign Uniapp 组件库。 spline: explain --- @@ -8,7 +8,7 @@ spline: explain - TDesign UniApp 组件库 npm 包名自 0.7.0 版本开始,从 tdesign-uniapp 变更为 @tdesign/uniapp + TDesign Uniapp 组件库 npm 包名自 0.7.0 版本开始,从 tdesign-uniapp 变更为 @tdesign/uniapp ## 预览 @@ -149,11 +149,11 @@ import TLoading from '@tdesign/uniapp/loading/loading.vue'; | 模板 | 描述 | 预览 | | --- | --- | --- | -| [TDesign UniApp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI 模式模板 - 通用类 | | -| [TDesign UniApp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI 模式模板 - 活动报名 | | -| [TDesign UniApp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX 模式模板 | | -| [TDesign UniApp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI 模式模板 | | -| [TDesign UniApp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX 模式模板 | | +| [TDesign Uniapp Starter](https://github.com/TDesignOteam/tdesign-uniapp-starter/) | Vue3 + CLI 模式模板 - 通用类 | | +| [TDesign Uniapp Starter Apply](https://github.com/TDesignOteam/tdesign-uniapp-starter-apply/) | Vue3 + CLI 模式模板 - 活动报名 | | +| [TDesign Uniapp Starter Vue3 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue3-hx/) | Vue3 + HBuilderX 模式模板 | | +| [TDesign Uniapp Starter Vue2 CLI](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-cli/) | Vue2 + CLI 模式模板 | | +| [TDesign Uniapp Starter Vue2 HX](https://github.com/TDesignOteam/tdesign-uniapp-starter-vue2-hx/) | Vue2 + HBuilderX 模式模板 | | ## 开发 diff --git a/packages/tdesign-uniapp/site/docs/overview.en-US.md b/packages/tdesign-uniapp/site/docs/overview.en-US.md index fd25ead9e..1e6896373 100644 --- a/packages/tdesign-uniapp/site/docs/overview.en-US.md +++ b/packages/tdesign-uniapp/site/docs/overview.en-US.md @@ -5,7 +5,7 @@ spline: explain --- -

Base6

+

Base7

@@ -54,6 +54,14 @@ spline: explain

Link

+ +
+ + + +

Typography 排版

+
+

Navigation8

diff --git a/packages/tdesign-uniapp/site/docs/overview.md b/packages/tdesign-uniapp/site/docs/overview.md index 337641b52..802e81d06 100644 --- a/packages/tdesign-uniapp/site/docs/overview.md +++ b/packages/tdesign-uniapp/site/docs/overview.md @@ -4,7 +4,7 @@ description: 将根据业务实践持续新增组件类型,敬请留意组件 spline: explain --- -

基础6

+

基础7

@@ -53,6 +53,14 @@ spline: explain

Link 链接

+ +
+ + + +

Typography 排版

+
+

导航8

diff --git a/packages/tdesign-uniapp/site/web/stackblitz/content.ts b/packages/tdesign-uniapp/site/web/stackblitz/content.ts index dab1ea2ed..4b2d7d108 100644 --- a/packages/tdesign-uniapp/site/web/stackblitz/content.ts +++ b/packages/tdesign-uniapp/site/web/stackblitz/content.ts @@ -42,7 +42,7 @@ export function createApp() { `; export const MANIFEST_JSON_CONTENT = JSON.stringify({ - name: 'TDesign UniApp', + name: 'TDesign Uniapp', appid: '', description: '', versionName: '1.0.0', @@ -111,7 +111,7 @@ export const PAGES_JSON_CONTENT = JSON.stringify({ { path: 'pages/index/index', style: { - navigationBarTitleText: 'TDesign UniApp', + navigationBarTitleText: 'TDesign Uniapp', }, }, ], diff --git a/packages/uniapp-components/cascader/README.en-US.md b/packages/uniapp-components/cascader/README.en-US.md index e0c4f2c50..f03d32863 100644 --- a/packages/uniapp-components/cascader/README.en-US.md +++ b/packages/uniapp-components/cascader/README.en-US.md @@ -9,6 +9,9 @@ name | type | default | description | required custom-style | Object | - | CSS(Cascading Style Sheets) | N check-strictly | Boolean | false | \- | N close-btn | Boolean | true | \- | N +filter | Function | - | Typescript: `CascaderFilterFunction ` `type CascaderFilterFunction = (keyword: string, option: CascaderOption, path: CascaderOption[]) => boolean`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N +filter-placeholder | String | - | \- | N +filterable | Boolean | false | \- | N keys | Object | - | Typescript: `CascaderKeysType` `type CascaderKeysType = TreeKeysType`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N options | Array | [] | Typescript: `Array` | N placeholder | String | - | \- | N diff --git a/packages/uniapp-components/cascader/README.md b/packages/uniapp-components/cascader/README.md index 288a69674..441ea1494 100644 --- a/packages/uniapp-components/cascader/README.md +++ b/packages/uniapp-components/cascader/README.md @@ -51,6 +51,9 @@ import TCascader from '@tdesign/uniapp/cascader/cascader.vue'; custom-style | Object | - | 自定义样式 | N check-strictly | Boolean | false | 父子节点选中状态不再关联,可各自选中或取消 | N close-btn | Boolean | true | 关闭按钮 | N +filter | Function | - | 自定义过滤函数。返回 true 表示匹配,未设置时使用内置匹配规则:对路径中所有 label 拼接后做大小写不敏感的 includes 匹配。TS 类型:`CascaderFilterFunction ` `type CascaderFilterFunction = (keyword: string, option: CascaderOption, path: CascaderOption[]) => boolean`。[通用类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N +filter-placeholder | String | - | 搜索框占位符描述文本 | N +filterable | Boolean | false | 是否可搜索,开启后顶部会展示一个搜索框 | N keys | Object | - | 用来定义 value / label / children / disabled 在 `options` 中对应的字段别名。TS 类型:`CascaderKeysType` `type CascaderKeysType = TreeKeysType`。[通用类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N options | Array | [] | 可选项数据源。TS 类型:`Array` | N placeholder | String | - | 未选中时的提示文案。组件内置默认值为:'选择选项' | N diff --git a/packages/uniapp-components/cascader/_example/cascader.vue b/packages/uniapp-components/cascader/_example/cascader.vue index d20c6e32d..a3440b9c3 100644 --- a/packages/uniapp-components/cascader/_example/cascader.vue +++ b/packages/uniapp-components/cascader/_example/cascader.vue @@ -36,6 +36,10 @@ + + + + @@ -43,6 +47,7 @@ + diff --git a/packages/uniapp-components/cascader/cascader.less b/packages/uniapp-components/cascader/cascader.less index 66f5e1b05..df8b9f6fc 100644 --- a/packages/uniapp-components/cascader/cascader.less +++ b/packages/uniapp-components/cascader/cascader.less @@ -12,6 +12,15 @@ @cascader-border-color: var(--td-cascader-border-color, @component-stroke); @cascader-content-height: var(--td-cascader-content-height, 78vh); @cascader-options-height: var(--td-cascader-options-height, calc(100% - @cascader-step-height)); +// filter (search) +@cascader-filter-padding: var(--td-cascader-filter-padding, 0 @spacer-2 @spacer-1); +@cascader-filter-item-padding: var(--td-cascader-filter-item-padding, 24rpx 32rpx); +@cascader-filter-item-color: var(--td-cascader-filter-item-color, @text-color-primary); +@cascader-filter-item-hover-bg: var(--td-cascader-filter-item-hover-bg, @bg-color-secondarycontainer); +@cascader-filter-item-disabled-color: var(--td-cascader-filter-item-disabled-color, @text-color-disabled); +@cascader-filter-highlight-color: var(--td-cascader-filter-highlight-color, @brand-color); +@cascader-filter-empty-color: var(--td-cascader-filter-empty-color, @text-color-placeholder); +@cascader-filter-empty-padding: var(--td-cascader-filter-empty-padding, 96rpx @spacer-2); // steps @cascader-step-height: var(--td-cascader-step-height, 88rpx); @cascader-step-dot-size: var(--td-cascader-step-dot-size, 16rpx); @@ -116,4 +125,43 @@ margin-left: auto; } } + + &__filter { + padding: @cascader-filter-padding; + box-sizing: border-box; + + &-result { + flex: 1; + width: 100%; + box-sizing: border-box; + } + + &-result-item { + padding: @cascader-filter-item-padding; + color: @cascader-filter-item-color; + font: @font-body-medium; + box-sizing: border-box; + .border(bottom, @cascader-border-color); + + &--hover { + background-color: @cascader-filter-item-hover-bg; + } + + &--disabled { + color: @cascader-filter-item-disabled-color; + } + } + + &-highlight { + color: @cascader-filter-highlight-color; + font-weight: 600; + } + + &-empty { + padding: @cascader-filter-empty-padding; + text-align: center; + color: @cascader-filter-empty-color; + font: @font-body-medium; + } + } } diff --git a/packages/uniapp-components/cascader/cascader.vue b/packages/uniapp-components/cascader/cascader.vue index 4349cedb1..d2cc6acae 100644 --- a/packages/uniapp-components/cascader/cascader.vue +++ b/packages/uniapp-components/cascader/cascader.vue @@ -33,99 +33,145 @@ - - + + + + + + + - - - {{ item }} + '__step-dot ' + + classPrefix + + '__step-dot--' + + (item !== placeholder ? 'active' : '') + + ' ' + + classPrefix + + '__step-dot--' + + (index === steps.length - 1 ? 'last' : '') + " + /> + + + {{ item }} + + + + - + - + + + + + + + {{ subTitles[stepIndex] }} - - - + :class="classPrefix + '__options'" + scroll-y + :scroll-top="scrollTopList[index]" + type="list" + :style="'height: ' + optionsHeight + 'px'" + > + + + + + - - - - {{ subTitles[stepIndex] }} - - - + - - + + + {{ frag.text }} + - + + {{ globalConfig.empty }} + + @@ -134,12 +180,13 @@ + + diff --git a/packages/uniapp-components/paragraph/_example/combination/index.vue b/packages/uniapp-components/paragraph/_example/combination/index.vue new file mode 100644 index 000000000..66e55b7ef --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/combination/index.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/packages/uniapp-components/paragraph/_example/copyable/index.vue b/packages/uniapp-components/paragraph/_example/copyable/index.vue new file mode 100644 index 000000000..de4776794 --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/copyable/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/packages/uniapp-components/paragraph/_example/ellipsis/index.vue b/packages/uniapp-components/paragraph/_example/ellipsis/index.vue new file mode 100644 index 000000000..9f6a0aa93 --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/ellipsis/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/packages/uniapp-components/paragraph/_example/paragraph.less b/packages/uniapp-components/paragraph/_example/paragraph.less new file mode 100644 index 000000000..1af7bc8bf --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/paragraph.less @@ -0,0 +1,27 @@ +.typography-example { + display: flex; + padding: 0 32rpx; + background-color: var(--bg-color-demo, #fff); + + &--inline { + display: inline-block; + } + + &--theme { + gap: 24px; + } + + &--border { + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 16px; + right: 16px; + border-bottom: 1px solid var(--td-stroke-color, #e7e7e7); + transform: scaleY(0.5); + } + } +} diff --git a/packages/uniapp-components/paragraph/_example/paragraph.vue b/packages/uniapp-components/paragraph/_example/paragraph.vue new file mode 100644 index 000000000..be7a1959a --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/paragraph.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/packages/uniapp-components/paragraph/_example/theme/index.vue b/packages/uniapp-components/paragraph/_example/theme/index.vue new file mode 100644 index 000000000..81a3ea005 --- /dev/null +++ b/packages/uniapp-components/paragraph/_example/theme/index.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/packages/uniapp-components/paragraph/computed.js b/packages/uniapp-components/paragraph/computed.js new file mode 100644 index 000000000..19415b33e --- /dev/null +++ b/packages/uniapp-components/paragraph/computed.js @@ -0,0 +1,42 @@ +/* typography 公共计算逻辑 */ + +/* 计算省略内容的内联样式 */ +export function ellipsisStyle(ellipsis, isExpanded) { + if (!ellipsis || isExpanded) return ''; + const row = typeof ellipsis === 'object' && ellipsis.row ? ellipsis.row : 1; + return ( + `overflow:hidden;text-overflow:ellipsis;white-space:normal;display:-webkit-box;-webkit-line-clamp:${ + row + };-webkit-box-orient:vertical;` + ); +} + +/* 计算外层容器 class */ +export function wrapperClass(classPrefix, ellipsis) { + if (ellipsis) { + return `${classPrefix}__ellipsis-wrapper`; + } + return ''; +} + +/* 根据装饰属性拼接内层 class */ +export function decorClass(classPrefix, strong, underline, del, code, mark, keyboard, italic) { + const list = []; + if (strong) list.push(`${classPrefix}--strong`); + if (underline) list.push(`${classPrefix}--underline`); + if (del) list.push(`${classPrefix}--delete`); + if (code) list.push(`${classPrefix}--code`); + if (mark) list.push(`${classPrefix}--mark`); + if (keyboard) list.push(`${classPrefix}--keyboard`); + if (italic) list.push(`${classPrefix}--italic`); + return list.join(' '); +} + +/* mark 自定义颜色 */ +export function markStyle(mark) { + if (!mark || mark === true || mark === 'true') return ''; + if (mark && mark !== 'false' && mark !== false) { + return `background-color:${mark};`; + } + return ''; +} diff --git a/packages/uniapp-components/paragraph/paragraph.less b/packages/uniapp-components/paragraph/paragraph.less new file mode 100644 index 000000000..244f2cd93 --- /dev/null +++ b/packages/uniapp-components/paragraph/paragraph.less @@ -0,0 +1,168 @@ +@import '../common/style/base.less'; + +@typography-text-primary-color: @text-color-primary; +@typography-text-secondary-color: @text-color-secondary; +@typography-text-disabled-color: @text-color-disabled; +@typography-text-success-color: @success-color; +@typography-text-error-color: @error-color; +@typography-text-warning-color: @warning-color; +@typography-text-mark-color: #fcdf47; +@typography-icon-color: @brand-color; + +@typography-text-strong: 600; + +@typography-text-font: @font-body-medium; +@typography-code-font: @font-body-small; +@typography-h1-font: @font-headline-large; +@typography-h2-font: @font-headline-medium; +@typography-h3-font: @font-headline-small; +@typography-h4-font: @font-title-large; +@typography-h5-font: @font-title-medium; +@typography-h6-font: @font-title-small; + +@typography-code-family: + Source Code Pro, + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Hiragino Sans GB, + Microsoft YaHei UI, + Microsoft YaHei; + +// ==================== 主样式 ==================== +.@{prefix}-typography { + color: @typography-text-primary-color; + font: @font-body-medium; + margin: @spacer-2 0; + + &--h1 { + font: @typography-h1-font; + margin-top: @spacer-4; + margin-bottom: @spacer-3; + } + + &--h2 { + font: @typography-h2-font; + margin-top: @spacer-4; + margin-bottom: @spacer-3; + } + + &--h3 { + font: @typography-h3-font; + margin-top: @spacer-4; + margin-bottom: @spacer-2; + } + + &--h4 { + font: @typography-h4-font; + margin-top: @spacer-3; + margin-bottom: @spacer-2; + } + + &--h5 { + font: @typography-h5-font; + margin-top: @spacer-3; + margin-bottom: @spacer-2; + } + + &--h6 { + font: @typography-h6-font; + } + + &--strong { + font-weight: @typography-text-strong; + } + + &--mark { + background-color: @typography-text-mark-color; + } + + &--code { + border-radius: @radius-default; + border: 1px solid @component-border; + margin: 0 @spacer; + background-color: @bg-color-secondarycontainer; + padding: 0 @spacer; + transition: background-color 0.2s; + white-space: nowrap; + font: @typography-code-font; + font-family: @typography-code-family; + display: inline-block; + } + + &--keyboard { + border-radius: @radius-default; + border: 1px solid @component-border; + margin: 0 calc(@spacer / 2); + background-color: @bg-color-secondarycontainer; + padding: 0 @spacer; + box-shadow: 0 1px 0 0 @component-border; + font: @typography-code-font; + font-family: @typography-code-family; + display: inline-block; + } + + &--disabled { + color: @typography-text-disabled-color; + cursor: not-allowed; + } + + &--success { + color: @typography-text-success-color; + } + + &--warning { + color: @typography-text-warning-color; + } + + &--error { + color: @typography-text-error-color; + } + + &--secondary { + color: @typography-text-secondary-color; + } + + &-ellipsis-symbol { + color: @typography-icon-color; + cursor: pointer; + text-decoration: none; + white-space: nowrap; + flex: 1; + } + + &--italic { + font-style: italic; + } + + &--underline { + text-decoration: underline; + } + + &--delete { + text-decoration: line-through; + } + + &__ellipsis-wrapper { + display: flex; + align-items: flex-end; + } + + &__ellipsis-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + display: -webkit-box; + -webkit-box-orient: vertical; + } + + &__copy { + display: inline-flex; + align-items: center; + margin-left: 16rpx; + flex-shrink: 0; + color: @typography-icon-color; + cursor: pointer; + } +} diff --git a/packages/uniapp-components/paragraph/paragraph.vue b/packages/uniapp-components/paragraph/paragraph.vue new file mode 100644 index 000000000..cc8149ac7 --- /dev/null +++ b/packages/uniapp-components/paragraph/paragraph.vue @@ -0,0 +1,105 @@ + + + diff --git a/packages/uniapp-components/paragraph/props.ts b/packages/uniapp-components/paragraph/props.ts new file mode 100644 index 000000000..e6ca51080 --- /dev/null +++ b/packages/uniapp-components/paragraph/props.ts @@ -0,0 +1,18 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import type { TdParagraphProps } from './type'; +export default { + /** 段落内容 */ + content: { + type: String, + }, + /** 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 */ + ellipsis: { + type: [Boolean, Object], + default: false as TdParagraphProps['ellipsis'], + }, +}; diff --git a/packages/uniapp-components/paragraph/type.ts b/packages/uniapp-components/paragraph/type.ts new file mode 100644 index 000000000..757697e1d --- /dev/null +++ b/packages/uniapp-components/paragraph/type.ts @@ -0,0 +1,19 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import type { TypographyEllipsis } from '../text/type'; + +export interface TdParagraphProps { + /** + * 段落内容 + */ + content?: string; + /** + * 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 + * @default false + */ + ellipsis?: boolean | TypographyEllipsis; +} diff --git a/packages/uniapp-components/search/search.vue b/packages/uniapp-components/search/search.vue index e280a7696..309c84076 100644 --- a/packages/uniapp-components/search/search.vue +++ b/packages/uniapp-components/search/search.vue @@ -140,6 +140,7 @@ export default { ...props, }, emits: [ + 'update:value', ], data() { return { diff --git a/packages/uniapp-components/stepper/stepper.vue b/packages/uniapp-components/stepper/stepper.vue index 6964bd91e..fde50dfcf 100644 --- a/packages/uniapp-components/stepper/stepper.vue +++ b/packages/uniapp-components/stepper/stepper.vue @@ -201,6 +201,9 @@ export default { this.$emit('focus', { value }); }, + /** + * 输入过程中仅过滤非法字符并更新显示值,不做 min/max 边界约束。范围校验和 change 事件统一在 handleBlur 中处理 + */ handleInput(e) { const { value } = e.detail; // 允许输入空值 @@ -209,21 +212,15 @@ export default { } const formatted = this.filterIllegalChar(value); - const newValue = this.format(formatted); - const displayValue = this.integer ? newValue : formatted; // 当过滤后的值与当前值相同时,需要先清空再回填,强制触发视图更新 - if (String(this.currentValue) === String(displayValue)) { + if (String(this.currentValue) === String(formatted)) { this.updateCurrentValue(''); nextTick().then(() => { - this.updateCurrentValue(displayValue); + this.updateCurrentValue(formatted); }); } else { - this.updateCurrentValue(displayValue); - } - - if (this.integer || /\.\d*[1-9]/.test(formatted)) { - this.setValue(formatted); + this.updateCurrentValue(formatted); } }, diff --git a/packages/uniapp-components/text/props.ts b/packages/uniapp-components/text/props.ts new file mode 100644 index 000000000..ce93987f0 --- /dev/null +++ b/packages/uniapp-components/text/props.ts @@ -0,0 +1,50 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import type { TdTextProps } from './type'; +export default { + /** 是否添加代码样式 */ + code: Boolean, + /** 文本内容 */ + content: { + type: String, + }, + /** 是否可复制 */ + copyable: { + type: [Boolean, Object], + default: false as TdTextProps['copyable'], + }, + /** 是否添加删除线样式 */ + delete: Boolean, + /** 是否添加不可用样式 */ + disabled: Boolean, + /** 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 */ + ellipsis: { + type: [Boolean, Object], + default: false as TdTextProps['ellipsis'], + }, + /** 文本是否为斜体 */ + italic: Boolean, + /** 是否添加键盘样式 */ + keyboard: Boolean, + /** 是否添加标记样式,默认为黄色,可通过配置颜色修改标记样式,如#0052D9 */ + mark: { + type: [String, Boolean], + default: false as TdTextProps['mark'], + }, + /** 文本是否加粗 */ + strong: Boolean, + /** 主题 */ + theme: { + type: String, + validator(val: TdTextProps['theme']): boolean { + if (!val) return true; + return ['primary', 'secondary', 'success', 'warning', 'error'].includes(val); + }, + }, + /** 是否添加下划线样式 */ + underline: Boolean, +}; diff --git a/packages/uniapp-components/text/text.less b/packages/uniapp-components/text/text.less new file mode 100644 index 000000000..d20abff77 --- /dev/null +++ b/packages/uniapp-components/text/text.less @@ -0,0 +1 @@ +@import '../paragraph/paragraph.less'; diff --git a/packages/uniapp-components/text/text.vue b/packages/uniapp-components/text/text.vue new file mode 100644 index 000000000..cfd3481bf --- /dev/null +++ b/packages/uniapp-components/text/text.vue @@ -0,0 +1,175 @@ + + + diff --git a/packages/uniapp-components/text/type.ts b/packages/uniapp-components/text/type.ts new file mode 100644 index 000000000..fa2014004 --- /dev/null +++ b/packages/uniapp-components/text/type.ts @@ -0,0 +1,78 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +export interface TdTextProps { + /** + * 是否添加代码样式 + * @default false + */ + code?: boolean; + /** + * 文本内容 + */ + content?: string; + /** + * 是否可复制 + * @default false + */ + copyable?: boolean | TypographyCopyable; + /** + * 是否添加删除线样式 + * @default false + */ + delete?: boolean; + /** + * 是否添加不可用样式 + * @default false + */ + disabled?: boolean; + /** + * 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 + * @default false + */ + ellipsis?: boolean | TypographyEllipsis; + /** + * 文本是否为斜体 + * @default false + */ + italic?: boolean; + /** + * 是否添加键盘样式 + * @default false + */ + keyboard?: boolean; + /** + * 是否添加标记样式,默认为黄色,可通过配置颜色修改标记样式,如#0052D9 + * @default false + */ + mark?: string | boolean; + /** + * 文本是否加粗 + * @default false + */ + strong?: boolean; + /** + * 主题 + */ + theme?: 'primary' | 'secondary' | 'success' | 'warning' | 'error'; + /** + * 是否添加下划线样式 + * @default false + */ + underline?: boolean; +} + +export interface TypographyCopyable { + text?: string; + suffix?: boolean; +} + +export interface TypographyEllipsis { + collapsible?: boolean; + expandable?: boolean; + row?: number; + suffix?: boolean; +} diff --git a/packages/uniapp-components/title/props.ts b/packages/uniapp-components/title/props.ts new file mode 100644 index 000000000..a615830b8 --- /dev/null +++ b/packages/uniapp-components/title/props.ts @@ -0,0 +1,27 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import type { TdTitleProps } from './type'; +export default { + /** 段落内容 */ + content: { + type: String, + }, + /** 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 */ + ellipsis: { + type: [Boolean, Object], + default: false as TdTitleProps['ellipsis'], + }, + /** 标题等级 */ + level: { + type: String, + default: 'h1' as TdTitleProps['level'], + validator(val: TdTitleProps['level']): boolean { + if (!val) return true; + return ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(val); + }, + }, +}; diff --git a/packages/uniapp-components/title/title.less b/packages/uniapp-components/title/title.less new file mode 100644 index 000000000..d20abff77 --- /dev/null +++ b/packages/uniapp-components/title/title.less @@ -0,0 +1 @@ +@import '../paragraph/paragraph.less'; diff --git a/packages/uniapp-components/title/title.vue b/packages/uniapp-components/title/title.vue new file mode 100644 index 000000000..fd3dbd164 --- /dev/null +++ b/packages/uniapp-components/title/title.vue @@ -0,0 +1,94 @@ + + + diff --git a/packages/uniapp-components/title/type.ts b/packages/uniapp-components/title/type.ts new file mode 100644 index 000000000..06df8fdd9 --- /dev/null +++ b/packages/uniapp-components/title/type.ts @@ -0,0 +1,24 @@ +/* eslint-disable */ + +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import type { TypographyEllipsis } from '../text/type'; + +export interface TdTitleProps { + /** + * 段落内容 + */ + content?: string; + /** + * 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式 + * @default false + */ + ellipsis?: boolean | TypographyEllipsis; + /** + * 标题等级 + * @default h1 + */ + level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; +} diff --git a/packages/uniapp-components/types/index.d.ts b/packages/uniapp-components/types/index.d.ts index aae6edc8f..1faadfeaf 100644 --- a/packages/uniapp-components/types/index.d.ts +++ b/packages/uniapp-components/types/index.d.ts @@ -42,6 +42,7 @@ export * from '../message/type'; export * from '../navbar/type'; export * from '../notice-bar/type'; export * from '../overlay/type'; +export * from '../paragraph/type'; export * from '../picker/type'; export * from '../picker-item/type'; export * from '../popover/type'; @@ -74,7 +75,9 @@ export * from '../tab-panel/type'; export * from '../table/type'; export * from '../tabs/type'; export * from '../tag/type'; +export * from '../text/type'; export * from '../textarea/type'; +export * from '../title/type'; export * from '../toast/type'; export * from '../tree-select/type'; export * from '../upload/type'; diff --git a/packages/uniapp-components/types/paragraph.d.ts b/packages/uniapp-components/types/paragraph.d.ts new file mode 100644 index 000000000..9e4fddcb8 --- /dev/null +++ b/packages/uniapp-components/types/paragraph.d.ts @@ -0,0 +1,7 @@ +import type { TransformEventHandlers, ExtractNonOnProps } from '../common/common'; +import type { TdParagraphProps } from '../paragraph/type'; + +export type ParagraphProps = ExtractNonOnProps; +export type ParagraphEmits = TransformEventHandlers; +declare const ParagraphComponent: import('vue').DefineComponent; +export default ParagraphComponent; diff --git a/packages/uniapp-components/types/text.d.ts b/packages/uniapp-components/types/text.d.ts new file mode 100644 index 000000000..2d499a8c3 --- /dev/null +++ b/packages/uniapp-components/types/text.d.ts @@ -0,0 +1,7 @@ +import type { TransformEventHandlers, ExtractNonOnProps } from '../common/common'; +import type { TdTextProps } from '../text/type'; + +export type TextProps = ExtractNonOnProps; +export type TextEmits = TransformEventHandlers; +declare const TextComponent: import('vue').DefineComponent; +export default TextComponent; diff --git a/packages/uniapp-components/types/title.d.ts b/packages/uniapp-components/types/title.d.ts new file mode 100644 index 000000000..0061d0797 --- /dev/null +++ b/packages/uniapp-components/types/title.d.ts @@ -0,0 +1,7 @@ +import type { TransformEventHandlers, ExtractNonOnProps } from '../common/common'; +import type { TdTitleProps } from '../title/type'; + +export type TitleProps = ExtractNonOnProps; +export type TitleEmits = TransformEventHandlers; +declare const TitleComponent: import('vue').DefineComponent; +export default TitleComponent; diff --git a/packages/uniapp-components/upload/README.en-US.md b/packages/uniapp-components/upload/README.en-US.md index be032f292..1f608d230 100644 --- a/packages/uniapp-components/upload/README.en-US.md +++ b/packages/uniapp-components/upload/README.en-US.md @@ -9,6 +9,7 @@ name | type | default | description | required custom-style | Object | - | CSS(Cascading Style Sheets) | N add-btn | Boolean | true | \- | N add-content | String | - | \- | N +allow-upload-duplicate-file | Boolean | false | allow to upload duplicate name files | N config | Object | - | Typescript: `UploadMpConfig` `type UploadMpConfig = UploadImageConfig \| UploadVideoConfig` `interface UploadImageConfig { count?: number; sizeType?: Array; sourceType?: Array }` `type SizeTypeValues = 'original' \| 'compressed'` `type SourceTypeValues = 'album' \| 'camera'` `interface UploadVideoConfig { sourceType?: Array; compressed?: boolean; maxDuration?: number; camera?: 'back' \| 'front' }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N disabled | Boolean | undefined | make upload to be disabled | N draggable | Boolean / Object | - | Typescript: `boolean \| {vibrate?: boolean; collisionVibrate?: boolean}` | N @@ -18,12 +19,13 @@ grid-config | Object | - | Typescript: `{column?: number; width?: number; heigh gutter | Number | 16 | \- | N image-props | Object | - | Typescript: `ImageProps`,[Image API Documents](./image?tab=api)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N max | Number | 0 | max count of files limit | N -media-type | Array | ['image', 'video'] | Typescript: `Array` `type MediaType = 'image' \| 'video'`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N +media-type | Array | ['image', 'video'] | Typescript: `Array` `type MediaType = 'image' \| 'video' \| 'mix'`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N preview | Boolean | true | \- | N remove-btn | Boolean | true | \- | N request-method | Function | - | Typescript: `(files: UploadFile \| UploadFile[]) => Promise` `interface RequestMethodResponse { status: 'success' \| 'fail'; error?: string; response: { url?: string; files?: UploadFile[]; [key: string]: any } }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N size-limit | Number / Object | - | files size limit。Typescript: `number \| SizeLimitObj` `interface SizeLimitObj { size: number; unit: SizeUnit ; message?: string }` `type SizeUnitArray = ['B', 'KB', 'MB', 'GB']` `type SizeUnit = SizeUnitArray[number]`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N source | String | media | options: media/messageFile | N +theme | String | grid | options: grid/list | N transition | Object | { backTransition: true, duration: 300, timingFunction: 'ease' } | Typescript: `Transition` `interface Transition { backTransition?: boolean, duration?: number, timingFunction?: string }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N ### Upload Events diff --git a/packages/uniapp-components/upload/README.md b/packages/uniapp-components/upload/README.md index 6a4746472..e0fc44bb4 100644 --- a/packages/uniapp-components/upload/README.md +++ b/packages/uniapp-components/upload/README.md @@ -64,6 +64,7 @@ import TUpload from '@tdesign/uniapp/upload/upload.vue'; custom-style | Object | - | 自定义样式 | N add-btn | Boolean | true | 添加按钮 | N add-content | String | - | 添加按钮内容 | N +allow-upload-duplicate-file | Boolean | false | 是否允许重复上传相同文件名的文件 | N config | Object | - | 图片上传配置,视频上传配置,文件上传配置等,包含图片尺寸、图片来源、视频来源、视频拍摄最长时间等。更多细节查看小程序官网。[图片上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html)。[视频上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseVideo.html)。TS 类型:`UploadMpConfig` `type UploadMpConfig = UploadImageConfig \| UploadVideoConfig` `interface UploadImageConfig { count?: number; sizeType?: Array; sourceType?: Array }` `type SizeTypeValues = 'original' \| 'compressed'` `type SourceTypeValues = 'album' \| 'camera'` `interface UploadVideoConfig { sourceType?: Array; compressed?: boolean; maxDuration?: number; camera?: 'back' \| 'front' }`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N disabled | Boolean | undefined | 是否禁用组件 | N draggable | Boolean / Object | - | 是否支持拖拽排序。长按时是否振动,碰撞时是否振动。示例一:`true`。示例二:`{ vibrate: true, collisionVibrate: true }`。TS 类型:`boolean \| {vibrate?: boolean; collisionVibrate?: boolean}` | N @@ -73,12 +74,13 @@ grid-config | Object | - | upload组件每行上传图片列数以及图片的 gutter | Number | 16 | 预览窗格的 `gutter` 大小,单位 rpx | N image-props | Object | - | 透传 Image 组件全部属性。TS 类型:`ImageProps`,[Image API Documents](./image?tab=api)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N max | Number | 0 | 用于控制文件上传数量,值为 0 则不限制 | N -media-type | Array | ['image', 'video'] | 支持上传的文件类型,图片或视频。TS 类型:`Array` `type MediaType = 'image' \| 'video'`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N +media-type | Array | ['image', 'video'] | 支持上传的文件类型,图片或视频。TS 类型:`Array` `type MediaType = 'image' \| 'video' \| 'mix'`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N preview | Boolean | true | 是否支持图片预览,文件没有预览 | N remove-btn | Boolean | true | 移除按钮 | N request-method | Function | - | 自定义上传方法。TS 类型:`(files: UploadFile \| UploadFile[]) => Promise` `interface RequestMethodResponse { status: 'success' \| 'fail'; error?: string; response: { url?: string; files?: UploadFile[]; [key: string]: any } }`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N size-limit | Number / Object | - | 图片文件大小限制,默认单位 KB。可选单位有:`'B' \| 'KB' \| 'MB' \| 'GB'`。示例一:`1000`。示例二:`{ size: 2, unit: 'MB', message: '图片大小不超过 {sizeLimit} MB' }`。TS 类型:`number \| SizeLimitObj` `interface SizeLimitObj { size: number; unit: SizeUnit ; message?: string }` `type SizeUnitArray = ['B', 'KB', 'MB', 'GB']` `type SizeUnit = SizeUnitArray[number]`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N source | String | media | 来源。可选项:media/messageFile | N +theme | String | grid | 组件风格。提供宫格和列表两种布局风格。可选项:grid/list | N transition | Object | { backTransition: true, duration: 300, timingFunction: 'ease' } | 拖拽位置移动时的过渡参数,`duration`单位为ms。TS 类型:`Transition` `interface Transition { backTransition?: boolean, duration?: number, timingFunction?: string }`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/upload/type.ts) | N ### Upload Events diff --git a/packages/uniapp-components/upload/props.ts b/packages/uniapp-components/upload/props.ts index 5b18b57c7..79890b14a 100644 --- a/packages/uniapp-components/upload/props.ts +++ b/packages/uniapp-components/upload/props.ts @@ -15,6 +15,8 @@ export default { addContent: { type: String, }, + /** 是否允许重复上传相同文件名的文件 */ + allowUploadDuplicateFile: Boolean, /** 图片上传配置,视频上传配置,文件上传配置等,包含图片尺寸、图片来源、视频来源、视频拍摄最长时间等。更多细节查看小程序官网。[图片上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html)。[视频上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseVideo.html) */ config: { type: Object, @@ -86,6 +88,15 @@ export default { return ['media', 'messageFile'].includes(val); }, }, + /** 组件风格。提供宫格和列表两种布局风格 */ + theme: { + type: String, + default: 'grid' as TdUploadProps['theme'], + validator(val: TdUploadProps['theme']): boolean { + if (!val) return true; + return ['grid', 'list'].includes(val); + }, + }, /** 拖拽位置移动时的过渡参数,`duration`单位为ms */ transition: { type: Object, diff --git a/packages/uniapp-components/upload/type.ts b/packages/uniapp-components/upload/type.ts index 56f9b02cb..e6b2b8f5d 100644 --- a/packages/uniapp-components/upload/type.ts +++ b/packages/uniapp-components/upload/type.ts @@ -16,6 +16,11 @@ export interface TdUploadProps { * 添加按钮内容 */ addContent?: string; + /** + * 是否允许重复上传相同文件名的文件 + * @default false + */ + allowUploadDuplicateFile?: boolean; /** * 图片上传配置,视频上传配置,文件上传配置等,包含图片尺寸、图片来源、视频来源、视频拍摄最长时间等。更多细节查看小程序官网。[图片上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html)。[视频上传](https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseVideo.html) */ @@ -82,6 +87,11 @@ export interface TdUploadProps { * @default media */ source?: 'media' | 'messageFile'; + /** + * 组件风格。提供宫格和列表两种布局风格 + * @default grid + */ + theme?: 'grid' | 'list'; /** * 拖拽位置移动时的过渡参数,`duration`单位为ms * @default { backTransition: true, duration: 300, timingFunction: 'ease' } @@ -149,7 +159,7 @@ export interface UploadFile { status: 'loading' | 'reload' | 'failed' | 'done'; } -export type MediaType = 'image' | 'video'; +export type MediaType = 'image' | 'video' | 'mix'; export interface RequestMethodResponse { status: 'success' | 'fail'; diff --git a/packages/uniapp-components/upload/upload.computed.js b/packages/uniapp-components/upload/upload.computed.js index e510763e4..6eafbeafa 100644 --- a/packages/uniapp-components/upload/upload.computed.js +++ b/packages/uniapp-components/upload/upload.computed.js @@ -11,3 +11,78 @@ export function getWrapperAriaLabel(file) { } return file.type === 'video' ? '视频' : '图像'; } + +export function isImageType(file) { + if (file.type === 'image') return true; + if (file.url) { + const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'tiff']; + const url = String(file.url).toLowerCase(); + for (let i = 0; i < imageExts.length; i++) { + if (url.indexOf(`.${imageExts[i]}`) !== -1) return true; + } + } + return false; +} + +function getFileExt(file) { + const name = file.name || ''; + const url = file.url || ''; + let ext = ''; + const dotIndex = name.lastIndexOf('.'); + if (dotIndex !== -1) { + ext = name.substring(dotIndex).toLowerCase(); + } + if (ext === '' && url) { + const urlDotIndex = url.lastIndexOf('.'); + if (urlDotIndex !== -1) { + const qIndex = url.indexOf('?', urlDotIndex); + if (qIndex !== -1) { + ext = url.substring(urlDotIndex, qIndex).toLowerCase(); + } else { + ext = url.substring(urlDotIndex).toLowerCase(); + } + } + } + return ext; +} + +function getFileCategory(ext) { + if (ext === '.pdf') return 'pdf'; + if (['.xlsx', '.xls', '.csv', '.xlc', '.xlm', '.xlt', '.xlw'].includes(ext)) return 'excel'; + if (['.pptx', '.ppt', '.key'].includes(ext)) return 'ppt'; + if (['.docx', '.doc', '.document', '.wps', '.wdb', '.msword'].includes(ext)) return 'word'; + if (['.avi', '.mp4', '.wmv', '.mpg', '.mpeg', '.mov', '.rm', '.ram', '.swf', '.flv', '.rmvb', '.3gp', '.mp2', '.mp3', '.ogg', '.3gpp', '.ac3', '.au'].includes(ext)) return 'media'; + if (['.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz'].includes(ext)) return 'zip'; + return 'other'; +} + +const FILE_CATEGORY_ICON_MAP = { + pdf: 'file-pdf-filled', + excel: 'file-excel-filled', + ppt: 'file-powerpoint-filled', + word: 'file-word-filled', + media: 'video-filled', + zip: 'file-zip-filled', + other: 'file-1', +}; + +export function getFileTypeIcon(file) { + const ext = getFileExt(file); + const category = getFileCategory(ext); + return FILE_CATEGORY_ICON_MAP[category]; +} + +export function getFileTypeIconColorClass(file, classPrefix) { + const ext = getFileExt(file); + const category = getFileCategory(ext); + return `${classPrefix}__file-type--${category}`; +} + +export function formatSize(size) { + if (size == null || size === undefined) return ''; + const num = +size; + if (num < 1024) return `${num}B`; + if (num < 1024 * 1024) return `${(num / 1024).toFixed(1)}KB`; + if (num < 1024 * 1024 * 1024) return `${(num / (1024 * 1024)).toFixed(1)}MB`; + return `${(num / (1024 * 1024 * 1024)).toFixed(1)}GB`; +} diff --git a/packages/uniapp-components/upload/upload.less b/packages/uniapp-components/upload/upload.less index c112e7cf9..3acfc3704 100644 --- a/packages/uniapp-components/upload/upload.less +++ b/packages/uniapp-components/upload/upload.less @@ -6,7 +6,8 @@ @upload-radius: var(--td-upload-radius, @radius-default); @upload-add-icon-size: var(--td-upload-add-icon-size, 56rpx); @upload-add-icon-disabled-color: var(--td-upload-add-icon-disabled-color, @text-color-disabled); -@upload-disabled-mask: var(--td-upload-disabled-mask, rgba(0, 0, 0, 0.6)); +@upload-disabled-mask: var(--td-upload-disabled-mask, @mask-disabled); +@upload-background: var(--td-upload-background, @upload-add-bg-color); @upload-drag-z-index: var(--td-upload-drag-z-index, 999); .@{prefix}-upload { @@ -54,6 +55,10 @@ border-radius: @upload-radius; overflow: hidden; + &--file { + background-color: @upload-background; + } + &--disabled::before { content: ''; position: absolute; @@ -66,6 +71,61 @@ } } + &__file-content { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 16rpx 8rpx; + box-sizing: border-box; + } + + &__file-icon { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 8rpx; + } + + &__file-name { + width: 100%; + font: @font-body-small; + color: @text-color-secondary; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; + padding: 0 4rpx; + box-sizing: border-box; + } + + &__file-type { + font-size: 48rpx; + + &--pdf, + &--media { + color: @error-color; + } + + &--excel { + color: @success-color; + } + + &--word { + color: @brand-color; + } + + &--ppt { + color: @warning-color; + } + + &--other { + color: @text-color-primary; + } + } + &__close-btn { position: absolute; top: 0; @@ -96,6 +156,10 @@ color: @text-color-anti; padding: 32rpx 0; box-sizing: border-box; + + &--file { + background-color: @font-gray-2; + } } &-text { @@ -108,6 +172,10 @@ } } + &__list-item-loading { + animation: spin infinite linear 0.6s; + } + &__drag { position: relative; width: 100%; @@ -133,6 +201,184 @@ z-index: @upload-drag-z-index; } } + + // ========== list 布局 ========== + &--list { + display: flex; + flex-direction: column; + row-gap: 24rpx; + } + + &__list { + display: flex; + flex-direction: column; + row-gap: 24rpx; + } + + &__list-drag { + position: relative; + width: 100%; + } + + &__list-drag-item { + position: absolute; + z-index: 1; + top: 0; + left: 0; + width: 100%; + padding-bottom: 24rpx; + box-sizing: border-box; + + .@{prefix}-upload__list-item { + margin: 0; + } + } + + &__list-item { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + column-gap: 24rpx; + padding: 16rpx 24rpx; + background: @upload-background; + border-radius: @upload-radius; + box-sizing: border-box; + + &-loading { + flex-shrink: 0; + font-size: 48rpx; + color: @brand-color; + } + + &-error-icon { + flex-shrink: 0; + font-size: 48rpx; + color: @error-color; + } + + &-icon { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + &-thumbnail { + flex-shrink: 0; + width: 48rpx; + height: 48rpx; + border-radius: @radius-small; + overflow: hidden; + } + + &-content { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + justify-content: center; + } + + &-name { + font: @font-body-medium; + color: @text-color-primary; + } + + &-size { + font: @font-body-small; + color: @text-color-placeholder; + } + + &-name, + &-size { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &-action { + display: flex; + align-items: center; + flex-shrink: 0; + column-gap: 8rpx; + } + + &-delete { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 36rpx; + color: @text-color-placeholder; + } + + &--progress &-name, + &--progress &-size { + color: @text-color-placeholder; + } + + &--fail &-name { + color: @error-color; + } + } + + // grid 布局:无 progress-mask 的图片加 disabled-mask 遮罩 + // list 布局:缩略图加 disabled-mask 遮罩 + &__disabled-mask { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: @upload-disabled-mask; + } + + &--disabled { + pointer-events: none; + + .@{prefix}-upload__add-icon, + .@{prefix}-upload__file-name, + .@{prefix}-upload__list-item-name, + .@{prefix}-upload__list-item-size { + color: @text-color-disabled; + } + + .@{prefix}-upload__file-type { + &--pdf, + &--media { + color: @error-color-disabled; + } + + &--excel { + color: @success-color-disabled; + } + + &--word { + color: @brand-color-disabled; + } + + &--ppt { + color: @warning-color-disabled; + } + + &--other { + color: @text-color-disabled; + } + } + + .@{prefix}-upload__close-btn, + .@{prefix}-upload__list-item-action { + display: none; + } + + .@{prefix}-upload__list-item-loading { + color: @brand-color-disabled; + } + + .@{prefix}-upload__list-item-error-icon { + color: @error-color-disabled; + } + } } @keyframes spin { diff --git a/packages/uniapp-components/upload/upload.vue b/packages/uniapp-components/upload/upload.vue index 3865f397b..4fbdb4481 100644 --- a/packages/uniapp-components/upload/upload.vue +++ b/packages/uniapp-components/upload/upload.vue @@ -1,9 +1,118 @@