主题
云函数调用与打包上线(一)
本页对应 云函数调用与打包上线,共 8 段视频,约 1 小时 6 分。
学习目标
- 能够独立创建 uniCloud 云函数,并在页面中通过
uniCloud.callFunction调用,准确传入参数并获取返回值。 - 能够完成腾讯地图应用配置,申请并校验 WebService API Key,将其正确配置到项目中以支持地图展示。
- 能够在云函数中使用
uniCloud.request调用腾讯地图路线规划接口,并返回接口数据供页面使用。 - 能够搭建查看物流页面模板,新建药品订单,并通过地址参数将药品订单 ID 传递到物流页面。
- 能够封装并调用药品物流信息接口,根据物流状态与图标类名完成物流节点渲染。
- 能够接收地图服务返回的压缩经纬度数据,完成解压、遍历转换并在页面中生成可用的经纬度数组。
知识点
先理解云函数:本质是放到服务器上运行的普通函数
为什么需要:页面直接请求腾讯地图接口会遇到跨域,浏览器不允许当前 localhost 页面直接访问腾讯地图域名。转写稿里演示时控制台报的就是跨域错误。云函数运行在服务器上,由服务器发请求,就不受浏览器跨域限制。
怎么想:不要把“云函数”神秘化。它本质上仍是一个函数,有参数、有返回值;区别只是运行位置在服务器,而不是本机浏览器。调用云函数时,可以把它想成“后端提供的接口”:name 像接口地址,data 像请求参数,返回值像接口响应。
怎么做:在已开通云空间的项目中,找到 uniCloud 下的 cloudfunctions,右键新建云函数,模板选默认模板,命名为 QQ-map。转写稿口述为“QQm”,后文以实际创建的 QQ-map 指代。默认 index.js 大致是:
js
exports.main = async (event, context) => {
return {
name: event.name
}
}易错点:不要把云函数名、页面文件名、接口路径混在一起;云函数创建后要确认目录下确实生成了 index.js。
调用云函数:用 uniCloud.callFunction
为什么需要:创建完云函数后,页面必须通过专门 API 调用,不能直接 import 服务器函数。
怎么想:调用形态和调接口一致:name 指定云函数名,data 传参数,返回值从结果对象中取。转写稿里先用 name: '小明' 测试,再把云函数改成返回 小小明,观察页面控制台和 uniCloud 控制台的变化。
怎么做:
js
const res = await uniCloud.callFunction({
name: 'QQ-map',
data: {
name: '小明'
}
})
console.log('云函数返回值', res)云函数中接收参数:
js
exports.main = async (event, context) => {
return {
name: event.name
}
}易错点:转写稿中反复强调要区分两个调试位置:看云函数内部执行日志,去 uniCloud 控制台;看页面调用云函数后的返回值,去页面控制台。不要把 res、res.result 和云函数内部 return 的数据结构搞混。
申请腾讯地图 Key:必须勾选 WebServiceAPI
为什么需要:云函数要请求腾讯地图路线规划接口,必须携带有效 Key;页面要显示地图,也需要在项目里配置地图 Key。
怎么想:腾讯地图应用管理里创建或编辑 Key 时,转写稿明确要求勾选 WebServiceAPI,并勾选域名白名单;其他选项不用乱勾。已有 Key 也可以直接编辑补勾。
怎么做:登录腾讯地图开发者平台,在应用管理中找到 Key,确认 WebServiceAPI 已勾选。然后打开路线规划文档,确认请求地址和必传参数。转写稿中驾车路线规划必传三项:key、from、to;from、to 是经纬度,格式为“纬度在前、经度在后”,中间用英文半角逗号。
易错点:不要使用讲师的 Key,转写稿明确说会有次数限制;经纬度不要随便编,否则路线可能跑到海里;逗号不要写中文逗号。
在云函数里请求腾讯地图并返回数据
为什么需要:页面直接请求会跨域,所以把请求放进云函数。转写稿区分了两个请求 API:页面里用 uni.request,云函数里用 uniCloud.request。
怎么想:云函数接收页面传来的 from、to,再向腾讯地图路线规划地址发请求;腾讯地图返回的数据里真正有用的是 data,所以云函数返回它。
怎么做:云函数中写:
js
exports.main = async (event, context) => {
const result = await uniCloud.request({
url: 'https://apis.map.qq.com/ws/direction/v1/driving/',
data: {
key: '你的key',
from: event.from,
to: event.to
}
})
return result.data
}页面调用时传起点终点:
js
const res = await uniCloud.callFunction({
name: 'QQ-map',
data: {
from: '纬度,经度',
to: '纬度,经度'
}
})
console.log(res)易错点:转写稿中本地运行云函数曾出现“运行失败”,重跑后恢复,属于网络不稳定;调试时先看 event 是否拿到参数,再看腾讯地图返回结构。页面拿到的结果里可能还有一层 result,要按实际打印结构解构,不要凭感觉取。
页面接入地图、物流模板与订单 ID
为什么需要:物流路线不能写死起点终点,必须根据药品订单 ID 查询物流信息,再把起点终点交给地图云函数。
怎么想:先创建药品订单,进入待收货/物流详情页,把订单 ID 通过地址参数传到 timeline 页面;页面 onLoad 接收 props.id,再调用物流接口。地图显示还需要在 manifest.json 的 Web 配置里勾选腾讯地图并填入自己的 Key,否则会报地图 Key 相关错误。
怎么做:跳转时拼 ?id=orderDetail.id;页面接收:
js
onLoad(props) {
orderId.value = props.id
}调用物流接口时传 props.id。物流状态按转写稿表格映射:1 已发货、2 已揽货、3 运输中、4 派送中、5 已签收;不同状态对应小绿点、小卡车、对勾等类名,渲染时按状态判断。
易错点:转写稿中曾因模板里用了 paymentMethod 但数据没定义而报错,补回定义即可;也出现过 ref 未定义、接口没传 id 导致“入参有错误”,要检查 props.id 是否真正传入。
处理地图 polyline:先解压,再转成经纬度对象
为什么需要:腾讯地图返回的 polyline 是压缩后的经纬度,不能直接给地图画线;必须按官方文档解压。
怎么想:转写稿中先打印数据结构,确认路径在 result.result.routes[0].polyline 一类层级中;解压后得到“纬度、经度、纬度、经度……”的数组。为了页面使用方便,再遍历成 { latitude, longitude } 对象数组。
怎么做:按官方示例解压后,用 i += 2 遍历:
js
for (let i = 0; i < coors.length; i += 2) {
points.push({
latitude: coors[i],
longitude: coors[i + 1]
})
}易错点:转写稿明确说解压算法是固定写法,可以直接按文档搬,但不要改错数组下标;先打印确认结构,再解构,避免把 res.result 和内部 result 弄混。
为什么需要腾讯地图 Key
为什么需要:本节要做的是地图相关功能,后续会通过云函数调用腾讯地图服务,把物流线路等数据渲染到页面。腾讯地图的接口不是匿名随便调的,必须携带申请到的 Key,服务端才能识别调用方并返回数据。转写稿里也明确说,前面“想家生活”类项目已经用过腾讯地图,这次重点是检查并申请可用的 Key。
怎么想:不要把 Key 理解成“随便复制一串字符”,而要理解成“应用凭证”。申请时要选对服务类型,因为本项目是在云函数里发 HTTP 请求调接口,不是在小程序里直接调 SDK,所以应使用 WebService API 这一类 Key。
怎么做:登录腾讯位置服务,在“应用管理”里新建应用或编辑已有应用;填写名称、描述;勾选 WebService API,同时按转写稿要求勾选“域名白名单”;保存后拿到该应用的 Key。已有 Key 也可以直接编辑,不一定要新建。
易错点:只创建应用但不勾选 WebService API,Key 不能用于本节的接口调用;不要拿别人的 Key 反复测试,转写稿提到每天有调用次数限制,演示时用完了会影响后续;Key 要保存好,后面云函数和页面地图配置都会用到。
怎么想:先确认文档和接口类型
为什么需要:申请完 Key 只是第一步,还要知道接口怎么传参。转写稿中打开腾讯地图开发文档,找到 WebService API,再进入“路线规划”,选择“驾车”线路规划。这样做的原因是:物流运输线路需要在地图上画出一条线,路线规划接口正好返回线路坐标数据。
怎么想:看文档时不要被一堆参数吓住。先找“必须参数”。转写稿里强调,路线规划接口至少关注三个参数:key、from、to。其他参数用到再补,不需要一次记住全部。
怎么做:在文档的驾车路线规划中确认请求地址和参数说明;from 是起点,to 是终点,值都是经纬度;经纬度格式要注意“纬度在前、经度在后”,中间用英文半角逗号分隔。
易错点:经纬度顺序写反、用中文逗号,都会导致接口报错或路线异常;不要把起点终点随便编到国外或海里,否则地图上可能看不到合理线路;Key 放在请求参数里,不要误以为只放在页面配置里就够了。
怎么做:在云函数中携带 Key 调接口
为什么需要:转写稿专门演示了“页面直接请求会跨域”的问题:当前页面是 localhost,请求的是腾讯地图域名,浏览器会报跨域错误。前端直接解决跨域很困难,所以要把请求放到云函数里,由服务器去请求腾讯地图,再把结果返回页面。
怎么想:页面只负责调用云函数;云函数负责携带 Key 请求腾讯地图;腾讯地图返回数据后,云函数再把真正需要的数据返回给页面。这样既避开浏览器跨域,也避免把 Key 直接暴露在页面请求里。
怎么做:页面调用云函数时传起点和终点,示意如下:
js
uniCloud.callFunction({
name: 'QQ-map',
data: {
from: '纬度,经度',
to: '纬度,经度'
}
})云函数中接收参数并发请求,示意如下:
js
const res = await uniCloud.request({
url: '腾讯地图路线规划接口地址',
data: {
key: '你的Key',
from: event.from,
to: event.to
}
})
return res.data易错点:云函数里要用 event.from、event.to 接收页面传来的参数,不能继续写死;返回数据里通常要取 data,转写稿调试时还出现过多层 result 的情况,打印后再解构;运行云函数可在云函数文件上右键“运行本地云函数”验证,页面调用结果则看页面控制台或 uniCloud 控制台,两个位置不要混淆。
易错点:页面地图不显示也要检查 Key
为什么需要:转写稿后面在页面里展示地图时出现 map key not found 一类错误,原因是页面使用地图组件还需要在项目配置里填 Key。只在腾讯地图后台申请了 Key,并不等于页面地图组件自动生效。
怎么想:区分两个使用位置:云函数调 WebService API 用 Key;页面 H5 地图组件也要在 manifest.json 的 H5 配置中勾选腾讯地图并填写 Key。
怎么做:打开 manifest.json,找到 H5 配置中的定位和地图服务,勾选腾讯地图,填入自己的 Key,保存后开发者工具会自动重启,页面地图即可显示。
易错点:仍然不要填别人的 Key;改完配置要等自动重启;如果地图还是不显示,先看控制台报错,再检查 Key 是否勾选了正确服务、是否填在正确配置项里。转写稿还提到返回小图标缺失的问题,那属于静态资源路径问题,不是 Key 问题,排查时要区分开。
云函数是什么:先把它当成“服务器上的普通函数”
为什么需要:页面直接调腾讯地图会跨域,而云函数运行在服务器上,适合替页面发请求。怎么想:转写稿反复强调,云函数本质上就是普通函数,有参数、有返回值,只是运行位置在服务器,所以叫“云函数”。怎么做:在 uniCloud 目录的 cloudfunctions 上右键新建云函数,名字要与后续调用一致,例如 QQ-map,模板选默认。创建后打开 index.js,能看到箭头函数、参数和返回值。易错点:不要纠结概念,先看它如何被调用;云函数名不要随意改,页面里的 name 必须与它一致。
页面如何调用云函数
为什么需要:创建完云函数只是有了“后端接口”,还要在页面里触发。怎么想:把云函数想成后端接口,name 像 URL,data 像请求参数,返回值从 res 里拿。怎么做:
js
uniCloud.callFunction({
name: 'QQ-map',
data: { from, to }
}).then(res => {
console.log(res)
})转写稿中先传了测试参数,云函数里用 event 接收,再把 event 返回,页面就能看到结果。易错点:调用方法是 uniCloud.callFunction,不是 uni.callFunction;看云函数调试去 uniCloud 控制台,看页面调用结果去页面控制台,两个位置不要混。
申请腾讯地图 WebService Key
为什么需要:路线规划接口必须带 key。怎么想:之前项目已有腾讯地图账号,不必重新创建应用,但 key 必须勾选 WebServiceAPI。怎么做:进入腾讯位置服务应用管理,编辑已有 key 或新建 key,勾选 WebServiceAPI,域名白名单按需勾选。打开 WebServiceAPI 文档,找到路线规划中的驾车接口,确认请求地址和参数。易错点:key 不要用的,次数有限;from、to 是经纬度,纬度在前、经度在后,用英文半角逗号分隔。
为什么地图请求要放到云函数里
为什么需要:转写稿用 uni.request 直接请求 apis.map.qq.com 时,浏览器报跨域错误。怎么想:跨域是浏览器同源策略导致的,服务器发请求没有这个限制,所以让云函数去请求腾讯地图。怎么做:页面调 uniCloud.callFunction,云函数里用 uniCloud.request:
js
uniCloud.request({
url: 'https://apis.map.qq.com/ws/direction/v1/driving/',
data: {
key: '你的Key',
from: event.from,
to: event.to
}
})易错点:页面里发请求是 uni.request,云函数里是 uniCloud.request;不要把 key 写错,也不要把经纬度顺序写反。
云函数接收起点终点并返回数据
为什么需要:页面不能把起点终点写死,否则不同订单路线都一样。怎么想:页面调用云函数时传 from、to,云函数用 event.from、event.to 接收。怎么做:在云函数中把原来写死的 from、to 改成 event.from、event.to,请求成功后把腾讯地图返回的数据返回给页面。页面接收时注意转写稿中的结构:外层有 result,里面还有 result,调试时可先打印:
js
const { result } = res
console.log(result.result)易错点:不要直接把整个 res 当路线数据;data 才是真正地图数据,解构时要看清层级。
页面模板、地图 key 与订单 ID
为什么需要:拿到地图数据后要展示地图和物流信息,还要知道查哪个订单。怎么想:地图展示要在 manifest.json 的 H5 配置里勾选“定位和地图服务”,选腾讯地图并填自己的 key;物流页需要从订单详情跳转时带 ID。怎么做:跳转地址拼成类似 分包路径/timeline/index?ID=${orderDetail.ID},timeline 页面用 props 接收地址参数 ID。易错点:转写稿中漏定义 paymentMethod 导致读属性报错,复制模板后要检查数据是否定义;地图不显示先查 key 配置。
物流状态渲染与经纬度解压
为什么需要:物流列表状态不同,图标不同;腾讯地图返回的 polyline 是压缩经纬度,不能直接画线。怎么想:状态 5 已签收用对勾类名,4 派送中用卡车类名,1—3 用圆点类名;经纬度按官方文档解压后再处理。怎么做:解压后按 i += 2 遍历,组装成 { latitude, longitude } 对象数组,再交给地图使用。易错点:转写稿口述中经纬度奇偶有口误,实际以打印结果为准;解压算法按官方文档粘贴,不要手写猜;调试通一次即可,避免反复消耗 key 次数。
代码示例
1. 云函数 QQMap/index.js(uniCloud-aliyun/cloudfunctions/QQMap/index.js)
js
'use strict';
// 腾讯地图 key:必须勾选 WebServiceAPI,域名白名单也勾上
const MAP_KEY = '你申请的腾讯地图key';
exports.main = async (event, context) => {
// event 就是页面调用云函数时通过 data 传过来的参数
console.log('event:', event);
const res = await uniCloud.request({
// 只写到问号前,问号后面的参数全部走 data
url: 'https://apis.map.qq.com/ws/direction/v1/driving/',
method: 'GET',
data: {
key: MAP_KEY,
from: event.from, // 起点:纬度,经度(纬度在前!)
to: event.to // 终点:纬度,经度
}
});
console.log('QQ地图:', res);
// res 里有 code、header、data,真正有用的是 data
const { data } = res;
// 返回给页面,页面拿到的是 res.result
return data;
};关键行 / 易错点
uniCloud.request只能在云函数里用;页面里发请求要用uni.request。用错地方就等于把跨域问题又请回来了。url只写到/driving/,key / from / to全部通过data传,不要把参数拼到 url 上。from和to的格式是纬度,经度(纬前经后),中间必须是英文半角逗号,写成中文逗号会直接报错。key在云函数里写死即可(一个项目一个 key),但不要用讲师的 key,每人每天只有 50 次额度,用完就演示不了。- 云函数里
console.log的输出要到 uniCloud 控制台看;页面里console.log的输出在页面控制台看,两个地方别搞混。 - 云函数代码改完要保存并重新运行/上传,否则页面调用的还是旧版本。
2. 页面调用云函数 + 解压 polyline(pages/subpkg/medicine/timeline/index.vue)
vue
<template>
<view class="timeline-page">
<map
class="map"
:latitude="mapCenter.latitude"
:longitude="mapCenter.longitude"
:polyline="polyline"
:markers="markers"
></map>
<view class="log">经纬度点数量:{{ points.length }}</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const points = ref([]); // 处理后的 [{ latitude, longitude }, ...]
const polyline = ref([]); // 传给 map 组件的折线
const markers = ref([]); // 起点/终点标记
const mapCenter = ref({ latitude: 39.984154, longitude: 116.30749 });
// 调用云函数获取地图数据
const getMapData = async () => {
const res = await uniCloud.callFunction({
name: 'QQMap', // 云函数名,必须和文件夹名一致
data: {
// 起点、终点先写死,后面从订单接口的运输信息里取
from: '39.984154,116.307490',
to: '31.230416,121.473701'
}
});
console.log('云函数返回值', res);
// 注意:外层 result 是 callFunction 的返回值,内层 result 才是云函数 return 的数据
const { result: mapResult } = res;
console.log('地图数据', mapResult);
// 结构:mapResult.result.routes[0].polyline
const polylineStr = mapResult.result.routes[0].polyline;
// ---------- 第一步:按官方文档解压 ----------
const coors = [...polylineStr]; // 拷贝一份,别改动原始数据
const kr = 1000000;
for (let i = 2; i < coors.length; i++) {
coors[i] = coors[i - 2] + coors[i] / kr;
}
// ---------- 第二步:转成 { latitude, longitude } 对象数组 ----------
const arr = [];
for (let i = 0; i < coors.length; i += 2) {
arr.push({
latitude: coors[i], // 偶数位:纬度
longitude: coors[i + 1] // 奇数位:经度
});
}
points.value = arr;
console.log('解压处理后的点', points.value);
// ---------- 第三步:组装 polyline 交给 map 组件 ----------
polyline.value = [
{
points: points.value,
color: '#1AAD19',
width: 6
}
];
// 地图中心点取起点
mapCenter.value = points.value[0];
};
onLoad(() => {
getMapData();
});
</script>
<style lang="scss" scoped>
.map {
width: 100%;
height: 400rpx;
}
.log {
padding: 20rpx;
font-size: 28rpx;
}
</style>关键行 / 易错点
uniCloud.callFunction({ name, data }):name是云函数文件夹名,写错就是“找不到云函数”。- 返回值是两层
result:res.result是 callFunction 的壳,res.result.result才是云函数return的内容。讲师特意打印出来讲过这个坑。 - 路线数据在
result.result.routes[0].polyline,polyline是压缩过的经纬度数组,不能直接丢给 map 组件,必须先解压。 - 解压的
kr = 1000000和coors[i] = coors[i - 2] + coors[i] / kr是腾讯地图官方文档写死的算法,照抄即可,别自己改。 - 第二个循环
i += 2是关键:偶数下标是纬度、奇数下标i + 1是经度,顺序写反地图上会跑到南极去。 const coors = [...polylineStr]先拷贝一份,否则会污染云函数返回的原始数据。from/to写死只是测试,正式要从“订单接口的运输信息”里取起点终点再传进来。- 页面里忘了
ref定义就直接赋值,会报“读不到属性”之类的错误,讲师自己就踩过。 - 调用接口通了就别反复测,一天 50 次额度很快用完。
3. manifest.json 里配置腾讯地图 key(H5 端)
json
{
"h5": {
"sdkConfigs": {
"maps": {
"qqmap": {
"key": "你申请的腾讯地图key"
}
}
}
}
}关键行 / 易错点
- 不配这个 key,页面里
<map>组件会报map key not...之类的错误,地图直接不出来。 - 实操时不建议手写:在 HBuilderX 里打开
manifest.json→ 「Web 配置」→ 勾选「腾讯地图」→ 把 key 粘进去,保存后会自动生成上面的结构,并自动重启项目。 - 这里填的 key 和云函数里的 key 可以是同一个,但一定填自己的,不要用讲师的(额度会被用光)。
- 改完 manifest 会自动重启,页面刷新后地图才显示;不重启看不到效果别以为是写错了。
常见错误
- 现象:页面调用云函数无结果或拿到
undefined→ 原因:callFunction的name与云函数目录名不一致,或未从返回结构中取result→ 修法:核对云函数名,检查云函数是否return,页面按实际结构解构result。 - 现象:腾讯地图接口返回 key 错误、无路线数据 → 原因:key 未勾选
WebService API/域名白名单,或误用他人 key 导致次数耗尽 → 修法:编辑自己的 key,勾选WebService API和域名白名单,联调通过后避免反复请求。 - 现象:H5 页面地图空白,控制台提示 map key 相关错误 → 原因:
manifest.json的 H5 配置未勾选腾讯地图或未填 key → 修法:在 Web 配置中勾选腾讯地图并填入自己的 key,等待自动重启后复查。 - 现象:页面直接请求腾讯地图地址报跨域 → 原因:浏览器同源策略限制,页面端直接请求第三方域名 → 修法:改为页面调云函数,由云函数内使用
uniCloud.request请求腾讯地图。 - 现象:物流节点图标显示错误 → 原因:未按
status判断类名,圆点/卡车/对勾混用 → 修法:按约定映射status=5用对勾、status=4用卡车、status<=3用圆点等。 - 现象:地图路线无法渲染或坐标错乱 → 原因:腾讯返回的
polyline是压缩坐标,未解压或经纬度提取顺序错误 → 修法:按官方算法解压,再按偶数位取经度、奇数位取纬度转为对象数组。 - 现象:物流接口报 ID 入参错误 → 原因:列表跳转未拼订单 ID,或详情页未通过
props接收并传给接口 → 修法:跳转 URL 拼?ID=orderDetail.ID,详情页props接收后传入接口。
练习
- 在
timeLine页面调用QQ-map云函数,传入from、to,分别说明在页面控制台和 uniCloud 控制台应查看什么结果。 - 检查并修正腾讯地图 key:确认
WebService API、域名白名单已勾选;再修复 H5 地图不显示问题。 - 给药品订单“待收货”入口补跳转链接,携带订单 ID,并在
timeLine页面接收后传入物流接口。 - 对腾讯地图返回的
polyline做解压,并转换为[{ lng, lat }]结构,说明偶数位和奇数位分别对应什么。 - 按物流
status渲染节点样式,列出status=5、status=4、status<=3分别应使用的图标类名。
课堂画面






