Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ npx @create-uni/info@latest
| [skiyee-ui](https://skiyee-ui.netlify.app/) | 随心创造差异化 | skiyee |
| [uv-ui](https://www.uvui.cn/components/intro.html) | 多平台快速开发的UI框架 | uv |
| [ano-ui](https://ano-ui.netlify.app/) | 轻量级、漂亮、快速的 UnoCSS 组件库 | ano |
| [tmui](https://tmui.design/) | 优质Vue3 TS Pinia Vite跨端组件库 | tmui |

## 🤝 参与贡献

Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/question/ui/ui.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,12 @@ export const UIList = [
github: 'https://github.com/ano-ui/ano-ui',
website: 'https://ano-ui.netlify.app/',
},
{
label: rgb(255, 127, 0)('tmui'),
hint: '优质Vue3 TS Pinia Vite跨端组件库',
name: 'tmui',
value: 'tmui',
github: 'https://gitee.com/LYTB/tmui-design',
website: 'https://tmui.design/',
},
] as Options[]
18 changes: 18 additions & 0 deletions packages/core/template/UI/tmui/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<title></title>
<!--preload-links-->
<!--app-context-->
</head>

<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>

</html>
12 changes: 12 additions & 0 deletions packages/core/template/UI/tmui/jsconfig.json.data.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function getData({ oldData }) {
const tmuiConfig = {
id: 'tmuiConfig',
types: ['tmui-uni/global.d.ts'],
}
return {
...oldData,
config: oldData.config.flatMap(config =>
config.id === 'baseConfig' ? [tmuiConfig, config] : config,
),
}
}
12 changes: 12 additions & 0 deletions packages/core/template/UI/tmui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"dependencies": {
"@vue/compiler-core": "^3.5.11",
"echarts": "5.4.2",
"pinia": "^2.0.33",
"sass": "^1.77.5",
"tmui-uni": "^3.2.7",
"vue": "^3.5.16",
"vue-docgen-api": "^4.79.2",
"vue-i18n": "^11.1.5"
}
Comment on lines +2 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Several runtime-only deps look like build-time/dev deps
@vue/compiler-core, sass and vue-docgen-api inflate the production bundle when declared under dependencies. Move them to devDependencies unless they are required at runtime.

 {
   "dependencies": {
-    "@vue/compiler-core": "^3.5.11",
-    "sass": "^1.77.5",
-    "vue-docgen-api": "^4.79.2",
+  },
+  "devDependencies": {
+    "@vue/compiler-core": "^3.5.11",
+    "sass": "^1.77.5",
+    "vue-docgen-api": "^4.79.2"
   ...
 }

This keeps end-user installs leaner.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"dependencies": {
"@vue/compiler-core": "^3.5.11",
"echarts": "5.4.2",
"pinia": "^2.0.33",
"sass": "^1.77.5",
"tmui-uni": "^3.2.7",
"vue": "^3.5.16",
"vue-docgen-api": "^4.79.2",
"vue-i18n": "^11.1.5"
}
"dependencies": {
"echarts": "5.4.2",
"pinia": "^2.0.33",
"tmui-uni": "^3.2.7",
"vue": "^3.5.16",
"vue-i18n": "^11.1.5"
},
"devDependencies": {
"@vue/compiler-core": "^3.5.11",
"sass": "^1.77.5",
"vue-docgen-api": "^4.79.2"
}
🤖 Prompt for AI Agents
In packages/core/template/UI/tmui/package.json lines 2 to 11, the dependencies
@vue/compiler-core, sass, and vue-docgen-api are incorrectly listed under
"dependencies" but are only needed during build or development. Move these three
packages from "dependencies" to "devDependencies" to prevent inflating the
production bundle and keep end-user installs leaner.

}
10 changes: 10 additions & 0 deletions packages/core/template/UI/tmui/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const {
uniPostcssPlugin,
} = require('@dcloudio/uni-cli-shared')

module.exports = {
plugins: [
uniPostcssPlugin(),
require('autoprefixer')(),
],
}
15 changes: 15 additions & 0 deletions packages/core/template/UI/tmui/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script setup lang="ts">
import { onLaunch } from '@dcloudio/uni-app'

onLaunch(() => {})
</script>

<style>
/* 图标必须 */
@import url(tmui-uni/css/remixicon.min.css);
/* 自定预处理类,可选 */
@import url(tmui-uni/css/tmui.css);
page {
background: #f5f5f5;
}
</style>
3 changes: 3 additions & 0 deletions packages/core/template/UI/tmui/src/androidPrivacy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"prompt": "template"
}
29 changes: 29 additions & 0 deletions packages/core/template/UI/tmui/src/main.js.data.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default function getData({ oldData }) {
if (!oldData.entries) {
oldData.entries = []
}

const hasPiniaImport = oldData.entries.some(entry =>
entry.importer && entry.importer.includes('pinia'),
)
Comment on lines +6 to +8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Apply optional chaining to improve code safety.

The static analysis tool correctly identifies that optional chaining should be used here to prevent potential runtime errors if entry.importer is undefined.

Apply this fix:

-  const hasPiniaImport = oldData.entries.some(entry =>
-    entry.importer && entry.importer.includes('pinia'),
-  )
+  const hasPiniaImport = oldData.entries.some(entry =>
+    entry.importer?.includes('pinia'),
+  )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hasPiniaImport = oldData.entries.some(entry =>
entry.importer && entry.importer.includes('pinia'),
)
const hasPiniaImport = oldData.entries.some(entry =>
entry.importer?.includes('pinia'),
)
🧰 Tools
🪛 Biome (1.9.4)

[error] 7-7: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🤖 Prompt for AI Agents
In packages/core/template/UI/tmui/src/main.js.data.mjs around lines 6 to 8, the
code accesses entry.importer without checking if entry is defined, which can
cause runtime errors. Update the condition to use optional chaining by replacing
entry.importer with entry.importer?. This will safely handle cases where
importer might be undefined and prevent errors.


const hasTmuiImport = oldData.entries.some(entry =>
entry.importer && (entry.importer.includes('tmui') || entry.importer.includes('tm-ui')),
)
Comment on lines +10 to +12
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Apply optional chaining for consistency.

For consistency with the fix above, apply optional chaining here as well.

-  const hasTmuiImport = oldData.entries.some(entry =>
-    entry.importer && (entry.importer.includes('tmui') || entry.importer.includes('tm-ui')),
-  )
+  const hasTmuiImport = oldData.entries.some(entry =>
+    entry.importer?.includes('tmui') || entry.importer?.includes('tm-ui'),
+  )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hasTmuiImport = oldData.entries.some(entry =>
entry.importer && (entry.importer.includes('tmui') || entry.importer.includes('tm-ui')),
)
const hasTmuiImport = oldData.entries.some(entry =>
entry.importer?.includes('tmui') || entry.importer?.includes('tm-ui'),
)
🤖 Prompt for AI Agents
In packages/core/template/UI/tmui/src/main.js.data.mjs around lines 10 to 12,
the code checks entry.importer without optional chaining, which can cause errors
if importer is undefined. Update the condition to use optional chaining on
entry.importer before calling includes, ensuring consistent and safe property
access.


if (!hasPiniaImport) {
oldData.entries.push({
importer: 'import * as Pinia from "pinia"',
use: 'app.use(Pinia.createPinia())',
})
}

if (!hasTmuiImport) {
oldData.entries.push({
importer: 'import tmUi from "tmui-uni"',
use: 'app.use(tmUi)',
})
}

return oldData
}
14 changes: 14 additions & 0 deletions packages/core/template/UI/tmui/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts" setup>
</script>

<template>
<view>
<tm-button :block="true">
嗨~TMUI
</tm-button>
</view>
</template>

<style>

</style>
Empty file.
170 changes: 170 additions & 0 deletions packages/core/template/UI/tmui/vite.config.js.data.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
export default function getData({ oldData }) {
// 一次性检测所有包
const existing = new Set(
oldData.plugins
.filter(p => p.importer)
.map(p => p.importer)
.join(' ')
.match(/@[\w-]+\/[\w-]+/g) || [],
)

// 检查是否已存在 Components 插件
const hasComponentsPlugin = oldData.plugins.some(p =>
p.initializer?.includes('Components('),
)

// TMUI resolver 函数 - 优化版本
const tmuiResolver = `(name) => {
if (!name.startsWith('Tm')) return
const comp = name.slice(2).replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, 'tm-')
return { name, from: \`tmui-uni/components/\${comp}/\${comp}.vue\` }
}`

// 基础配置优化
const baseConfig = {
...oldData,
define: {
__VUE_I18N_FULL_INSTALL__: true,
__VUE_I18N_LEGACY_API__: true,
__VUE_I18N_PROD_DEVTOOLS__: false,
...oldData.define,
},
build: {
target: 'es6',
cssCodeSplit: true,
...oldData.build,
},
css: {
preprocessorOptions: {
scss: {
api: 'modern-compiler',
silenceDeprecations: ['legacy-js-api'],
},
},
...oldData.css,
},
server: {
port: 1314,
proxy: {
'/pag': {
target: 'https://cdn.tmui.design',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '/api'),
},
},
Comment on lines +48 to +54
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Review the proxy configuration for security.

The proxy configuration redirects /pag to https://cdn.tmui.design. However, there's a potential issue with the rewrite rule.

The rewrite rule on line 52 replaces /api with /api, which is redundant. If the intent is to proxy /pag requests, the rewrite should be:

-        rewrite: path => path.replace(/^\/api/, '/api'),
+        rewrite: path => path.replace(/^\/pag/, ''),

Or if no rewrite is needed:

-        rewrite: path => path.replace(/^\/api/, '/api'),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
proxy: {
'/pag': {
target: 'https://cdn.tmui.design',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '/api'),
},
},
proxy: {
'/pag': {
target: 'https://cdn.tmui.design',
changeOrigin: true,
rewrite: path => path.replace(/^\/pag/, ''),
},
},
🤖 Prompt for AI Agents
In packages/core/template/UI/tmui/vite.config.js.data.mjs around lines 48 to 54,
the proxy rewrite rule for '/pag' is redundant as it replaces '/api' with
'/api'. To fix this, either update the rewrite function to correctly transform
the '/pag' path as intended or remove the rewrite rule entirely if no path
modification is needed for the proxy target.

...oldData.server,
},
}

// 创建插件工厂函数
const createPlugins = () => {
const plugins = []

// Components 插件
if (!hasComponentsPlugin) {
plugins.push({
id: 'tmuiComponents',
...(!existing.has('@uni-helper/vite-plugin-uni-components') && {
importer: `import Components from '@uni-helper/vite-plugin-uni-components'`,
}),
initializer: `Components({
dts: true,
resolvers: [${tmuiResolver}],
include: [/\\.vue$/, /\\.uvue$/]
})`,
})
}

// Vue JSX 插件
plugins.push({
id: 'vueJsx',
...(!existing.has('@vitejs/plugin-vue-jsx') && {
importer: 'import vueJsx from "@vitejs/plugin-vue-jsx"',
}),
initializer: 'vueJsx()',
})

return plugins
}

// 合并现有 Components 插件配置
const mergeComponentsPlugin = (plugin) => {
const hasTmuiResolver = plugin.initializer.includes('tmui-uni/components')
if (hasTmuiResolver)
return plugin

// 解析现有配置
const configMatch = plugin.initializer.match(/Components\(\{([^}]+)\}\)/)
if (!configMatch)
return plugin

const existingConfig = configMatch[1]
const configItems = []

// 提取并规范化配置项
const extractConfig = (key, defaultValue) => {
const match = existingConfig.match(new RegExp(`${key}:\\s*([^,\\n}]+)`))
return match ? `${key}: ${match[1].trim()}` : `${key}: ${defaultValue}`
}

configItems.push(extractConfig('dts', 'true'))

// 处理 resolvers
const resolversMatch = existingConfig.match(/resolvers:\s*\[([^\]]*)\]/)
if (resolversMatch) {
const existingResolvers = resolversMatch[1].trim()
const resolversList = existingResolvers
? `${existingResolvers.split('\n').map(line => line.trim()).filter(Boolean).join(',\n ')},\n ${tmuiResolver}`
: tmuiResolver
configItems.push(`resolvers: [\n ${resolversList}\n ]`)
}
else {
configItems.push(`resolvers: [${tmuiResolver}]`)
}

