修改位置交互,修改代码逻辑
This commit is contained in:
@@ -42,7 +42,7 @@ Page({
|
||||
userInfo: {
|
||||
id: 1,
|
||||
name: '管理员',
|
||||
role: 'ADMIN',
|
||||
role: 'ADMIN' as any,
|
||||
phone: '13800138000'
|
||||
}
|
||||
});
|
||||
@@ -150,10 +150,11 @@ Page({
|
||||
|
||||
// 添加员工位置标记
|
||||
deliveryPersons.forEach(person => {
|
||||
// 使用默认坐标,实际位置由locationTrackingService统一管理
|
||||
markers.push({
|
||||
id: 20000 + person.id, // 避免ID冲突
|
||||
longitude: person.currentLocation.longitude,
|
||||
latitude: person.currentLocation.latitude,
|
||||
longitude: 102.833722, // 默认经度
|
||||
latitude: 24.880095, // 默认纬度
|
||||
title: person.name,
|
||||
iconPath: this.getStaffStatusIcon(person.status),
|
||||
width: 32,
|
||||
@@ -259,7 +260,7 @@ Page({
|
||||
|
||||
if (assignedPerson) {
|
||||
this.setData({
|
||||
mapCenter: assignedPerson.currentLocation
|
||||
mapCenter: { longitude: 102.833722, latitude: 24.880095 } // 默认坐标
|
||||
});
|
||||
|
||||
// 绘制从起点到终点的路线
|
||||
@@ -526,25 +527,19 @@ Page({
|
||||
this.hideAddModal();
|
||||
},
|
||||
|
||||
// 切换底部页签
|
||||
// 底部页签切换
|
||||
switchMainTab(e: any) {
|
||||
const tab = e.currentTarget.dataset.tab;
|
||||
this.setData({
|
||||
currentTab: tab
|
||||
});
|
||||
|
||||
// 根据不同的页签执行不同的逻辑
|
||||
switch (tab) {
|
||||
case 'main':
|
||||
// 管理中心,显示所有内容
|
||||
break;
|
||||
case 'orders':
|
||||
// 订单详情,可能需要调整布局
|
||||
break;
|
||||
case 'staff':
|
||||
// 员工管理,可能需要调整布局
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// 跳转到员工管理页面
|
||||
goToEmployeeManagement() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/employee/employee'
|
||||
});
|
||||
},
|
||||
|
||||
// 地图点击事件
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<view class="staff-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">员工管理</text>
|
||||
<button class="manage-btn" bindtap="goToEmployeeManagement">管理员工</button>
|
||||
</view>
|
||||
|
||||
<scroll-view class="staff-list" scroll-y>
|
||||
|
||||
@@ -112,6 +112,20 @@
|
||||
min-width: 160rpx;
|
||||
}
|
||||
|
||||
.manage-btn {
|
||||
background-color: #1890ff;
|
||||
color: white;
|
||||
font-size: 28rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 40rpx;
|
||||
border: none;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
|
||||
.manage-btn:active {
|
||||
background-color: #096dd9;
|
||||
}
|
||||
|
||||
/* 订单标签页 */
|
||||
.order-tabs {
|
||||
display: flex;
|
||||
|
||||
@@ -8,7 +8,6 @@ Page({
|
||||
data: {
|
||||
applyForm: {
|
||||
name: '',
|
||||
idCard: '',
|
||||
phone: ''
|
||||
}
|
||||
},
|
||||
@@ -44,7 +43,7 @@ Page({
|
||||
* 提交申请
|
||||
*/
|
||||
async onSubmit() {
|
||||
const { name, idCard, phone } = this.data.applyForm;
|
||||
const { name, phone } = this.data.applyForm;
|
||||
|
||||
// 表单验证
|
||||
if (!this.validateForm()) {
|
||||
@@ -58,7 +57,7 @@ Page({
|
||||
});
|
||||
|
||||
// 调用API提交申请
|
||||
const result = await this.submitApplication({ name, idCard, phone });
|
||||
const result = await this.submitApplication({ name, phone });
|
||||
|
||||
if (result.success) {
|
||||
wx.showToast({
|
||||
@@ -115,9 +114,9 @@ Page({
|
||||
* 表单验证
|
||||
*/
|
||||
validateForm(): boolean {
|
||||
const { name, idCard, phone } = this.data.applyForm;
|
||||
const { name, phone } = this.data.applyForm;
|
||||
|
||||
if (!name || !idCard || !phone) {
|
||||
if (!name || !phone) {
|
||||
wx.showToast({
|
||||
title: '请填写完整信息',
|
||||
icon: 'none',
|
||||
@@ -126,16 +125,6 @@ Page({
|
||||
return false;
|
||||
}
|
||||
|
||||
// 身份证号验证
|
||||
if (idCard.length !== 18) {
|
||||
wx.showToast({
|
||||
title: '请输入正确的身份证号',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 手机号验证
|
||||
if (!/^1[3-9]\d{9}$/.test(phone)) {
|
||||
wx.showToast({
|
||||
|
||||
@@ -25,21 +25,7 @@
|
||||
<view class="apply-form-underline"></view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证号输入 -->
|
||||
<view class="apply-form-group">
|
||||
<text class="apply-form-label">身份证号</text>
|
||||
<input
|
||||
class="apply-form-input"
|
||||
type="idcard"
|
||||
value="{{applyForm.idCard}}"
|
||||
data-field="idCard"
|
||||
bindinput="onApplyFormInput"
|
||||
placeholder="请输入18位身份证号码"
|
||||
placeholder-class="apply-form-placeholder"
|
||||
maxlength="18"
|
||||
/>
|
||||
<view class="apply-form-underline"></view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 手机号输入 -->
|
||||
<view class="apply-form-group">
|
||||
|
||||
7
miniprogram/pages/employee/employee.json
Normal file
7
miniprogram/pages/employee/employee.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationBarTitleText": "员工管理",
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true,
|
||||
"backgroundColor": "#f5f5f5"
|
||||
}
|
||||
339
miniprogram/pages/employee/employee.ts
Normal file
339
miniprogram/pages/employee/employee.ts
Normal file
@@ -0,0 +1,339 @@
|
||||
// 员工管理页面逻辑
|
||||
import { EmployeeInfo } from '../../types';
|
||||
import employeeService from '../../services/employeeService';
|
||||
import { Role, getRoleOptions } from '../../utils/roleUtils';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
// 员工列表
|
||||
employees: [] as EmployeeInfo[],
|
||||
filteredEmployees: [] as EmployeeInfo[],
|
||||
|
||||
// 页面状态
|
||||
currentTab: 'list', // list: 列表页, add: 添加页
|
||||
loading: false,
|
||||
|
||||
// 添加员工表单数据
|
||||
addForm: {
|
||||
name: '',
|
||||
phone: '',
|
||||
role: Role.DELIVERY_PERSON
|
||||
},
|
||||
|
||||
// 错误信息
|
||||
errorMessage: '',
|
||||
successMessage: '',
|
||||
|
||||
// 搜索关键词
|
||||
searchKeyword: '',
|
||||
|
||||
// 角色选项
|
||||
roleOptions: getRoleOptions()
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 页面加载时获取员工列表
|
||||
this.loadEmployees();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 页面显示时刷新数据
|
||||
this.loadEmployees();
|
||||
},
|
||||
|
||||
/**
|
||||
* 加载员工列表
|
||||
*/
|
||||
async loadEmployees() {
|
||||
this.setData({
|
||||
loading: true,
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
|
||||
try {
|
||||
const employees = await employeeService.getEmployees();
|
||||
// 获取过滤后的员工列表
|
||||
const filteredEmployees = this.getFilteredEmployees(employees);
|
||||
|
||||
this.setData({
|
||||
employees,
|
||||
filteredEmployees,
|
||||
loading: false
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('加载员工列表失败:', error);
|
||||
this.setData({
|
||||
loading: false,
|
||||
errorMessage: '加载员工列表失败,请稍后重试'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换页面标签
|
||||
*/
|
||||
switchTab(e: any) {
|
||||
const tab = e.currentTarget.dataset.tab;
|
||||
this.setData({
|
||||
currentTab: tab,
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
|
||||
if (tab === 'list') {
|
||||
this.loadEmployees();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理添加员工表单输入
|
||||
*/
|
||||
onFormInput(e: any) {
|
||||
const { field } = e.currentTarget.dataset;
|
||||
const value = e.detail.value;
|
||||
|
||||
this.setData({
|
||||
[`addForm.${field}`]: value,
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理角色选择
|
||||
*/
|
||||
onRoleChange(e: any) {
|
||||
const index = e.detail.value;
|
||||
const selectedRole = this.data.roleOptions[index].value;
|
||||
this.setData({
|
||||
'addForm.role': selectedRole
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证表单数据
|
||||
*/
|
||||
validateForm(): boolean {
|
||||
const { name, phone, role } = this.data.addForm;
|
||||
|
||||
if (!name.trim()) {
|
||||
this.setData({
|
||||
errorMessage: '请输入员工姓名'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!phone.trim()) {
|
||||
this.setData({
|
||||
errorMessage: '请输入手机号'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 简单的手机号格式验证
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
if (!phoneRegex.test(phone)) {
|
||||
this.setData({
|
||||
errorMessage: '请输入正确的手机号格式'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!role) {
|
||||
this.setData({
|
||||
errorMessage: '请选择员工角色'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交添加员工表单
|
||||
*/
|
||||
async submitAddForm() {
|
||||
if (!this.validateForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
loading: true,
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
|
||||
try {
|
||||
await employeeService.addEmployee(this.data.addForm);
|
||||
|
||||
this.setData({
|
||||
loading: false,
|
||||
successMessage: '员工添加成功',
|
||||
addForm: {
|
||||
name: '',
|
||||
phone: '',
|
||||
role: Role.DELIVERY_PERSON
|
||||
}
|
||||
});
|
||||
|
||||
// 添加成功后自动切换到列表页
|
||||
setTimeout(() => {
|
||||
this.setData({
|
||||
currentTab: 'list'
|
||||
});
|
||||
this.loadEmployees();
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
console.error('添加员工失败:', error);
|
||||
this.setData({
|
||||
loading: false,
|
||||
errorMessage: (error as Error).message || '添加员工失败,请稍后重试'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除员工
|
||||
*/
|
||||
async deleteEmployee(e: any) {
|
||||
const employeeId = e.currentTarget.dataset.id;
|
||||
const employee = this.data.employees.find(emp => emp.id === employeeId);
|
||||
|
||||
if (!employee) {
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showModal({
|
||||
title: '确认删除',
|
||||
content: `确定要删除员工 ${employee.name} (${employee.phone}) 吗?此操作不可恢复。`,
|
||||
confirmText: '删除',
|
||||
confirmColor: '#ff4d4f',
|
||||
cancelText: '取消',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
this.setData({
|
||||
loading: true,
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await employeeService.deleteEmployee(employeeId);
|
||||
|
||||
if (result.success) {
|
||||
this.setData({
|
||||
loading: false,
|
||||
successMessage: result.message || '员工删除成功'
|
||||
});
|
||||
|
||||
// 重新加载员工列表
|
||||
this.loadEmployees();
|
||||
} else {
|
||||
this.setData({
|
||||
loading: false,
|
||||
errorMessage: result.message || '删除员工失败'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除员工失败:', error);
|
||||
this.setData({
|
||||
loading: false,
|
||||
errorMessage: '删除员工失败,请稍后重试'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 搜索员工
|
||||
*/
|
||||
onSearchInput(e: any) {
|
||||
const keyword = e.detail.value;
|
||||
this.setData({
|
||||
searchKeyword: keyword
|
||||
});
|
||||
|
||||
// 更新过滤后的员工列表
|
||||
this.updateFilteredEmployees();
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新过滤后的员工列表
|
||||
*/
|
||||
updateFilteredEmployees() {
|
||||
const { employees } = this.data;
|
||||
const filteredEmployees = this.getFilteredEmployees(employees);
|
||||
this.setData({
|
||||
filteredEmployees
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取过滤后的员工列表
|
||||
*/
|
||||
getFilteredEmployees(employees?: EmployeeInfo[]): EmployeeInfo[] {
|
||||
const { searchKeyword } = this.data;
|
||||
|
||||
// 如果employees为空,返回空数组
|
||||
if (!employees || !Array.isArray(employees)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 获取当前登录用户信息
|
||||
const app = getApp();
|
||||
const currentUser = app.globalData.userInfo;
|
||||
|
||||
// 过滤掉当前登录用户
|
||||
let filteredEmployees = employees.filter(emp => {
|
||||
// 如果没有当前用户信息,显示所有员工
|
||||
if (!currentUser || !currentUser.id) {
|
||||
return true;
|
||||
}
|
||||
// 过滤掉当前用户
|
||||
return emp.id !== currentUser.id;
|
||||
});
|
||||
|
||||
// 更严格的搜索关键词检查
|
||||
if (!searchKeyword || typeof searchKeyword !== 'string' || !searchKeyword.trim()) {
|
||||
return filteredEmployees;
|
||||
}
|
||||
|
||||
const keyword = searchKeyword.toLowerCase();
|
||||
return filteredEmployees.filter(emp =>
|
||||
emp.name.toLowerCase().includes(keyword) ||
|
||||
emp.phone.includes(keyword) ||
|
||||
(emp.role || '').toLowerCase().includes(keyword)
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取角色显示文本
|
||||
*/
|
||||
getRoleText(role: string): string {
|
||||
const roleMap: Record<string, string> = {
|
||||
'DELIVERY_PERSON': '配送员',
|
||||
'ADMIN': '管理员'
|
||||
};
|
||||
return roleMap[role] || role;
|
||||
},
|
||||
|
||||
/**
|
||||
* 清空消息
|
||||
*/
|
||||
clearMessages() {
|
||||
this.setData({
|
||||
errorMessage: '',
|
||||
successMessage: ''
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回上一页
|
||||
*/
|
||||
goBack() {
|
||||
wx.navigateBack();
|
||||
}
|
||||
});
|
||||
166
miniprogram/pages/employee/employee.wxml
Normal file
166
miniprogram/pages/employee/employee.wxml
Normal file
@@ -0,0 +1,166 @@
|
||||
<!-- 员工管理页面 -->
|
||||
<view class="employee-container">
|
||||
<!-- 顶部导航栏 -->
|
||||
<view class="top-nav">
|
||||
<view class="nav-left">
|
||||
<text class="back-btn" bindtap="goBack">←</text>
|
||||
<text class="nav-title">员工管理</text>
|
||||
</view>
|
||||
<view class="nav-right">
|
||||
<text class="nav-count">共{{filteredEmployees.length}}名员工</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 页面标签 -->
|
||||
<view class="page-tabs">
|
||||
<view
|
||||
class="tab-item {{currentTab === 'list' ? 'active' : ''}}"
|
||||
bindtap="switchTab"
|
||||
data-tab="list"
|
||||
>
|
||||
<text class="tab-text">员工列表</text>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item {{currentTab === 'add' ? 'active' : ''}}"
|
||||
bindtap="switchTab"
|
||||
data-tab="add"
|
||||
>
|
||||
<text class="tab-text">添加员工</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消息提示 -->
|
||||
<view class="message-container">
|
||||
<view wx:if="{{errorMessage}}" class="error-message">
|
||||
<text class="message-text">{{errorMessage}}</text>
|
||||
<text class="close-btn" bindtap="clearMessages">×</text>
|
||||
</view>
|
||||
<view wx:if="{{successMessage}}" class="success-message">
|
||||
<text class="message-text">{{successMessage}}</text>
|
||||
<text class="close-btn" bindtap="clearMessages">×</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view wx:if="{{loading}}" class="loading-container">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 员工列表页面 -->
|
||||
<view wx:if="{{currentTab === 'list'}}" class="list-container">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-container">
|
||||
<view class="search-input-wrapper">
|
||||
<input
|
||||
class="search-input"
|
||||
placeholder="搜索员工姓名、手机号或角色"
|
||||
bindinput="onSearchInput"
|
||||
value="{{searchKeyword}}"
|
||||
/>
|
||||
<text class="search-icon">🔎</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 员工列表 -->
|
||||
<scroll-view class="employee-list" scroll-y>
|
||||
<view wx:for="{{filteredEmployees}}" wx:key="id" class="employee-item">
|
||||
<view class="employee-info">
|
||||
<view class="employee-avatar">
|
||||
<text class="avatar-text">{{item.name.charAt(0)}}</text>
|
||||
</view>
|
||||
<view class="employee-details">
|
||||
<view class="employee-name-row">
|
||||
<text class="employee-name">{{item.name}}</text>
|
||||
<text class="employee-role {{item.role === 'ADMIN' ? 'admin-role' : ''}}">
|
||||
<text class="role-icon">{{item.role === 'ADMIN' ? '👑' : '🚚'}}</text>
|
||||
{{getRoleText(item.role)}}
|
||||
</text>
|
||||
</view>
|
||||
<text class="employee-phone">{{item.phone}}</text>
|
||||
<text class="employee-id">ID: {{item.id}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="employee-actions">
|
||||
<button
|
||||
class="delete-btn"
|
||||
bindtap="deleteEmployee"
|
||||
data-id="{{item.id}}"
|
||||
size="mini"
|
||||
>
|
||||
删除
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view wx:if="{{filteredEmployees.length === 0}}" class="empty-state">
|
||||
<text class="empty-icon">👥</text>
|
||||
<text class="empty-text">
|
||||
{{searchKeyword ? '没有找到匹配的员工' : '暂无员工数据'}}
|
||||
</text>
|
||||
<text wx:if="{{!searchKeyword}}" class="empty-hint">点击右上角"添加员工"开始管理</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 添加员工页面 -->
|
||||
<view wx:if="{{currentTab === 'add'}}" class="add-container">
|
||||
<view class="form-container">
|
||||
<view class="form-item">
|
||||
<text class="form-label">员工姓名</text>
|
||||
<input
|
||||
class="form-input"
|
||||
placeholder="请输入员工姓名"
|
||||
value="{{addForm.name}}"
|
||||
bindinput="onFormInput"
|
||||
data-field="name"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="form-label">手机号码</text>
|
||||
<input
|
||||
class="form-input"
|
||||
placeholder="请输入手机号码"
|
||||
type="number"
|
||||
value="{{addForm.phone}}"
|
||||
bindinput="onFormInput"
|
||||
data-field="phone"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="form-label">员工角色</text>
|
||||
<picker
|
||||
class="form-picker"
|
||||
bindchange="onRoleChange"
|
||||
value="{{addForm.role}}"
|
||||
range="{{roleOptions}}"
|
||||
range-key="label"
|
||||
>
|
||||
<view class="picker-display">
|
||||
<text class="picker-text">
|
||||
{{addForm.role === 'ADMIN' ? '管理员' : addForm.role === 'DELIVERY_PERSON' ? '配送员' : '请选择角色'}}
|
||||
</text>
|
||||
<text class="picker-arrow">▼</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<view class="form-hint">
|
||||
<text class="hint-text">
|
||||
提示:添加员工后,用户可以使用该员工的姓名和手机号进行注册
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="submit-btn"
|
||||
bindtap="submitAddForm"
|
||||
disabled="{{loading}}"
|
||||
>
|
||||
{{loading ? '添加中...' : '添加员工'}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
485
miniprogram/pages/employee/employee.wxss
Normal file
485
miniprogram/pages/employee/employee.wxss
Normal file
@@ -0,0 +1,485 @@
|
||||
/* 员工管理页面样式 */
|
||||
.employee-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-nav {
|
||||
height: 90rpx;
|
||||
background-color: #1aad19;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
font-size: 28rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* 页面标签 */
|
||||
.page-tabs {
|
||||
height: 80rpx;
|
||||
background-color: white;
|
||||
display: flex;
|
||||
border-bottom: 1rpx solid #e0e0e0;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
border-bottom: 4rpx solid transparent;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #1aad19;
|
||||
border-bottom-color: #1aad19;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
/* 消息提示 */
|
||||
.message-container {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.error-message, .success-message {
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #fff2f0;
|
||||
color: #ff4d4f;
|
||||
border: 1rpx solid #ffccc7;
|
||||
}
|
||||
|
||||
.success-message {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
border: 1rpx solid #b7eb8f;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
font-size: 36rpx;
|
||||
cursor: pointer;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.loading-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border: 4rpx solid #f3f3f3;
|
||||
border-top: 4rpx solid #1aad19;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 列表容器 */
|
||||
.list-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 60rpx; /* 添加底部边距,避免内容被底部遮挡 */
|
||||
}
|
||||
|
||||
/* 搜索框 */
|
||||
.search-container {
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(135deg, #ffffff, #fafafa);
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 2rpx 15rpx rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.search-input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
background: linear-gradient(135deg, #f8f9fa, #f1f3f4);
|
||||
border-radius: 40rpx;
|
||||
padding: 0 80rpx 0 35rpx;
|
||||
font-size: 30rpx;
|
||||
border: 2rpx solid transparent;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
border-color: #1aad19;
|
||||
background: linear-gradient(135deg, #ffffff, #f8f9fa);
|
||||
box-shadow: 0 6rpx 25rpx rgba(26, 173, 25, 0.15);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
right: 35rpx;
|
||||
font-size: 36rpx;
|
||||
color: #1aad19;
|
||||
filter: drop-shadow(0 2rpx 4rpx rgba(26, 173, 25, 0.3));
|
||||
}
|
||||
|
||||
/* 员工列表 */
|
||||
.employee-list {
|
||||
flex: 1;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.employee-item {
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
||||
border-radius: 20rpx;
|
||||
padding: 35rpx;
|
||||
margin: 25rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.08);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.8);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.employee-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4rpx;
|
||||
background: linear-gradient(90deg, #1aad19, #52c41a);
|
||||
}
|
||||
|
||||
.employee-item:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.employee-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.employee-avatar {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #1aad19, #52c41a);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 25rpx;
|
||||
box-shadow: 0 4rpx 15rpx rgba(26, 173, 25, 0.3);
|
||||
border: 3rpx solid rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
color: white;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.employee-details {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.employee-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.employee-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
letter-spacing: 0.5rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 200rpx;
|
||||
}
|
||||
|
||||
.employee-role {
|
||||
font-size: 24rpx;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(135deg, #f0f2f5, #e8ecef);
|
||||
color: #595959;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.role-icon {
|
||||
font-size: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.employee-role.admin-role {
|
||||
background: linear-gradient(135deg, #fff7e6, #ffe7ba);
|
||||
color: #d46b08;
|
||||
border: 1rpx solid rgba(250, 140, 22, 0.2);
|
||||
}
|
||||
|
||||
.employee-phone {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.employee-phone::before {
|
||||
content: '📱';
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.employee-id {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.employee-id::before {
|
||||
content: '🆔';
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.employee-actions {
|
||||
margin-left: 25rpx;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7875);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 25rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 77, 79, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.delete-btn:active {
|
||||
background: linear-gradient(135deg, #d9363e, #ff7875);
|
||||
transform: translateY(1rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(255, 77, 79, 0.2);
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 120rpx 30rpx;
|
||||
color: #999;
|
||||
background: linear-gradient(135deg, #fafafa, #f5f5f5);
|
||||
border-radius: 25rpx;
|
||||
margin: 30rpx;
|
||||
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.05);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
display: block;
|
||||
margin-bottom: 25rpx;
|
||||
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 36rpx;
|
||||
display: block;
|
||||
margin-bottom: 15rpx;
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 30rpx;
|
||||
opacity: 0.8;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 添加容器 */
|
||||
.add-container {
|
||||
flex: 1;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: white;
|
||||
border-radius: 15rpx;
|
||||
padding: 40rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 15rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #e0e0e0;
|
||||
border-radius: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: #1aad19;
|
||||
}
|
||||
|
||||
.form-picker {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #e0e0e0;
|
||||
border-radius: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-display {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.picker-arrow {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
background-color: #f6ffed;
|
||||
border: 1rpx solid #b7eb8f;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
font-size: 26rpx;
|
||||
color: #52c41a;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #1aad19;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.submit-btn:active {
|
||||
background-color: #179b16;
|
||||
}
|
||||
|
||||
.submit-btn:disabled {
|
||||
background-color: #ccc;
|
||||
color: #999;
|
||||
}
|
||||
@@ -149,25 +149,68 @@ page {
|
||||
|
||||
/* 控制按钮样式统一 */
|
||||
.control-btn.signin-btn,
|
||||
.control-btn.register-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
.control-btn.register-btn,
|
||||
.control-btn.sign-out-btn,
|
||||
.control-btn.auth-btn,
|
||||
.control-btn.location-btn,
|
||||
.control-btn.reset-btn,
|
||||
.control-btn.staff-management-btn {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 6rpx 30rpx rgba(0, 0, 0, 0.2);
|
||||
font-size: 24rpx;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 按钮图标样式 */
|
||||
.btn-icon {
|
||||
font-size: 40rpx;
|
||||
margin-bottom: 8rpx;
|
||||
display: block;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* 按钮文字样式 */
|
||||
.btn-text {
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.control-btn.signin-btn:active,
|
||||
.control-btn.register-btn:active {
|
||||
.control-btn.register-btn:active,
|
||||
.control-btn.sign-out-btn:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 所有按钮点击状态 */
|
||||
.control-btn.signin-btn:active,
|
||||
.control-btn.register-btn:active,
|
||||
.control-btn.auth-btn:active,
|
||||
.control-btn.sign-out-btn:active,
|
||||
.control-btn.location-btn:active,
|
||||
.control-btn.reset-btn:active,
|
||||
.control-btn.staff-management-btn:active {
|
||||
background: rgba(240, 240, 240, 0.9);
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-signin {
|
||||
background-color: #1aad19;
|
||||
color: white;
|
||||
|
||||
@@ -1,61 +1,64 @@
|
||||
// index.ts
|
||||
|
||||
// 引入服务和工具函数
|
||||
import { UserInfo, Marker } from '../../types';
|
||||
import { showToast } from '../../utils/helpers';
|
||||
import userService from '../../services/userService';
|
||||
import locationTrackingService from '../../services/locationTrackingService';
|
||||
|
||||
// 引入模块
|
||||
// 引入主页面模块
|
||||
import { MainPageModule } from './modules/mainPageModule';
|
||||
|
||||
// 主页面组件
|
||||
Component({
|
||||
// 主页面组件接口定义
|
||||
interface IndexPageComponent {
|
||||
data: {
|
||||
// 地图中心点坐标
|
||||
longitude: 102.833722,
|
||||
latitude: 24.880095,
|
||||
scale: 13, // 地图缩放级别
|
||||
markers: [] as Marker[], // 地图标记点数组
|
||||
userInfo: null as UserInfo | null, // 用户信息
|
||||
// 用户认证状态(分离外部登录状态和用户二级状态)
|
||||
authStatus: {
|
||||
hasWxCode: false, // 是否已获取微信code(外部登录状态)
|
||||
userStatus: 'unknown' as 'unknown' | 'registered' | 'unregistered' | 'signed_in' | 'signed_out', // 用户二级状态
|
||||
},
|
||||
showUserPanel: false, // 是否显示用户信息面板
|
||||
showOrderPanel: false, // 是否显示订单详情面板
|
||||
currentOrder: null as any, // 当前选中的订单
|
||||
currentDeliveryPerson: null as any, // 当前选中的货运人员
|
||||
currentWarehouse: null as any, // 当前选中的仓库
|
||||
currentPanelPosition: { x: 0, y: 0 }, // 当前信息面板位置
|
||||
polyline: null as any, // 路线规划结果
|
||||
pendingOrders: [] as any[] ,// 待分配订单
|
||||
currentRoute: null as any, // 当前路线信息
|
||||
showRoute: false, // 是否显示路线
|
||||
routeDistance: 0, // 路线距离
|
||||
routeDuration: 0, // 路线预计时间
|
||||
|
||||
// 底部弹窗相关状态
|
||||
showWarehouseModal: false, // 仓库底部弹窗
|
||||
showDeliveryPersonModal: false, // 货运人员底部弹窗
|
||||
// 底部弹窗状态(bottom或full)
|
||||
warehouseModalState: 'bottom',
|
||||
deliveryPersonModalState: 'bottom',
|
||||
// 操作按钮显示状态(基于用户状态动态计算)
|
||||
mainPageModule: MainPageModule | null;
|
||||
// 核心UI状态
|
||||
showUserPanel: boolean;
|
||||
showOrderPanel: boolean;
|
||||
showDeliveryPersonModal: boolean;
|
||||
showWarehouseModal: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
showSignOutButton: false // 是否显示签退按钮
|
||||
// 主页面组件
|
||||
Component<IndexPageComponent>({
|
||||
data: {
|
||||
mainPageModule: null as MainPageModule | null,
|
||||
// 核心UI状态
|
||||
showUserPanel: false,
|
||||
showOrderPanel: false,
|
||||
showDeliveryPersonModal: false,
|
||||
showWarehouseModal: false
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
async attached() {
|
||||
// 组件挂载时初始化
|
||||
await this.initPage();
|
||||
attached() {
|
||||
console.log('index page attached');
|
||||
this.initPage();
|
||||
},
|
||||
|
||||
detached() {
|
||||
console.log('index page detached');
|
||||
// 清理资源
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.cleanup();
|
||||
}
|
||||
},
|
||||
|
||||
detached() {
|
||||
// 组件卸载时清理
|
||||
(this as any).mainPageModule = null;
|
||||
show() {
|
||||
console.log('index page show');
|
||||
// 页面显示时调用主页面模块的onShow方法
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.onShow();
|
||||
}
|
||||
},
|
||||
|
||||
hide() {
|
||||
console.log('index page hide');
|
||||
// 页面隐藏时调用主页面模块的onHide方法
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.onHide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -82,11 +85,14 @@ Component({
|
||||
const app = getApp<any>();
|
||||
|
||||
// 初始化主页面模块
|
||||
(this as any).mainPageModule = new MainPageModule(this);
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
this.setData({
|
||||
mainPageModule: new MainPageModule(this)
|
||||
});
|
||||
|
||||
// 设置globalData中的loginModule引用,用于废弃方法的重定向
|
||||
app.globalData.loginModule = loginModule;
|
||||
if (this.data.mainPageModule) {
|
||||
app.globalData.loginModule = this.data.mainPageModule.getLoginModule();
|
||||
}
|
||||
|
||||
// 异步检查登录状态
|
||||
await this.checkAndUpdateLoginStatus();
|
||||
@@ -95,9 +101,14 @@ Component({
|
||||
// 异步检查并更新登录状态
|
||||
async checkAndUpdateLoginStatus() {
|
||||
const app = getApp<any>();
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
|
||||
try {
|
||||
// 获取登录模块
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
// 显示加载状态
|
||||
wx.showLoading({
|
||||
title: '检查登录状态...',
|
||||
@@ -108,21 +119,8 @@ Component({
|
||||
const isLoggedIn = await this.asyncCheckLoginStatus(loginModule);
|
||||
|
||||
if (isLoggedIn) {
|
||||
// 已登录状态
|
||||
const userStatus = await loginModule.determineUserStatus(app.globalData.userInfo);
|
||||
this.setData({
|
||||
userInfo: app.globalData.userInfo,
|
||||
'authStatus.hasWxCode': true,
|
||||
'authStatus.userStatus': userStatus,
|
||||
// 初始化按钮显示状态
|
||||
showSignInButton: loginModule.shouldShowSignInButton(),
|
||||
showRegisterButton: loginModule.shouldShowRegisterButton(),
|
||||
showAuthButton: false
|
||||
});
|
||||
|
||||
// === 全局登录流程完成,登录成功 ===
|
||||
// 统一在此处执行一次完整的页面刷新
|
||||
this.refreshPageAfterLogin();
|
||||
// 已登录状态 - 按钮状态会在refreshPageAfterLogin中统一更新
|
||||
console.log('✅ 登录检查成功,等待统一页面刷新');
|
||||
} else {
|
||||
// 未登录状态
|
||||
this.setData({
|
||||
@@ -173,6 +171,9 @@ Component({
|
||||
|
||||
console.log('✅ 使用本地登录状态,用户状态已更新:', userStatus);
|
||||
|
||||
// 登录成功后统一刷新页面
|
||||
this.refreshPageAfterLogin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -213,19 +214,24 @@ Component({
|
||||
|
||||
// 更新按钮显示状态
|
||||
updateButtonDisplayStatus() {
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
const showSignInButton = loginModule.shouldShowSignInButton();
|
||||
const showRegisterButton = loginModule.shouldShowRegisterButton();
|
||||
|
||||
// 签退按钮显示逻辑:已签到用户显示签退按钮
|
||||
const showSignOutButton = this.data.authStatus.userStatus === 'signed_in';
|
||||
const showSignOutButton = this.data.authStatus && this.data.authStatus.userStatus === 'signed_in';
|
||||
|
||||
console.log('🔄 更新按钮显示状态:');
|
||||
console.log(' - showSignInButton:', showSignInButton);
|
||||
console.log(' - showRegisterButton:', showRegisterButton);
|
||||
console.log(' - showSignOutButton:', showSignOutButton);
|
||||
console.log(' - 当前用户状态:', this.data.authStatus.userStatus);
|
||||
console.log(' - 当前hasWxCode:', this.data.authStatus.hasWxCode);
|
||||
console.log(' - 当前用户状态:', this.data.authStatus ? this.data.authStatus.userStatus : 'undefined');
|
||||
console.log(' - 当前hasWxCode:', this.data.authStatus ? this.data.authStatus.hasWxCode : 'undefined');
|
||||
|
||||
this.setData({
|
||||
showSignInButton,
|
||||
@@ -238,7 +244,12 @@ Component({
|
||||
|
||||
// 登录成功后统一刷新页面
|
||||
async refreshPageAfterLogin() {
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
const app = getApp<any>();
|
||||
|
||||
console.log('🔄 === 全局登录流程完成,执行统一页面刷新 ===');
|
||||
@@ -250,13 +261,14 @@ Component({
|
||||
this.updateButtonDisplayStatus();
|
||||
|
||||
// 3. 初始化主页面模块
|
||||
await (this as any).mainPageModule.onLoad();
|
||||
await this.data.mainPageModule.onLoad();
|
||||
|
||||
// 4. 登录成功后主动加载业务数据(仓库、订单等)
|
||||
// 4. 登录成功后只加载公开数据(仓库等),不加载业务数据
|
||||
// 业务数据(员工位置等)只有在用户签到后才应该加载
|
||||
if (app.globalData.isLoggedIn) {
|
||||
console.log('🔍 登录成功,开始加载业务数据...');
|
||||
await (this as any).mainPageModule.refreshAllData();
|
||||
console.log('✅ 业务数据加载完成');
|
||||
console.log('🔍 登录成功,开始加载公开数据...');
|
||||
await this.data.mainPageModule.loadPublicData();
|
||||
console.log('✅ 公开数据加载完成');
|
||||
}
|
||||
|
||||
console.log('✅ 统一页面刷新完成');
|
||||
@@ -278,7 +290,12 @@ Component({
|
||||
|
||||
// 处理签到 - 已迁移到LoginModule
|
||||
async handleSignIn() {
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
const success = await loginModule.handleSignIn();
|
||||
|
||||
if (success) {
|
||||
@@ -286,18 +303,22 @@ Component({
|
||||
this.updateButtonDisplayStatus();
|
||||
|
||||
// 刷新页面数据
|
||||
await (this as any).mainPageModule.refreshAllData();
|
||||
await this.data.mainPageModule.refreshAllData();
|
||||
}
|
||||
},
|
||||
|
||||
// 处理授权登录 - 已迁移到LoginModule
|
||||
async handleAuthLogin() {
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
const success = await loginModule.handleAuthLogin();
|
||||
|
||||
if (success) {
|
||||
const app = getApp<any>();
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
const userStatus = loginModule.determineUserStatus(app.globalData.userInfo);
|
||||
this.setData({
|
||||
userInfo: app.globalData.userInfo,
|
||||
@@ -323,7 +344,11 @@ Component({
|
||||
});
|
||||
|
||||
// 调用loginModule的logout方法
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (!this.data.mainPageModule) {
|
||||
console.error('mainPageModule未初始化');
|
||||
return;
|
||||
}
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
await loginModule.logout();
|
||||
|
||||
// 更新页面状态
|
||||
@@ -364,10 +389,18 @@ Component({
|
||||
console.warn('调试信息 - 停止位置追踪失败:', trackingError);
|
||||
}
|
||||
|
||||
// 清除登录信息,防止自动重新登录
|
||||
console.log('调试信息 - 开始清除登录信息');
|
||||
const app = getApp<any>();
|
||||
app.doGlobalLogout();
|
||||
// 停止位置模块的实时跟踪
|
||||
try {
|
||||
if (this.data.mainPageModule) {
|
||||
const locationModule = this.data.mainPageModule.getLocationModule();
|
||||
if (locationModule) {
|
||||
await locationModule.stopRealTimeTracking();
|
||||
console.log('调试信息 - 位置模块实时跟踪已停止');
|
||||
}
|
||||
}
|
||||
} catch (trackingError) {
|
||||
console.warn('调试信息 - 停止位置模块实时跟踪失败:', trackingError);
|
||||
}
|
||||
|
||||
// 保存签退状态到本地存储,防止自动重新登录
|
||||
console.log('调试信息 - 保存签退状态到本地存储');
|
||||
@@ -377,13 +410,25 @@ Component({
|
||||
const savedStatus = wx.getStorageSync('userStatus');
|
||||
console.log('调试信息 - 验证保存的签退状态:', savedStatus);
|
||||
|
||||
// 更新用户状态为已签退
|
||||
// 更新用户状态为已签退(不调用doGlobalLogout,保持登录状态)
|
||||
this.setData({
|
||||
'authStatus.userStatus': 'signed_out',
|
||||
showSignOutButton: false,
|
||||
showSignInButton: true
|
||||
});
|
||||
|
||||
// 清除所有员工图标
|
||||
if (this.data.mainPageModule) {
|
||||
const employeeModule = this.data.mainPageModule.getEmployeeModule();
|
||||
if (employeeModule) {
|
||||
// 清除员工标记点
|
||||
const { markers } = this.data;
|
||||
const filteredMarkers = markers.filter((marker: any) => marker.type !== 'employee');
|
||||
this.setData({ markers: filteredMarkers });
|
||||
console.log('调试信息 - 已清除所有员工图标');
|
||||
}
|
||||
}
|
||||
|
||||
wx.hideLoading();
|
||||
showToast('签退成功');
|
||||
console.log('调试信息 - 用户签退完成');
|
||||
@@ -401,9 +446,25 @@ Component({
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到管理员页面
|
||||
goToAdminPage() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/admin/admin'
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到员工管理页面
|
||||
goToEmployeeManagement() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/employee/employee'
|
||||
});
|
||||
},
|
||||
|
||||
// 阻止事件冒泡
|
||||
stopPropagation(e: any) {
|
||||
e.stopPropagation();
|
||||
if (e && typeof e.stopPropagation === 'function') {
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -422,8 +483,8 @@ Component({
|
||||
|
||||
// 用户登出
|
||||
userLogout() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const loginModule = (this as any).mainPageModule.getLoginModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const loginModule = this.data.mainPageModule.getLoginModule();
|
||||
loginModule.logout();
|
||||
|
||||
// 更新页面状态
|
||||
@@ -449,91 +510,91 @@ Component({
|
||||
|
||||
// 隐藏所有面板
|
||||
hideAllPanels() {
|
||||
if ((this as any).mainPageModule) {
|
||||
(this as any).mainPageModule.hideAllPanels();
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.hideAllPanels();
|
||||
}
|
||||
},
|
||||
|
||||
// 重置标记点状态
|
||||
resetMarkers() {
|
||||
if ((this as any).mainPageModule) {
|
||||
(this as any).mainPageModule.resetMarkers();
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.resetMarkers();
|
||||
}
|
||||
},
|
||||
|
||||
// 地图点击事件
|
||||
onMapTap(e: any) {
|
||||
if ((this as any).mainPageModule) {
|
||||
(this as any).mainPageModule.onMapTap(e);
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.onMapTap(e);
|
||||
}
|
||||
},
|
||||
|
||||
// 标记点点击事件
|
||||
onMarkerTap(e: any) {
|
||||
if ((this as any).mainPageModule) {
|
||||
(this as any).mainPageModule.onMarkerTap(e);
|
||||
if (this.data.mainPageModule) {
|
||||
this.data.mainPageModule.onMarkerTap(e);
|
||||
}
|
||||
},
|
||||
|
||||
// 分配订单
|
||||
async assignOrder(orderId: number, deliveryPersonId: number) {
|
||||
if ((this as any).mainPageModule) {
|
||||
const orderModule = (this as any).mainPageModule.getOrderModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const orderModule = this.data.mainPageModule.getOrderModule();
|
||||
await orderModule.assignOrder(orderId, deliveryPersonId);
|
||||
}
|
||||
},
|
||||
|
||||
// 更新订单状态
|
||||
async updateOrderStatus(orderId: number, status: 'pending' | 'assigned' | 'in_transit' | 'delivered') {
|
||||
if ((this as any).mainPageModule) {
|
||||
const orderModule = (this as any).mainPageModule.getOrderModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const orderModule = this.data.mainPageModule.getOrderModule();
|
||||
await orderModule.updateOrderStatus(orderId, status);
|
||||
}
|
||||
},
|
||||
|
||||
// 展开仓库面板
|
||||
expandWarehousePanel() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const warehouseModule = (this as any).mainPageModule.getWarehouseModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const warehouseModule = this.data.mainPageModule.getWarehouseModule();
|
||||
warehouseModule.expandWarehousePanel();
|
||||
}
|
||||
},
|
||||
|
||||
// 收起仓库面板
|
||||
collapseWarehousePanel() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const warehouseModule = (this as any).mainPageModule.getWarehouseModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const warehouseModule = this.data.mainPageModule.getWarehouseModule();
|
||||
warehouseModule.collapseWarehousePanel();
|
||||
}
|
||||
},
|
||||
|
||||
// 展开货运人员面板
|
||||
// 展开员工面板
|
||||
expandDeliveryPersonPanel() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const deliveryPersonModule = (this as any).mainPageModule.getDeliveryPersonModule();
|
||||
deliveryPersonModule.expandDeliveryPersonPanel();
|
||||
if (this.data.mainPageModule) {
|
||||
const employeeModule = this.data.mainPageModule.getEmployeeModule();
|
||||
employeeModule.expandDeliveryPersonPanel();
|
||||
}
|
||||
},
|
||||
|
||||
// 收起货运人员面板
|
||||
// 收起员工面板
|
||||
collapseDeliveryPersonPanel() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const deliveryPersonModule = (this as any).mainPageModule.getDeliveryPersonModule();
|
||||
deliveryPersonModule.collapseDeliveryPersonPanel();
|
||||
if (this.data.mainPageModule) {
|
||||
const employeeModule = this.data.mainPageModule.getEmployeeModule();
|
||||
employeeModule.collapseDeliveryPersonPanel();
|
||||
}
|
||||
},
|
||||
|
||||
// 刷新所有数据
|
||||
async refreshAllData() {
|
||||
if ((this as any).mainPageModule) {
|
||||
await (this as any).mainPageModule.refreshAllData();
|
||||
if (this.data.mainPageModule) {
|
||||
await this.data.mainPageModule.refreshAllData();
|
||||
}
|
||||
},
|
||||
|
||||
// 开始定位(处理地图控制按钮点击)
|
||||
async startLocation() {
|
||||
if ((this as any).mainPageModule) {
|
||||
const mapModule = (this as any).mainPageModule.getMapModule();
|
||||
if (this.data.mainPageModule) {
|
||||
const mapModule = this.data.mainPageModule.getMapModule();
|
||||
await mapModule.startLocation();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
type="primary"
|
||||
size="mini"
|
||||
>
|
||||
签到
|
||||
<text class="btn-icon">✅</text>
|
||||
<text class="btn-text">签到</text>
|
||||
</button>
|
||||
|
||||
<!-- 注册按钮 - 游客用户 -->
|
||||
@@ -37,7 +38,8 @@
|
||||
type="default"
|
||||
size="mini"
|
||||
>
|
||||
注册
|
||||
<text class="btn-icon">📝</text>
|
||||
<text class="btn-text">注册</text>
|
||||
</button>
|
||||
|
||||
<!-- 授权登录按钮 - 未授权用户 -->
|
||||
@@ -48,7 +50,8 @@
|
||||
type="warn"
|
||||
size="mini"
|
||||
>
|
||||
登录
|
||||
<text class="btn-icon">🔑</text>
|
||||
<text class="btn-text">登录</text>
|
||||
</button>
|
||||
|
||||
<!-- 签退按钮 - 已签到用户 -->
|
||||
@@ -59,14 +62,16 @@
|
||||
type="warn"
|
||||
size="mini"
|
||||
>
|
||||
签退
|
||||
<text class="btn-icon">🚪</text>
|
||||
<text class="btn-text">签退</text>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 地图控制按钮 -->
|
||||
<view class="map-controls">
|
||||
<view class="control-btn location-btn" bindtap="startLocation">
|
||||
<image src="/images/ma.png" mode="aspectFit"></image>
|
||||
<text class="btn-icon">📍</text>
|
||||
<text class="btn-text">定位</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -74,11 +79,17 @@
|
||||
<view wx:if="{{authStatus.hasWxCode}}"
|
||||
class="control-btn reset-btn"
|
||||
bindtap="showUserPanel">
|
||||
<image
|
||||
src="/images/trucks.png"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<view wx:if="{{userInfo.role === 'ADMIN'}}" class="admin-badge">管理</view>
|
||||
<text class="btn-icon">👤</text>
|
||||
<text class="btn-text">我的</text>
|
||||
<view wx:if="{{userInfo.role === 'ADMIN'}}" class="admin-badge"/>
|
||||
</view>
|
||||
|
||||
<!-- 员工管理按钮(仅管理员可见) -->
|
||||
<view wx:if="{{authStatus.hasWxCode && userInfo.role === 'ADMIN'}}"
|
||||
class="control-btn staff-management-btn"
|
||||
bindtap="goToEmployeeManagement">
|
||||
<text class="btn-icon">👥</text>
|
||||
<text class="btn-text">员工</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -92,7 +103,7 @@
|
||||
<view class="user-panel-content" bindtap="stopPropagation">
|
||||
<view class="user-avatar">
|
||||
<image
|
||||
src="/images/user-avatar.png"
|
||||
src="/images/trucks.png"
|
||||
mode="aspectFill"
|
||||
class="avatar-image"
|
||||
></image>
|
||||
@@ -103,6 +114,7 @@
|
||||
<text class="user-id">ID: {{userInfo.id || '未获取'}}</text>
|
||||
<text class="user-phone">电话:{{userInfo.phone || '未设置'}}</text>
|
||||
<text class="user-role">角色:{{userInfo.role === 'ADMIN' ? '管理员' : '货运员'}}</text>
|
||||
|
||||
<!-- 退出后台代码 -->
|
||||
<button class="btn-logout" bindtap="handleLogout" size="mini">退出登录</button>
|
||||
</view>
|
||||
|
||||
@@ -88,6 +88,17 @@
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
/* 右侧控制按钮容器 */
|
||||
.right-controls-container {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 30rpx;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
@@ -1407,4 +1418,26 @@
|
||||
100% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
/* 员工管理按钮样式 */
|
||||
.staff-management-btn {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.staff-management-btn:active {
|
||||
background-color: #f5f5f5;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.staff-management-btn image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
@@ -14,11 +14,32 @@ export class DataModule {
|
||||
/**
|
||||
* 初始化页面数据
|
||||
*/
|
||||
public initializeData(): void {
|
||||
public async initializeData(): Promise<void> {
|
||||
// 检查是否已静默登录,如果是则尝试获取真实位置
|
||||
let initialLongitude = 102.833722;
|
||||
let initialLatitude = 24.880095;
|
||||
|
||||
const app = getApp<any>();
|
||||
if (app.globalData.isLoggedIn) {
|
||||
try {
|
||||
// 导入地图服务
|
||||
const mapService = require('../../../services/mapService').default;
|
||||
const location = await mapService.getCurrentLocation();
|
||||
|
||||
if (location && !isNaN(location.latitude) && !isNaN(location.longitude)) {
|
||||
initialLongitude = location.longitude;
|
||||
initialLatitude = location.latitude;
|
||||
console.log('[DATA MODULE] 静默登录后使用真实位置:', location);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[DATA MODULE] 获取真实位置失败,使用默认位置:', error);
|
||||
}
|
||||
}
|
||||
|
||||
this.pageContext.setData({
|
||||
// 地图相关数据
|
||||
longitude: 102.833722,
|
||||
latitude: 24.880095,
|
||||
longitude: initialLongitude,
|
||||
latitude: initialLatitude,
|
||||
scale: 13,
|
||||
markers: [] as Marker[],
|
||||
polyline: null,
|
||||
@@ -148,7 +169,7 @@ export class DataModule {
|
||||
*/
|
||||
public updateMarkers(markers: Marker[]): void {
|
||||
// 验证每个标记点的坐标
|
||||
const validatedMarkers = markers.map((marker, index) => {
|
||||
const validatedMarkers = markers.map((marker) => {
|
||||
// 检查经纬度是否为有效数字
|
||||
if (isNaN(marker.longitude) || isNaN(marker.latitude)) {
|
||||
// 为无效坐标设置默认值
|
||||
@@ -283,4 +304,26 @@ export class DataModule {
|
||||
public resetAllData(): void {
|
||||
this.initializeData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取位置模块(用于其他模块访问位置模块)
|
||||
*/
|
||||
public getLocationModule(): any {
|
||||
// 通过页面上下文获取位置模块
|
||||
if (this.pageContext.data.mainPageModule) {
|
||||
return this.pageContext.data.mainPageModule.getLocationModule();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地图模块(用于其他模块访问地图模块)
|
||||
*/
|
||||
public getMapModule(): any {
|
||||
// 通过页面上下文获取地图模块
|
||||
if (this.pageContext.data.mainPageModule) {
|
||||
return this.pageContext.data.mainPageModule.getMapModule();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
// 货运人员模块 - 处理货运人员管理、位置跟踪、交互
|
||||
import deliveryPersonService from '../../../services/deliveryPersonService';
|
||||
// 员工模块 - 处理所有员工(管理员和货运人员)管理、位置跟踪、交互
|
||||
import employeeService from '../../../services/employeeService';
|
||||
import { Role } from '../../../utils/roleUtils';
|
||||
// getApp是微信小程序全局函数,无需导入
|
||||
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import { DataModule } from './dataModule';
|
||||
|
||||
export class DeliveryPersonModule {
|
||||
export class EmployeeModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
|
||||
@@ -14,210 +16,44 @@ export class DeliveryPersonModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载货运人员数据
|
||||
* 加载所有员工数据(包括管理员和货运人员)
|
||||
*/
|
||||
async loadDeliveryPersons(): Promise<void> {
|
||||
async loadAllEmployees(): Promise<void> {
|
||||
try {
|
||||
const deliveryPersons = await deliveryPersonService.getDeliveryPersons();
|
||||
// 获取所有员工数据
|
||||
const allEmployees = await employeeService.getEmployees();
|
||||
|
||||
// 更新地图标记点
|
||||
this.updateDeliveryPersonMarkers(deliveryPersons);
|
||||
|
||||
console.log('货运人员数据加载完成,数量:', deliveryPersons.length);
|
||||
console.log('所有员工数据加载完成,数量:', allEmployees.length);
|
||||
} catch (error) {
|
||||
console.error('加载货运人员数据失败:', error);
|
||||
showToast('加载货运人员数据失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新货运人员位置
|
||||
*/
|
||||
async updateDeliveryPersonLocation(personId: number, location: { longitude: number, latitude: number }): Promise<void> {
|
||||
try {
|
||||
await deliveryPersonService.updateDeliveryPersonLocation(personId, location);
|
||||
|
||||
console.log(`货运人员 ${personId} 位置更新:`, location);
|
||||
|
||||
// 重新加载货运人员数据
|
||||
await this.loadDeliveryPersons();
|
||||
|
||||
} catch (error) {
|
||||
console.error('更新货运人员位置失败:', error);
|
||||
showToast('更新位置失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开始实时位置跟踪
|
||||
*/
|
||||
async startRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 使用新的WebSocket接口订阅位置更新
|
||||
await deliveryPersonService.subscribeToRealTimeLocations(userInfo.id);
|
||||
|
||||
// 设置位置更新回调
|
||||
deliveryPersonService.subscribeToRealTimeLocations(this.handleRealTimeLocationUpdate.bind(this));
|
||||
|
||||
showToast('开始实时跟踪');
|
||||
console.log('开始实时跟踪货运人员位置');
|
||||
} catch (error) {
|
||||
console.error('开始实时跟踪失败:', error);
|
||||
showToast('开始实时跟踪失败');
|
||||
console.error('加载员工数据失败:', error);
|
||||
showToast('加载员工数据失败');
|
||||
}
|
||||
}
|
||||
|
||||
handleRealTimeLocationUpdate(location: any): void {
|
||||
console.log('收到实时位置更新:', location);
|
||||
// 这里可以添加更新地图标记点的逻辑
|
||||
// 根据位置更新信息更新对应的货运人员标记点
|
||||
if (location && location.deliveryPersonId) {
|
||||
this.updateSingleDeliveryPersonMarker(location);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个货运人员标记点
|
||||
* 获取员工角色对应的图标
|
||||
*/
|
||||
private updateSingleDeliveryPersonMarker(location: any): void {
|
||||
const { markers } = this.pageContext.data;
|
||||
private getEmployeeIcon(role: string): string {
|
||||
console.log(`获取员工图标,角色: ${role}`);
|
||||
|
||||
// 查找并更新对应的货运人员标记点
|
||||
const updatedMarkers = markers.map((marker: any) => {
|
||||
if (marker.type === 'delivery_person' && marker.data && marker.data.id === location.deliveryPersonId) {
|
||||
// 更新标记点位置
|
||||
return {
|
||||
...marker,
|
||||
longitude: location.longitude,
|
||||
latitude: location.latitude,
|
||||
data: {
|
||||
...marker.data,
|
||||
currentLocation: {
|
||||
longitude: location.longitude,
|
||||
latitude: location.latitude
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
});
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止实时跟踪货运人员位置
|
||||
*/
|
||||
async stopRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 使用新的WebSocket接口取消订阅
|
||||
await deliveryPersonService.unsubscribeFromRealTimeLocations();
|
||||
|
||||
showToast('已停止实时跟踪');
|
||||
console.log('停止实时跟踪货运人员位置');
|
||||
} catch (error) {
|
||||
console.error('停止实时跟踪失败:', error);
|
||||
showToast('停止实时跟踪失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新货运人员标记点
|
||||
*/
|
||||
private updateDeliveryPersonMarkers(deliveryPersons: any[]): void {
|
||||
console.log(`[DELIVERY PERSON MODULE] 开始更新货运人员标记点,货运人员总数: ${deliveryPersons.length}`);
|
||||
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 移除现有的货运人员标记点
|
||||
const filteredMarkers = markers.filter((marker: any) => marker.type !== 'delivery_person');
|
||||
console.log(`[DELIVERY PERSON MODULE] 移除现有货运人员标记点后,剩余标记点数量: ${filteredMarkers.length}`);
|
||||
|
||||
// 添加新的货运人员标记点
|
||||
const deliveryPersonMarkers = deliveryPersons.map((person, index) => {
|
||||
// 验证货运人员坐标是否有效
|
||||
// 注意:坐标信息嵌套在currentLocation对象中
|
||||
let validLongitude = person.currentLocation?.longitude;
|
||||
let validLatitude = person.currentLocation?.latitude;
|
||||
|
||||
if (isNaN(validLongitude) || isNaN(validLatitude)) {
|
||||
console.error(`[DELIVERY PERSON MODULE] 货运人员${index} (ID: ${person.id}) 坐标无效: (${validLongitude}, ${validLatitude}),使用默认坐标`);
|
||||
validLongitude = 102.833722; // 默认经度
|
||||
validLatitude = 24.880095; // 默认纬度
|
||||
} else {
|
||||
console.log(`[DELIVERY PERSON MODULE] 货运人员${index} (ID: ${person.id}) 坐标有效: (${validLongitude}, ${validLatitude})`);
|
||||
}
|
||||
|
||||
const iconPath = this.getDeliveryPersonIcon(person.status);
|
||||
|
||||
return {
|
||||
id: 2000 + index, // 货运人员标记点ID从2000开始
|
||||
longitude: validLongitude,
|
||||
latitude: validLatitude,
|
||||
iconPath: iconPath,
|
||||
width: 26,
|
||||
height: 26,
|
||||
zIndex: 20,
|
||||
type: 'delivery_person',
|
||||
data: person
|
||||
};
|
||||
});
|
||||
|
||||
console.log(`[DELIVERY PERSON MODULE] 生成新货运人员标记点数量: ${deliveryPersonMarkers.length}`);
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
const allMarkers = [...filteredMarkers, ...deliveryPersonMarkers];
|
||||
console.log(`[DELIVERY PERSON MODULE] 准备更新所有标记点,总数: ${allMarkers.length}`);
|
||||
this.dataModule.updateMarkers(allMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员状态对应的图标
|
||||
*/
|
||||
private getDeliveryPersonIcon(status: string): string {
|
||||
console.log(`获取货运人员图标,状态: ${status}`);
|
||||
|
||||
// 根据报错信息,直接使用已知存在的备用图片路径
|
||||
// 实际项目中,应确保相关图片资源正确放置在指定路径
|
||||
const fallbackIconPath = '/images/trucks.png';
|
||||
|
||||
// 根据不同状态使用不同的图片路径
|
||||
// 根据角色使用不同的图标
|
||||
let iconPath = '';
|
||||
|
||||
switch (status) {
|
||||
case 'idle':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(idle状态)');
|
||||
switch (role) {
|
||||
case Role.ADMIN:
|
||||
// 管理员使用皇冠图标
|
||||
iconPath = '/images/crown.png';
|
||||
console.log('使用管理员图标(👑)');
|
||||
break;
|
||||
case 'busy':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(busy状态)');
|
||||
break;
|
||||
case 'offline':
|
||||
// 为避免图片加载失败,暂时使用备用图片
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(offline状态)');
|
||||
case Role.DELIVERY_PERSON:
|
||||
// 货运人员使用货车图标
|
||||
iconPath = '/images/truck.png';
|
||||
console.log('使用货运人员图标(🚚)');
|
||||
break;
|
||||
default:
|
||||
iconPath = fallbackIconPath;
|
||||
console.log('使用备用图标(默认状态)');
|
||||
// 默认使用货车图标
|
||||
iconPath = '/images/truck.png';
|
||||
console.log('使用默认图标(🚚)');
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
278
miniprogram/pages/index/modules/locationModule.ts
Normal file
278
miniprogram/pages/index/modules/locationModule.ts
Normal file
@@ -0,0 +1,278 @@
|
||||
// 位置模块 - 处理位置追踪、位置更新和地图标记点更新
|
||||
import { DataModule } from './dataModule';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
import locationTrackingService from '../../../services/locationTrackingService';
|
||||
import { OnlineUserInfo } from '../../../services/locationTrackingService';
|
||||
|
||||
// 位置模块接口定义
|
||||
export interface LocationModule {
|
||||
initialize(): Promise<void>;
|
||||
cleanup(): void;
|
||||
startRealTimeTracking(): Promise<void>;
|
||||
stopRealTimeTracking(): Promise<void>;
|
||||
updateEmployeeLocation(employeeId: number, location: { longitude: number, latitude: number }): Promise<void>;
|
||||
}
|
||||
|
||||
export class LocationModule {
|
||||
private pageContext: any;
|
||||
private dataModule: DataModule;
|
||||
private isTracking: boolean;
|
||||
|
||||
constructor(pageContext: any, dataModule: DataModule) {
|
||||
this.pageContext = pageContext;
|
||||
this.dataModule = dataModule;
|
||||
this.isTracking = false;
|
||||
|
||||
// 绑定回调方法
|
||||
this.handleLocationUpdates = this.handleLocationUpdates.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化位置模块
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
console.log('位置模块初始化');
|
||||
|
||||
// 订阅位置更新
|
||||
this.subscribeToLocationUpdates();
|
||||
|
||||
console.log('位置模块初始化完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理位置模块
|
||||
*/
|
||||
cleanup(): void {
|
||||
console.log('清理位置模块');
|
||||
|
||||
// 取消位置更新订阅
|
||||
this.unsubscribeFromLocationUpdates();
|
||||
|
||||
// 停止实时跟踪
|
||||
if (this.isTracking) {
|
||||
this.stopRealTimeTracking().catch(error => {
|
||||
console.error('停止实时跟踪失败:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始实时跟踪位置
|
||||
*/
|
||||
async startRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 启动位置跟踪订阅
|
||||
await locationTrackingService.startTrackingAfterSignIn();
|
||||
|
||||
this.isTracking = true;
|
||||
showToast('已开始实时跟踪');
|
||||
console.log('开始实时跟踪位置');
|
||||
} catch (error) {
|
||||
console.error('开始实时跟踪失败:', error);
|
||||
showToast('开始实时跟踪失败');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止实时跟踪位置
|
||||
*/
|
||||
async stopRealTimeTracking(): Promise<void> {
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (!userInfo || !userInfo.id) {
|
||||
throw new Error('用户信息获取失败');
|
||||
}
|
||||
|
||||
// 停止位置跟踪
|
||||
await locationTrackingService.stopTracking();
|
||||
|
||||
this.isTracking = false;
|
||||
showToast('已停止实时跟踪');
|
||||
console.log('停止实时跟踪位置');
|
||||
} catch (error) {
|
||||
console.error('停止实时跟踪失败:', error);
|
||||
showToast('停止实时跟踪失败');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新员工位置
|
||||
*/
|
||||
async updateEmployeeLocation(employeeId: number, location: { longitude: number, latitude: number }): Promise<void> {
|
||||
try {
|
||||
console.log(`员工 ${employeeId} 位置更新:`, location);
|
||||
|
||||
// 通过locationTrackingService更新位置
|
||||
await locationTrackingService.updateUserLocation(location);
|
||||
|
||||
console.log(`员工 ${employeeId} 位置更新完成`);
|
||||
} catch (error) {
|
||||
console.error('更新员工位置失败:', error);
|
||||
showToast('更新位置失败');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅位置更新
|
||||
*/
|
||||
private subscribeToLocationUpdates(): void {
|
||||
console.log('订阅位置更新');
|
||||
locationTrackingService.subscribeToLocationUpdates(this.handleLocationUpdates);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订阅位置更新
|
||||
*/
|
||||
private unsubscribeFromLocationUpdates(): void {
|
||||
console.log('取消订阅位置更新');
|
||||
locationTrackingService.unsubscribeFromLocationUpdates(this.handleLocationUpdates);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理位置更新回调
|
||||
*/
|
||||
private handleLocationUpdates(locationData: any): void {
|
||||
console.log('收到位置更新回调:', locationData);
|
||||
|
||||
if (locationData.type === 'onlineUserList' && locationData.users) {
|
||||
// 处理在线用户列表更新
|
||||
console.log('处理在线用户列表,用户数量:', locationData.users.length);
|
||||
this.updateEmployeeMarkers(locationData.users);
|
||||
} else if (Array.isArray(locationData)) {
|
||||
// 处理位置更新数组(旧格式)
|
||||
console.log('处理位置更新数组,用户数量:', locationData.length);
|
||||
this.updateEmployeeMarkers(locationData);
|
||||
} else if (locationData.userId && locationData.latitude && locationData.longitude) {
|
||||
// 处理单个用户位置更新
|
||||
console.log('处理单个用户位置更新:', locationData.userId);
|
||||
this.updateSingleEmployeeMarker(locationData);
|
||||
} else {
|
||||
console.warn('未知的位置数据格式:', locationData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新员工标记点
|
||||
*/
|
||||
private updateEmployeeMarkers(onlineUsers: any[]): void {
|
||||
console.log('开始更新员工标记点,在线用户数量:', onlineUsers.length);
|
||||
|
||||
// 获取地图模块来更新标记点
|
||||
const mapModule = this.dataModule.getMapModule();
|
||||
if (!mapModule) {
|
||||
console.error('地图模块未找到,无法更新员工标记点');
|
||||
return;
|
||||
}
|
||||
|
||||
// 为每个在线用户创建标记点
|
||||
const employeeMarkers = onlineUsers.map(user => {
|
||||
// 获取用户角色信息
|
||||
const userRole = user.role || this.getUserRole(user.userId);
|
||||
|
||||
// 解析位置信息(支持多种格式)
|
||||
const longitude = user.longitude || (user.lastLocation && user.lastLocation.longitude) || 0;
|
||||
const latitude = user.latitude || (user.lastLocation && user.lastLocation.latitude) || 0;
|
||||
const lastUpdateTime = user.lastUpdateTime || Date.now();
|
||||
|
||||
const employeeMarker = {
|
||||
id: 10000 + user.userId, // 避免ID冲突
|
||||
type: 'employee',
|
||||
title: user.userName || `员工${user.userId}`,
|
||||
longitude: longitude,
|
||||
latitude: latitude,
|
||||
iconPath: this.getEmployeeIcon(user.userId, userRole),
|
||||
width: 32,
|
||||
height: 32,
|
||||
zIndex: 30,
|
||||
data: {
|
||||
userId: user.userId,
|
||||
role: userRole,
|
||||
lastUpdateTime: lastUpdateTime
|
||||
}
|
||||
};
|
||||
|
||||
return employeeMarker;
|
||||
});
|
||||
|
||||
// 调用地图模块更新员工标记点
|
||||
mapModule.updateEmployeeMarkers(employeeMarkers);
|
||||
|
||||
console.log(`成功更新了 ${employeeMarkers.length} 个员工标记点`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个员工标记点
|
||||
*/
|
||||
private updateSingleEmployeeMarker(locationUpdate: any): void {
|
||||
console.log('更新单个员工标记点:', locationUpdate.userId);
|
||||
|
||||
// 获取地图模块
|
||||
const mapModule = this.dataModule.getMapModule();
|
||||
if (!mapModule) {
|
||||
console.error('地图模块未找到,无法更新员工标记点');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取用户角色信息
|
||||
const userRole = this.getUserRole(locationUpdate.userId);
|
||||
|
||||
// 创建单个员工标记点
|
||||
const employeeMarker = {
|
||||
id: 10000 + locationUpdate.userId,
|
||||
type: 'employee',
|
||||
title: `员工${locationUpdate.userId}`,
|
||||
longitude: locationUpdate.longitude,
|
||||
latitude: locationUpdate.latitude,
|
||||
iconPath: this.getEmployeeIcon(locationUpdate.userId, userRole),
|
||||
width: 32,
|
||||
height: 32,
|
||||
zIndex: 30,
|
||||
data: {
|
||||
userId: locationUpdate.userId,
|
||||
role: userRole,
|
||||
lastUpdateTime: locationUpdate.timestamp || Date.now()
|
||||
}
|
||||
};
|
||||
|
||||
// 调用地图模块更新单个标记点
|
||||
mapModule.updateSingleEmployeeMarker(employeeMarker);
|
||||
|
||||
console.log('单个员工标记点更新完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户角色
|
||||
*/
|
||||
private getUserRole(userId: number): string {
|
||||
// 从数据模块获取用户信息
|
||||
const userInfo = this.dataModule.getData().userInfo;
|
||||
if (userInfo && userInfo.id === userId) {
|
||||
return userInfo.role || 'employee';
|
||||
}
|
||||
|
||||
// 如果是其他用户,默认为货运人员
|
||||
return 'employee';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取员工图标
|
||||
*/
|
||||
private getEmployeeIcon(userId: number, userRole: string): string {
|
||||
// 根据用户角色返回不同的图标
|
||||
if (userRole === 'ADMIN') {
|
||||
return '/images/crown.png'; // 管理员图标
|
||||
} else {
|
||||
return '/images/trucks.png'; // 货运人员图标
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,9 +234,17 @@ export class LoginModule {
|
||||
|
||||
// 启动位置追踪服务
|
||||
try {
|
||||
// 先启动位置追踪服务
|
||||
await locationTrackingService.startTrackingAfterSignIn();
|
||||
console.log('位置追踪服务已启动');
|
||||
|
||||
// 然后调用位置模块的实时跟踪功能
|
||||
const locationModule = this.dataModule.getLocationModule();
|
||||
if (locationModule) {
|
||||
await locationModule.startRealTimeTracking();
|
||||
console.log('位置模块实时跟踪已启动');
|
||||
}
|
||||
|
||||
// 订阅位置更新回调,采用统一方式更新所有用户位置
|
||||
locationTrackingService.subscribeToLocationUpdates((onlineUsers) => {
|
||||
console.log('🚚 位置更新回调 - 在线用户列表已更新,用户数量:', onlineUsers.length);
|
||||
@@ -433,10 +441,8 @@ export class LoginModule {
|
||||
// 根据服务器返回的状态映射到前端状态
|
||||
switch (response.status) {
|
||||
case 'signed_in':
|
||||
case 'online':
|
||||
return 'signed_in';
|
||||
case 'signed_out':
|
||||
case 'offline':
|
||||
return 'signed_out';
|
||||
case 'registered':
|
||||
return 'registered';
|
||||
|
||||
@@ -3,17 +3,32 @@ import { LoginModule } from './loginModule';
|
||||
import { MapModule } from './mapModule';
|
||||
import { OrderModule } from './orderModule';
|
||||
import { WarehouseModule } from './warehouseModule';
|
||||
import { DeliveryPersonModule } from './deliveryPersonModule';
|
||||
import { EmployeeModule } from './deliveryPersonModule';
|
||||
import { LocationModule } from './locationModule';
|
||||
import { DataModule } from './dataModule';
|
||||
import { showToast } from '../../../utils/helpers';
|
||||
|
||||
// 主页面模块接口定义
|
||||
export interface MainPageModule {
|
||||
getLoginModule(): LoginModule;
|
||||
onLoad(): Promise<void>;
|
||||
onShow(): void;
|
||||
onHide(): void;
|
||||
onLogout(): void;
|
||||
hideAllPanels(): void;
|
||||
resetMarkers(): void;
|
||||
cleanup(): void;
|
||||
refreshAllData(): Promise<void>;
|
||||
}
|
||||
|
||||
export class MainPageModule {
|
||||
private pageContext: any;
|
||||
private loginModule: LoginModule;
|
||||
private mapModule: MapModule;
|
||||
private orderModule: OrderModule;
|
||||
private warehouseModule: WarehouseModule;
|
||||
private deliveryPersonModule: DeliveryPersonModule;
|
||||
private employeeModule: EmployeeModule;
|
||||
private locationModule: LocationModule;
|
||||
private dataModule: DataModule;
|
||||
|
||||
constructor(pageContext: any) {
|
||||
@@ -25,7 +40,8 @@ export class MainPageModule {
|
||||
this.mapModule = new MapModule(pageContext, this.dataModule);
|
||||
this.orderModule = new OrderModule(pageContext, this.dataModule);
|
||||
this.warehouseModule = new WarehouseModule(pageContext, this.dataModule);
|
||||
this.deliveryPersonModule = new DeliveryPersonModule(pageContext, this.dataModule);
|
||||
this.employeeModule = new EmployeeModule(pageContext, this.dataModule);
|
||||
this.locationModule = new LocationModule(pageContext, this.dataModule);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +54,9 @@ export class MainPageModule {
|
||||
// 初始化应用
|
||||
await this.initApp();
|
||||
|
||||
// 初始化位置模块
|
||||
await this.locationModule.initialize();
|
||||
|
||||
// 加载地图数据
|
||||
await this.loadAllData();
|
||||
|
||||
@@ -58,12 +77,22 @@ export class MainPageModule {
|
||||
this.refreshDataIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面隐藏
|
||||
*/
|
||||
onHide(): void {
|
||||
console.log('主页面隐藏');
|
||||
|
||||
// 清理位置模块
|
||||
this.locationModule.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化应用
|
||||
*/
|
||||
private async initApp(): Promise<void> {
|
||||
// 初始化数据
|
||||
this.dataModule.initializeData();
|
||||
await this.dataModule.initializeData();
|
||||
console.log('应用初始化');
|
||||
}
|
||||
|
||||
@@ -119,7 +148,7 @@ export class MainPageModule {
|
||||
// 并行加载各种业务数据(需要登录)
|
||||
await Promise.all([
|
||||
this.orderModule.loadPendingOrders(),
|
||||
this.deliveryPersonModule.loadDeliveryPersons()
|
||||
this.employeeModule.loadAllEmployees()
|
||||
]);
|
||||
|
||||
console.log('所有业务数据加载完成');
|
||||
@@ -160,7 +189,7 @@ export class MainPageModule {
|
||||
this.dataModule.updatePendingOrders([]);
|
||||
|
||||
const filteredMarkers = this.pageContext.data.markers.filter((marker: any) =>
|
||||
marker.type !== 'warehouse' && marker.type !== 'delivery_person'
|
||||
marker.type !== 'warehouse' && marker.type !== 'employee'
|
||||
);
|
||||
this.dataModule.updateMarkers(filteredMarkers);
|
||||
}
|
||||
@@ -230,7 +259,7 @@ export class MainPageModule {
|
||||
this.warehouseModule.onWarehouseMarkerClick(marker.data, e);
|
||||
break;
|
||||
case 'delivery_person':
|
||||
this.deliveryPersonModule.onDeliveryPersonMarkerClick(marker.data, e);
|
||||
this.employeeModule.onDeliveryPersonMarkerClick(marker.data, e);
|
||||
break;
|
||||
default:
|
||||
this.mapModule.onMarkerTap(e);
|
||||
@@ -267,10 +296,17 @@ export class MainPageModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取货运人员模块
|
||||
* 获取员工模块
|
||||
*/
|
||||
getDeliveryPersonModule(): DeliveryPersonModule {
|
||||
return this.deliveryPersonModule;
|
||||
getEmployeeModule(): EmployeeModule {
|
||||
return this.employeeModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取位置模块
|
||||
*/
|
||||
getLocationModule(): LocationModule {
|
||||
return this.locationModule;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,11 +83,16 @@ export class MapModule {
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新数据模块中的位置信息和缩放级别
|
||||
// 强制重置地图视角到用户位置
|
||||
// 1. 更新用户位置
|
||||
this.dataModule.updateUserLocation(location.latitude, location.longitude);
|
||||
this.dataModule.setMapScale(15); // 定位成功后放大到更详细的级别
|
||||
// 2. 重置地图缩放级别到15(详细级别)
|
||||
this.dataModule.setMapScale(15);
|
||||
// 3. 添加地图动画效果,让视角平滑回到用户位置
|
||||
this.animateMapToUserLocation(location.latitude, location.longitude);
|
||||
|
||||
console.log('[MAP MODULE] 定位成功,坐标已更新:', location);
|
||||
console.log('[MAP MODULE] 定位成功,坐标已更新,视角已重置:', location);
|
||||
showToast('已定位到您的位置');
|
||||
} catch (error) {
|
||||
console.error('[MAP MODULE] 定位失败:', error);
|
||||
this.setDefaultLocation();
|
||||
@@ -105,9 +110,44 @@ export class MapModule {
|
||||
// 更新数据模块中的位置信息和缩放级别
|
||||
this.dataModule.updateUserLocation(defaultLatitude, defaultLongitude);
|
||||
this.dataModule.setMapScale(13);
|
||||
// 动画效果回到默认位置
|
||||
this.animateMapToUserLocation(defaultLatitude, defaultLongitude);
|
||||
|
||||
console.log('[MAP MODULE] 默认位置设置完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 动画效果将地图视角平滑移动到用户位置
|
||||
*/
|
||||
private animateMapToUserLocation(latitude: number, longitude: number): void {
|
||||
// 使用微信小程序的MapContext.moveToLocation方法实现地图移动
|
||||
const mapContext = wx.createMapContext('myMap', this.pageContext);
|
||||
|
||||
// 先设置地图中心点
|
||||
this.pageContext.setData({
|
||||
latitude: latitude,
|
||||
longitude: longitude
|
||||
});
|
||||
|
||||
// 使用moveToLocation方法平滑移动地图视角
|
||||
mapContext.moveToLocation({
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
success: () => {
|
||||
console.log('[MAP MODULE] 地图视角移动成功,位置:', { latitude, longitude });
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error('[MAP MODULE] 地图视角移动失败:', err);
|
||||
// 如果moveToLocation失败,直接设置中心点
|
||||
this.pageContext.setData({
|
||||
latitude: latitude,
|
||||
longitude: longitude
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log('[MAP MODULE] 地图视角动画已启动,移动到位置:', { latitude, longitude });
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载地图数据(仓库和货运人员)
|
||||
@@ -126,39 +166,30 @@ export class MapModule {
|
||||
/**
|
||||
* 生成初始标记点
|
||||
*/
|
||||
private generateInitialMarkers(): Marker[] {
|
||||
// 获取当前坐标
|
||||
const longitude = this.pageContext.data.longitude;
|
||||
const latitude = this.pageContext.data.latitude;
|
||||
public generateInitialMarkers(): Marker[] {
|
||||
console.log('生成初始标记点');
|
||||
|
||||
// 检查坐标是否为有效数字
|
||||
let validLongitude = longitude;
|
||||
let validLatitude = latitude;
|
||||
const markers: Marker[] = [];
|
||||
|
||||
if (isNaN(longitude) || isNaN(latitude)) {
|
||||
console.warn(`无效的坐标值: longitude=${longitude}, latitude=${latitude}, 使用默认坐标`);
|
||||
validLongitude = 102.833722; // 默认经度
|
||||
validLatitude = 24.880095; // 默认纬度
|
||||
|
||||
// 更新页面数据中的坐标
|
||||
this.dataModule.updateUserLocation(validLatitude, validLongitude);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 生成初始标记点
|
||||
return [
|
||||
{
|
||||
id: -1, // 用户位置标记
|
||||
// 获取用户位置
|
||||
const userLocation = this.pageContext.data.userLocation;
|
||||
if (userLocation && userLocation.longitude && userLocation.latitude) {
|
||||
// 添加用户位置标记点
|
||||
markers.push({
|
||||
id: -1,
|
||||
title: '用户位置',
|
||||
longitude: validLongitude,
|
||||
latitude: validLatitude,
|
||||
longitude: userLocation.longitude,
|
||||
latitude: userLocation.latitude,
|
||||
iconPath: '/images/trucks.png',
|
||||
width: 40,
|
||||
height: 40,
|
||||
zIndex: 99
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
console.log('已添加用户位置标记点');
|
||||
}
|
||||
|
||||
return markers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,6 +222,57 @@ export class MapModule {
|
||||
console.log('用户头像已更新');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新员工标记点
|
||||
*/
|
||||
updateEmployeeMarkers(employeeMarkers: Marker[]): void {
|
||||
console.log('开始更新员工标记点,数量:', employeeMarkers.length);
|
||||
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 过滤掉现有的员工标记点
|
||||
const filteredMarkers = markers.filter((marker: any) =>
|
||||
marker.type !== 'employee'
|
||||
);
|
||||
|
||||
// 合并标记点
|
||||
const updatedMarkers = [...filteredMarkers, ...employeeMarkers];
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
|
||||
console.log('员工标记点更新完成,总标记点数量:', updatedMarkers.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个员工标记点
|
||||
*/
|
||||
updateSingleEmployeeMarker(employeeMarker: Marker): void {
|
||||
console.log('更新单个员工标记点:', employeeMarker.id);
|
||||
|
||||
const { markers } = this.pageContext.data;
|
||||
|
||||
// 查找现有的员工标记点
|
||||
const markerIndex = markers.findIndex((marker: any) =>
|
||||
marker.type === 'employee' && marker.id === employeeMarker.id
|
||||
);
|
||||
|
||||
let updatedMarkers;
|
||||
if (markerIndex !== -1) {
|
||||
// 更新现有的标记点
|
||||
updatedMarkers = [...markers];
|
||||
updatedMarkers[markerIndex] = employeeMarker;
|
||||
} else {
|
||||
// 添加新的标记点
|
||||
updatedMarkers = [...markers, employeeMarker];
|
||||
}
|
||||
|
||||
// 更新数据模块中的标记点
|
||||
this.dataModule.updateMarkers(updatedMarkers);
|
||||
|
||||
console.log('单个员工标记点更新完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理地图点击事件
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user