项目描述
本文讲述从微信小程序代码编辑到个人开发者微信小程序发布大致过程,其中使用了微信官方接口wx.chooseLocation实现获取当前用户地理位置信息,下方小程序为实体效果,可扫描看下是否胃口,具体实现步骤请往下滑…
前期准备
项目主要功能为展现近24小时天气及展示7天天气预报信息,接口数据准备如下
1. 和风天气SDK
和风天气官网获取天气SDK,个人开发者注册后可免费使用1个SDK
因作者已创建项目,无法选择免费订阅,具体操作如下:选择免费订阅,选择Web API其他名称自行输入后创建,成功后查看KEY,这玩意等下代码内会用着
2.微信小程序接口权限
微信小程序公众号获取地理信息接口权限
登录微信小程序公众号>>开发管理>>接口设置,如图
这里进行小程序接口权限申请,最好是申请黄色框内权限,但作者看了哈,个人开发者貌似比较麻烦更甚着无法申请,作者就未作纠结就申请了红色框内权限(申请时间大概花费两小时)
如果后来者只是想了解一下,不想将小程序提交为线上小程序情况可忽略此步骤
上代码
wxml代码
<view class="header-modular" wx:if="{{now}}">
<image class="bg-wave" src="https://codermoyv.gitee.io/coder-moyv/assets/images/wechat/bg_wave.gif"></image>
<view class="row">
<view class="row location-wrap" bindtap="designatedSpot">
<image class="icon" src="/images/icon_location.png"></image>
<view class="title">{{City}} {{County}}</view>
</view>
</view>
<view class="row">
<view class="tmp">{{now.temp}}°</view>
<image class="icon-weather" src="https://codermoyv.gitee.io/coder-moyv/assets/images/wechat/weather_custom/{{now.icon}}.png"></image>
</view>
<view class="tips-wrap">
<view class="tips ">{{now.windDir}} {{now.windScale}}级</view>
<view class="tips ">湿度 {{now.humidity}}%</view>
<view class="tips ">气压 {{now.pressure}}Pa</view>
</view>
</view>
<view class="card-modular " wx:if="{{hourly}}">
<view class="title">24小时预报</view>
<view class="card-wrap">
<block wx:for="{{hourly}}" wx:key="index">
<view class="item hourly">
<view class="text-gray">{{item.time}}</view>
<image class="icon" src="https://codermoyv.gitee.io/coder-moyv/assets/images/wechat/weather_custom/{{item.icon}}.png"></image>
<view class="text-primary mb-32">{{item.temp}}°</view>
<view>{{item.windDir}}</view>
<view class="text-gray">{{item.windScale}}级</view>
</view>
</block>
</view>
</view>
<view class="card-modular" wx:if="{{daily}}">
<view class="title">7天预报</view>
<view class="card-wrap">
<block wx:for="{{daily}}" wx:key="index">
<view class="item daily">
<view>{{item.dateToString}}</view>
<view class="text-gray">{{item.date}}</view>
<image class="icon" src="https://codermoyv.gitee.io/coder-moyv/assets/images/wechat/weather_custom/{{item.iconDay}}.png"></image>
<view class="text-primary ">{{item.tempMin}}°~{{item.tempMax}}°</view>
<image class="icon" src="https://codermoyv.gitee.io/coder-moyv/assets/images/wechat/weather_custom/{{item.iconNight}}.png"></image>
<view>{{item.windDirDay}}</view>
<view class="text-gray">{{item.windScaleDay}}级</view>
</view>
</block>
</view>
</view>
js代码
需输入自己获取的KEY
//和天下 天气apikey
const APIKEY = "KEY";
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getLocation()
},
designatedSpot() {
var that = this
wx.chooseLocation({
success(res) {
that.setData({
location: res.longitude + "," + res.latitude
})
that.getWeather()
that.getCityByLoaction()
},
fail() {
wx.chooseLocation({
type: 'gcj02',
fail() {
wx.showModal({
title: '获取地图位置失败',
content: '为了给您提供准确的天气预报服务,请在设置中授权【位置信息】',
success(mRes) {
if (mRes.confirm) {
wx.openSetting({
success: function (data) {
if (data.authSetting["scope.userLocation"] === true) {
that.designatedSpot()
} else {
wx.showToast({
title: '授权失败',
icon: 'none',
duration: 1000
})
}
},
fail(err) {
console.log(err)
wx.showToast({
title: '唤起设置页失败,请手动打开',
icon: 'none',
duration: 1000
})
}
})
}
}
})
}
})
}
})
},
getLocation() {
var that = this
wx.chooseLocation({
type: 'gcj02',
success(res) {
that.setData({
location: res.longitude + "," + res.latitude
})
that.getWeather()
that.getCityByLoaction()
},
fail(err) {
wx.showModal({
title: '获取定位信息失败',
content: '为了给您提供准确的天气预报服务,请在设置中授权【位置信息】',
success(mRes) {
if (mRes.confirm) {
wx.openSetting({
success: function (data) {
if (data.authSetting["scope.userLocation"] === true) {
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1000
})
that.getLocation()
} else {
wx.showToast({
title: '授权失败',
icon: 'none',
duration: 1000
})
that.setData({
location: "116.41,39.92"
})
that.getWeather()
that.getCityByLoaction()
}
},
fail(err) {
console.log(err)
wx.showToast({
title: '唤起设置页失败,请手动打开',
icon: 'none',
duration: 1000
})
that.setData({
location: "116.41,39.92"
})
that.getWeather()
that.getCityByLoaction()
}
})
} else if (mRes.cancel) {
that.setData({
location: "116.41,39.92"
})
that.getWeather()
that.getCityByLoaction()
}
}
})
}
})
},
getCityByLoaction() {
var that = this
wx.request({
url: 'https://geoapi.qweather.com/v2/city/lookup?key=' + APIKEY + "&location=" + that.data.location,
success(result) {
var res = result.data
if (res.code == "200") {
var data = res.location[0]
that.setData({
City: data.adm2,
County: data.name
})
} else {
wx.showToast({
title: '获取城市信息失败',
icon: 'none'
})
}
}
})
},
getWeather() {
var that = this
wx.showLoading({
title: '加载中',
})
wx.request({
url: 'https://devapi.qweather.com/v7/weather/now?key=' + APIKEY + "&location=" + that.data.location,
success(result) {
var res = result.data
that.setData({
now: res.now
})
}
})
wx.request({
url: 'https://devapi.qweather.com/v7/weather/24h?key=' + APIKEY + "&location=" + that.data.location,
success(result) {
var res = result.data
res.hourly.forEach(function (item) {
item.time = that.formatTime(new Date(item.fxTime)).hourly
})
that.setData({
hourly: res.hourly
})
}
})
wx.request({
url: 'https://devapi.qweather.com/v7/weather/7d?key=' + APIKEY + "&location=" + that.data.location,
success(result) {
var res = result.data
res.daily.forEach(function (item) {
item.date = that.formatTime(new Date(item.fxDate)).daily
item.dateToString = that.formatTime(new Date(item.fxDate)).dailyToString
})
that.setData({
daily: res.daily
})
wx.hideLoading()
}
})
},
formatTime(date) {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
const weekArray = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]
const isToday = date.setHours(0, 0, 0, 0) == new Date().setHours(0, 0, 0, 0)
return {
hourly: [hour, minute].map(this.formatNumber).join(":"),
daily: [month, day].map(this.formatNumber).join("-"),
dailyToString: isToday ? "今天" : weekArray[date.getDay()]
}
},
formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
wxss代码
page {
background-color: linear-gradient(to bottom, #ffffff, #ffffff, #F6F6F6);
padding-bottom: 60rpx;
}
.row {
display: flex;
align-items: center;
}
.mb-32 {
margin-bottom: 32rpx;
}
.header-modular {
height: 400rpx;
background-color: #64C8FA;
background: linear-gradient(to bottom, #56CCF2, #2F80ED);
position: relative;
padding: 30rpx;
}
.header-modular .bg-wave {
width: 100vw;
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 120rpx;
mix-blend-mode: screen;
}
.header-modular .location-wrap {
color: #ffffff;
font-weight: bold;
font-size: 36rpx;
}
.header-modular .location-wrap .icon {
width: 40rpx;
height: 40rpx;
margin-right: 8rpx;
}
.header-modular .tmp {
font-size: 200rpx;
color: #ffffff;
margin-right: auto;
}
.header-modular .icon-weather {
width: 200rpx;
height: 200rpx;
}
.header-modular .tips-wrap {
display: flex;
justify-content: space-between;
}
.header-modular .tips {
font-size: 28rpx;
opacity: 0.8;
color: #ffffff;
flex: 1;
}
.header-modular .tips:nth-child(3) {
text-align: right;
}
.header-modular .tips:nth-child(2) {
text-align: center;
}
.card-modular {
padding: 0 30rpx;
margin-top: 30rpx;
}
.card-modular>.title {
font-size: 40rpx;
font-weight: bold;
position: relative;
margin-left: 14rpx;
margin-bottom: 16rpx;
}
.card-modular>.title::before {
content: "";
position: absolute;
left: -14rpx;
top: 10rpx;
bottom: 10rpx;
width: 8rpx;
border-radius: 10rpx;
background-color: #2F80ED;
}
.card-modular .card-wrap {
width: 690rpx;
border-radius: 18rpx;
background-color: #ffffff;
box-shadow: 0 0 20rpx 0 rgba(0, 0, 0, 0.2);
overflow-x: auto;
white-space: nowrap;
}
.card-modular .card-wrap .item {
display: inline-flex;
flex-direction: column;
align-items: center;
font-size: 28rpx;
padding: 18rpx 0;
}
.card-modular .card-wrap .item.hourly {
width: 138rpx;
}
.card-modular .card-wrap .item.daily {
width: 172.5rpx;
}
.card-modular .card-wrap .item .icon {
width: 60rpx;
height: 60rpx;
margin: 64rpx 0;
}
.card-modular .card-wrap .item .text-gray {
color: gray;
}
.card-modular .card-wrap .item .text-primary {
color: #2F80ED;
}
app.json代码
小程序之前进行了更新,使用定位需在app.json文件内添加如下代码,如小程序不需要上线可忽略
{
"permission": {
"scope.userLocation": {
"desc": "小程序需要使用您的位置信息 已确认您的采样地址"
}
},
"requiredPrivateInfos": [
"chooseLocation"
]
}
如小程序不需要显示底部导航栏,则在app.json内删除键值对“tabBar”信息即可
小程序上线
代码提交审核
首先进入微信小程序公众号>>版本管理,此时在开发者工具内上次的版本会出现在开发版本内,此时点击提交审核进入审核步骤,如存在微信小程序接口权限未申请、app.json对应接口信息未添加情况将直接申请不通过。
等待代码审核通过(作者忘记了具体时间,只记得下午16点左右提交了审核,23点突然想起,进入发现已审核过)
小程序发布
代码审核后可直接提交为线上版本(此过程大概20分钟),但因上线问题需要填写小程序一些用途、协议等,如实填写即可
结尾
溜了