@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.
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/example/index.html +12 -0
- package/example/package-lock.json +11120 -0
- package/example/package.json +37 -0
- package/example/patches/@dcloudio+vite-plugin-uni+3.0.0-4060620250520001.patch +13 -0
- package/example/src/App.vue +25 -0
- package/example/src/assets/styles/index.scss +130 -0
- package/example/src/env.d.ts +10 -0
- package/example/src/main.ts +10 -0
- package/example/src/manifest.json +40 -0
- package/example/src/pages/home/index.vue +74 -0
- package/example/src/pages/mine/index.vue +339 -0
- package/example/src/pages/uxto/index.vue +109 -0
- package/example/src/pages.json +28 -0
- package/example/src/stores/index.ts +1 -0
- package/example/src/stores/theme.ts +95 -0
- package/example/tsconfig.json +20 -0
- package/example/vite.config.js +30 -0
- package/package.json +46 -0
- package/template/index.html +12 -0
- package/template/package.json +37 -0
- package/template/src/App.vue +22 -0
- package/template/src/assets/styles/index.scss +213 -0
- package/template/src/env.d.ts +20 -0
- package/template/src/main.ts +12 -0
- package/template/src/manifest.json +69 -0
- package/template/src/pages/api/index.vue +43 -0
- package/template/src/pages/components/index.vue +43 -0
- package/template/src/pages/index/index.vue +51 -0
- package/template/src/pages/store/index.vue +43 -0
- package/template/src/pages/tabbar/index.vue +111 -0
- package/template/src/pages/utils/index.vue +43 -0
- package/template/src/pages.json +53 -0
- package/template/src/static/tabbar/README.md +30 -0
- package/template/src/stores/cart.ts +50 -0
- package/template/src/stores/counter.ts +28 -0
- package/template/src/stores/index.ts +4 -0
- package/template/src/stores/theme.ts +100 -0
- package/template/src/stores/user.ts +48 -0
- package/template/src/utils/common.ts +106 -0
- package/template/src/utils/http.ts +46 -0
- package/template/src/utils/index.ts +3 -0
- package/template/src/utils/storage.ts +26 -0
- package/template/tsconfig.json +30 -0
- package/template/vite.config.js +27 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "uxto-frontend",
|
|
3
|
+
"appid": "__UNI__UXTO_FRONTEND",
|
|
4
|
+
"description": "UXTO 前端应用框架 - 支持 iOS、Android、鸿蒙",
|
|
5
|
+
"versionName": "1.0.0",
|
|
6
|
+
"versionCode": "100",
|
|
7
|
+
"transformPx": false,
|
|
8
|
+
"app-plus": {
|
|
9
|
+
"usingComponents": true,
|
|
10
|
+
"nvueStyleCompiler": "uni-app",
|
|
11
|
+
"compilerVersion": 3,
|
|
12
|
+
"splashscreen": {
|
|
13
|
+
"alwaysShowBeforeRender": true,
|
|
14
|
+
"waiting": true,
|
|
15
|
+
"autoclose": true,
|
|
16
|
+
"delay": 0
|
|
17
|
+
},
|
|
18
|
+
"modules": {},
|
|
19
|
+
"distribute": {
|
|
20
|
+
"android": {
|
|
21
|
+
"permissions": [
|
|
22
|
+
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
|
|
23
|
+
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"ios": {
|
|
27
|
+
"idfa": false
|
|
28
|
+
},
|
|
29
|
+
"sdkConfigs": {}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"quickapp": {},
|
|
33
|
+
"mp-weixin": {
|
|
34
|
+
"appid": "",
|
|
35
|
+
"setting": {
|
|
36
|
+
"urlCheck": false
|
|
37
|
+
},
|
|
38
|
+
"usingComponents": true
|
|
39
|
+
},
|
|
40
|
+
"mp-alipay": {
|
|
41
|
+
"usingComponents": true
|
|
42
|
+
},
|
|
43
|
+
"mp-baidu": {
|
|
44
|
+
"usingComponents": true
|
|
45
|
+
},
|
|
46
|
+
"mp-toutiao": {
|
|
47
|
+
"usingComponents": true
|
|
48
|
+
},
|
|
49
|
+
"uniStatistics": {
|
|
50
|
+
"enable": false
|
|
51
|
+
},
|
|
52
|
+
"vueVersion": "3",
|
|
53
|
+
"app-harmony": {
|
|
54
|
+
"mode": "development",
|
|
55
|
+
"projectName": "UXTO",
|
|
56
|
+
"appSign": "",
|
|
57
|
+
"appDebug": true
|
|
58
|
+
},
|
|
59
|
+
"h5": {
|
|
60
|
+
"template": "index.html",
|
|
61
|
+
"router": {
|
|
62
|
+
"mode": "hash"
|
|
63
|
+
},
|
|
64
|
+
"optimization": {
|
|
65
|
+
"prefetch": true,
|
|
66
|
+
"preload": true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="page-container">
|
|
3
|
+
<view class="header">
|
|
4
|
+
<text class="title">API 示例</text>
|
|
5
|
+
</view>
|
|
6
|
+
|
|
7
|
+
<view class="content">
|
|
8
|
+
<text class="content-text">API 示例内容</text>
|
|
9
|
+
</view>
|
|
10
|
+
</view>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="scss">
|
|
17
|
+
.page-container {
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f7f8fa;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.header {
|
|
23
|
+
padding: 40rpx;
|
|
24
|
+
text-align: center;
|
|
25
|
+
|
|
26
|
+
.title {
|
|
27
|
+
display: block;
|
|
28
|
+
font-size: 40rpx;
|
|
29
|
+
font-weight: bold;
|
|
30
|
+
color: #333;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
padding: 40rpx;
|
|
36
|
+
text-align: center;
|
|
37
|
+
|
|
38
|
+
.content-text {
|
|
39
|
+
font-size: 28rpx;
|
|
40
|
+
color: #666;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="page-container">
|
|
3
|
+
<view class="header">
|
|
4
|
+
<text class="title">组件示例</text>
|
|
5
|
+
</view>
|
|
6
|
+
|
|
7
|
+
<view class="content">
|
|
8
|
+
<text class="content-text">组件示例内容</text>
|
|
9
|
+
</view>
|
|
10
|
+
</view>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="scss">
|
|
17
|
+
.page-container {
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f7f8fa;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.header {
|
|
23
|
+
padding: 40rpx;
|
|
24
|
+
text-align: center;
|
|
25
|
+
|
|
26
|
+
.title {
|
|
27
|
+
display: block;
|
|
28
|
+
font-size: 40rpx;
|
|
29
|
+
font-weight: bold;
|
|
30
|
+
color: #333;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
padding: 40rpx;
|
|
36
|
+
text-align: center;
|
|
37
|
+
|
|
38
|
+
.content-text {
|
|
39
|
+
font-size: 28rpx;
|
|
40
|
+
color: #666;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="page-container">
|
|
3
|
+
<view class="header">
|
|
4
|
+
<text class="title">UXTO Example</text>
|
|
5
|
+
<text class="subtitle">前端框架示例项目</text>
|
|
6
|
+
</view>
|
|
7
|
+
|
|
8
|
+
<view class="content">
|
|
9
|
+
<text class="content-text">欢迎使用 UXTO 前端框架</text>
|
|
10
|
+
</view>
|
|
11
|
+
</view>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<style lang="scss">
|
|
18
|
+
.page-container {
|
|
19
|
+
min-height: 100vh;
|
|
20
|
+
background: #f7f8fa;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.header {
|
|
24
|
+
padding: 80rpx 40rpx 60rpx;
|
|
25
|
+
text-align: center;
|
|
26
|
+
|
|
27
|
+
.title {
|
|
28
|
+
display: block;
|
|
29
|
+
font-size: 52rpx;
|
|
30
|
+
font-weight: bold;
|
|
31
|
+
color: #1989fa;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.subtitle {
|
|
35
|
+
display: block;
|
|
36
|
+
font-size: 28rpx;
|
|
37
|
+
color: #999;
|
|
38
|
+
margin-top: 16rpx;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.content {
|
|
43
|
+
padding: 40rpx;
|
|
44
|
+
text-align: center;
|
|
45
|
+
|
|
46
|
+
.content-text {
|
|
47
|
+
font-size: 32rpx;
|
|
48
|
+
color: #666;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
</style>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="page-container">
|
|
3
|
+
<view class="header">
|
|
4
|
+
<text class="title">状态管理</text>
|
|
5
|
+
</view>
|
|
6
|
+
|
|
7
|
+
<view class="content">
|
|
8
|
+
<text class="content-text">状态管理示例内容</text>
|
|
9
|
+
</view>
|
|
10
|
+
</view>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="scss">
|
|
17
|
+
.page-container {
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f7f8fa;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.header {
|
|
23
|
+
padding: 40rpx;
|
|
24
|
+
text-align: center;
|
|
25
|
+
|
|
26
|
+
.title {
|
|
27
|
+
display: block;
|
|
28
|
+
font-size: 40rpx;
|
|
29
|
+
font-weight: bold;
|
|
30
|
+
color: #333;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
padding: 40rpx;
|
|
36
|
+
text-align: center;
|
|
37
|
+
|
|
38
|
+
.content-text {
|
|
39
|
+
font-size: 28rpx;
|
|
40
|
+
color: #666;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="tabbar-demo-page">
|
|
3
|
+
<!-- 环境光背景 -->
|
|
4
|
+
<view class="ambient"></view>
|
|
5
|
+
|
|
6
|
+
<!-- 内容区域 -->
|
|
7
|
+
<view class="content-area">
|
|
8
|
+
<!-- 首页内容 -->
|
|
9
|
+
<view v-if="activeTab === 'home'" class="card">
|
|
10
|
+
<text class="sub-title">首页</text>
|
|
11
|
+
<text class="title">欢迎回来</text>
|
|
12
|
+
<text class="desc">这里是首页内容区域</text>
|
|
13
|
+
</view>
|
|
14
|
+
|
|
15
|
+
<!-- UXTO内容 -->
|
|
16
|
+
<view v-else-if="activeTab === 'uxto'" class="card">
|
|
17
|
+
<text class="sub-title">UXTO</text>
|
|
18
|
+
<text class="title">图域中心</text>
|
|
19
|
+
<text class="desc">这里是UXTO内容区域</text>
|
|
20
|
+
</view>
|
|
21
|
+
|
|
22
|
+
<!-- 我的页面内容 -->
|
|
23
|
+
<view v-else class="card">
|
|
24
|
+
<text class="sub-title">我的</text>
|
|
25
|
+
<text class="title">个人中心</text>
|
|
26
|
+
<text class="desc">这里是"我的"页面</text>
|
|
27
|
+
</view>
|
|
28
|
+
</view>
|
|
29
|
+
|
|
30
|
+
<!-- 底部导航 -->
|
|
31
|
+
<u-tabbar
|
|
32
|
+
v-model="activeTab"
|
|
33
|
+
center-brand="TU"
|
|
34
|
+
center-label="图域"
|
|
35
|
+
:left-tab="{ label: '首页', icon: '⌂', value: 'home' }"
|
|
36
|
+
:center-tab="{ label: '图域', icon: 'TU', value: 'uxto' }"
|
|
37
|
+
:right-tab="{ label: '我的', icon: '◉', value: 'mine' }"
|
|
38
|
+
@tab-change="onTabChange"
|
|
39
|
+
/>
|
|
40
|
+
</view>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
import { ref } from 'vue'
|
|
45
|
+
|
|
46
|
+
const activeTab = ref('home')
|
|
47
|
+
|
|
48
|
+
const onTabChange = (tab: string) => {
|
|
49
|
+
console.log('Tab changed:', tab)
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<style lang="scss" scoped>
|
|
54
|
+
$--mint-1: #12b6af;
|
|
55
|
+
$--mint-2: #9fe4dd;
|
|
56
|
+
$--ink: #1b4d4a;
|
|
57
|
+
|
|
58
|
+
.tabbar-demo-page {
|
|
59
|
+
position: relative;
|
|
60
|
+
width: 100%;
|
|
61
|
+
max-width: 430px;
|
|
62
|
+
min-height: 100vh;
|
|
63
|
+
margin: 0 auto;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
background: linear-gradient(180deg, #f2fcfb 0%, #e7f8f5 40%, #ddf4f0 100%);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.ambient {
|
|
69
|
+
position: absolute;
|
|
70
|
+
inset: -120px -40px auto;
|
|
71
|
+
height: 320px;
|
|
72
|
+
background: radial-gradient(circle at 50% 20%, rgba(18, 182, 175, 0.35) 0%, rgba(18, 182, 175, 0) 72%);
|
|
73
|
+
pointer-events: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.content-area {
|
|
77
|
+
position: relative;
|
|
78
|
+
z-index: 1;
|
|
79
|
+
padding: 30px 18px 120px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.card {
|
|
83
|
+
border-radius: 20px;
|
|
84
|
+
padding: 18px;
|
|
85
|
+
background: rgba(255, 255, 255, 0.88);
|
|
86
|
+
backdrop-filter: blur(8px);
|
|
87
|
+
box-shadow: 0 14px 36px rgba(9, 100, 95, 0.15);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.sub-title {
|
|
91
|
+
display: block;
|
|
92
|
+
font-size: 13px;
|
|
93
|
+
letter-spacing: 2px;
|
|
94
|
+
color: #3f9892;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.title {
|
|
98
|
+
display: block;
|
|
99
|
+
margin: 10px 0 8px;
|
|
100
|
+
font-size: 28px;
|
|
101
|
+
color: $--ink;
|
|
102
|
+
font-weight: 700;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.desc {
|
|
106
|
+
display: block;
|
|
107
|
+
line-height: 1.6;
|
|
108
|
+
color: #4f7f7b;
|
|
109
|
+
font-size: 14px;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="page-container">
|
|
3
|
+
<view class="header">
|
|
4
|
+
<text class="title">工具类</text>
|
|
5
|
+
</view>
|
|
6
|
+
|
|
7
|
+
<view class="content">
|
|
8
|
+
<text class="content-text">工具类示例内容</text>
|
|
9
|
+
</view>
|
|
10
|
+
</view>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang="scss">
|
|
17
|
+
.page-container {
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f7f8fa;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.header {
|
|
23
|
+
padding: 40rpx;
|
|
24
|
+
text-align: center;
|
|
25
|
+
|
|
26
|
+
.title {
|
|
27
|
+
display: block;
|
|
28
|
+
font-size: 40rpx;
|
|
29
|
+
font-weight: bold;
|
|
30
|
+
color: #333;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
padding: 40rpx;
|
|
36
|
+
text-align: center;
|
|
37
|
+
|
|
38
|
+
.content-text {
|
|
39
|
+
font-size: 28rpx;
|
|
40
|
+
color: #666;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pages": [
|
|
3
|
+
{
|
|
4
|
+
"path": "pages/index/index",
|
|
5
|
+
"style": {
|
|
6
|
+
"navigationBarTitleText": "示例中心"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"path": "pages/components/index",
|
|
11
|
+
"style": {
|
|
12
|
+
"navigationBarTitleText": "组件示例"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"path": "pages/api/index",
|
|
17
|
+
"style": {
|
|
18
|
+
"navigationBarTitleText": "API 示例"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "pages/store/index",
|
|
23
|
+
"style": {
|
|
24
|
+
"navigationBarTitleText": "状态管理"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"path": "pages/utils/index",
|
|
29
|
+
"style": {
|
|
30
|
+
"navigationBarTitleText": "工具类"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"path": "pages/tabbar/index",
|
|
35
|
+
"style": {
|
|
36
|
+
"navigationBarTitleText": "底部导航",
|
|
37
|
+
"navigationStyle": "custom"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"globalStyle": {
|
|
42
|
+
"navigationBarTextStyle": "black",
|
|
43
|
+
"navigationBarTitleText": "UXTO Example",
|
|
44
|
+
"navigationBarBackgroundColor": "#ffffff",
|
|
45
|
+
"backgroundColor": "#f7f8fa"
|
|
46
|
+
},
|
|
47
|
+
"easycom": {
|
|
48
|
+
"autoscan": true,
|
|
49
|
+
"custom": {
|
|
50
|
+
"^u-(.*)": "@atooyu/uxto-ui/src/components/u-$1/u-$1.vue"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Tabbar 图标说明
|
|
2
|
+
|
|
3
|
+
本目录用于存放底部导航栏的图标文件。
|
|
4
|
+
|
|
5
|
+
## 需要的图标文件
|
|
6
|
+
|
|
7
|
+
请准备以下 6 个图标文件:
|
|
8
|
+
|
|
9
|
+
| 文件名 | 用途 | 建议尺寸 |
|
|
10
|
+
|--------|------|---------|
|
|
11
|
+
| home.png | 馨页图标(未选中) | 81x81 px |
|
|
12
|
+
| home-active.png | 馨页图标(选中) | 81x81 px |
|
|
13
|
+
| uxto.png | UXTO 图标(未选中) | 81x81 px |
|
|
14
|
+
| uxto-active.png | UXTO 图标(选中) | 81x81 px |
|
|
15
|
+
| mine.png | 我的图标(未选中) | 81x81 px |
|
|
16
|
+
| mine-active.png | 我的图标(选中) | 81x81 px |
|
|
17
|
+
|
|
18
|
+
## 设计规范
|
|
19
|
+
|
|
20
|
+
- 未选中状态建议使用灰色(#999999)
|
|
21
|
+
- 选中状态建议使用主题色(#1989fa)
|
|
22
|
+
- 保持图标风格一致
|
|
23
|
+
- 建议使用简洁的线性图标风格
|
|
24
|
+
|
|
25
|
+
## 临时方案
|
|
26
|
+
|
|
27
|
+
如果暂时没有图标文件,可以:
|
|
28
|
+
1. 使用文字导航(在 pages.json 中不设置 iconPath)
|
|
29
|
+
2. 使用占位图
|
|
30
|
+
3. 使用图标字体
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
interface CartItem {
|
|
5
|
+
id: number
|
|
6
|
+
name: string
|
|
7
|
+
price: number
|
|
8
|
+
quantity: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useCartStore = defineStore('cart', () => {
|
|
12
|
+
const items = ref<CartItem[]>([])
|
|
13
|
+
|
|
14
|
+
const totalItems = computed(() =>
|
|
15
|
+
items.value.reduce((total, item) => total + item.quantity, 0)
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const totalPrice = computed(() =>
|
|
19
|
+
items.value.reduce((total, item) => total + item.price * item.quantity, 0)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const addItem = (item: CartItem) => {
|
|
23
|
+
const existingItem = items.value.find(i => i.id === item.id)
|
|
24
|
+
if (existingItem) {
|
|
25
|
+
existingItem.quantity += item.quantity
|
|
26
|
+
} else {
|
|
27
|
+
items.value.push(item)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const removeItem = (id: number) => {
|
|
32
|
+
const index = items.value.findIndex(item => item.id === id)
|
|
33
|
+
if (index > -1) {
|
|
34
|
+
items.value.splice(index, 1)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const clearCart = () => {
|
|
39
|
+
items.value = []
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
items,
|
|
44
|
+
totalItems,
|
|
45
|
+
totalPrice,
|
|
46
|
+
addItem,
|
|
47
|
+
removeItem,
|
|
48
|
+
clearCart
|
|
49
|
+
}
|
|
50
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
export const useCounterStore = defineStore('counter', () => {
|
|
5
|
+
const count = ref(0)
|
|
6
|
+
|
|
7
|
+
const doubleCount = computed(() => count.value * 2)
|
|
8
|
+
|
|
9
|
+
const increment = () => {
|
|
10
|
+
count.value++
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const decrement = () => {
|
|
14
|
+
count.value--
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const reset = () => {
|
|
18
|
+
count.value = 0
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
count,
|
|
23
|
+
doubleCount,
|
|
24
|
+
increment,
|
|
25
|
+
decrement,
|
|
26
|
+
reset
|
|
27
|
+
}
|
|
28
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref, watch } 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
|
+
// 应用主题到页面
|
|
24
|
+
applyTheme()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 应用主题到页面根元素
|
|
28
|
+
const applyTheme = () => {
|
|
29
|
+
// 在H5环境下操作document
|
|
30
|
+
// #ifdef H5
|
|
31
|
+
const root = document.documentElement
|
|
32
|
+
root.classList.remove('dark-mode', 'gray-mode')
|
|
33
|
+
|
|
34
|
+
if (darkMode.value) {
|
|
35
|
+
root.classList.add('dark-mode')
|
|
36
|
+
} else if (grayMode.value) {
|
|
37
|
+
root.classList.add('gray-mode')
|
|
38
|
+
}
|
|
39
|
+
// #endif
|
|
40
|
+
|
|
41
|
+
// 在小程序/App环境下通过uni.setStorageSync传递给页面
|
|
42
|
+
uni.setStorageSync('currentThemeMode', {
|
|
43
|
+
dark: darkMode.value,
|
|
44
|
+
gray: grayMode.value
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 切换暗黑模式
|
|
49
|
+
const toggleDarkMode = () => {
|
|
50
|
+
darkMode.value = !darkMode.value
|
|
51
|
+
// 暗黑模式开启时关闭灰色模式
|
|
52
|
+
if (darkMode.value && grayMode.value) {
|
|
53
|
+
grayMode.value = false
|
|
54
|
+
}
|
|
55
|
+
uni.setStorageSync('darkMode', darkMode.value)
|
|
56
|
+
applyTheme()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 切换灰色模式
|
|
60
|
+
const toggleGrayMode = () => {
|
|
61
|
+
grayMode.value = !grayMode.value
|
|
62
|
+
// 灰色模式开启时关闭暗黑模式
|
|
63
|
+
if (grayMode.value && darkMode.value) {
|
|
64
|
+
darkMode.value = false
|
|
65
|
+
}
|
|
66
|
+
uni.setStorageSync('grayMode', grayMode.value)
|
|
67
|
+
applyTheme()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 设置暗黑模式
|
|
71
|
+
const setDarkMode = (value: boolean) => {
|
|
72
|
+
darkMode.value = value
|
|
73
|
+
if (value && grayMode.value) {
|
|
74
|
+
grayMode.value = false
|
|
75
|
+
}
|
|
76
|
+
uni.setStorageSync('darkMode', value)
|
|
77
|
+
applyTheme()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 设置灰色模式
|
|
81
|
+
const setGrayMode = (value: boolean) => {
|
|
82
|
+
grayMode.value = value
|
|
83
|
+
if (value && darkMode.value) {
|
|
84
|
+
darkMode.value = false
|
|
85
|
+
}
|
|
86
|
+
uni.setStorageSync('grayMode', value)
|
|
87
|
+
applyTheme()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
darkMode,
|
|
92
|
+
grayMode,
|
|
93
|
+
loadFromStorage,
|
|
94
|
+
toggleDarkMode,
|
|
95
|
+
toggleGrayMode,
|
|
96
|
+
setDarkMode,
|
|
97
|
+
setGrayMode,
|
|
98
|
+
applyTheme
|
|
99
|
+
}
|
|
100
|
+
})
|