This commit is contained in:
RISE
2026-03-11 18:34:19 +08:00
parent 71314c5b12
commit 42ce139dd1
10 changed files with 3265 additions and 671 deletions

View File

@@ -2,6 +2,8 @@
* API接口配置 * API接口配置
*/ */
import { get, post, put, uploadFile } from '../utils/request.js' import { get, post, put, uploadFile } from '../utils/request.js'
import request from '../utils/request.js'
import Taro from '@tarojs/taro'
// 认证相关API // 认证相关API
export const authAPI = { export const authAPI = {
@@ -45,6 +47,36 @@ export const orderAPI = {
driverConfirm: (data) => post('/api/twopoint/zhxyOrderCheck/driverConfirm', data) driverConfirm: (data) => post('/api/twopoint/zhxyOrderCheck/driverConfirm', data)
} }
// 运输管理相关API
export const transportAPI = {
// 获取运输管理列表
getTransportList: (params) => get('/api/twopoint/zhxyOrderCompany/myOrder', params),
// 获取所有固废品类
getAllOrderTypeCompany: (params) => get('/api/twopoint/zhxyOrderTypeCompanyCompany/getAll', params),
// 获取GPS轨迹数据
getGpsTrack: (params) => get('/api/twopoint/zhxyGpsCompany/page', params),
// 获取最后一条订单
getLastOrder: () => get('/api/twopoint/zhxyOrderCompany/getLastZhxyOrder'),
// 获取可用车辆列表
getCompanyAllCar: (params) => get('/api/twopoint/zhxyCarCompany/getCompanyAllCar', params),
// 获取司机列表
getAllCompanyDriver: () => get('/api/twopoint/zhxyDriverCompany/getAllCompanyDriver'),
// 获取固废种类列表
getAllGufeiCompany: () => get('/api/twopoint/zhxyGufeiCompany/getAll'),
// 根据固废种类获取固废代码列表
getAllGufeiItemCompany: (params) => get('/api/twopoint/zhxyGufeiItemCompany/getAll', params),
// 提交新增订单
createOrder: (data) => post('/api/twopoint/zhxyOrderCompany', data)
}
// 车辆相关API // 车辆相关API
export const carAPI = { export const carAPI = {
// 获取车辆分页数据支持orderType和orderNum参数 // 获取车辆分页数据支持orderType和orderNum参数
@@ -92,3 +124,58 @@ export const userAPI = {
// 发送短信验证码 // 发送短信验证码
sendSmsCode: (data) => get(`/api/twopoint/zhxyDriver/getCode?tel=${data.phone}&type=1`) sendSmsCode: (data) => get(`/api/twopoint/zhxyDriver/getCode?tel=${data.phone}&type=1`)
} }
/**
* 将树形菜单数据扁平化为水平数组
* @param {Array} treeData 树形数据
* @param {Array} result 结果数组(递归使用)
* @returns {Array} 扁平化后的数组
*/
function flattenMenuTree(treeData, result = []) {
if (!Array.isArray(treeData)) {
return result
}
treeData.forEach(item => {
// 创建新对象,不包含 children
const { children, ...menuItem } = item
result.push(menuItem)
// 如果有子菜单,递归处理
if (children && Array.isArray(children) && children.length > 0) {
flattenMenuTree(children, result)
}
})
return result
}
// 菜单相关API
export const menuAPI = {
// 获取菜单列表
getMenuList() {
const token = Taro.getStorageSync('token') || ''
return request({
url: '/api/admin/menu',
method: 'GET',
header: {
Authorization: token ? `Bearer ${token}` : ''
}
}).then(res => {
// 处理响应数据,将树形数据转换为扁平数据
if (res.statusCode === 200 && res.data) {
if (res.data.code === 0 && res.data.data) {
// 如果是数组,扁平化处理
if (Array.isArray(res.data.data)) {
const flattenedData = flattenMenuTree(res.data.data)
res.data.data = flattenedData
}
}
}
return res
}).catch(err => {
throw err
})
}
}

View File

@@ -4,6 +4,7 @@ export default {
'pages/vehicle/index', 'pages/vehicle/index',
'pages/statistics/index', 'pages/statistics/index',
'pages/history/index', 'pages/history/index',
'pages/transport/index',
'pages/profile/index', 'pages/profile/index',
'pages/login/index', 'pages/login/index',
'pages/register/index', 'pages/register/index',

View File

@@ -242,6 +242,7 @@
<script> <script>
import { Photograph, Edit, Scan, Scan2, Location, Location2 } from '@nutui/icons-vue' import { Photograph, Edit, Scan, Scan2, Location, Location2 } from '@nutui/icons-vue'
import CarForm from '../../components/CarForm.vue' import CarForm from '../../components/CarForm.vue'
import Taro from '@tarojs/taro'
import { checkLoginAndRedirect, getUserInfo, logout, getDriverInfo, saveUserInfo } from '../../utils/auth.js' import { checkLoginAndRedirect, getUserInfo, logout, getDriverInfo, saveUserInfo } from '../../utils/auth.js'
import { orderAPI, carAPI, companyAPI, driverAPI } from '../../api/index.js' import { orderAPI, carAPI, companyAPI, driverAPI } from '../../api/index.js'
import { API_CONFIG } from '../../utils/request.js' import { API_CONFIG } from '../../utils/request.js'
@@ -311,6 +312,12 @@ export default {
// 获取用户信息(未登录时也能正常显示) // 获取用户信息(未登录时也能正常显示)
this.getUserInfo() this.getUserInfo()
// 检查用户是否是司机,如果不是则跳转到运输管理页面(清空栈避免左上角返回)
if (this.userInfo && this.userInfo.isDriver === false) {
Taro.reLaunch({ url: '/pages/transport/index' })
return
}
// 只有在用户已登录时才获取数据 // 只有在用户已登录时才获取数据
if (this.userInfo && this.userInfo.token) { if (this.userInfo && this.userInfo.token) {
// 获取司机ID // 获取司机ID
@@ -332,6 +339,12 @@ export default {
// 页面显示时重新获取用户信息 // 页面显示时重新获取用户信息
this.getUserInfo() this.getUserInfo()
// 检查用户是否是司机,如果不是则跳转到运输管理页面(清空栈避免左上角返回)
if (this.userInfo && this.userInfo.isDriver === false) {
Taro.reLaunch({ url: '/pages/transport/index' })
return
}
// 只有在用户已登录时才刷新数据 // 只有在用户已登录时才刷新数据
if (this.userInfo && this.userInfo.token) { if (this.userInfo && this.userInfo.token) {
// 刷新司机数据以获取最新的认证状态 // 刷新司机数据以获取最新的认证状态
@@ -451,9 +464,14 @@ export default {
if (response.statusCode === 200 && response.data) { if (response.statusCode === 200 && response.data) {
if (response.data.code === 0 && response.data.data) { if (response.data.code === 0 && response.data.data) {
// 检查是否包含司机ID
const hasDriverId = response.data.data.id || response.data.data.driverId
if (hasDriverId) {
// 更新本地用户信息中的司机数据 // 更新本地用户信息中的司机数据
const updatedUserInfo = { const updatedUserInfo = {
...storedUserInfo, ...storedUserInfo,
isDriver: true,
driverInfo: { driverInfo: {
...storedUserInfo.driverInfo, ...storedUserInfo.driverInfo,
data: response.data.data data: response.data.data
@@ -466,13 +484,58 @@ export default {
// 更新当前页面的用户信息 // 更新当前页面的用户信息
this.userInfo = updatedUserInfo this.userInfo = updatedUserInfo
} else { } else {
console.error('获取司机信息失败:', response.data) // 没有司机ID标记为非司机用户并跳转
const updatedUserInfo = {
...storedUserInfo,
isDriver: false
}
saveUserInfo(updatedUserInfo)
this.userInfo = updatedUserInfo
// 跳转到运输管理页面(清空栈避免左上角返回)
Taro.reLaunch({ url: '/pages/transport/index' })
} }
} else { } else {
// 获取司机信息失败,标记为非司机用户并跳转
console.error('获取司机信息失败:', response.data)
const updatedUserInfo = {
...storedUserInfo,
isDriver: false
}
saveUserInfo(updatedUserInfo)
this.userInfo = updatedUserInfo
// 跳转到运输管理页面(清空栈避免左上角返回)
Taro.reLaunch({ url: '/pages/transport/index' })
}
} else {
// 获取司机信息API调用失败标记为非司机用户并跳转
console.error('获取司机信息API调用失败:', response) console.error('获取司机信息API调用失败:', response)
const updatedUserInfo = {
...storedUserInfo,
isDriver: false
}
saveUserInfo(updatedUserInfo)
this.userInfo = updatedUserInfo
// 跳转到运输管理页面(清空栈避免左上角返回)
Taro.reLaunch({ url: '/pages/transport/index' })
} }
} catch (error) { } catch (error) {
// 获取司机信息异常,标记为非司机用户并跳转
console.error('刷新司机数据失败:', error) console.error('刷新司机数据失败:', error)
const storedUserInfo = getUserInfo()
if (storedUserInfo) {
const updatedUserInfo = {
...storedUserInfo,
isDriver: false
}
saveUserInfo(updatedUserInfo)
this.userInfo = updatedUserInfo
// 跳转到运输管理页面(清空栈避免左上角返回)
Taro.reLaunch({ url: '/pages/transport/index' })
}
} }
}, },
// 刷新待完成车次数据 // 刷新待完成车次数据

View File

@@ -72,7 +72,7 @@ import { My, Setting } from '@nutui/icons-vue'
import Taro from '@tarojs/taro' import Taro from '@tarojs/taro'
import { aesEncrypt } from '../../utils/crypto.js' import { aesEncrypt } from '../../utils/crypto.js'
import { saveUserInfo } from '../../utils/auth.js' import { saveUserInfo } from '../../utils/auth.js'
import { authAPI, driverAPI } from '../../api/index.js' import { authAPI, driverAPI, menuAPI } from '../../api/index.js'
// 账号密码登录表单数据 // 账号密码登录表单数据
const loginForm = reactive({ const loginForm = reactive({
@@ -150,6 +150,21 @@ const handleLogin = async () => {
// 等待更长时间确保token完全生效 // 等待更长时间确保token完全生效
await new Promise(resolve => setTimeout(resolve, 1000)) await new Promise(resolve => setTimeout(resolve, 1000))
// 先获取菜单列表
try {
const menuResponse = await menuAPI.getMenuList()
if (menuResponse.statusCode === 200 && menuResponse.data) {
if (menuResponse.data.code === 0 && menuResponse.data.data) {
// 过滤出 miniShow === 1 的数据
const filteredMenuList = menuResponse.data.data.filter(item => item.miniShow === 1)
console.log('过滤后的菜单列表:', filteredMenuList)
wx.setStorageSync('menuList', filteredMenuList)
}
}
} catch (menuError) {
// 菜单获取失败不影响登录流程
}
// 检查用户是否为司机 // 检查用户是否为司机
try { try {
// 添加重试机制避免token未生效的问题 // 添加重试机制避免token未生效的问题
@@ -163,7 +178,6 @@ const handleLogin = async () => {
break // 成功获取,跳出循环 break // 成功获取,跳出循环
} catch (error) { } catch (error) {
retryCount++ retryCount++
console.warn(`获取司机信息失败,重试第${retryCount}次:`, error)
if (retryCount < maxRetries) { if (retryCount < maxRetries) {
// 等待一段时间后重试 // 等待一段时间后重试
@@ -212,67 +226,45 @@ const handleLogin = async () => {
}, 1000) }, 1000)
} }
} else { } else {
// 用户不是司机或没有司机ID登录失败 // 用户不是司机或没有司机ID静默跳转到运输管理页面
showMessage('登录失败:您不是司机用户')
}
} else {
// 获取司机信息失败,登录失败
showMessage('登录失败:无法获取司机信息')
}
} catch (error) {
console.error('获取司机信息失败:', error)
// 检查是否是token相关错误
if (error.message && error.message.includes('用户凭证已过期')) {
// 如果是token过期错误可能是token还未完全生效重试一次
console.log('检测到token过期错误尝试重新获取司机信息...')
try {
// 再次等待并重试
await new Promise(resolve => setTimeout(resolve, 1000))
const retryResponse = await driverAPI.getDriverInfo(userInfo.userId)
if (retryResponse.statusCode === 200 && retryResponse.data) {
// 处理重试成功的响应
const hasDriverId = retryResponse.data.id || retryResponse.data.driverId ||
(retryResponse.data.data && (retryResponse.data.data.id || retryResponse.data.data.driverId))
if (hasDriverId) {
const updatedUserInfo = { const updatedUserInfo = {
...userInfo, ...userInfo,
isDriver: true, isDriver: false
driverInfo: retryResponse.data,
driverId: retryResponse.data.id || retryResponse.data.driverId ||
(retryResponse.data.data && (retryResponse.data.data.id || retryResponse.data.data.driverId))
} }
saveUserInfo(updatedUserInfo) saveUserInfo(updatedUserInfo)
showMessage('登录成功')
// 检查认证状态并跳转
const driverStatus = retryResponse.data?.driverStatus ||
retryResponse.data?.data?.driverStatus
const isIdentityVerified = retryResponse.data?.identityVerified ||
retryResponse.data?.data?.identityVerified ||
updatedUserInfo.identityVerified
if (driverStatus === '1' || isIdentityVerified) {
setTimeout(() => { setTimeout(() => {
Taro.switchTab({ url: '/pages/index/index' }) Taro.reLaunch({ url: '/pages/transport/index' })
}, 1000) }, 500)
} else {
setTimeout(() => {
Taro.navigateTo({ url: '/pages/realname/index?from=login' })
}, 1000)
}
return return
} }
} else {
// 获取司机信息失败,静默跳转到运输管理页面
const updatedUserInfo = {
...userInfo,
isDriver: false
} }
} catch (retryError) { saveUserInfo(updatedUserInfo)
console.error('重试获取司机信息仍然失败:', retryError)
}
}
showMessage('登录失败:无法验证司机身份') setTimeout(() => {
Taro.reLaunch({ url: '/pages/transport/index' })
}, 500)
return
}
} catch (error) {
// 司机接口调用失败,静默跳转到运输管理页面
// 保存用户信息,标记为非司机用户(不显示运输管理菜单)
const updatedUserInfo = {
...userInfo,
isDriver: false
}
saveUserInfo(updatedUserInfo)
// 静默跳转到运输管理页面
setTimeout(() => {
Taro.reLaunch({ url: '/pages/transport/index' })
}, 500)
return
} }
} else { } else {
// 登录失败 // 登录失败
@@ -281,7 +273,6 @@ const handleLogin = async () => {
} }
} catch (error) { } catch (error) {
console.error('登录失败:', error)
showMessage('登录失败,请重试') showMessage('登录失败,请重试')
} finally { } finally {
isLoading.value = false isLoading.value = false

View File

@@ -44,6 +44,19 @@
</view> </view>
</view> </view>
<!-- 运输管理 - 仅非司机用户显示 -->
<view class="menu-item" v-if="!userInfo.isDriver" @click="goToTransport">
<view class="menu-icon">
<Order size="40" color="#666" />
</view>
<view class="menu-content">
<text class="menu-text">运输管理</text>
</view>
<view class="menu-arrow">
<Right size="32" color="#999" />
</view>
</view>
<!-- 修改头像 --> <!-- 修改头像 -->
<view class="menu-item" @click="changeAvatar" :class="{ 'disabled': isUploadingAvatar }"> <view class="menu-item" @click="changeAvatar" :class="{ 'disabled': isUploadingAvatar }">
<view class="menu-icon"> <view class="menu-icon">
@@ -163,7 +176,8 @@ const userInfo = reactive({
username: '', username: '',
userId: '', userId: '',
phone: '', phone: '',
avatar: '' avatar: '',
isDriver: false // 默认为非司机用户
}) })
// 页面加载时检查登录状态 // 页面加载时检查登录状态
@@ -460,6 +474,10 @@ const goToTrips = () => {
Taro.navigateTo({ url: '/pages/history/index' }) Taro.navigateTo({ url: '/pages/history/index' })
} }
const goToTransport = () => {
Taro.reLaunch({ url: '/pages/transport/index' })
}
// 实名认证 // 实名认证
const goToIdentity = () => { const goToIdentity = () => {
Taro.navigateTo({ url: '/pages/realname/index' }) Taro.navigateTo({ url: '/pages/realname/index' })

View File

@@ -0,0 +1,7 @@
export default {
navigationBarTitleText: '运输管理',
// 注意左上角返回按钮由页面栈决定navigateTo 会出现),不是这里能彻底控制的
navigationStyle: 'custom',
enablePullDownRefresh: true,
onReachBottomDistance: 50
}

File diff suppressed because it is too large Load Diff

View File

@@ -272,9 +272,10 @@ export function resetRedirectState() {
* 退出登录 * 退出登录
*/ */
export function logout() { export function logout() {
clearUserInfo() wx.reLaunch({
resetRedirectState()
wx.navigateTo({
url: '/pages/login/index' url: '/pages/login/index'
}) })
clearUserInfo()
resetRedirectState()
} }

View File

@@ -7,12 +7,8 @@ import { checkLoginAndRedirect, isLoggedIn, clearUserInfo, resetRedirectState }
// API基础配置 // API基础配置
// 根据环境变量设置不同的API地址 // 根据环境变量设置不同的API地址
const getBaseUrl = () => { const getBaseUrl = () => {
// 开发环境使用测试地址
if (process.env.NODE_ENV === 'development') {
return 'https://green.hrln.com.cn/'//'https://green.cyweb.top/'
}
// 生产环境使用正式地址 // 生产环境使用正式地址
return 'https://green.hrln.com.cn/' //'https://green.hrln.com.cn' return 'https://green.cyweb.top' //'https://green.hrln.com.cn'
} }
const API_CONFIG = { const API_CONFIG = {

1222
yarn.lock

File diff suppressed because it is too large Load Diff