소스 검색

✨ feat:init

zbb 1 일 전
부모
커밋
f5817af948
14개의 변경된 파일391개의 추가작업 그리고 207개의 파일을 삭제
  1. 14 1
      .gitignore
  2. 13 17
      api/index.js
  3. 4 90
      api/request.js
  4. 10 31
      api/user.js
  5. 109 0
      config/README.md
  6. 22 0
      config/env.development.js
  7. 22 0
      config/env.production.js
  8. 45 0
      config/index.js
  9. 1 1
      package.json
  10. 20 6
      pages/login/login.vue
  11. 13 8
      pages/splash/splash.vue
  12. 0 20
      static/README.md
  13. 0 33
      static/TABBAR_ICONS.md
  14. 118 0
      utils/request.js

+ 14 - 1
.gitignore

@@ -1 +1,14 @@
-unpackage/dist/
+node_modules/
+unpackage/
+.DS_Store
+*.log
+.hbuilderx/
+.idea/
+*.swp
+*.swo
+*~
+
+# 环境文件(可选:如果不想提交敏感信息)
+# .env
+# .env.local
+# .env.*.local

+ 13 - 17
api/index.js

@@ -1,24 +1,20 @@
 /**
- * 统一拦截器配置
+ * API 接口统一导出
  */
+import request from './request.js'
 
