food_wechat/utils/index.js
air 747ee9226f 【类 型】:feat
【原  因】:客服功能 拨打电话
【过  程】:调用微信提供的拨打电话接口 从后台获取客服的电话参数
【影  响】:

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2025-01-16 14:14:10 +08:00

333 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import mqtt from './mqtt.js'
import store from '../store/index.js'
/**
* 文本过长截取
* @param {string} value 文本内容
* @param {Number} length 设定长度
* @returns {string} 截取完的内容最后加省略号
*/
export function truncate(value, length = 5) {
if (!value) return '';
return value.length > length ? value.slice(0, length) + '...' : value;
}
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else {
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
// eslint-disable-next-line camelcase
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
return value.toString().padStart(2, '0')
})
// eslint-disable-next-line camelcase
return time_str
}
/**
* 过滤时间 格式化当天时间 比如把"20:00:00" 格式化成(晚上)8:00
* @param {string} value 时间格式位"20:00:00"
*/
export function formatTime(value) {
if (!value) return '' // 如果时间为空,则返回空字符串
// 将时间字符串转换为 Date 对象
let time = new Date("2000/01/01 " + value)
// 获取小时和分钟
let hour = time.getHours()
let minute = time.getMinutes()
// 根据小时判断是上午还是下午
let period = hour >= 12 ? '下午' : '上午'
// 格式化小时如果是下午则减去12小时
hour = hour % 12 === 0 ? 12 : hour % 12
// 格式化分钟,补零操作
minute = minute.toString().padStart(2, '0')
return `(${period})${hour}:${minute}`
}
/**
* 格式化秒数为 mm:ss 的格式
* @param {number} seconds 总秒数
* @returns {string} 格式化后的时间字符串
*/
export function formatSeconds(seconds) {
if (seconds < 0) return '00:00' // 如果秒数为负,则返回 00:00
let minutes = Math.floor(seconds / 60)
let remainingSeconds = seconds % 60
minutes = minutes.toString().padStart(2, '0')
remainingSeconds = remainingSeconds.toString().padStart(2, '0')
return `${minutes}:${remainingSeconds}`
}
/**
* 过滤价格数值 超过小数点两位得 保留两位
* @param {string} value
*/
export function formatPrice(value) {
if (isNaN(value)) return '' // 如果不是数字,则返回空字符串
// 格式化价格为保留两位小数
let formattedPrice = parseFloat(value).toFixed(2)
// 如果价格有两位小数以上,则保留两位小数,否则显示整数或者一位小数
let decimalCount = (formattedPrice.split('.')[1] || []).length
if (decimalCount > 2) {
formattedPrice = parseFloat(formattedPrice).toFixed(2)
}
return formattedPrice
}
/**
* 计算单spu 的单价 ps: spu可能有单sku组成 也可能
* @param {string} value
*/
export function calculateTotal(order) {
// 检查参数是否有效
if (!order || typeof order !== 'object' || !order.spu_id || !order.skuG || !order.countG || !order
.priceG) {
return ''
}
// 计算总价
let total = 0
for (let i = 0; i < order.skuG.length; i++) {
let price = parseFloat(order.priceG[i])
if (!isNaN(price)) {
total += price
}
}
// 保留两位小数并返回
return total.toFixed(2)
}
/**
* 计算单购物车列表商品的价格总和
* @param {string} cartList 购物车列表
* @returns {string | null} 价格总和
*/
export function totalPrice(cartList) {
let totalPrice = 0
if (cartList.length !== 0) {
cartList.forEach(item => {
for (let i = 0; i < item.priceG.length; i++) {
totalPrice += item.priceG[i] * item.countG[i]
}
})
}
return Number(totalPrice) // 将 totalPrice 转换为小数点后两位的格式
}
/**
* 检查用户信息登录 信息
*/
export function checkUserInfo() {
//刚打开app token未赋值到内存时
if (store.state.userInfo.token === null) {
//先从storage里调取token
uni.getStorage({
key: 'userInfo',
success: (res) => {
store.commit('setUserInfo', res.data) //token拿到内存当中
//验证token
isTokenValid().then((isValid) => {
if (isValid.data.status === -1) { //token验证失败或过期
//清除内存和本地的token
store.commit('clearUserInfo')
uni.removeStorage({
key: 'userInfo'
})
//重新登录并且把token写入本地和内存 登录失败跳转到登陆页面
wxLogin()
} else { //token验证成功之后
if (!store.state.mqttState) { //判断是否已经订阅了mqtt
initMqtt() //连接mqtt 并订阅 和执行回调逻辑
store.commit('setMqttState', true) //标记订阅
}
//登录成功后更新一次订单列表
store.dispatch('fetchOrderList')
}
})
},
fail: (err) => { //storage没有token进行登录
//重新登录并且把token写入本地和内存 登录失败跳转到登陆页面
wxLogin()
}
})
} else { //内存中已经赋值了token时
//验证token
isTokenValid().then((isValid) => {
if (isValid.data.status === -1) { //token验证失败或过期
//清除内存和本地的token
store.commit('clearUserInfo')
uni.removeStorage({
key: 'userInfo'
})
//重新登录并且把token写入本地和内存 登录失败跳转到登陆页面
wxLogin()
} else { //token验证成功之后
if (!store.state.mqttState) { //判断是否已经订阅了mqtt
initMqtt() //连接mqtt 并订阅 和执行回调逻辑
store.commit('setMqttState', true) //标记订阅
}
}
})
}
}
/**
* 微信登录 ps;请求接口 判断token是否有效
*/
async function isTokenValid() {
const res = await uni.$u.http.get('/Api/Check/index', {
header: {
'Token': store.state.userInfo.token,
}
})
return res
}
/**
* 微信登录 ps;无感登录
*/
export function wxLogin() {
uni.login({
provider: 'weixin',
success: res => {
if (res.code) {
uni.$u.http.post('/Api/Login/authLogin', {
code: res.code
}, {
header: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(res => {
// 登录接口访问成功后
if (res.data.status === 0) {
uni.redirectTo({ //无感登录失败 跳转到登陆页面
url: '/pages/main/login'
})
} else if (res.data.status === 1) {
//写入 用户信息缓存
uni.setStorage({
key: 'userInfo',
data: res.data.userInfo,
success: () => {
//登录成功后 把用户信息提取到内存
store.commit('setUserInfo', res.data.userInfo)
//登录成功后更新一次订单列表
store.dispatch('fetchOrderList')
}
})
}
})
} else {
uni.redirectTo({ //无感登录失败 跳转到登陆页面
url: '/pages/main/login'
})
}
},
fail: err => {
uni.redirectTo({ //无感登录失败 跳转到登陆页面
url: '/pages/main/login'
})
}
})
}
/**
* 微信登录 ps;订阅主题
* @param {obj} store vex $store对象
*/
function initMqtt() {
/* mqtt */
mqtt.mqttConf() // 连接mqtt
// 订阅游客下单频道
const topic = `refreshOrderList/${store.state.userInfo.topic_prefix}`
mqtt.doSubscribe(topic, (res) => {
if (res.topic.indexOf(topic) > -1) {
store.dispatch('fetchOrderList').then(() => {
console.log('有订单更新')
}) //更新订单
}
})
}
/**
* 微信接口 拨打电话
* @param {string} tel 电话号码
*/
export function callPhone(tel) {
if (!tel) {
console.error("电话号码为空,无法拨打")
wx.showToast({
title: "电话号码为空",
icon: "none",
duration: 2000
})
return
}
wx.showActionSheet({
itemList: [`拨打电话:${tel}`],
success: () => {
wx.makePhoneCall({
phoneNumber: tel, // 电话号码来源
success: () => {
console.log("拨打电话成功")
wx.showToast({
title: "电话拨打完成",
icon: "success",
duration: 2000
})
},
fail: (err) => {
console.error("拨打电话失败", err)
}
})
},
fail: (err) => {
console.error("用户取消拨打电话", err)
}
})
}