// 处理 include
const includeMatch = existingConfig.match(/include:\s*\[([^\]]*)\]/)
configItems.push(includeMatch
? `include: [${includeMatch[1]}]`
: 'include: [/\\.vue$/, /\\.uvue$/]',
)

return {
...plugin,
initializer: `Components({\n ${configItems.join(',\n ')}\n })`,
}
}

// 插入插件到正确位置
const insertPlugins = (plugins, newPlugins) => {
const autoImportIndex = plugins.findIndex(p => p.id === 'autoImport')
const uniIndex = plugins.findIndex(p => p.id === 'uni')
const insertIndex = autoImportIndex !== -1 ? autoImportIndex + 1 : uniIndex

const result = [...plugins]
result.splice(insertIndex, 0, ...newPlugins)
return result
}

// 主逻辑
if (hasComponentsPlugin) {
const updatedPlugins = baseConfig.plugins.map(plugin =>
plugin.initializer?.includes('Components(')
? mergeComponentsPlugin(plugin)
: plugin,
)

// 只添加 vueJsx 插件
const vueJsxPlugin = createPlugins().find(p => p.id === 'vueJsx')
return {
...baseConfig,
plugins: vueJsxPlugin ? insertPlugins(updatedPlugins, [vueJsxPlugin]) : updatedPlugins,
}
}

// 添加所有新插件
return {
...baseConfig,
plugins: insertPlugins(baseConfig.plugins, createPlugins()),
}
}
Loading