-// 不需要登录验证的白名单页面
-export const whiteList = [
-	'pages/login/login',
-	'pages/agreement/user',
-	'pages/agreement/privacy'
-]
-
-/**
- * 检查页面是否在白名单中
- * @param {string} pagePath - 页面路径
- * @returns {boolean} 是否在白名单中
- */
-export const isInWhiteList = (pagePath) => {
-	return whiteList.includes(pagePath)
+// 用户相关接口
+export const userApi = {
+	// 发送验证码
+	sendCode: (data) => request.post('/api/auth/send-code', data),
+	
+	// 手机号登录
+	login: (data) => request.post('/api/auth/login', data),
+	
+	// 获取用户信息
+	getUserInfo: () => request.get('/api/user/info')
 }
 
 export default {
-	whiteList,
-	isInWhiteList
+	user: userApi
 }

+ 4 - 90
api/request.js

@@ -1,92 +1,6 @@
 /**
- * 请求封装
+ * API 请求统一导出
+ * 实际请求逻辑在 utils/request.js
  */
-
-// 基础配置
-const BASE_URL = 'https://api.example.com' // TODO: 替换为实际接口地址
-const TIMEOUT = 10000
-
-/**
- * 统一请求方法
- */
-export const request = (options) => {
-	return new Promise((resolve, reject) => {
-		// 获取 token
-		const token = uni.getStorageSync('token') || ''
-		
-		uni.request({
-			url: BASE_URL + options.url,
-			method: options.method || 'GET',
-			data: options.data || {},
-			header: {
-				'Content-Type': 'application/json',
-				'Authorization': token ? `Bearer ${token}` : ''
-			},
-			timeout: TIMEOUT,
-			success: (res) => {
-				const { statusCode, data } = res
-				
-				// HTTP 状态码判断
-				if (statusCode === 200) {
-					// 业务状态码判断
-					if (data.code === 0 || data.code === 200 || data.success) {
-						resolve(data)
-					} else {
-						// 业务错误
-						uni.showToast({
-							title: data.message || data.msg || '请求失败',
-							icon: 'none',
-							duration: 2000
-						})
-						reject(data)
-					}
-				} else if (statusCode === 401) {
-					// 未授权,清除缓存并跳转登录页
-					uni.removeStorageSync('userInfo')
-					uni.removeStorageSync('token')
-					uni.reLaunch({
-						url: '/pages/login/login'
-					})
-					reject({ message: '未授权,请重新登录' })
-				} else {
-					// 其他错误
-					uni.showToast({
-						title: '网络请求失败',
-						icon: 'none',
-						duration: 2000
-					})
-					reject(res)
-				}
-			},
-			fail: (err) => {
-				uni.showToast({
-					title: '网络连接失败',
-					icon: 'none',
-					duration: 2000
-				})
-				reject(err)
-			}
-		})
-	})
-}
-
-/**
- * 快捷请求方法
- */
-export const get = (url, data) => {
-	return request({ url, method: 'GET', data })
-}
-
-export const post = (url, data) => {
-	return request({ url, method: 'POST', data })
-}
-
-export const put = (url, data) => {
-	return request({ url, method: 'PUT', data })
-}
-
-export const del = (url, data) => {
-	return request({ url, method: 'DELETE', data })
-}
-
-export default request
+export { request, get, post, put, del } from '@/utils/request.js'
+export { default } from '@/utils/request.js'

+ 10 - 31
api/user.js

@@ -1,52 +1,31 @@
 /**
- * 用户相关 API
+ * 用户相关接口
  */
-
-import { post } from './request.js'
+import request from './request.js'
 
 /**
  * 发送验证码
- * @param {string} phone - 手机号
  */
-export const sendVerifyCode = (phone) => {
-	return post('/api/auth/send-code', { phone })
+export const sendCode = (data) => {
+	return request.post('/api/auth/send-code', data)
 }
 
 /**
  * 手机号登录
- * @param {string} phone - 手机号
- * @param {string} code - 验证码
- */
-export const loginByPhone = (phone, code) => {
-	return post('/api/auth/login', { phone, code })
-}
-
-/**
- * 微信登录
- * @param {string} code - 微信登录 code
  */
-export const loginByWechat = (code) => {
-	return post('/api/auth/wechat-login', { code })
+export const login = (data) => {
+	return request.post('/api/auth/login', data)
 }
 
 /**
  * 获取用户信息
  */
 export const getUserInfo = () => {
-	return post('/api/user/info')
-}
-
-/**
- * 退出登录
- */
-export const logout = () => {
-	return post('/api/auth/logout')
+	return request.get('/api/user/info')
 }
 
 export default {
-	sendVerifyCode,
-	loginByPhone,
-	loginByWechat,
-	getUserInfo,
-	logout
+	sendCode,
+	login,
+	getUserInfo
 }

+ 109 - 0
config/README.md

@@ -0,0 +1,109 @@
+# 环境配置说明
+
+## 目录结构
+
+```
+config/
+├── index.js              # 配置入口
+├── env.development.js    # 开发环境
+├── env.test.js           # 测试环境
+├── env.production.js     # 生产环境
+└── README.md             # 使用说明
+```
+
+## 切换环境
+
+编辑 `config/index.js` 文件,修改 `CURRENT_ENV` 变量:
+
+```javascript
+// 手动修改此处切换环境:development | test | production
+const CURRENT_ENV = 'development'
+```
+
+## 配置项说明
+
+每个环境文件包含以下配置:
+
+| 配置项 | 类型 | 说明 |
+|--------|------|------|
+| `env` | string | 环境标识 |
+| `baseUrl` | string | API 基础地址 |
+| `timeout` | number | 请求超时时间 (ms) |
+| `appName` | string | 应用名称 |
+| `appVersion` | string | 应用版本 |
+| `appId` | string | 微信小程序 AppID |
+| `debug` | boolean | 是否开启调试模式 |
+| `enableLog` | boolean | 是否打印日志 |
+
+## 使用方式
+
+### 在 request 中使用(已自动集成)
+
+```javascript
+import request from '@/utils/request.js'
+// 会自动使用对应环境的 baseUrl
+await request.post('/api/auth/login', data)
+```
+
+### 在组件中获取配置
+
+```javascript
+import { getCurrentConfig } from '@/config/index.js'
+
+const config = await getCurrentConfig()
+console.log('当前环境:', config.env)
+console.log('API 地址:', config.baseUrl)
+console.log('应用名称:', config.appName)
+console.log('AppID:', config.appId)
+```
+
+### 在 JS 文件中获取配置
+
+```javascript
+import { getCurrentConfig, CURRENT_ENV } from '@/config/index.js'
+
+// 获取当前环境标识
+console.log('当前环境:', CURRENT_ENV)
+
+// 获取完整配置
+const config = await getCurrentConfig()
+```
+
+## 修改配置
+
+编辑对应的环境文件,例如 `config/env.development.js`:
+
+```javascript
+export default {
+	env: 'development',
+	baseUrl: 'https://dev-api.example.com',  // 修改 API 地址
+	timeout: 10000,
+	appName: '布尔销销乐',
+	appVersion: '1.0.0',
+	appId: 'wx6124d881774fb80a',
+	debug: true,
+	enableLog: true
+}
+```
+
+## 添加新环境
+
+1. 创建新文件 `config/env.<name>.js`
+2. 在 `config/index.js` 的 `envConfigMap` 中添加映射
+3. 修改 `CURRENT_ENV` 为新环境名
+
+示例:
+
+```javascript
+// config/env.staging.js
+export default {
+	env: 'staging',
+	baseUrl: 'https://staging-api.example.com',
+	timeout: 10000,
+	appName: '布尔销销乐',
+	appVersion: '1.0.0',
+	appId: 'wx6124d881774fb80a',
+	debug: true,
+	enableLog: true
+}
+```

+ 22 - 0
config/env.development.js

@@ -0,0 +1,22 @@
+/**
+ * 开发环境配置
+ */
+export default {
+	// 环境标识
+	env: 'development',
+	
+	// API 配置
+	baseUrl: 'https://dev-api.example.com',
+	timeout: 10000,
+	
+	// 应用信息
+	appName: '布尔销销乐测试',
+	appVersion: '1.0.0',
+	
+	// 微信小程序配置
+	appId: 'wx6124d881774fb80a',
+	
+	// 调试配置
+	debug: true,
+	enableLog: true
+}

+ 22 - 0
config/env.production.js

@@ -0,0 +1,22 @@
+/**
+ * 生产环境配置
+ */
+export default {
+	// 环境标识
+	env: 'production',
+	
+	// API 配置
+	baseUrl: 'https://api.example.com',
+	timeout: 10000,
+	
+	// 应用信息
+	appName: '布尔销销乐',
+	appVersion: '1.0.0',
+	
+	// 微信小程序配置
+	appId: 'wx6124d881774fb80a',
+	
+	// 调试配置
+	debug: false,
+	enableLog: false
+}

+ 45 - 0
config/index.js

@@ -0,0 +1,45 @@
+/**
+ * 环境配置入口
+ * 手动修改 CURRENT_ENV 切换环境
+ */
+
+// 手动修改此处切换环境:development | test | production
+const CURRENT_ENV = 'development'
+
+// 环境配置映射
+const envConfigMap = {
+	development: () => import('./env.development.js'),
+	production: () => import('./env.production.js')
+}
+
+// 获取当前环境配置
+const getCurrentConfig = async () => {
+	const configLoader = envConfigMap[CURRENT_ENV] || envConfigMap.development
+	try {
+		const config = await configLoader()
+		return config.default
+	} catch (error) {
+		console.error('加载环境配置失败:', error)
+		// 返回默认配置
+		return {
+			env: 'development',
+			baseUrl: 'https://dev-api.example.com',
+			timeout: 10000,
+			appName: '布尔销销乐',
+			appVersion: '1.0.0',
+			appId: 'wx6124d881774fb80a',
+			debug: true,
+			enableLog: true
+		}
+	}
+}
+
+// 同步获取配置(用于初始化)
+const getSyncConfig = () => {
+	const configLoader = envConfigMap[CURRENT_ENV] || envConfigMap.development
+	// 注意:这里是同步导入,实际使用时建议用异步
+	return configLoader().then(m => m.default)
+}
+
+export { CURRENT_ENV, getCurrentConfig, getSyncConfig }
+export default getCurrentConfig

+ 1 - 1
package.json

@@ -1,5 +1,5 @@
 {
-  "name": "wechat-crm",
+  "name": "布尔销销乐",
   "version": "1.0.0",
   "description": "布尔销销乐 - 微信小程序 CRM 系统",
   "main": "main.js",

+ 20 - 6
pages/login/login.vue

@@ -8,7 +8,7 @@
 		<!-- Logo 区域 -->
 		<view class="logo-section">
 			<image class="logo-icon" src="/static/image/public/logo.png" mode="aspectFill"></image>
-			<text class="app-name">布尔销销乐</text>
+			<text class="app-name">{{appName}}</text>
 		</view>
 
 		<!-- 表单区域 -->
@@ -249,16 +249,30 @@
 
 <script setup>
 	import {
-		ref
+		getCurrentConfig
+	} from '@/config/index.js'
+	import {
+		ref,
+		onMounted
 	} from 'vue'
 	import {
-		sendVerifyCode,
-		loginByPhone
+		login,
+		sendCode
 	} from '@/api/user.js'
 	import {
 		saveUserInfo
 	} from '@/utils/userCache.js'
 
+
+
+	let appName = ref('')
+
+	onMounted(async () => {
+		const config = await getCurrentConfig()
+		appName.value = config.appName
+		version.value = config.appVersion
+	})
+
 	// 表单数据
 	const phoneNumber = ref('')
 	const verifyCode = ref('')
@@ -283,7 +297,7 @@
 		}
 
 		try {
-			const res = await sendVerifyCode(phoneNumber.value)
+			const res = await login(phoneNumber.value)
 			console.log('验证码发送成功:', res)
 
 			// 开始倒计时
@@ -327,7 +341,7 @@
 		isLoading.value = true
 
 		try {
-			const res = await loginByPhone(phoneNumber.value, verifyCode.value)
+			const res = await sendCode(phoneNumber.value, verifyCode.value)
 			console.log('登录成功:', res)
 
 			// 保存用户信息和 token

+ 13 - 8
pages/splash/splash.vue

@@ -3,7 +3,7 @@
 		<!-- Logo 区域 -->
 		<view class="logo-section">
 			<image class="logo-icon" src="/static/image/public/logo.png" mode="aspectFill"></image>
-			<text class="app-name">布尔销销乐</text>
+			<text class="app-name">{{appName}}</text>
 			<text class="app-slogan">您的客户关系管理助手</text>
 		</view>
 
@@ -19,7 +19,7 @@
 
 		<!-- 版本信息 -->
 		<view class="version-info">
-			<text class="version-text">v1.0.0</text>
+			<text class="version-text">{{version}}</text>
 			<view class="version-text">
 				浙江舒博特网络科技有限公司提供技术支持
 			</view>
@@ -35,11 +35,17 @@
 	import {
 		isLogin
 	} from '@/utils/userCache.js'
-
+	import {
+		getCurrentConfig
+	} from '@/config/index.js'
 	const loadingText = ref('正在加载...')
-
+	let appName = ref('')
+	let version = ref('')
 	// 页面加载
-	onMounted(() => {
+	onMounted(async () => {
+		const config = await getCurrentConfig()
+		appName.value = config.appName
+		version.value = config.appVersion
 		initApp()
 	})
 
@@ -59,7 +65,7 @@
 			// 再延迟一点,让动画更流畅
 			// await sleep(800)
 
-			if (false) {
+			if (true) {
 				// 已登录,跳转首页
 				uni.reLaunch({
 					url: '/pages/index/index'
@@ -110,9 +116,7 @@
 		.logo-icon {
 			width: 200rpx;
 			height: 200rpx;
-			background: linear-gradient(135deg, #ffffff 0%, #e6f7ff 100%);
 			border-radius: 40rpx;
-			box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.2);
 			display: flex;
 			align-items: center;
 			justify-content: center;
@@ -182,6 +186,7 @@
 		flex-direction: column;
 		align-items: center;
 		justify-content: center;
+
 		.version-text {
 			font-size: 22rpx;
 			color: rgba(255, 255, 255, 0.6);

+ 0 - 20
static/README.md

@@ -1,20 +0,0 @@
-# 静态资源说明
-
-请将以下图片资源放入此目录:
-
-## 必需资源
-
-1. **avatar-default.png** - 默认用户头像 (建议尺寸:200x200px)
-2. **visitor-icon.png** - 访客图标 (建议尺寸:64x64px)
-3. **avatar-1.png** - 示例访客头像 (建议尺寸:160x160px)
-
-## 可选资源
-
-如需更多访客头像,可添加:
-- avatar-2.png
-- avatar-3.png
-- ...
-
-## 图标替代方案
-
-如果暂时没有图片资源,可以使用 emoji 表情替代,代码中已预留 emoji 图标。

+ 0 - 33
static/TABBAR_ICONS.md

@@ -1,33 +0,0 @@
-# TabBar 图标资源说明
-
-请准备以下 TabBar 图标(建议尺寸:81x81px,实际显示 27x27px):
-
-## 首页
-- **tabbar-home.png** - 首页图标(未选中)
-- **tabbar-home-active.png** - 首页图标(选中,蓝色)
-
-## 客户
-- **tabbar-customer.png** - 客户图标(未选中)
-- **tabbar-customer-active.png** - 客户图标(选中,蓝色)
-
-## 消息
-- **tabbar-message.png** - 消息图标(未选中)
-- **tabbar-message-active.png** - 消息图标(选中,蓝色)
-
-## 统计
-- **tabbar-stats.png** - 统计图标(未选中)
-- **tabbar-stats-active.png** - 统计图标(选中,蓝色)
-
-## 我的
-- **tabbar-mine.png** - 我的图标(未选中)
-- **tabbar-mine-active.png** - 我的图标(选中,蓝色)
-
-## 颜色建议
-- 未选中:#999999
-- 选中:#667eea(紫色渐变主题色)
-
-## 临时方案
-如果暂时没有图标,可以:
-1. 使用 emoji 或文字代替
-2. 从 iconfont.cn 下载合适的图标
-3. 使用设计工具(Figma/Sketch)制作简单图标

+ 118 - 0
utils/request.js

@@ -0,0 +1,118 @@
+/**
+ * 请求封装
+ * 根据环境自动切换 API 地址
+ */
+import { getCurrentConfig, CURRENT_ENV } from '@/config/index.js'
+
+// 缓存配置
+let configCache = null
+
+// 初始化配置
+const initConfig = async () => {
+	if (!configCache) {
+		configCache = await getCurrentConfig()
+		console.log('当前环境:', configCache.env, '| API 地址:', configCache.baseUrl)
+	}
+	return configCache
+}
+
+// 预加载配置
+initConfig()
+
+/**
+ * 统一请求方法
+ */
+export const request = async (options) => {
+	// 确保配置已加载
+	const config = await initConfig()
+	const { baseUrl, timeout, debug } = config
+	
+	return new Promise((resolve, reject) => {
+		// 获取 token
+		const token = uni.getStorageSync('token') || ''
+		
+		if (debug) {
+			console.log('Request:', options.method || 'GET', options.url, options.data)
+		}
+		
+		uni.request({
+			url: baseUrl + options.url,
+			method: options.method || 'GET',
+			data: options.data || {},
+			header: {
+				'Content-Type': 'application/json',
+				'Authorization': token ? `Bearer ${token}` : ''
+			},
+			timeout: timeout,
+			success: (res) => {
+				const { statusCode, data } = res
+				
+				if (debug) {
+					console.log('Response:', statusCode, data)
+				}
+				
+				// HTTP 状态码判断
+				if (statusCode === 200) {
+					// 业务状态码判断
+					if (data.code === 0 || data.code === 200 || data.success) {
+						resolve(data)
+					} else {
+						// 业务错误
+						uni.showToast({
+							title: data.message || data.msg || '请求失败',
+							icon: 'none',
+							duration: 2000
+						})
+						reject(data)
+					}
+				} else if (statusCode === 401) {
+					// 未授权,清除缓存并跳转登录页
+					uni.removeStorageSync('userInfo')
+					uni.removeStorageSync('token')
+					uni.reLaunch({
+						url: '/pages/login/login'
+					})
+					reject({ message: '未授权,请重新登录' })
+				} else {
+					// 其他错误
+					uni.showToast({
+						title: '网络请求失败',
+						icon: 'none',
+						duration: 2000
+					})
+					reject(res)
+				}
+			},
+			fail: (err) => {
+				console.error('Request fail:', err)
+				uni.showToast({
+					title: '网络连接失败',
+					icon: 'none',
+					duration: 2000
+				})
+				reject(err)
+			}
+		})
+	})
+}
+
+/**
+ * 快捷请求方法
+ */
+export const get = (url, data) => {
+	return request({ url, method: 'GET', data })
+}
+
+export const post = (url, data) => {
+	return request({ url, method: 'POST', data })
+}
+
+export const put = (url, data) => {
+	return request({ url, method: 'PUT', data })
+}
+
+export const del = (url, data) => {
+	return request({ url, method: 'DELETE', data })
+}
+
+export default request