@atooyu/uxto-fronted 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/example/index.html +12 -0
  4. package/example/package-lock.json +11120 -0
  5. package/example/package.json +37 -0
  6. package/example/patches/@dcloudio+vite-plugin-uni+3.0.0-4060620250520001.patch +13 -0
  7. package/example/src/App.vue +25 -0
  8. package/example/src/assets/styles/index.scss +130 -0
  9. package/example/src/env.d.ts +10 -0
  10. package/example/src/main.ts +10 -0
  11. package/example/src/manifest.json +40 -0
  12. package/example/src/pages/home/index.vue +74 -0
  13. package/example/src/pages/mine/index.vue +339 -0
  14. package/example/src/pages/uxto/index.vue +109 -0
  15. package/example/src/pages.json +28 -0
  16. package/example/src/stores/index.ts +1 -0
  17. package/example/src/stores/theme.ts +95 -0
  18. package/example/tsconfig.json +20 -0
  19. package/example/vite.config.js +30 -0
  20. package/package.json +46 -0
  21. package/template/index.html +12 -0
  22. package/template/package.json +37 -0
  23. package/template/src/App.vue +22 -0
  24. package/template/src/assets/styles/index.scss +213 -0
  25. package/template/src/env.d.ts +20 -0
  26. package/template/src/main.ts +12 -0
  27. package/template/src/manifest.json +69 -0
  28. package/template/src/pages/api/index.vue +43 -0
  29. package/template/src/pages/components/index.vue +43 -0
  30. package/template/src/pages/index/index.vue +51 -0
  31. package/template/src/pages/store/index.vue +43 -0
  32. package/template/src/pages/tabbar/index.vue +111 -0
  33. package/template/src/pages/utils/index.vue +43 -0
  34. package/template/src/pages.json +53 -0
  35. package/template/src/static/tabbar/README.md +30 -0
  36. package/template/src/stores/cart.ts +50 -0
  37. package/template/src/stores/counter.ts +28 -0
  38. package/template/src/stores/index.ts +4 -0
  39. package/template/src/stores/theme.ts +100 -0
  40. package/template/src/stores/user.ts +48 -0
  41. package/template/src/utils/common.ts +106 -0
  42. package/template/src/utils/http.ts +46 -0
  43. package/template/src/utils/index.ts +3 -0
  44. package/template/src/utils/storage.ts +26 -0
  45. package/template/tsconfig.json +30 -0
  46. package/template/vite.config.js +27 -0
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <view class="page-container">
3
+ <!-- 底部导航 -->
4
+ <u-tabbar
5
+ v-model="activeTab"
6
+ center-brand="U"
7
+ center-label="UXTO"
8
+ :left-tab="{ label: '首页', icon: '⌂', value: 'home' }"
9
+ :center-tab="{ label: 'UXTO', icon: 'U', value: 'uxto' }"
10
+ :right-tab="{ label: '我的', icon: '◉', value: 'mine' }"
11
+ @tab-change="onTabChange"
12
+ />
13
+ </view>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { ref } from 'vue'
18
+
19
+ const activeTab = ref('uxto')
20
+
21
+ const onTabChange = (tab: string) => {
22
+ if (tab === 'home') {
23
+ uni.redirectTo({ url: '/pages/home/index' })
24
+ } else if (tab === 'mine') {
25
+ uni.redirectTo({ url: '/pages/mine/index' })
26
+ }
27
+ }
28
+ </script>
29
+
30
+ <style>
31
+ .page-container {
32
+ min-height: 100vh;
33
+ background: #f7f8fa;
34
+ padding-bottom: 120rpx;
35
+ }
36
+
37
+ .header {
38
+ padding: 80rpx 40rpx 60rpx;
39
+ text-align: center;
40
+ background: linear-gradient(135deg, #12b6af 0%, #9fe4dd 100%);
41
+ }
42
+
43
+ .title {
44
+ display: block;
45
+ font-size: 64rpx;
46
+ font-weight: bold;
47
+ color: #fff;
48
+ }
49
+
50
+ .subtitle {
51
+ display: block;
52
+ font-size: 28rpx;
53
+ color: rgba(255, 255, 255, 0.9);
54
+ margin-top: 16rpx;
55
+ }
56
+
57
+ .demo-section {
58
+ margin: 24rpx;
59
+ border-radius: 16rpx;
60
+ overflow: hidden;
61
+ }
62
+
63
+ .section-title {
64
+ display: block;
65
+ font-size: 32rpx;
66
+ font-weight: bold;
67
+ color: #333;
68
+ padding: 24rpx;
69
+ background: #fff;
70
+ }
71
+
72
+ .content-card {
73
+ background: #fff;
74
+ padding: 24rpx;
75
+ }
76
+
77
+ .desc {
78
+ font-size: 28rpx;
79
+ color: #666;
80
+ line-height: 1.6;
81
+ }
82
+
83
+ .feature-list {
84
+ background: #fff;
85
+ padding: 24rpx;
86
+ display: flex;
87
+ flex-wrap: wrap;
88
+ gap: 20rpx;
89
+ }
90
+
91
+ .feature-item {
92
+ width: calc(50% - 10rpx);
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 12rpx;
96
+ padding: 20rpx;
97
+ background: #f7f8fa;
98
+ border-radius: 12rpx;
99
+ }
100
+
101
+ .feature-icon {
102
+ font-size: 36rpx;
103
+ }
104
+
105
+ .feature-text {
106
+ font-size: 28rpx;
107
+ color: #333;
108
+ }
109
+ </style>
@@ -0,0 +1,28 @@
1
+ {
2
+ "pages": [
3
+ {
4
+ "path": "pages/home/index",
5
+ "style": { "navigationBarTitleText": "首页" }
6
+ },
7
+ {
8
+ "path": "pages/uxto/index",
9
+ "style": { "navigationBarTitleText": "UXTO" }
10
+ },
11
+ {
12
+ "path": "pages/mine/index",
13
+ "style": { "navigationBarTitleText": "我的" }
14
+ }
15
+ ],
16
+ "globalStyle": {
17
+ "navigationBarTextStyle": "black",
18
+ "navigationBarTitleText": "UXTO Example",
19
+ "navigationBarBackgroundColor": "#ffffff",
20
+ "backgroundColor": "#f7f8fa"
21
+ },
22
+ "easycom": {
23
+ "autoscan": true,
24
+ "custom": {
25
+ "^u-(.*)": "uxto-ui/u-$1/u-$1.vue"
26
+ }
27
+ }
28
+ }
@@ -0,0 +1 @@
1
+ export { useThemeStore } from './theme'
@@ -0,0 +1,95 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
+
4
+ export const useThemeStore = defineStore('theme', () => {
5
+ // 暗黑模式 - 深邃墨蓝,沉浸式夜间体验
6
+ const darkMode = ref(false)
7
+
8
+ // 灰色模式 - 温柔灰调,护眼阅读体验
9
+ const grayMode = ref(false)
10
+
11
+ // 初始化时从本地存储加载
12
+ const loadFromStorage = () => {
13
+ const savedDarkMode = uni.getStorageSync('darkMode')
14
+ const savedGrayMode = uni.getStorageSync('grayMode')
15
+
16
+ if (savedDarkMode !== '') {
17
+ darkMode.value = savedDarkMode === true || savedDarkMode === 'true'
18
+ }
19
+ if (savedGrayMode !== '') {
20
+ grayMode.value = savedGrayMode === true || savedGrayMode === 'true'
21
+ }
22
+
23
+ applyTheme()
24
+ }
25
+
26
+ // 应用主题到页面根元素
27
+ const applyTheme = () => {
28
+ // #ifdef H5
29
+ const root = document.documentElement
30
+ root.classList.remove('dark-mode', 'gray-mode')
31
+
32
+ if (darkMode.value) {
33
+ root.classList.add('dark-mode')
34
+ } else if (grayMode.value) {
35
+ root.classList.add('gray-mode')
36
+ }
37
+ // #endif
38
+
39
+ uni.setStorageSync('currentThemeMode', {
40
+ dark: darkMode.value,
41
+ gray: grayMode.value
42
+ })
43
+ }
44
+
45
+ // 切换暗黑模式
46
+ const toggleDarkMode = () => {
47
+ darkMode.value = !darkMode.value
48
+ if (darkMode.value && grayMode.value) {
49
+ grayMode.value = false
50
+ }
51
+ uni.setStorageSync('darkMode', darkMode.value)
52
+ applyTheme()
53
+ }
54
+
55
+ // 切换灰色模式
56
+ const toggleGrayMode = () => {
57
+ grayMode.value = !grayMode.value
58
+ if (grayMode.value && darkMode.value) {
59
+ darkMode.value = false
60
+ }
61
+ uni.setStorageSync('grayMode', grayMode.value)
62
+ applyTheme()
63
+ }
64
+
65
+ // 设置暗黑模式
66
+ const setDarkMode = (value: boolean) => {
67
+ darkMode.value = value
68
+ if (value && grayMode.value) {
69
+ grayMode.value = false
70
+ }
71
+ uni.setStorageSync('darkMode', value)
72
+ applyTheme()
73
+ }
74
+
75
+ // 设置灰色模式
76
+ const setGrayMode = (value: boolean) => {
77
+ grayMode.value = value
78
+ if (value && darkMode.value) {
79
+ darkMode.value = false
80
+ }
81
+ uni.setStorageSync('grayMode', value)
82
+ applyTheme()
83
+ }
84
+
85
+ return {
86
+ darkMode,
87
+ grayMode,
88
+ loadFromStorage,
89
+ toggleDarkMode,
90
+ toggleGrayMode,
91
+ setDarkMode,
92
+ setGrayMode,
93
+ applyTheme
94
+ }
95
+ })
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "jsx": "preserve",
9
+ "resolveJsonModule": true,
10
+ "isolatedModules": true,
11
+ "esModuleInterop": true,
12
+ "lib": ["ESNext", "DOM"],
13
+ "skipLibCheck": true,
14
+ "noEmit": true,
15
+ "paths": { "@/*": ["./src/*"] },
16
+ "types": ["@dcloudio/types", "@types/node"]
17
+ },
18
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }
@@ -0,0 +1,30 @@
1
+ const { defineConfig } = require('vite')
2
+ const uni = require('@dcloudio/vite-plugin-uni').default
3
+ const path = require('path')
4
+
5
+ const uxtoUiComponentsPath = path.resolve(__dirname, '../../uxto-ui/src/components').replace(/\\/g, '/')
6
+ const variablesPath = path.resolve(__dirname, '../../uxto-ui/src/styles/variables.scss').replace(/\\/g, '/')
7
+
8
+ module.exports = defineConfig({
9
+ plugins: [uni()],
10
+ server: {
11
+ host: '0.0.0.0',
12
+ port: 5173
13
+ },
14
+ resolve: {
15
+ alias: {
16
+ '@': path.resolve(__dirname, 'src').replace(/\\/g, '/'),
17
+ 'uxto-ui': uxtoUiComponentsPath
18
+ },
19
+ extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
20
+ },
21
+ css: {
22
+ preprocessorOptions: {
23
+ scss: {
24
+ api: 'modern-compiler',
25
+ additionalData: `@import "${variablesPath}";`,
26
+ silenceDeprecations: ['import', 'legacy-js-api']
27
+ }
28
+ }
29
+ }
30
+ })
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@atooyu/uxto-fronted",
3
+ "version": "1.0.0",
4
+ "description": "UXTO UniApp 前端脚手架模板 - 支持 iOS、Android、鸿蒙",
5
+ "keywords": [
6
+ "uxto",
7
+ "uniapp",
8
+ "scaffold",
9
+ "template",
10
+ "vue3",
11
+ "typescript",
12
+ "mobile",
13
+ "ios",
14
+ "android",
15
+ "harmony",
16
+ "cross-platform"
17
+ ],
18
+ "author": "atooyu <chujingu@163.com>",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/atooyu/uxto-fronted.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/atooyu/uxto-fronted/issues"
26
+ },
27
+ "homepage": "https://github.com/atooyu/uxto-fronted#readme",
28
+ "files": [
29
+ "template",
30
+ "example",
31
+ "README.md"
32
+ ],
33
+ "scripts": {
34
+ "test": "echo \"Run tests in template or example directory\""
35
+ },
36
+ "publishConfig": {
37
+ "access": "public",
38
+ "registry": "https://registry.npmjs.org/"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
43
+ "peerDependencies": {
44
+ "@atooyu/uxto-cli": "^1.0.0"
45
+ }
46
+ }
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
6
+ <title>UXTO</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.ts"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev:h5": "uni",
8
+ "dev:app": "uni -p app",
9
+ "dev:mp-weixin": "uni -p mp-weixin",
10
+ "dev:harmony": "uni -p app-harmony",
11
+ "build:h5": "uni build",
12
+ "build:app": "uni build -p app",
13
+ "build:mp-weixin": "uni build -p mp-weixin",
14
+ "build:harmony": "uni build -p app-harmony"
15
+ },
16
+ "dependencies": {
17
+ "@atooyu/uxto-ui": "^1.0.0",
18
+ "@dcloudio/uni-app": "3.0.0-4060620250520001",
19
+ "@dcloudio/uni-app-harmony": "3.0.0-4060620250520001",
20
+ "@dcloudio/uni-components": "3.0.0-4060620250520001",
21
+ "@dcloudio/uni-h5": "3.0.0-4060620250520001",
22
+ "vue": "^3.5.13",
23
+ "pinia": "^2.1.7"
24
+ },
25
+ "devDependencies": {
26
+ "@dcloudio/types": "^3.4.14",
27
+ "@dcloudio/uni-automator": "3.0.0-4060620250520001",
28
+ "@dcloudio/uni-cli-shared": "3.0.0-4060620250520001",
29
+ "@dcloudio/uni-stacktracey": "3.0.0-4060620250520001",
30
+ "@dcloudio/vite-plugin-uni": "3.0.0-4060620250520001",
31
+ "@types/node": "^22.13.10",
32
+ "sass": "^1.85.1",
33
+ "typescript": "^5.8.2",
34
+ "vite": "^5.2.8"
35
+ },
36
+ "author": "{{author}}"
37
+ }
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import { useThemeStore } from '@/stores/theme'
3
+
4
+ export default {
5
+ onLaunch: function() {
6
+ console.log('UXTO Frontend Launch')
7
+ // 加载主题配置
8
+ const themeStore = useThemeStore()
9
+ themeStore.loadFromStorage()
10
+ },
11
+ onShow: function() {
12
+ console.log('UXTO Frontend Show')
13
+ },
14
+ onHide: function() {
15
+ console.log('UXTO Frontend Hide')
16
+ }
17
+ }
18
+ </script>
19
+
20
+ <style lang="scss">
21
+ @import "@/assets/styles/index.scss";
22
+ </style>
@@ -0,0 +1,213 @@
1
+ /* UXTO Frontend 全局样式 */
2
+
3
+ /* ============================================
4
+ 默认模式 - 明亮清新
5
+ ============================================ */
6
+ :root {
7
+ --color-primary: #1989fa;
8
+ --color-success: #07c160;
9
+ --color-warning: #ff976a;
10
+ --color-danger: #ee0a24;
11
+ --color-info: #969799;
12
+
13
+ --text-color: #323233;
14
+ --text-color-2: #646566;
15
+ --text-color-3: #969799;
16
+
17
+ --bg-color: #f7f8fa;
18
+ --bg-color-2: #ffffff;
19
+ --bg-color-3: #f5f5f5;
20
+
21
+ --border-color: #ebedf0;
22
+ --shadow-color: rgba(0, 0, 0, 0.08);
23
+
24
+ --card-bg: #ffffff;
25
+ --header-bg: linear-gradient(135deg, #1989fa 0%, #07c160 100%);
26
+ --input-bg: #ffffff;
27
+ --switch-bg: #e5e5e5;
28
+ }
29
+
30
+ /* ============================================
31
+ 暗黑模式 - 深邃墨蓝,沉浸式夜间体验
32
+ 带有微妙光晕效果,营造高级感
33
+ ============================================ */
34
+ .dark-mode,
35
+ [data-theme="dark"] {
36
+ --color-primary: #58a6ff;
37
+ --color-success: #3fb950;
38
+ --color-warning: #f0883e;
39
+ --color-danger: #f85149;
40
+ --color-info: #8b949e;
41
+
42
+ --text-color: #c9d1d9;
43
+ --text-color-2: #8b949e;
44
+ --text-color-3: #6e7681;
45
+
46
+ --bg-color: #0d1117;
47
+ --bg-color-2: #161b22;
48
+ --bg-color-3: #21262d;
49
+
50
+ --border-color: #30363d;
51
+ --shadow-color: rgba(0, 0, 0, 0.4);
52
+
53
+ --card-bg: #161b22;
54
+ --header-bg: linear-gradient(135deg, #1f3a5f 0%, #0d2137 100%);
55
+ --input-bg: #21262d;
56
+ --switch-bg: #21262d;
57
+ }
58
+
59
+ /* 暗黑模式特殊样式 */
60
+ .dark-mode page,
61
+ [data-theme="dark"] page {
62
+ background-color: var(--bg-color);
63
+ }
64
+
65
+ .dark-mode .page-container,
66
+ [data-theme="dark"] .page-container {
67
+ background: var(--bg-color);
68
+ }
69
+
70
+ .dark-mode .card,
71
+ .dark-mode .section,
72
+ .dark-mode .menu-section,
73
+ [data-theme="dark"] .card,
74
+ [data-theme="dark"] .section,
75
+ [data-theme="dark"] .menu-section {
76
+ background: var(--card-bg);
77
+ box-shadow: 0 2rpx 16rpx var(--shadow-color);
78
+ }
79
+
80
+ /* ============================================
81
+ 灰色模式 - 温柔灰调,护眼阅读体验
82
+ 降低对比度,营造书卷气息
83
+ ============================================ */
84
+ .gray-mode,
85
+ [data-theme="gray"] {
86
+ --color-primary: #737373;
87
+ --color-success: #525252;
88
+ --color-warning: #737373;
89
+ --color-danger: #737373;
90
+ --color-info: #a3a3a3;
91
+
92
+ --text-color: #525252;
93
+ --text-color-2: #737373;
94
+ --text-color-3: #a3a3a3;
95
+
96
+ --bg-color: #e5e5e5;
97
+ --bg-color-2: #f5f5f5;
98
+ --bg-color-3: #d4d4d4;
99
+
100
+ --border-color: #d4d4d4;
101
+ --shadow-color: rgba(0, 0, 0, 0.04);
102
+
103
+ --card-bg: #f5f5f5;
104
+ --header-bg: linear-gradient(135deg, #a3a3a3 0%, #d4d4d4 100%);
105
+ --input-bg: #f5f5f5;
106
+ --switch-bg: #d4d4d4;
107
+
108
+ /* 灰色模式全局滤镜 */
109
+ filter: grayscale(85%);
110
+ }
111
+
112
+ .gray-mode page,
113
+ [data-theme="gray"] page {
114
+ background-color: var(--bg-color);
115
+ }
116
+
117
+ .gray-mode .page-container,
118
+ [data-theme="gray"] .page-container {
119
+ background: var(--bg-color);
120
+ }
121
+
122
+ /* ============================================
123
+ 重置样式
124
+ ============================================ */
125
+ page {
126
+ background-color: var(--bg-color);
127
+ font-size: 28rpx;
128
+ color: var(--text-color);
129
+ line-height: 1.5;
130
+ transition: background-color 0.3s ease, color 0.3s ease;
131
+ }
132
+
133
+ /* ============================================
134
+ 通用类
135
+ ============================================ */
136
+ .flex {
137
+ display: flex;
138
+ }
139
+
140
+ .flex-center {
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ }
145
+
146
+ .flex-between {
147
+ display: flex;
148
+ align-items: center;
149
+ justify-content: space-between;
150
+ }
151
+
152
+ .flex-column {
153
+ display: flex;
154
+ flex-direction: column;
155
+ }
156
+
157
+ .text-center {
158
+ text-align: center;
159
+ }
160
+
161
+ .text-primary {
162
+ color: var(--color-primary);
163
+ }
164
+
165
+ .text-success {
166
+ color: var(--color-success);
167
+ }
168
+
169
+ .text-warning {
170
+ color: var(--color-warning);
171
+ }
172
+
173
+ .text-danger {
174
+ color: var(--color-danger);
175
+ }
176
+
177
+ /* ============================================
178
+ 间距类
179
+ ============================================ */
180
+ .p-20 {
181
+ padding: 20rpx;
182
+ }
183
+
184
+ .p-30 {
185
+ padding: 30rpx;
186
+ }
187
+
188
+ .mt-20 {
189
+ margin-top: 20rpx;
190
+ }
191
+
192
+ .mt-30 {
193
+ margin-top: 30rpx;
194
+ }
195
+
196
+ .mb-20 {
197
+ margin-bottom: 20rpx;
198
+ }
199
+
200
+ .mb-30 {
201
+ margin-bottom: 30rpx;
202
+ }
203
+
204
+ /* ============================================
205
+ 主题切换动画
206
+ ============================================ */
207
+ .theme-transition,
208
+ .theme-transition *,
209
+ .theme-transition *::before,
210
+ .theme-transition *::after {
211
+ transition: all 0.3s ease !important;
212
+ transition-delay: 0s !important;
213
+ }
@@ -0,0 +1,20 @@
1
+ /// <reference types="@dcloudio/types" />
2
+
3
+ // 声明全局 uni 对象
4
+ declare const uni: UniNamespace.Uni
5
+ declare const getCurrentPages: () => Page.PageInstance[]
6
+
7
+ declare module '*.vue' {
8
+ import type { DefineComponent } from 'vue'
9
+ const component: DefineComponent<object, object, unknown>
10
+ export default component
11
+ }
12
+
13
+ interface ImportMetaEnv {
14
+ readonly VITE_APP_NAME: string
15
+ readonly VITE_API_BASE_URL: string
16
+ }
17
+
18
+ interface ImportMeta {
19
+ readonly env: ImportMetaEnv
20
+ }
@@ -0,0 +1,12 @@
1
+ import { createSSRApp } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import App from './App.vue'
4
+
5
+ export function createApp() {
6
+ const app = createSSRApp(App)
7
+ const pinia = createPinia()
8
+
9
+ app.use(pinia)
10
+
11
+ return { app }
12
+ }