@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,48 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
interface UserInfo {
|
|
5
|
+
username: string
|
|
6
|
+
email: string
|
|
7
|
+
role: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const useUserStore = defineStore('user', () => {
|
|
11
|
+
const isLoggedIn = ref(false)
|
|
12
|
+
const userInfo = ref<UserInfo>({
|
|
13
|
+
username: '',
|
|
14
|
+
email: '',
|
|
15
|
+
role: ''
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const isAdmin = computed(() => userInfo.value.role === 'admin')
|
|
19
|
+
|
|
20
|
+
const login = (user: UserInfo) => {
|
|
21
|
+
isLoggedIn.value = true
|
|
22
|
+
userInfo.value = user
|
|
23
|
+
uni.setStorageSync('user_info', user)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const logout = () => {
|
|
27
|
+
isLoggedIn.value = false
|
|
28
|
+
userInfo.value = { username: '', email: '', role: '' }
|
|
29
|
+
uni.removeStorageSync('user_info')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const loadFromStorage = () => {
|
|
33
|
+
const savedUser = uni.getStorageSync('user_info')
|
|
34
|
+
if (savedUser) {
|
|
35
|
+
isLoggedIn.value = true
|
|
36
|
+
userInfo.value = savedUser
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
isLoggedIn,
|
|
42
|
+
userInfo,
|
|
43
|
+
isAdmin,
|
|
44
|
+
login,
|
|
45
|
+
logout,
|
|
46
|
+
loadFromStorage
|
|
47
|
+
}
|
|
48
|
+
})
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 日期格式化
|
|
3
|
+
*/
|
|
4
|
+
export const formatDate = (date: Date | number | string, format = 'YYYY-MM-DD HH:mm:ss'): string => {
|
|
5
|
+
const d = new Date(date)
|
|
6
|
+
const year = d.getFullYear()
|
|
7
|
+
const month = String(d.getMonth() + 1).padStart(2, '0')
|
|
8
|
+
const day = String(d.getDate()).padStart(2, '0')
|
|
9
|
+
const hours = String(d.getHours()).padStart(2, '0')
|
|
10
|
+
const minutes = String(d.getMinutes()).padStart(2, '0')
|
|
11
|
+
const seconds = String(d.getSeconds()).padStart(2, '0')
|
|
12
|
+
|
|
13
|
+
return format
|
|
14
|
+
.replace('YYYY', String(year))
|
|
15
|
+
.replace('MM', month)
|
|
16
|
+
.replace('DD', day)
|
|
17
|
+
.replace('HH', hours)
|
|
18
|
+
.replace('mm', minutes)
|
|
19
|
+
.replace('ss', seconds)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 金额格式化
|
|
24
|
+
*/
|
|
25
|
+
export const formatMoney = (amount: number, decimals = 2): string => {
|
|
26
|
+
return amount.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 手机号脱敏
|
|
31
|
+
*/
|
|
32
|
+
export const maskPhone = (phone: string): string => {
|
|
33
|
+
if (!phone || phone.length !== 11) return phone
|
|
34
|
+
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 验证手机号
|
|
39
|
+
*/
|
|
40
|
+
export const isValidPhone = (phone: string): boolean => {
|
|
41
|
+
return /^1[3-9]\d{9}$/.test(phone)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 验证邮箱
|
|
46
|
+
*/
|
|
47
|
+
export const isValidEmail = (email: string): boolean => {
|
|
48
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 生成随机字符串
|
|
53
|
+
*/
|
|
54
|
+
export const randomString = (length = 16): string => {
|
|
55
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
56
|
+
let result = ''
|
|
57
|
+
for (let i = 0; i < length; i++) {
|
|
58
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
59
|
+
}
|
|
60
|
+
return result
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 生成UUID
|
|
65
|
+
*/
|
|
66
|
+
export const generateUUID = (): string => {
|
|
67
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
68
|
+
const r = Math.random() * 16 | 0
|
|
69
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8)
|
|
70
|
+
return v.toString(16)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 节流函数
|
|
76
|
+
*/
|
|
77
|
+
export const throttle = <T extends (...args: any[]) => any>(
|
|
78
|
+
fn: T,
|
|
79
|
+
delay = 300
|
|
80
|
+
): (...args: Parameters<T>) => void => {
|
|
81
|
+
let lastTime = 0
|
|
82
|
+
return (...args: Parameters<T>) => {
|
|
83
|
+
const now = Date.now()
|
|
84
|
+
if (now - lastTime >= delay) {
|
|
85
|
+
fn(...args)
|
|
86
|
+
lastTime = now
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 防抖函数
|
|
93
|
+
*/
|
|
94
|
+
export const debounce = <T extends (...args: any[]) => any>(
|
|
95
|
+
fn: T,
|
|
96
|
+
delay = 300
|
|
97
|
+
): (...args: Parameters<T>) => void => {
|
|
98
|
+
let timer: number | null = null
|
|
99
|
+
return (...args: Parameters<T>) => {
|
|
100
|
+
if (timer) clearTimeout(timer)
|
|
101
|
+
timer = setTimeout(() => {
|
|
102
|
+
fn(...args)
|
|
103
|
+
timer = null
|
|
104
|
+
}, delay)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP工具类
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface RequestConfig {
|
|
6
|
+
url: string
|
|
7
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
8
|
+
data?: any
|
|
9
|
+
header?: Record<string, string>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const BASE_URL = ''
|
|
13
|
+
|
|
14
|
+
export const request = async <T = any>(config: RequestConfig): Promise<T> => {
|
|
15
|
+
const token = uni.getStorageSync('token')
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const response = await uni.request({
|
|
19
|
+
url: BASE_URL + config.url,
|
|
20
|
+
method: config.method || 'GET',
|
|
21
|
+
data: config.data,
|
|
22
|
+
header: {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'Authorization': token ? `Bearer ${token}` : '',
|
|
25
|
+
...config.header
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
if (response.statusCode !== 200) {
|
|
30
|
+
throw new Error(`请求失败: ${response.statusCode}`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return response.data as T
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('[HTTP Error]', error)
|
|
36
|
+
throw error
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const get = <T = any>(url: string, data?: any): Promise<T> => {
|
|
41
|
+
return request<T>({ url, method: 'GET', data })
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const post = <T = any>(url: string, data?: any): Promise<T> => {
|
|
45
|
+
return request<T>({ url, method: 'POST', data })
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 存储工具类
|
|
3
|
+
*/
|
|
4
|
+
export const setStorage = <T>(key: string, value: T): void => {
|
|
5
|
+
uni.setStorageSync(key, value)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getStorage = <T>(key: string, defaultValue?: T): T | undefined => {
|
|
9
|
+
const value = uni.getStorageSync(key)
|
|
10
|
+
return value || defaultValue
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const removeStorage = (key: string): void => {
|
|
14
|
+
uni.removeStorageSync(key)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const clearStorage = (): void => {
|
|
18
|
+
uni.clearStorageSync()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const STORAGE_KEYS = {
|
|
22
|
+
TOKEN: 'token',
|
|
23
|
+
USER_INFO: 'user_info',
|
|
24
|
+
THEME: 'theme',
|
|
25
|
+
CART: 'cart'
|
|
26
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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": {
|
|
16
|
+
"@/*": ["./src/*"]
|
|
17
|
+
},
|
|
18
|
+
"types": [
|
|
19
|
+
"@dcloudio/types",
|
|
20
|
+
"@types/node"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"include": [
|
|
24
|
+
"src/**/*.ts",
|
|
25
|
+
"src/**/*.d.ts",
|
|
26
|
+
"src/**/*.tsx",
|
|
27
|
+
"src/**/*.vue"
|
|
28
|
+
],
|
|
29
|
+
"exclude": ["node_modules", "dist"]
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
resolve: {
|
|
11
|
+
alias: {
|
|
12
|
+
'@': path.resolve(__dirname, 'src').replace(/\\/g, '/'),
|
|
13
|
+
'uxto-ui': uxtoUiComponentsPath,
|
|
14
|
+
'@atooyu/uxto-ui': uxtoUiComponentsPath
|
|
15
|
+
},
|
|
16
|
+
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
|
|
17
|
+
},
|
|
18
|
+
css: {
|
|
19
|
+
preprocessorOptions: {
|
|
20
|
+
scss: {
|
|
21
|
+
api: 'modern-compiler',
|
|
22
|
+
additionalData: `@import "${variablesPath}";`,
|
|
23
|
+
silenceDeprecations: ['import', 'legacy-js-api']
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|