订阅消息鉴权和发送订阅消息
/**
* @description: 订阅消息鉴权
*/
export function getSubscriptionSetting() {
return wx
.getSetting({
withSubscriptions: true,
})
.then(res => {
console.log(res, '调起授权界面弹窗')
// 调起授权界面弹窗
if (!res.subscriptionsSetting.mainSwitch) {
wx.showToast({
title: '请到小程序设置-订阅消息-接收通知中开启订阅消息',
icon: 'none',
duration: 8000,
})
return false
} else {
console.log('success')
return true
}
})
.catch(err => {
console.log(err, 'getSetting失败')
return false
})
}
/**
* @description: 发送模板消息
* @param {String} tmplId 模板消息id
*/
export function subscription(tmplId) {
return wx
.requestSubscribeMessage({
// 调起消息订阅界面
tmplIds: [tmplId],
})
.then(res => {
console.log(res, '订阅消息 成功 ')
})
.catch(err => {
console.log(err, '订阅消息 失败 ')
})
}
获取经纬度
/* 获取用户当前经纬度 */
export function getLocation() {
return new Promise((resolve) => {
wx.authorize({
scope: "scope.userLocation", // 位置授权
success: (_res) => {
wx.getLocation({
type: "gcj02",
success: (res) => {
resolve({
longitude: res.longitude,
latitude: res.latitude,
});
},
fail: (_err) => {
wx.getSetting({
success: (res) => {
if (!res.authSetting["scope.userLocation"]) {
wx.showModal({
title: "打开定位授权",
success: (res) => {
if (res.confirm) {
wx.openSetting({
success: (_open) => {
wx.getLocation({
type: "gcj02",
success: (res) => {
resolve(res.longitude, res.latitude);
},
});
},
});
}
},
});
} else {
wx.showModal({
title: "您手机定位功能没有开启",
content: "请在系统设置中打开定位服务",
showCancel: false,
success: () => {},
});
}
},
});
},
});
},
fail: (_err) => {
wx.showModal({
title: "提示",
content: "您拒绝了位置的授权,将无法使用地图功能",
showCancel: false,
success: function (_res) {
wx.openSetting({
complete() {
getLocation();
},
});
},
});
},
});
});
}
request请求封装
需要进一步根据后端封装修改
const globalData = getApp().globalData
/**
* @typedef {Object} requestReturns
* @property {String} Message
* @property {Number} Tag
* @property {Object} Data
*/
/**
* @param {String} title loading的标题
* @param {String} url 请求url
* @param {Object} data request body
* @returns {Promise<requestReturns>}
*/
const request = function (title, url, data) {
if (title != '') {
wx.showLoading({
title: title,
mask: true,
})
}
const token = wx.getStorageSync('token')
token && (data.Token = token)
const header = { 'content-type': 'application/json;charset=UTF-8' }
return new Promise((resolve, reject) => {
wx.request({
url: globalData.serverUrl + url,
method: 'POST',
data: data,
header: header,
timeout: 60000,
success: res => {
title && wx.hideLoading()
if (res.statusCode === 200) {
resolve(res.data)
} else {
wx.showToast({
title: '请求错误,请稍后重试!',
icon: 'none',
})
reject('请求错误,请稍后重试!')
}
},
fail: () => {
title && wx.hideLoading()
wx.showToast({
title: '服务器开小差了,再试一下吧~',
icon: 'none',
})
reject('请求失败')
},
})
})
}
export default request
图片临时地址 base64互转
const fsm = wx.getFileSystemManager();
/**
* @description: base64转图片临时url
* @param {String} base64data base64url
* @param {Function} cb 成功的回调函数,参数是图片临时url
*/
export function base64src(base64data, cb) {
const [, format, bodyData] =
/data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
const FILE_BASE_NAME = new Date().getTime().toString(); //自定义文件名
if (!format) {
return new Error("ERROR_BASE64SRC_PARSE");
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
const buffer = wx.base64ToArrayBuffer(bodyData);
fsm.writeFile({
filePath,
data: buffer,
encoding: "binary",
success() {
cb(filePath);
},
fail() {
return new Error("ERROR_BASE64SRC_WRITE");
},
});
}
/**
* @description: 图片临时url转base64
* @param {String} templateSrc
*/
export function srcToBase64(templateSrc) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: templateSrc,
success() {
wx.getFileSystemManager().readFile({
filePath: templateSrc, //选择图片返回的相对路径
encoding: "base64", //这个是很重要的
success: (res) => {
//成功的回调
//返回base64格式
var base64Str = res.data;
resolve(base64Str);
},
fail: (err) => {
reject(err);
},
});
},
});
});
}
图片or视频选择
/**
* @description: 获取一张图片
*/
export const chooseImage = async () => {
return new Promise((resolve, reject) => {
wx.chooseMedia({
count: 1,
mediaType: ['image'],
success(res) {
resolve(res.tempFiles[0].tempFilePath)
},
fail() {
reject('未选择图片')
},
})
})
}
文件选择(PC不可用)
wx.chooseMessageFile({
count: 1,
type: 'file',
extension: ['pdf'], // 替换为你自己需要的文件后缀名
success: async res => {
const fileTempUrl = res.tempFiles[0].path
const fileBase64 = await urlToBase64(fileTempUrl)
// 业务操作
},
})
文件选择(PC使用)
PC真机目前唯一选择文件的方法是嵌套一个webview网页
使用html的input[type="file"]可以获取文件内容、大小、真实名称等,也能指定需要上传的后缀
注意必须要引入jweixin jssdk包,postMessage方法会在页面会退回webview上一级小程序页面栈时触发,传递所需要的上传信息
也可以在html文件的js中直接完成上传的逻辑,而非跳转回到小程序进行上传
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
width: 400px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.heading {
font-size: 24px;
text-align: center;
margin-bottom: 20px;
}
.description {
font-size: 18px;
margin-bottom: 20px;
}
.upload-button {
display: block;
margin: 0 auto;
text-align: center;
width: 80px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.label {
display: inline-block;
text-align: center;
}
.upload-button:hover {
background-color: #0056b3;
}
#fileItem {
position: absolute;
left: -999px;
opacity: 0;
}
</style>
</head>
<body>
<div class="container">
<h1 class="heading">文件上传</h1>
<p class="description">操作步骤</p>
<p class="description">1、点击一键上传</p>
<p class="description">2、请选择您要上传的文件</p>
<p class="description">3、上传文件最大为2m</p>
<label for="fileItem" class="upload-button" id="uploadButton">
一键上传
</label>
<input id="fileItem" type="file">
</div>
<script src="./jweixin-1.3.2.js"></script>
<script>
var fileInput = document.getElementById("fileItem");
fileInput.addEventListener("change", function (event) {
var selectedFile = event.target.files[0];
if (selectedFile) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
// 截取文件base64
var base64Data = loadEvent.target.result.split(",")[1];
// 获取文件大小
var fileSize = selectedFile.size
var name = selectedFile.name
var data = {
base64Data: base64Data,
fileSize: fileSize,
name: name,
}
wx.miniProgram.postMessage({
data: data
});
wx.miniProgram.navigateBack();
};
reader.readAsDataURL(selectedFile);
}
});
</script>
</body>
</html>
获取传入base64的文件类型
如果传入的base64没有前缀会报错,请规范传入的字符串或者兜底处理
/**
* @description: 传入base64字符串,获取文件的类型
* @param {string} base64Data base64字符串
*/
export const getFileExtensionFromBase64 = base64Data => {
// 获取 Base64 数据的标识信息部分(如"data:image/png;base64,")
const base64Identifier = base64Data.split(',')[0]
// 提取文件类型部分(如"image/png")
const fileType = base64Identifier.split(';')[0].split(':')[1]
// 获取文件后缀(如"png")
const fileExtension = fileType.split('/')[1]
return fileExtension
}
PC端文件和图片保存
saveFileToDisk只能用于PC端,可以保存到用户指定的任意位置
/**
* @description: 文件保存(仅限PC端使用)
* @param {string} base64Data base64字符串,需要携带前缀
* @param {string} fileRealName 待保存的文件名
* @returns {Promise<void>}
*/
export const saveFile = (base64Data, fileRealName) => {
return new Promise((resolve, reject) => {
const fs = wx.getFileSystemManager()
const handledBase64Data = decodeURIComponent(base64Data)
const fileType = getFileExtensionFromBase64(handledBase64Data)
const filename = `${fileRealName}.${fileType}`
const filePath = `${wx.env.USER_DATA_PATH}/${filename}`
const data = extractBase64FromPrefix(handledBase64Data)
fs.writeFile({
filePath,
data: data,
encoding: 'base64',
success: () => {
wx.saveFileToDisk({
filePath: `${wx.env.USER_DATA_PATH}/${filename}`,
success() {
resolve()
},
fail(err) {
reject(err)
},
})
},
})
})
}
非PC端文件保存
第一步writeFile会把文件写入到微信的临时缓存目录,但这个目录一到2g会自动清空,并且用户也很难找到这个目录
第二步openDocument可以临时打开这个文件,真机右上角会有操作按钮支持用户自己保存
const fs = wx.getFileSystemManager();
const fileType = "文件类型后缀";
const fileData = "无类型前缀的base64字符串";
const filePath = wx.env.USER_DATA_PATH + "/" + Date.now() + `.${fileType}`;
fs.writeFile({
filePath,
data: fileData,
encoding: "base64",
success: () => {
wx.showModal({
title: "提示",
content: "请从右上角保存",
success() {
wx.openDocument({
filePath,
showMenu: true,
fileType: fileType,
});
},
});
},
});
非PC端图片保存
使用previewImage api的长按操作,就可以保存到用户的相册,imgUrl可以是网络地址,也可以是base64,还可以是临时图片地址
const imgUrl = "图片的URL";
wx.showModal({
title: "提示",
content: "请长按保存到相册",
success() {
wx.previewImage({
current: imgUrl, // 当前显示图片的http链接
urls: [imgUrl], // 需要预览的图片http链接列表
});
},
});
图片base64和临时url互转
const fsm = wx.getFileSystemManager()
/**
* @description: base64转图片临时url
* @param {String} base64data base64url
* @param {Function} cb 成功的回调函数,参数是图片临时url
*/
export function base64src(base64data, cb) {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []
const FILE_BASE_NAME = new Date().getTime().toString() //自定义文件名
if (!format) {
return new Error('ERROR_BASE64SRC_PARSE')
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`
const buffer = wx.base64ToArrayBuffer(bodyData)
fsm.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
cb(filePath)
},
fail() {
return new Error('ERROR_BASE64SRC_WRITE')
},
})
}
/**
* @description: 图片临时url转base64
* @param {String} templateSrc
* @returns {Promise<string>} base64字符串
*/
export function srcToBase64(templateSrc) {
console.log(templateSrc)
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: templateSrc,
success() {
wx.getFileSystemManager().readFile({
filePath: templateSrc, //选择图片返回的相对路径
encoding: 'base64', //这个是很重要的
success: res => {
console.log(res)
//成功的回调
//返回base64格式
var base64Str = res.data
resolve(base64Str)
},
fail: err => {
console.log(err)
reject(err)
},
})
},
fail(err) {
console.log('getImageInfo 失败', err)
},
})
})
}