一 前端
1.统一请求 响应
https://blog.youkuaiyun.com/qq_36375343/article/details/136250792
https://blog.youkuaiyun.com/qq_67195968/article/details/134847507
/src/http/index.ts
const baseUrl = 'http://192.168.21.69:8090/api'; // 域名
// 带 Token 请求
const request = ( params:any) => {
uni.onNetworkStatusChange(function(res) {
if (!res.isConnected) {
uni.showToast({
title: '网络连接不可用!',
icon: 'none'
});
}
return false
});
let token = uni.getStorageSync('token');
let httpDefaultOpts = {
url: baseUrl + params.url,
data: params.data,
method: params.method || 'GET',
header: params.method == 'get' ? {
'token': token,
'X-Requested-With': 'XMLHttpRequest', //用于标记请求是由 AJAX 发起的
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded" //请求在url后面
} : {
'token': token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8'
},
dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(res:any) => {
if (res.data.code == 0) {
resolve(res.data.data)
} else {
if (res.data.code == 401) {
uni.showModal({
title: '提示',
content: res.data.message,
success: function (res) {
if (res.confirm) {
uni.reLaunch({
url: '/pages/index/index'
});
uni.clearStorageSync();
}
}
});
/* 清除持久化数据 */
uni.clearStorageSync();
} else {
uni.showModal({
title: '提示',
content: res.data.message,
});
}
}
}
).catch(
(response) => {
reject(response)
}
)
})
return promise;
};
// 导出去
export default request;
/src/api
//引入request.js文件
import request from "../http/index";
/* 根据用户ID查询用户行程 */
export function selectTripByUserId(params: any) {
return request({
url: "/trip/selectTripByUserId", // 这个地址是去掉公共地址剩下的地址
method: "GET", // 请求方式 支持多种方式 get post put delete 等等
data:params
});
}
原来这种:封装请求为对象中的方法
import http from "@/http"
export default {
get: {
name: "获取状态枚举",
path: "/api/enum",
call: async function (params: any = {}) {
return await http.get(this.path, params)
}
}
直接定义请求函数
export function selectTripByUserId(params: any) {
return request({
url: "/trip/selectTripByUserId", // 这个地址是去掉公共地址剩下的地址
method: "GET", // 请求方式 支持多种方式 get post put delete 等等
data: params
});
}
感受:原来的更直观一些 看起来更明了
直接定义请求函数
其中:baseUrl 使用的ip地址 不建议使用 localhost 后面如果真机调试 无法使用
uni.getStorageSync() 和 uni.setStorageSync() 是在多端应用开发框架中,用于操作本地存储的方法。这些方法是同步的
uni.clearStorageSync() 用于清除所有通过 uni.setStorageSync 存储在本地缓存中的数据。
对于更大的数据集或更复杂的操作,建议使用异步版本的 uni.getStorage 和 uni.setStorage。
uni.onNetworkStatusChange 是一个 API,用于监听网络状态的变化。当网络连接状态发生变化时,会触发相应的回调函数。
在微信小程序中 数据存储在微信小程序的沙箱环境中,通常是客户端设备上的本地存储空间内。
2.前端 功能页
2.1 拼车界面
2.1.1 省市区 选择
一个字 抄!!!
-
看看组件库有没有
https://wot-design-uni.netlify.app/component/col-picker.html
https://vant-ui.github.io/vant/#/zh-CN/area
2.找找别人有没有写过类似的 能不能拿来改改用
https://blog.youkuaiyun.com/yunhuaikong/article/details/134187623?ops_request_misc=&request_id=&biz_id=102&utm_term=uniapp%E5%9F%8E%E5%B8%82%E9%80%89%E6%8B%A9%E5%88%97%E8%A1%A8&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-8-134187623.142^v100^pc_search_result_base6&spm=1018.2226.3001.4187
2.1.2 时间选择器
组件库:
uni-app ui
https://uniapp.dcloud.net.cn/component/picker.html#%E6%97%B6%E9%97%B4%E9%80%89%E6%8B%A9%E5%99%A8
2.1.3 地图选点
csdn:
https://blog.youkuaiyun.com/luhanglh/article/details/140442793?ops_request_misc=%257B%2522request%255Fid%2522%253A%252264B5BE78-34E1-4749-B603-6981FDD64C61%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=64B5BE78-34E1-4749-B603-6981FDD64C61&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-140442793-null-null.142^v100^pc_search_result_base6&utm_term=uniapp%20%E4%BD%BF%E7%94%A8%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BE&spm=1018.2226.3001.4187
其中区别:
上述代码:所使用的为获取周边 不是在全国范围内
getPoiAround
myAmapFun.value.getPoiAround({
iconPath: '标记图片',
iconWidth: 22,
iconHeight: 32,
querykeywords: searchKey.value,
success: (data) => {
if (data.poisData.length == 0) {
uni.showModal({
title: '提示',
content: '没有搜索到结果',
showCancel: false,
});
} else {
searchAddressList.value = data.poisData; // 将搜索回来的数据放在列表中显示
}
},
fail: (data) => {
console.log('搜索失败', data);
},
高德:
https://lbs.amap.com/api/wx/guide/get-data/get-inputtips
getInputtips
myAmapFun.value.getInputtips({
keywords: searchKey.value,
location: '',
success: function (data) {
if (data && data.tips) {
console.log(data)
searchAddressList.value = data.tips;
}
}
})
点击地图的事件:
handleMarkerTap
const handleMarkerTap = (ev) => {
latitude.value = ev.detail.latitude;
longitude.value = ev.detail.longitude;
// 更改标记点
markers.value = [{
id: 1,
width: 40,
height: 40,
latitude: ev.detail.latitude,
longitude: ev.detail.longitude,
}, ];
getRegeo();
};
2.2我的行程
主要使用高德路线规划
https://lbs.amap.com/api/wx/guide/route/route
2.3 我的界面
登录看微信小程序开发 微信登录
一个简单的修改用户信息:
3.后端
关于 统一请求响应 token 拦截器 用原来写的 就好
其中特殊:
调用微信小程序 后端跨域问题 简单解决
在Controller上加个@CrossOrigin 注解 然后写相对应的方法
关于mongodb:
乘客取消行程 需要去除 passengerId 中对应的乘客id 并将 可乘坐的乘客数量 +1 :
Query query = new Query(Criteria.where("id").is(tripDto.getTripId()));
Update update = new Update()
.pull("passengerId", tripDto.getId())
.inc("num", 1); //想减1 可以直接 -1
UpdateResult result = mongoTemplate.updateFirst(query, update, Trip.class);
时间范围查询:
其中get gte
和 lte
分别代表“大于等于”和“小于等于” 时间类型为Date
query.addCriteria(
Criteria.where("startLocation.city").is(strings[0])
.andOperator(
Criteria.where("endLocation.city").is(strings2[0]),
Criteria.where("startData").gte(todayStartTime).lte(todayEndTime),
Criteria.where("status").is(1)
)
);
三. 常用组件
3.1 uni 提示框
https://blog.youkuaiyun.com/Quentin0823/article/details/131530559
uni.showModal({
title: '提示',
content: res.data.message,
});
//提示框 并且附带选择列表
uni.showActionSheet({
itemList: ['一座', '二座', '三座', '四座', '五座'],
success(res) {
num.value = res.tapIndex + 1,
create()
},
})
3.2 界面跳转
uni.reLaunch关闭所有页面并打开到应用内的某个页面
uni.reLaunch({
url: '/pages/index/index'
});
跳转到某个界面
uni.navigateTo({
url: "/pages/updateUserInfo/updateUserInfo"
})
界面返回// 返回上一级页面
uni.navigateBack();
// 返回上两级页面
uni.navigateBack({
delta: 2
});
其他:
检测向下滑动:
onPullDownRefresh(()=>{
console.log('触发了下拉刷新')
selectByUserId()
uni.stopPullDownRefresh()
})
下拉刷新
https://blog.youkuaiyun.com/yasinawolaopo/article/details/122070348 import {
onPullDownRefresh
} from '@dcloudio/uni-app';
onPullDownRefresh(()=>{
console.log('触发了下拉刷新')
selectByUserId()
uni.stopPullDownRefresh() //结束下拉刷新
})
四 微信服务号消息提醒
已经学过了 钉钉信息 邮件信息
4.1 首先进入微信开发者平台
https://mp.weixin.qq.com/
4.2 选择消息模板
点击基础功能 订阅消息 在公共模板库 找到线路调整通知
选择关键词 输入使用场景 点击提交
提交之后我们点击 我的模板 查看详情 模板id 与 详细内容的参数 很重要
微信关于参数内容限制 很严格 必须遵守 查询网址:
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/sendMessage.html#%E5%85%B6%E4%BB%96%E8%AF%B4%E6%98%8E
我这里选择的有 thing 与 time两种类型参数
4.3 前端授权
官网文档:
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html
其中 tmplIds 为 我们申请的模板id
可以把他添加到我们的任意方法中
wx.requestSubscribeMessage({
tmplIds: [''],
success (res) { }
})
4.4 后端方法
官方文档:
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/sendMessage.html
调用了一个post请求 请求体为json 类型 参数为所选择的参数
请求路径中 token获取 appid 微信的小程序id secret为对应的密钥
String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+*appid*+"&secret="+*secret*;
如上我们所选择的参数变成json 应当为
{
"touser": "OPENID", //用户的open_id
"template_id": "TEMPLATE_ID", //模板编号id
"page": "index", // 点击跳转小程序界面路径
"miniprogram_state":"developer", //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
"lang":"zh_CN", //语言
"data": {
"thing1": {
"value": "线路详情"
},
"thing3": {
"value": "始发站"
},
"thing5": {
"value": "重点站"
} ,
"thing6": {
"value": "提示说明"
} ,
"time8": {
"value": "2024年10月10日 10:10"
}
}
}
后端写了个发送请求的工具类: 感觉既然是json 用 JSONObject可能更好@Component
public class TripNotifyUtil {
private static String appid = "xxxxxxxxxxx";
private static String secret = "xxxxxxxxxxxxxx";
/*司机取消行程 给乘客发送信息*/
public static void cancelTripMessageNotify(String openId, Trip trip){
Map map = new HashMap();
map.put("template_id","boB9rZjDtrATPPuls4ydza64Q6gef6N0uSR0Infb1D4");
map.put("page","/pages/trip/trip");//点击详细跳转小程序页面,不填就没有查看详情
map.put("touser",openId);//发送用户的open_id
//跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
map.put("miniprogram_state","developer");
map.put("lang","zh_CN");
Map data = new HashMap();
// JSONObject jsonObject = new JSONObject();
// jsonObject.set()
Map thing1 = new HashMap();
/*线路详情*/
String str1 = trip.getStartLocation().getDistrict() + "-" + trip.getEndLocation().getDistrict();
thing1.put("value",str1);
/*始发站*/
Map thing3 = new HashMap();
String str2 = trip.getStartLocation().getCity() + "-" + trip.getStartLocation().getDistrict();
thing3.put("value",str2);
/*重点站*/
Map thing5 = new HashMap();
String str3 = trip.getEndLocation().getCity() + "-" + trip.getEndLocation().getDistrict();
thing5.put("value",str3);
/*提示说明*/
Map thing6 = new HashMap();
String str4 = "行程取消";
thing6.put("value",str4);
/*发车时间*/
Map time8 = new HashMap();
LocalDateTime now = LocalDateTime.now();
String date = now.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"));
time8.put("value",date);
data.put("thing1",thing1);
data.put("thing3",thing3);
data.put("thing5",thing5);
data.put("thing6",thing6);
data.put("time8",time8);
map.put("data",data);
String accessToken = getXcxAccessToken();//获取小程序的accessToken
// 使用 Hutool 解析 JSON 字符串
String ACCESS_TOKEN = JSONUtil.parseObj(accessToken).getStr("access_token");
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
String sendUrl = url.replace("ACCESS_TOKEN", ACCESS_TOKEN);
String post = HttpUtil.post(sendUrl, JSONUtil.toJsonStr(map));
System.out.println(post);
}
/*获取SessionKey*/
public static String getXcxAccessToken(){
String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;
return HttpUtil.get(url);
}
}