原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | uniCloud云函数创建及调用 | 11:17 |
| 2 | 腾讯地图创建应用并申请key | 08:03 |
| 3 | 云函数调用腾讯地图服务接口 | 08:52 |
| 4 | 优医咨询-查看物流页面模板 | 04:40 |
| 5 | 优医咨询-新建一个药品订单 | 04:08 |
| 6 | 优医咨询-地址传递药品订单ID | 05:36 |
| 7 | 优医咨询-获取物流信息并渲染 | 09:16 |
| 8 | 优医咨询-处理地图服务经纬度数据 | 14:45 |
小结
- 云函数是运行在服务端的普通函数,页面通过
callFunction按名称调用,用event传参、用返回结果取数据。 - 浏览器端直接请求腾讯地图会触发跨域,地图接口请求应下沉到云函数中完成。
- 腾讯地图 key 必须启用
WebService API;H5 地图展示还需在manifest.json中配置腾讯地图 key。 - 页面调用云函数后要关注返回结构,通常需先解构
result,再按业务取data。 - 物流页面依赖订单 ID,ID 必须从列表跳转带到详情页,并由页面接收后传给接口。
- 腾讯地图路线坐标是压缩
polyline,必须先按官方算法解压,再转换为经纬度对象数组。 - 调试时要区分:uniCloud 控制台看云函数日志,页面控制台看页面调用结果。
- 地图和接口 key 有调用次数限制,联调通过后不要反复请求,避免额度耗尽。