商城测试版v8_1

This commit is contained in:
2022-07-30 17:11:42 +08:00
parent e2b0b0c52b
commit 09e34ecabe
39 changed files with 3360 additions and 3274 deletions
+440 -440
View File
@@ -1,477 +1,477 @@
import React, {useRef, useState } from "react"
import Taro from "@tarojs/taro";
import { Command } from "@/common/bluetooth/command";
import { uint8ArrayToFloat32, uint8ArrayToHex, waitFor } from "@/common/bluetooth/utils";
import React, { useRef, useState } from 'react'
import Taro from '@tarojs/taro'
import { Command } from '@/common/bluetooth/command'
import { uint8ArrayToFloat32, uint8ArrayToHex, waitFor } from '@/common/bluetooth/utils'
interface params {
init: () => void
state: Object,
startScan: () => void,
measureAndGetLab: () => any,
getAdapterState: () => void,
connect: (any) => void,
disconnect: () => void
init: () => void
state: Object
startScan: () => void
measureAndGetLab: () => any
getAdapterState: () => void
connect: (any) => void
disconnect: () => void
}
const Context = React.createContext<params|unknown>(null)
const Context = React.createContext<params | unknown>(null)
interface stateStype {
listeners: any,
discovering: boolean,
available: boolean,
connected: any,
connecting: any,
serviceRule: any,
serviceId: any,
characteristicRule: any,
characteristicId: any,
listeners: any
discovering: boolean
available: boolean
connected: any
connecting: any
serviceRule: any
serviceId: any
characteristicRule: any
characteristicId: any
/** 正在执行的命令 */
command: any,
responseResolve: any,
responseReject: any,
responseTimer: any,
/** 正在执行的命令 */
command: any
responseResolve: any
responseReject: any
responseTimer: any
/** 是否显示蓝牙调试信息 */
debug: any,
//搜索到的设备
devices: any,
//取色仪主动返回的数据
deviceLab: any
/** 是否显示蓝牙调试信息 */
debug: any
//搜索到的设备
devices: any
//取色仪主动返回的数据
deviceLab: any
}
let stateObj: stateStype = {
/** 事件监听器 */
listeners: new Set(),
/** 正在扫描设备 */
discovering: false,
/** 蓝牙是否可用 */
available: true,
/** 当前连接的设备 */
connected: null,
/** 正在连接的设备 */
connecting: null,
/** 事件监听器 */
listeners: new Set(),
/** 正在扫描设备 */
discovering: false,
/** 蓝牙是否可用 */
available: true,
/** 当前连接的设备 */
connected: null,
/** 正在连接的设备 */
connecting: null,
serviceRule: /^0000FFE0/,
serviceId: null,
characteristicRule: /^0000FFE1/,
characteristicId: null,
serviceRule: /^0000FFE0/,
serviceId: null,
characteristicRule: /^0000FFE1/,
characteristicId: null,
/** 正在执行的命令 */
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
/** 正在执行的命令 */
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
/** 是否显示蓝牙调试信息 */
debug: true,
//搜索到的设备
devices: [],
//取色仪主动返回的数据
deviceLab: null
/** 是否显示蓝牙调试信息 */
debug: true,
//搜索到的设备
devices: [],
//取色仪主动返回的数据
deviceLab: null,
}
export default (props) => {
let refStatus = useRef(stateObj)
let [state, setState] = useState(refStatus.current)
let refStatus = useRef(stateObj)
let [state, setState] = useState(refStatus.current)
const changeStatus = (obj:Object): void => {
refStatus.current = {...refStatus.current, ...obj}
setState({...refStatus.current})
const changeStatus = (obj: Object): void => {
refStatus.current = { ...refStatus.current, ...obj }
setState({ ...refStatus.current })
}
const init = async () => {
try {
await openAdapter()
} catch (e) {
changeStatus({ available: false })
}
const init = async () => {
try{
await openAdapter();
}catch(e) {
changeStatus({available:false})
}
// 绑定事件通知
Taro.onBluetoothAdapterStateChange(res => {
emit({ type: 'stateUpdate', detail: res });
});
Taro.onBLEConnectionStateChange(res => {
emit({ type: res.connected ? 'connected' : 'disconnect', detail: res });
});
Taro.onBLECharacteristicValueChange(({ value }) => notifySubscriber(value));
subscribe(async ev => {
if (ev.type === 'stateUpdate') {
// 蓝牙状态发生的变化
changeStatus({discovering:ev.detail.discovering, available:ev.detail.available})
} else if (ev.type === 'disconnect' && refStatus.current.connected && refStatus.current.connected.deviceId === ev.detail.deviceId) {
// 断开连接
changeStatus({
connected:null,
serviceId:null,
characteristicId:null,
deviceLab:null,
devices:[]
})
Taro.showToast({ icon: 'none', title: '蓝牙连接已断开' });
} else if (ev.type === 'connected' && refStatus.current.connecting) {
// 连接成功
changeStatus({connected: refStatus.current.connecting, connecting: null})
Taro.showToast({ title: '蓝牙已连接' });
} else if (ev.type === 'measure') {
//监听取色仪主动推送lab
await measureAndGetLab()
}
});
}
/** 打开蓝牙适配器 */
const openAdapter = () => {
return new Promise((resolve, reject) => {
Taro.openBluetoothAdapter({
success: resolve,
fail: reject
});
});
}
/**
* 推送事件
* @param {{type: string; data: any}} event
*/
const emit = (event) => {
refStatus.current.listeners.forEach(cb => {
cb && cb(event);
});
}
const subscribe = (cb) => {
if (cb) {
changeStatus({
listeners: refStatus.current.listeners.add(cb)
})
}
}
/**
* 获取蓝牙适配器状态
* @returns {Promise<{discovering: boolean; available: boolean}>}
*/
const getAdapterState = () => {
return new Promise((resolve, reject) => {
Taro.getBluetoothAdapterState({
success: resolve,
fail: reject
})
})
}
/**
* 启动设备扫描
* @param {(res: { devices: { name: string, deviceId: string, RSSI: number }[] }) => void} cb
* @param {number} duration
*/
const startScan = (duration = 30000) => {
console.log('开始寻找')
changeStatus({devices:[]})
Taro.onBluetoothDeviceFound(getDevices);
return new Promise((resolve, reject) => {
Taro.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: resolve,
fail: reject
});
if (duration > 0) {
setTimeout(() => {
Taro.offBluetoothDeviceFound(getDevices);
Taro.stopBluetoothDevicesDiscovery();
console.log("停止搜索")
}, duration);
}
});
}
//获取搜索到的设备
const getDevices = (res) => {
res.devices.forEach(device => {
// 排除掉已搜索到的设备和名称不合法的设备, 将新发现的设备添加到列表中
if (/^CM/.test(device.name) && !refStatus.current.devices.find(i => i.deviceId === device.deviceId)) {
changeStatus({devices: [ ...refStatus.current.devices, device ]})
}
});
}
/**
* 连接设备
* @param {{ name: string, deviceId: string, RSSI: number }} device
*/
const connect = async (device) => {
try {
changeStatus({connecting: device})
console.log('connecting::', device)
await createConnection(device.deviceId);
await discoverService(device.deviceId);
await discoverCharacteristic(device.deviceId);
await notifyCharacteristicValueChange(device.deviceId);
} catch (e) {
changeStatus({connecting: null})
Taro.showToast({ icon: 'none', title: '蓝牙连接失败' });
throw e;
}
}
/** 断开当前连接的设备 */
const disconnect = async () => {
if (!refStatus.current.connected && !refStatus.current.connecting) return;
if (refStatus.current.connected) {
await closeConnection(refStatus.current.connected.deviceId);
resetCommand();
changeStatus({
connected: null,
serviceId: null,
characteristicId: null,
devices: [],
deviceLab: null
})
}
if (refStatus.current.connecting) {
await closeConnection(refStatus.current.connecting.deviceId);
changeStatus({connecting:null})
}
}
/** 创建 BLE 连接 */
function createConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
deviceId,
timeout: 2000,
success: resolve,
fail: reject
});
});
}
/** 关闭 BLE 连接 */
function closeConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.closeBLEConnection({
deviceId,
success: resolve,
fail: reject
});
});
}
/** 搜索服务 */
function discoverService(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceServices({
deviceId,
success: ({ services }) => {
const service = services.find(i => refStatus.current.serviceRule.test(i.uuid));
if (!service) {
reject(new Error('服务不可用'));
} else {
changeStatus({serviceId: service.uuid})
resolve(service);
}
},
fail: reject
});
});
}
/** 搜索特征 */
function discoverCharacteristic(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId: refStatus.current.serviceId,
success: ({ characteristics }) => {
const characteristic = characteristics.find(i => refStatus.current.characteristicRule.test(i.uuid));
if (!characteristic) {
reject(new Error('特征不可用'));
} else {
changeStatus({characteristicId: characteristic.uuid})
resolve(characteristic);
}
},
fail: reject
})
});
}
/** 启动特征通知 */
function notifyCharacteristicValueChange(deviceId, stateParm = true) {
return new Promise((resolve, reject) => {
Taro.notifyBLECharacteristicValueChange({
deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
state:stateParm,
success: resolve,
fail: reject
});
});
}
/**
* 通知订阅器
* @param {ArrayBuffer} buffer
*/
function notifySubscriber(buffer) {
if (refStatus.current.command) {
if (refStatus.current.debug) {
console.log(`[BLE RESP] ${uint8ArrayToHex(new Uint8Array(buffer))}`);
}
refStatus.current.command.fillResponse(buffer);
if (refStatus.current.command.isComplete) {
if (refStatus.current.command.isValid && refStatus.current.responseResolve) {
refStatus.current.responseResolve(refStatus.current.command.response);
} else if (!refStatus.current.command.isValid) {
refStatus.current.responseReject(new Error('无效数据'));
}
resetCommand();
}
} else {
const uint8Array = new Uint8Array(buffer);
if (uint8Array[0] === 0xbb && uint8Array[1] === 1 && uint8Array[3] === 0) {
const ev = { type: 'measure', detail: { mode: uint8Array[2] } };
emit(ev);
}
}
}
/**
* 发送命令
* @param {Command}} command
* @returns {Promise<Uint8Array>}
*/
function exec(command) {
return new Promise(async (resolve, reject) => {
if (refStatus.current.command) {
reject(new Error('正在执行其他命令'));
} else {
try {
refStatus.current.command = command;
const data = command.data;
for (let i = 0; i < data.length; i++) {
await sendData(data[i]);
}
if (command.responseSize <= 0) {
resolve(true);
resetCommand();
} else {
refStatus.current.responseReject = reject;
refStatus.current.responseResolve = resolve;
refStatus.current.responseTimer = setTimeout(() => {
reject(new Error('命令响应超时'));
resetCommand();
}, command.timeout);
}
} catch (e) {
reject(e);
}
}
});
}
/**
* 发送命令
* @param {ArrayBuffer} buffer
*/
function sendData(buffer) {
if (refStatus.current.debug) {
console.log(`[BLE SEND] ${uint8ArrayToHex(new Uint8Array(buffer))}`);
}
return new Promise((resolve, reject) => {
console.log('current:::',refStatus.current)
Taro.writeBLECharacteristicValue({
deviceId: refStatus.current.connected.deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
value: buffer,
success: resolve,
fail: reject
})
});
}
function resetCommand() {
if (refStatus.current.responseTimer) {
clearTimeout(refStatus.current.responseTimer);
}
// 绑定事件通知
Taro.onBluetoothAdapterStateChange((res) => {
emit({ type: 'stateUpdate', detail: res })
})
Taro.onBLEConnectionStateChange((res) => {
emit({ type: res.connected ? 'connected' : 'disconnect', detail: res })
})
Taro.onBLECharacteristicValueChange(({ value }) => notifySubscriber(value))
subscribe(async (ev) => {
if (ev.type === 'stateUpdate') {
// 蓝牙状态发生的变化
changeStatus({ discovering: ev.detail.discovering, available: ev.detail.available })
} else if (ev.type === 'disconnect' && refStatus.current.connected && refStatus.current.connected.deviceId === ev.detail.deviceId) {
// 断开连接
changeStatus({
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null
connected: null,
serviceId: null,
characteristicId: null,
deviceLab: null,
devices: [],
})
Taro.showToast({ icon: 'none', title: '蓝牙连接已断开' })
} else if (ev.type === 'connected' && refStatus.current.connecting) {
// 连接成功
changeStatus({ connected: refStatus.current.connecting, connecting: null })
Taro.showToast({ title: '蓝牙已连接' })
} else if (ev.type === 'measure') {
//监听取色仪主动推送lab
await measureAndGetLab()
}
})
}
/** 打开蓝牙适配器 */
const openAdapter = () => {
return new Promise((resolve, reject) => {
Taro.openBluetoothAdapter({
success: resolve,
fail: reject,
})
})
}
/**
* 推送事件
* @param {{type: string; data: any}} event
*/
const emit = (event) => {
refStatus.current.listeners.forEach((cb) => {
cb && cb(event)
})
}
const subscribe = (cb) => {
if (cb) {
changeStatus({
listeners: refStatus.current.listeners.add(cb),
})
}
}
/**
* 获取蓝牙适配器状态
* @returns {Promise<{discovering: boolean; available: boolean}>}
*/
const getAdapterState = () => {
return new Promise((resolve, reject) => {
Taro.getBluetoothAdapterState({
success: resolve,
fail: reject,
})
})
}
/**
* 启动设备扫描
* @param {(res: { devices: { name: string, deviceId: string, RSSI: number }[] }) => void} cb
* @param {number} duration
*/
const startScan = (duration = 30000) => {
console.log('开始寻找')
changeStatus({ devices: [] })
Taro.onBluetoothDeviceFound(getDevices)
return new Promise((resolve, reject) => {
Taro.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: resolve,
fail: reject,
})
if (duration > 0) {
setTimeout(() => {
Taro.offBluetoothDeviceFound(getDevices)
Taro.stopBluetoothDevicesDiscovery()
console.log('停止搜索')
}, duration)
}
})
}
//获取搜索到的设备
const getDevices = (res) => {
res.devices.forEach((device) => {
// 排除掉已搜索到的设备和名称不合法的设备, 将新发现的设备添加到列表中
if (/^CM/.test(device.name) && !refStatus.current.devices.find((i) => i.deviceId === device.deviceId)) {
changeStatus({ devices: [...refStatus.current.devices, device] })
}
})
}
/**
* 连接设备
* @param {{ name: string, deviceId: string, RSSI: number }} device
*/
const connect = async (device) => {
try {
changeStatus({ connecting: device })
console.log('connecting::', device)
await createConnection(device.deviceId)
await discoverService(device.deviceId)
await discoverCharacteristic(device.deviceId)
await notifyCharacteristicValueChange(device.deviceId)
} catch (e) {
changeStatus({ connecting: null })
Taro.showToast({ icon: 'none', title: '蓝牙连接失败' })
throw e
}
}
/** 断开当前连接的设备 */
const disconnect = async () => {
if (!refStatus.current.connected && !refStatus.current.connecting) return
if (refStatus.current.connected) {
await closeConnection(refStatus.current.connected.deviceId)
resetCommand()
changeStatus({
connected: null,
serviceId: null,
characteristicId: null,
devices: [],
deviceLab: null,
})
}
/**
* 测量
* @param {number} mode
* @returns {Promise}
*/
async function measure (mode = 0) {
console.log('current1:::',Command.WakeUp)
await exec(Command.WakeUp);
console.log('current2:::',Command.WakeUp)
await waitFor(50);
console.log('current3:::',Command.WakeUp)
return await exec(Command.measure(mode));
if (refStatus.current.connecting) {
await closeConnection(refStatus.current.connecting.deviceId)
changeStatus({ connecting: null })
}
}
/**
* 获取测量的 lab 值
* @param {number} mode
* @returns {Promise<{ L: number, a: number, b: number }>}
*/
async function getLab(mode = 0) {
await exec(Command.WakeUp);
await waitFor(50);
const data: any = await exec(Command.getLab(mode));
return {
L: uint8ArrayToFloat32(data.slice(5, 9)),
a: uint8ArrayToFloat32(data.slice(9, 13)),
b: uint8ArrayToFloat32(data.slice(13, 17)),
};
/** 创建 BLE 连接 */
function createConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
deviceId,
timeout: 2000,
success: resolve,
fail: reject,
})
})
}
/** 关闭 BLE 连接 */
function closeConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.closeBLEConnection({
deviceId,
success: resolve,
fail: reject,
})
})
}
/** 搜索服务 */
function discoverService(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceServices({
deviceId,
success: ({ services }) => {
const service = services.find((i) => refStatus.current.serviceRule.test(i.uuid))
if (!service) {
reject(new Error('服务不可用'))
} else {
changeStatus({ serviceId: service.uuid })
resolve(service)
}
},
fail: reject,
})
})
}
/** 搜索特征 */
function discoverCharacteristic(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId: refStatus.current.serviceId,
success: ({ characteristics }) => {
const characteristic = characteristics.find((i) => refStatus.current.characteristicRule.test(i.uuid))
if (!characteristic) {
reject(new Error('特征不可用'))
} else {
changeStatus({ characteristicId: characteristic.uuid })
resolve(characteristic)
}
},
fail: reject,
})
})
}
/** 启动特征通知 */
function notifyCharacteristicValueChange(deviceId, stateParm = true) {
return new Promise((resolve, reject) => {
Taro.notifyBLECharacteristicValueChange({
deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
state: stateParm,
success: resolve,
fail: reject,
})
})
}
/**
* 通知订阅器
* @param {ArrayBuffer} buffer
*/
function notifySubscriber(buffer) {
if (refStatus.current.command) {
if (refStatus.current.debug) {
console.log(`[BLE RESP] ${uint8ArrayToHex(new Uint8Array(buffer))}`)
}
refStatus.current.command.fillResponse(buffer)
if (refStatus.current.command.isComplete) {
if (refStatus.current.command.isValid && refStatus.current.responseResolve) {
refStatus.current.responseResolve(refStatus.current.command.response)
} else if (!refStatus.current.command.isValid) {
refStatus.current.responseReject(new Error('无效数据'))
}
resetCommand()
}
} else {
const uint8Array = new Uint8Array(buffer)
if (uint8Array[0] === 0xbb && uint8Array[1] === 1 && uint8Array[3] === 0) {
const ev = { type: 'measure', detail: { mode: uint8Array[2] } }
emit(ev)
}
}
}
/**
* 测量并获取 lab 值
* @param {number} mode
* @returns {Promise<{L: number, a: number, b: number}>}
*/
async function measureAndGetLab(mode = 0) {
await measure(mode);
await waitFor(50);
const lab = await getLab(mode);
console.log('lab2::',lab)
changeStatus({deviceLab:lab})
return lab
/**
* 发送命令
* @param {Command}} command
* @returns {Promise<Uint8Array>}
*/
function exec(command) {
return new Promise(async (resolve, reject) => {
if (refStatus.current.command) {
reject(new Error('正在执行其他命令'))
} else {
try {
refStatus.current.command = command
const data = command.data
for (let i = 0; i < data.length; i++) {
await sendData(data[i])
}
if (command.responseSize <= 0) {
resolve(true)
resetCommand()
} else {
refStatus.current.responseReject = reject
refStatus.current.responseResolve = resolve
refStatus.current.responseTimer = setTimeout(() => {
reject(new Error('命令响应超时'))
resetCommand()
}, command.timeout)
}
} catch (e) {
reject(e)
}
}
})
}
/**
* 发送命令
* @param {ArrayBuffer} buffer
*/
function sendData(buffer) {
if (refStatus.current.debug) {
console.log(`[BLE SEND] ${uint8ArrayToHex(new Uint8Array(buffer))}`)
}
return new Promise((resolve, reject) => {
console.log('current:::', refStatus.current)
Taro.writeBLECharacteristicValue({
deviceId: refStatus.current.connected.deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
value: buffer,
success: resolve,
fail: reject,
})
})
}
return <Context.Provider children={props.children} value={{
init,
function resetCommand() {
if (refStatus.current.responseTimer) {
clearTimeout(refStatus.current.responseTimer)
}
changeStatus({
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
})
}
/**
* 测量
* @param {number} mode
* @returns {Promise}
*/
async function measure(mode = 0) {
console.log('current1:::', Command.WakeUp)
await exec(Command.WakeUp)
console.log('current2:::', Command.WakeUp)
await waitFor(50)
console.log('current3:::', Command.WakeUp)
return await exec(Command.measure(mode))
}
/**
* 获取测量的 lab 值
* @param {number} mode
* @returns {Promise<{ L: number, a: number, b: number }>}
*/
async function getLab(mode = 0) {
await exec(Command.WakeUp)
await waitFor(50)
const data: any = await exec(Command.getLab(mode))
return {
L: uint8ArrayToFloat32(data.slice(5, 9)),
a: uint8ArrayToFloat32(data.slice(9, 13)),
b: uint8ArrayToFloat32(data.slice(13, 17)),
}
}
/**
* 测量并获取 lab 值
* @param {number} mode
* @returns {Promise<{L: number, a: number, b: number}>}
*/
async function measureAndGetLab(mode = 0) {
await measure(mode)
await waitFor(50)
const lab = await getLab(mode)
console.log('lab2::', lab)
changeStatus({ deviceLab: lab })
return lab
}
return (
<Context.Provider
children={props.children}
value={{
init,
state,
startScan,
measureAndGetLab,
getAdapterState,
connect,
disconnect
}} />
disconnect,
}}
/>
)
}
export const useBluetoothTwo = () => {
const res = React.useContext<any>(Context)
if(res) {
return {...res}
} else {
return {}
}
}
const res = React.useContext<any>(Context)
if (res) {
return { ...res }
} else {
return {}
}
}
+440 -440
View File
@@ -1,477 +1,477 @@
import React, {useRef, useState } from "react"
import Taro from "@tarojs/taro";
import { Command } from "@/common/bluetooth/command";
import { uint8ArrayToFloat32, uint8ArrayToHex, waitFor } from "@/common/bluetooth/utils";
import React, { useRef, useState } from 'react'
import Taro from '@tarojs/taro'
import { Command } from '@/common/bluetooth/command'
import { uint8ArrayToFloat32, uint8ArrayToHex, waitFor } from '@/common/bluetooth/utils'
interface params {
init: () => void
state: Object,
startScan: () => void,
measureAndGetLab: () => any,
getAdapterState: () => void,
connect: (any) => void,
disconnect: () => void
init: () => void
state: Object
startScan: () => void
measureAndGetLab: () => any
getAdapterState: () => void
connect: (any) => void
disconnect: () => void
}
const Context = React.createContext<params|unknown>(null)
const Context = React.createContext<params | unknown>(null)
interface stateStype {
listeners: any,
discovering: boolean,
available: boolean,
connected: any,
connecting: any,
serviceRule: any,
serviceId: any,
characteristicRule: any,
characteristicId: any,
listeners: any
discovering: boolean
available: boolean
connected: any
connecting: any
serviceRule: any
serviceId: any
characteristicRule: any
characteristicId: any
/** 正在执行的命令 */
command: any,
responseResolve: any,
responseReject: any,
responseTimer: any,
/** 正在执行的命令 */
command: any
responseResolve: any
responseReject: any
responseTimer: any
/** 是否显示蓝牙调试信息 */
debug: any,
//搜索到的设备
devices: any,
//取色仪主动返回的数据
deviceLab: any
/** 是否显示蓝牙调试信息 */
debug: any
//搜索到的设备
devices: any
//取色仪主动返回的数据
deviceLab: any
}
let stateObj: stateStype = {
/** 事件监听器 */
listeners: new Set(),
/** 正在扫描设备 */
discovering: false,
/** 蓝牙是否可用 */
available: true,
/** 当前连接的设备 */
connected: null,
/** 正在连接的设备 */
connecting: null,
/** 事件监听器 */
listeners: new Set(),
/** 正在扫描设备 */
discovering: false,
/** 蓝牙是否可用 */
available: true,
/** 当前连接的设备 */
connected: null,
/** 正在连接的设备 */
connecting: null,
serviceRule: /^0000FFE0/,
serviceId: null,
characteristicRule: /^0000FFE1/,
characteristicId: null,
serviceRule: /^0000FFE0/,
serviceId: null,
characteristicRule: /^0000FFE1/,
characteristicId: null,
/** 正在执行的命令 */
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
/** 正在执行的命令 */
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
/** 是否显示蓝牙调试信息 */
debug: true,
//搜索到的设备
devices: [],
//取色仪主动返回的数据
deviceLab: null
/** 是否显示蓝牙调试信息 */
debug: true,
//搜索到的设备
devices: [],
//取色仪主动返回的数据
deviceLab: null,
}
export default (props) => {
let refStatus = useRef(stateObj)
let [state, setState] = useState(refStatus.current)
let refStatus = useRef(stateObj)
let [state, setState] = useState(refStatus.current)
const changeStatus = (obj:Object): void => {
refStatus.current = {...refStatus.current, ...obj}
setState({...refStatus.current})
const changeStatus = (obj: Object): void => {
refStatus.current = { ...refStatus.current, ...obj }
setState({ ...refStatus.current })
}
const init = async () => {
try {
await openAdapter()
} catch (e) {
changeStatus({ available: false })
}
const init = async () => {
try{
await openAdapter();
}catch(e) {
changeStatus({available:false})
}
// 绑定事件通知
Taro.onBluetoothAdapterStateChange(res => {
emit({ type: 'stateUpdate', detail: res });
});
Taro.onBLEConnectionStateChange(res => {
emit({ type: res.connected ? 'connected' : 'disconnect', detail: res });
});
Taro.onBLECharacteristicValueChange(({ value }) => notifySubscriber(value));
subscribe(async ev => {
if (ev.type === 'stateUpdate') {
// 蓝牙状态发生的变化
changeStatus({discovering:ev.detail.discovering, available:ev.detail.available})
} else if (ev.type === 'disconnect' && refStatus.current.connected && refStatus.current.connected.deviceId === ev.detail.deviceId) {
// 断开连接
changeStatus({
connected:null,
serviceId:null,
characteristicId:null,
deviceLab:null,
devices:[]
})
Taro.showToast({ icon: 'none', title: '蓝牙连接已断开' });
} else if (ev.type === 'connected' && refStatus.current.connecting) {
// 连接成功
changeStatus({connected: refStatus.current.connecting, connecting: null})
Taro.showToast({ title: '蓝牙已连接' });
} else if (ev.type === 'measure') {
//监听取色仪主动推送lab
await measureAndGetLab()
}
});
}
/** 打开蓝牙适配器 */
const openAdapter = () => {
return new Promise((resolve, reject) => {
Taro.openBluetoothAdapter({
success: resolve,
fail: reject
});
});
}
/**
* 推送事件
* @param {{type: string; data: any}} event
*/
const emit = (event) => {
refStatus.current.listeners.forEach(cb => {
cb && cb(event);
});
}
const subscribe = (cb) => {
if (cb) {
changeStatus({
listeners: refStatus.current.listeners.add(cb)
})
}
}
/**
* 获取蓝牙适配器状态
* @returns {Promise<{discovering: boolean; available: boolean}>}
*/
const getAdapterState = () => {
return new Promise((resolve, reject) => {
Taro.getBluetoothAdapterState({
success: resolve,
fail: reject
})
})
}
/**
* 启动设备扫描
* @param {(res: { devices: { name: string, deviceId: string, RSSI: number }[] }) => void} cb
* @param {number} duration
*/
const startScan = (duration = 30000) => {
console.log('开始寻找')
changeStatus({devices:[]})
Taro.onBluetoothDeviceFound(getDevices);
return new Promise((resolve, reject) => {
Taro.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: resolve,
fail: reject
});
if (duration > 0) {
setTimeout(() => {
Taro.offBluetoothDeviceFound(getDevices);
Taro.stopBluetoothDevicesDiscovery();
console.log("停止搜索")
}, duration);
}
});
}
//获取搜索到的设备
const getDevices = (res) => {
res.devices.forEach(device => {
// 排除掉已搜索到的设备和名称不合法的设备, 将新发现的设备添加到列表中
if (/^CM/.test(device.name) && !refStatus.current.devices.find(i => i.deviceId === device.deviceId)) {
changeStatus({devices: [ ...refStatus.current.devices, device ]})
}
});
}
/**
* 连接设备
* @param {{ name: string, deviceId: string, RSSI: number }} device
*/
const connect = async (device) => {
try {
changeStatus({connecting: device})
console.log('connecting::', device)
await createConnection(device.deviceId);
await discoverService(device.deviceId);
await discoverCharacteristic(device.deviceId);
await notifyCharacteristicValueChange(device.deviceId);
} catch (e) {
changeStatus({connecting: null})
Taro.showToast({ icon: 'none', title: '蓝牙连接失败' });
throw e;
}
}
/** 断开当前连接的设备 */
const disconnect = async () => {
if (!refStatus.current.connected && !refStatus.current.connecting) return;
if (refStatus.current.connected) {
await closeConnection(refStatus.current.connected.deviceId);
resetCommand();
changeStatus({
connected: null,
serviceId: null,
characteristicId: null,
devices: [],
deviceLab: null
})
}
if (refStatus.current.connecting) {
await closeConnection(refStatus.current.connecting.deviceId);
changeStatus({connecting:null})
}
}
/** 创建 BLE 连接 */
function createConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
deviceId,
timeout: 2000,
success: resolve,
fail: reject
});
});
}
/** 关闭 BLE 连接 */
function closeConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.closeBLEConnection({
deviceId,
success: resolve,
fail: reject
});
});
}
/** 搜索服务 */
function discoverService(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceServices({
deviceId,
success: ({ services }) => {
const service = services.find(i => refStatus.current.serviceRule.test(i.uuid));
if (!service) {
reject(new Error('服务不可用'));
} else {
changeStatus({serviceId: service.uuid})
resolve(service);
}
},
fail: reject
});
});
}
/** 搜索特征 */
function discoverCharacteristic(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId: refStatus.current.serviceId,
success: ({ characteristics }) => {
const characteristic = characteristics.find(i => refStatus.current.characteristicRule.test(i.uuid));
if (!characteristic) {
reject(new Error('特征不可用'));
} else {
changeStatus({characteristicId: characteristic.uuid})
resolve(characteristic);
}
},
fail: reject
})
});
}
/** 启动特征通知 */
function notifyCharacteristicValueChange(deviceId, stateParm = true) {
return new Promise((resolve, reject) => {
Taro.notifyBLECharacteristicValueChange({
deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
state:stateParm,
success: resolve,
fail: reject
});
});
}
/**
* 通知订阅器
* @param {ArrayBuffer} buffer
*/
function notifySubscriber(buffer) {
if (refStatus.current.command) {
if (refStatus.current.debug) {
console.log(`[BLE RESP] ${uint8ArrayToHex(new Uint8Array(buffer))}`);
}
refStatus.current.command.fillResponse(buffer);
if (refStatus.current.command.isComplete) {
if (refStatus.current.command.isValid && refStatus.current.responseResolve) {
refStatus.current.responseResolve(refStatus.current.command.response);
} else if (!refStatus.current.command.isValid) {
refStatus.current.responseReject(new Error('无效数据'));
}
resetCommand();
}
} else {
const uint8Array = new Uint8Array(buffer);
if (uint8Array[0] === 0xbb && uint8Array[1] === 1 && uint8Array[3] === 0) {
const ev = { type: 'measure', detail: { mode: uint8Array[2] } };
emit(ev);
}
}
}
/**
* 发送命令
* @param {Command}} command
* @returns {Promise<Uint8Array>}
*/
function exec(command) {
return new Promise(async (resolve, reject) => {
if (refStatus.current.command) {
reject(new Error('正在执行其他命令'));
} else {
try {
refStatus.current.command = command;
const data = command.data;
for (let i = 0; i < data.length; i++) {
await sendData(data[i]);
}
if (command.responseSize <= 0) {
resolve(true);
resetCommand();
} else {
refStatus.current.responseReject = reject;
refStatus.current.responseResolve = resolve;
refStatus.current.responseTimer = setTimeout(() => {
reject(new Error('命令响应超时'));
resetCommand();
}, command.timeout);
}
} catch (e) {
reject(e);
}
}
});
}
/**
* 发送命令
* @param {ArrayBuffer} buffer
*/
function sendData(buffer) {
if (refStatus.current.debug) {
console.log(`[BLE SEND] ${uint8ArrayToHex(new Uint8Array(buffer))}`);
}
return new Promise((resolve, reject) => {
console.log('current:::',refStatus.current)
Taro.writeBLECharacteristicValue({
deviceId: refStatus.current.connected.deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
value: buffer,
success: resolve,
fail: reject
})
});
}
function resetCommand() {
if (refStatus.current.responseTimer) {
clearTimeout(refStatus.current.responseTimer);
}
// 绑定事件通知
Taro.onBluetoothAdapterStateChange((res) => {
emit({ type: 'stateUpdate', detail: res })
})
Taro.onBLEConnectionStateChange((res) => {
emit({ type: res.connected ? 'connected' : 'disconnect', detail: res })
})
Taro.onBLECharacteristicValueChange(({ value }) => notifySubscriber(value))
subscribe(async (ev) => {
if (ev.type === 'stateUpdate') {
// 蓝牙状态发生的变化
changeStatus({ discovering: ev.detail.discovering, available: ev.detail.available })
} else if (ev.type === 'disconnect' && refStatus.current.connected && refStatus.current.connected.deviceId === ev.detail.deviceId) {
// 断开连接
changeStatus({
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null
connected: null,
serviceId: null,
characteristicId: null,
deviceLab: null,
devices: [],
})
Taro.showToast({ icon: 'none', title: '蓝牙连接已断开' })
} else if (ev.type === 'connected' && refStatus.current.connecting) {
// 连接成功
changeStatus({ connected: refStatus.current.connecting, connecting: null })
Taro.showToast({ title: '蓝牙已连接' })
} else if (ev.type === 'measure') {
//监听取色仪主动推送lab
await measureAndGetLab()
}
})
}
/** 打开蓝牙适配器 */
const openAdapter = () => {
return new Promise((resolve, reject) => {
Taro.openBluetoothAdapter({
success: resolve,
fail: reject,
})
})
}
/**
* 推送事件
* @param {{type: string; data: any}} event
*/
const emit = (event) => {
refStatus.current.listeners.forEach((cb) => {
cb && cb(event)
})
}
const subscribe = (cb) => {
if (cb) {
changeStatus({
listeners: refStatus.current.listeners.add(cb),
})
}
}
/**
* 获取蓝牙适配器状态
* @returns {Promise<{discovering: boolean; available: boolean}>}
*/
const getAdapterState = () => {
return new Promise((resolve, reject) => {
Taro.getBluetoothAdapterState({
success: resolve,
fail: reject,
})
})
}
/**
* 启动设备扫描
* @param {(res: { devices: { name: string, deviceId: string, RSSI: number }[] }) => void} cb
* @param {number} duration
*/
const startScan = (duration = 30000) => {
console.log('开始寻找')
changeStatus({ devices: [] })
Taro.onBluetoothDeviceFound(getDevices)
return new Promise((resolve, reject) => {
Taro.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: resolve,
fail: reject,
})
if (duration > 0) {
setTimeout(() => {
Taro.offBluetoothDeviceFound(getDevices)
Taro.stopBluetoothDevicesDiscovery()
console.log('停止搜索')
}, duration)
}
})
}
//获取搜索到的设备
const getDevices = (res) => {
res.devices.forEach((device) => {
// 排除掉已搜索到的设备和名称不合法的设备, 将新发现的设备添加到列表中
if (/^CM/.test(device.name) && !refStatus.current.devices.find((i) => i.deviceId === device.deviceId)) {
changeStatus({ devices: [...refStatus.current.devices, device] })
}
})
}
/**
* 连接设备
* @param {{ name: string, deviceId: string, RSSI: number }} device
*/
const connect = async (device) => {
try {
changeStatus({ connecting: device })
console.log('connecting::', device)
await createConnection(device.deviceId)
await discoverService(device.deviceId)
await discoverCharacteristic(device.deviceId)
await notifyCharacteristicValueChange(device.deviceId)
} catch (e) {
changeStatus({ connecting: null })
Taro.showToast({ icon: 'none', title: '蓝牙连接失败' })
throw e
}
}
/** 断开当前连接的设备 */
const disconnect = async () => {
if (!refStatus.current.connected && !refStatus.current.connecting) return
if (refStatus.current.connected) {
await closeConnection(refStatus.current.connected.deviceId)
resetCommand()
changeStatus({
connected: null,
serviceId: null,
characteristicId: null,
devices: [],
deviceLab: null,
})
}
/**
* 测量
* @param {number} mode
* @returns {Promise}
*/
async function measure (mode = 0) {
console.log('current1:::',Command.WakeUp)
await exec(Command.WakeUp);
console.log('current2:::',Command.WakeUp)
await waitFor(50);
console.log('current3:::',Command.WakeUp)
return await exec(Command.measure(mode));
if (refStatus.current.connecting) {
await closeConnection(refStatus.current.connecting.deviceId)
changeStatus({ connecting: null })
}
}
/**
* 获取测量的 lab 值
* @param {number} mode
* @returns {Promise<{ L: number, a: number, b: number }>}
*/
async function getLab(mode = 0) {
await exec(Command.WakeUp);
await waitFor(50);
const data: any = await exec(Command.getLab(mode));
return {
L: uint8ArrayToFloat32(data.slice(5, 9)),
a: uint8ArrayToFloat32(data.slice(9, 13)),
b: uint8ArrayToFloat32(data.slice(13, 17)),
};
/** 创建 BLE 连接 */
function createConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
deviceId,
timeout: 2000,
success: resolve,
fail: reject,
})
})
}
/** 关闭 BLE 连接 */
function closeConnection(deviceId) {
return new Promise((resolve, reject) => {
Taro.closeBLEConnection({
deviceId,
success: resolve,
fail: reject,
})
})
}
/** 搜索服务 */
function discoverService(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceServices({
deviceId,
success: ({ services }) => {
const service = services.find((i) => refStatus.current.serviceRule.test(i.uuid))
if (!service) {
reject(new Error('服务不可用'))
} else {
changeStatus({ serviceId: service.uuid })
resolve(service)
}
},
fail: reject,
})
})
}
/** 搜索特征 */
function discoverCharacteristic(deviceId) {
return new Promise((resolve, reject) => {
Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId: refStatus.current.serviceId,
success: ({ characteristics }) => {
const characteristic = characteristics.find((i) => refStatus.current.characteristicRule.test(i.uuid))
if (!characteristic) {
reject(new Error('特征不可用'))
} else {
changeStatus({ characteristicId: characteristic.uuid })
resolve(characteristic)
}
},
fail: reject,
})
})
}
/** 启动特征通知 */
function notifyCharacteristicValueChange(deviceId, stateParm = true) {
return new Promise((resolve, reject) => {
Taro.notifyBLECharacteristicValueChange({
deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
state: stateParm,
success: resolve,
fail: reject,
})
})
}
/**
* 通知订阅器
* @param {ArrayBuffer} buffer
*/
function notifySubscriber(buffer) {
if (refStatus.current.command) {
if (refStatus.current.debug) {
console.log(`[BLE RESP] ${uint8ArrayToHex(new Uint8Array(buffer))}`)
}
refStatus.current.command.fillResponse(buffer)
if (refStatus.current.command.isComplete) {
if (refStatus.current.command.isValid && refStatus.current.responseResolve) {
refStatus.current.responseResolve(refStatus.current.command.response)
} else if (!refStatus.current.command.isValid) {
refStatus.current.responseReject(new Error('无效数据'))
}
resetCommand()
}
} else {
const uint8Array = new Uint8Array(buffer)
if (uint8Array[0] === 0xbb && uint8Array[1] === 1 && uint8Array[3] === 0) {
const ev = { type: 'measure', detail: { mode: uint8Array[2] } }
emit(ev)
}
}
}
/**
* 测量并获取 lab 值
* @param {number} mode
* @returns {Promise<{L: number, a: number, b: number}>}
*/
async function measureAndGetLab(mode = 0) {
await measure(mode);
await waitFor(50);
const lab = await getLab(mode);
console.log('lab2::',lab)
changeStatus({deviceLab:lab})
return lab
/**
* 发送命令
* @param {Command}} command
* @returns {Promise<Uint8Array>}
*/
function exec(command) {
return new Promise(async (resolve, reject) => {
if (refStatus.current.command) {
reject(new Error('正在执行其他命令'))
} else {
try {
refStatus.current.command = command
const data = command.data
for (let i = 0; i < data.length; i++) {
await sendData(data[i])
}
if (command.responseSize <= 0) {
resolve(true)
resetCommand()
} else {
refStatus.current.responseReject = reject
refStatus.current.responseResolve = resolve
refStatus.current.responseTimer = setTimeout(() => {
reject(new Error('命令响应超时'))
resetCommand()
}, command.timeout)
}
} catch (e) {
reject(e)
}
}
})
}
/**
* 发送命令
* @param {ArrayBuffer} buffer
*/
function sendData(buffer) {
if (refStatus.current.debug) {
console.log(`[BLE SEND] ${uint8ArrayToHex(new Uint8Array(buffer))}`)
}
return new Promise((resolve, reject) => {
console.log('current:::', refStatus.current)
Taro.writeBLECharacteristicValue({
deviceId: refStatus.current.connected.deviceId,
serviceId: refStatus.current.serviceId,
characteristicId: refStatus.current.characteristicId,
value: buffer,
success: resolve,
fail: reject,
})
})
}
return <Context.Provider children={props.children} value={{
init,
function resetCommand() {
if (refStatus.current.responseTimer) {
clearTimeout(refStatus.current.responseTimer)
}
changeStatus({
command: null,
responseResolve: null,
responseReject: null,
responseTimer: null,
})
}
/**
* 测量
* @param {number} mode
* @returns {Promise}
*/
async function measure(mode = 0) {
console.log('current1:::', Command.WakeUp)
await exec(Command.WakeUp)
console.log('current2:::', Command.WakeUp)
await waitFor(50)
console.log('current3:::', Command.WakeUp)
return await exec(Command.measure(mode))
}
/**
* 获取测量的 lab 值
* @param {number} mode
* @returns {Promise<{ L: number, a: number, b: number }>}
*/
async function getLab(mode = 0) {
await exec(Command.WakeUp)
await waitFor(50)
const data: any = await exec(Command.getLab(mode))
return {
L: uint8ArrayToFloat32(data.slice(5, 9)),
a: uint8ArrayToFloat32(data.slice(9, 13)),
b: uint8ArrayToFloat32(data.slice(13, 17)),
}
}
/**
* 测量并获取 lab 值
* @param {number} mode
* @returns {Promise<{L: number, a: number, b: number}>}
*/
async function measureAndGetLab(mode = 0) {
await measure(mode)
await waitFor(50)
const lab = await getLab(mode)
console.log('lab2::', lab)
changeStatus({ deviceLab: lab })
return lab
}
return (
<Context.Provider
children={props.children}
value={{
init,
state,
startScan,
measureAndGetLab,
getAdapterState,
connect,
disconnect
}} />
disconnect,
}}
/>
)
}
export const useBluetooth = () => {
const res = React.useContext<any>(Context)
if(res) {
return {...res}
} else {
return {}
}
}
const res = React.useContext<any>(Context)
if (res) {
return { ...res }
} else {
return {}
}
}
+57 -46
View File
@@ -1,51 +1,62 @@
import { alert } from "@/common/common";
import Taro from "@tarojs/taro";
import { memo, useCallback, useState } from "react";
import { alert } from '@/common/common'
import Taro from '@tarojs/taro'
import { memo, useCallback, useState } from 'react'
type Scope = 'scope.userLocation'|'scope.userLocation'|'scope.record'|'scope.camera'|'scope.bluetooth'|'scope.writePhotosAlbum'|'scope.addPhoneContact'|'scope.addPhoneCalendar'|'scope.werun'|'scope.address'|'scope.invoiceTitle'|'scope.invoice'|'scope.userInfo'
type Scope =
| 'scope.userLocation'
| 'scope.userLocation'
| 'scope.record'
| 'scope.camera'
| 'scope.bluetooth'
| 'scope.writePhotosAlbum'
| 'scope.addPhoneContact'
| 'scope.addPhoneCalendar'
| 'scope.werun'
| 'scope.address'
| 'scope.invoiceTitle'
| 'scope.invoice'
| 'scope.userInfo'
type Param = {
scope: Scope,
msg: string //检查不通过时警告
scope: Scope
msg: string //检查不通过时警告
}
export default ({scope, msg}: Param) => {
//这个hook微信授权检查授权
const check = useCallback(() => {
return new Promise((reslove, reject) => {
Taro.getSetting({
success: (res) => {
if(res.authSetting[scope]) {
reslove(true)
} else if (res.authSetting[scope] === undefined) {
Taro.authorize({
scope: scope,
success() {
reslove(true)
},
fail() {
alert.none(msg)
reject(false)
}
})
} else {
Taro.openSetting({
success(res) {
if(res.authSetting[scope]) {
reslove(true)
} else {
alert.none(msg)
reject(false)
}
}
})
}
}
export default ({ scope, msg }: Param) => {
//这个hook微信授权检查授权
const check = useCallback(() => {
return new Promise((reslove, reject) => {
Taro.getSetting({
success: (res) => {
if (res.authSetting[scope]) {
reslove(true)
} else if (res.authSetting[scope] === undefined) {
Taro.authorize({
scope: scope,
success() {
reslove(true)
},
fail() {
alert.none(msg)
reject(false)
},
})
})
}, [scope])
} else {
Taro.openSetting({
success(res) {
if (res.authSetting[scope]) {
reslove(true)
} else {
alert.none(msg)
reject(false)
}
},
})
}
},
})
})
}, [scope])
return {
check,
}
}
return {
check,
}
}
+77 -79
View File
@@ -1,92 +1,90 @@
import { SubscriptionMessageApi } from "@/api/user"
import Taro from "@tarojs/taro"
import dayjs from "dayjs"
import { useEffect, useRef, useState } from "react"
import { SubscriptionMessageApi } from '@/api/user'
import Taro from '@tarojs/taro'
import dayjs from 'dayjs'
import { useEffect, useRef, useState } from 'react'
//倒计时hook
export const useTimeCountDown = () => {
const [showTime, setShowTime] = useState({
DD: '',
HH: '',
MM: '',
SS: ''
})
const [timeStatus, setTimeStatus] = useState<0|1|2>(0) //倒计时状体 0:倒计时未开始 1:倒计时中, 2:倒计时已结束
const timeObj:any = useRef()
const endTime = useRef('')
const onStart = (val = '') => {
console.log('time:::', val)
endTime.current = val
if(endTime.current) {
clearInterval(timeObj.current)
timeObj.current = setInterval(() => {
count_down()
}, 1000)
}
const [showTime, setShowTime] = useState({
DD: '',
HH: '',
MM: '',
SS: '',
})
const [timeStatus, setTimeStatus] = useState<0 | 1 | 2>(0) //倒计时状体 0:倒计时未开始 1:倒计时中, 2:倒计时已结束
const timeObj: any = useRef()
const endTime = useRef('')
const onStart = (val = '') => {
console.log('time:::', val)
endTime.current = val
if (endTime.current) {
clearInterval(timeObj.current)
timeObj.current = setInterval(() => {
count_down()
}, 1000)
}
useEffect(() => {
return () => {
clearInterval(timeObj.current)
}
}, [])
const count_down = () => {
var startData = dayjs();
var endDate = dayjs(endTime.current);
setTimeStatus(() => 1)
if(startData >= endDate) {
clearInterval(timeObj.current)
setShowTime((e) => ({...e, DD:'00', HH:'00', MM:'00', SS:'00'}))
setTimeStatus(() => 2)
return false
}
var _dd = endDate.diff(startData,'day');
var _hh = endDate.diff(startData,'hour');
var _mm = endDate.diff(startData,'minute');
var _ss = endDate.diff(startData,'second');
// 转换
var hh = _hh - (_dd*24);
var mm = _mm - (_hh*60);
var ss = _ss - (_mm*60);
// 格式化
var DD = ('00'+_dd).slice(-2);
var HH = ('00'+hh).slice(-2);
var MM = ('00'+mm).slice(-2);
var SS = ('00'+ss).slice(-2);
console.log('endTime::', `${DD}-${HH}-${MM}-${SS}`)
setShowTime((e) => ({...e, DD, HH, MM, SS}))
}
useEffect(() => {
return () => {
clearInterval(timeObj.current)
}
return {
showTime,
onStart,
timeStatus
}, [])
const count_down = () => {
var startData = dayjs()
var endDate = dayjs(endTime.current)
setTimeStatus(() => 1)
if (startData >= endDate) {
clearInterval(timeObj.current)
setShowTime((e) => ({ ...e, DD: '00', HH: '00', MM: '00', SS: '00' }))
setTimeStatus(() => 2)
return false
}
var _dd = endDate.diff(startData, 'day')
var _hh = endDate.diff(startData, 'hour')
var _mm = endDate.diff(startData, 'minute')
var _ss = endDate.diff(startData, 'second')
// 转换
var hh = _hh - _dd * 24
var mm = _mm - _hh * 60
var ss = _ss - _mm * 60
// 格式化
var DD = ('00' + _dd).slice(-2)
var HH = ('00' + hh).slice(-2)
var MM = ('00' + mm).slice(-2)
var SS = ('00' + ss).slice(-2)
console.log('endTime::', `${DD}-${HH}-${MM}-${SS}`)
setShowTime((e) => ({ ...e, DD, HH, MM, SS }))
}
return {
showTime,
onStart,
timeStatus,
}
}
//订阅消息hook
export const UseSubscriptionMessage = () => {
const {fetchData: fetchDataMessage} = SubscriptionMessageApi()
const openSubscriptionMessage = ({orderId = 0, scenes = 0}:{orderId?: number, scenes: number}) => {
return new Promise(async (resolve) => {
let params:{sale_order_id?: number, scenes?: number} = {}
orderId&&(params.sale_order_id = orderId)
params.scenes = scenes
let res = await fetchDataMessage(params)
if(res.success&&res.data.TemplateID&&res.data.TemplateID.length > 0) {
Taro.requestSubscribeMessage({
tmplIds: res.data.TemplateID,
complete: function (res) {
resolve(res)
}
})
} else {
resolve(true)
}
const { fetchData: fetchDataMessage } = SubscriptionMessageApi()
const openSubscriptionMessage = ({ orderId = 0, scenes = 0 }: { orderId?: number; scenes: number }) => {
return new Promise(async (resolve) => {
let params: { sale_order_id?: number; scenes?: number } = {}
orderId && (params.sale_order_id = orderId)
params.scenes = scenes
let res = await fetchDataMessage(params)
if (res.success && res.data.TemplateID && res.data.TemplateID.length > 0) {
Taro.requestSubscribeMessage({
tmplIds: res.data.TemplateID,
complete: function (res) {
resolve(res)
},
})
}
} else {
resolve(true)
}
})
}
return {
openSubscriptionMessage
}
return {
openSubscriptionMessage,
}
}
+26 -26
View File
@@ -1,33 +1,33 @@
import { useDispatch } from 'react-redux'
import {SET_SHOPCOUNT, CLEAR_SHOPCOUNT} from '@/constants/common'
import {DataParam} from '@/reducers/commonData'
import { SET_SHOPCOUNT, CLEAR_SHOPCOUNT } from '@/constants/common'
import { DataParam } from '@/reducers/commonData'
import { useCallback, useState } from 'react'
import { GetShoppingCartApi } from '@/api/shopCart'
import { useSelector } from '@/reducers/hooks'
export default () => {
const commonData = useSelector(state => state.commonData)
const dispatch = useDispatch()
const setShopCount = (shopCount: number) => {
dispatch({type:SET_SHOPCOUNT, data:{shopCount}})
}
const commonData = useSelector((state) => state.commonData)
const dispatch = useDispatch()
const removeShopCount = () => {
dispatch({type:CLEAR_SHOPCOUNT})
}
const setShopCount = (shopCount: number) => {
dispatch({ type: SET_SHOPCOUNT, data: { shopCount } })
}
const {fetchData: fetchDataShopCount} = GetShoppingCartApi()
const getShopCount = async () => {
//获取购物车数据数量
const {data} = await fetchDataShopCount()
let color_list = data.color_list||[]
setShopCount(color_list.length)
}
return {
setShopCount,
removeShopCount,
getShopCount,
commonData
}
}
const removeShopCount = () => {
dispatch({ type: CLEAR_SHOPCOUNT })
}
const { fetchData: fetchDataShopCount } = GetShoppingCartApi()
const getShopCount = async () => {
//获取购物车数据数量
const { data } = await fetchDataShopCount()
let color_list = data.color_list || []
setShopCount(color_list.length)
}
return {
setShopCount,
removeShopCount,
getShopCount,
commonData,
}
}
+166 -173
View File
@@ -1,100 +1,98 @@
import Taro, { useRouter } from '@tarojs/taro'
import { useEffect, useRef, useState } from 'react'
import {BASE_URL, WX_APPID} from '@/common/constant'
import useUserInfo from "./useUserInfo"
import qs from 'qs';
import useLogin from './useLogin';
import useLoginRequest from './useLoginRequest';
import { BASE_URL, WX_APPID } from '@/common/constant'
import useUserInfo from './useUserInfo'
import qs from 'qs'
import useLogin from './useLogin'
import useLoginRequest from './useLoginRequest'
type Params = {
code: string|null
success: true|false
data: any,
msg: string,
loading: true|false,
error: any,
query: any,
filter: any,
sort: any,
total: number,
multiple: true|false, // 请求多次
count: number, // 第几次请求
token: string, // token
page?: number,
pageSize?: number
code: string | null
success: true | false
data: any
msg: string
loading: true | false
error: any
query: any
filter: any
sort: any
total: number
multiple: true | false // 请求多次
count: number // 第几次请求
token: string // token
page?: number
pageSize?: number
}
type option = {
url?: string,
method?: 'get'|'post'|'put'|'delete',
type?: string,
data?: any,
page?: number,
pageSize?: number,
pagination?: true|false,
base_url?: string,
apiMsgStatus?: true|false
url?: string
method?: 'get' | 'post' | 'put' | 'delete'
type?: string
data?: any
page?: number
pageSize?: number
pagination?: true | false
base_url?: string
apiMsgStatus?: true | false
}
/**
* 返回状态信息,根据 http 状态错
* @param {Number} status
* @returns
* @param {Number} status
* @returns
*/
const showStatus = (status) => {
let message = ''
switch (status) {
let message = ''
switch (status) {
case 400:
message = '请求错误(400)'
break
message = '请求错误(400)'
break
case 401:
message = '未授权,请重新登录(401)'
break
message = '未授权,请重新登录(401)'
break
case 403:
message = '拒绝访问(403)'
break
message = '拒绝访问(403)'
break
case 404:
message = '请求出错(404)'
break
message = '请求出错(404)'
break
case 408:
message = '请求超时(408)'
break
message = '请求超时(408)'
break
case 500:
message = '服务器错误(500)'
break
message = '服务器错误(500)'
break
case 501:
message = '服务未实现(501)'
break
message = '服务未实现(501)'
break
case 502:
message = '网络错误(502)'
break
message = '网络错误(502)'
break
case 503:
message = '服务不可用(503)'
break
message = '服务不可用(503)'
break
case 504:
message = '网络超时(504)'
break
message = '网络超时(504)'
break
case 505:
message = 'HTTP版本不受支持(505)'
break
message = 'HTTP版本不受支持(505)'
break
default:
message = `连接出错(${status})!`
}
return `${message},请检查网络或联系管理员!`
message = `连接出错(${status})!`
}
return `${message},请检查网络或联系管理员!`
}
/**
* axios 请求状态封装,返回响应式数据 fetch(), loading, error, code, msg 等常用方法/状态
* @param {Object} options 对象
* @param {String} options.url 请求的URL
* @param {String} options.method 请求的方法
* @param {Object} options.data 请求的参数
* @returns {Object} 返回fetch(), loading, error, code, msg
/**
* axios 请求状态封装,返回响应式数据 fetch(), loading, error, code, msg 等常用方法/状态
* @param {Object} options 对象
* @param {String} options.url 请求的URL
* @param {String} options.method 请求的方法
* @param {Object} options.data 请求的参数
* @returns {Object} 返回fetch(), loading, error, code, msg
*/
export const useRequest = (options:option = {
export const useRequest = (
options: option = {
url: '/',
method: 'get',
type: 'json',
@@ -103,112 +101,107 @@ export const useRequest = (options:option = {
pageSize: 24,
pagination: false, // 是否分页
base_url: '',
apiMsgStatus: true //是否直接弹出后端错误
}) => {
options.url = `${options.base_url||BASE_URL}${options.url}`
let params:Params = {
code: null, // 业务码
success: false, // 请求是否成功
data: {},
msg: '',
loading: false,
error: null,
query: {},
filter: null,
sort: '',
total: 0,
multiple: true, // 请求多次
count: 0, // 第几次请求
token: '', // token
}
apiMsgStatus: true, //是否直接弹出后端错误
},
) => {
options.url = `${options.base_url || BASE_URL}${options.url}`
let params: Params = {
code: null, // 业务码
success: false, // 请求是否成功
data: {},
msg: '',
loading: false,
error: null,
query: {},
filter: null,
sort: '',
total: 0,
multiple: true, // 请求多次
count: 0, // 第几次请求
token: '', // token
}
const stateRef = useRef({...params})
const [state, setState] = useState({...stateRef.current})
const {removeToken, removeSessionKey, removeUserInfo} = useUserInfo()
const {login} = useLoginRequest()
// 请求函数
const fetchData = async (sub_options?:any) => {
stateRef.current.loading = true
setState((e) => ({...e, loading:true}))
stateRef.current.query = {
...sub_options,
...options.pagination && {
page: stateRef.current.page,
size: stateRef.current.pageSize,
},
...stateRef.current.filter,
...stateRef.current.sort
}
try {
let token = Taro.getStorageSync('token')
const q = {
...options,
...{
header: {
"Platform": 6,
"Appid": WX_APPID,
"Authorization": token || stateRef.current.token,
}
},
...options.method?.toUpperCase() == 'GET' ? {
data: stateRef.current.query
} : {
data: options.type?.toUpperCase() == 'FORMDATA' ? qs.stringify(stateRef.current.query) : stateRef.current.query
}
const stateRef = useRef({ ...params })
const [state, setState] = useState({ ...stateRef.current })
const { removeToken, removeSessionKey, removeUserInfo } = useUserInfo()
const { login } = useLoginRequest()
// 请求函数
const fetchData = async (sub_options?: any) => {
stateRef.current.loading = true
setState((e) => ({ ...e, loading: true }))
stateRef.current.query = {
...sub_options,
...(options.pagination && {
page: stateRef.current.page,
size: stateRef.current.pageSize,
}),
...stateRef.current.filter,
...stateRef.current.sort,
}
try {
let token = Taro.getStorageSync('token')
const q = {
...options,
...{
header: {
Platform: 6,
Appid: WX_APPID,
Authorization: token || stateRef.current.token,
},
},
...(options.method?.toUpperCase() == 'GET'
? {
data: stateRef.current.query,
}
const result = await Taro.request(q as any)
const { statusCode } = result
const {
code,
msg,
data
} = result.data
if (statusCode === 200) {
stateRef.current.success = (code === 0 ? true : false)
stateRef.current.code = code
stateRef.current.msg = msg
stateRef.current.data = data
stateRef.current.total = data?.list ? data?.total : 0
if(code !== 0) {
options.apiMsgStatus !== false &&Taro.showToast({
title: `${msg}`,
icon: 'none'
})
console.log('错误::',msg)
}
}else{
if (statusCode === 401) {
removeToken()
removeSessionKey()
removeUserInfo()
login()
} else {
Taro.showToast({
title: `错误:${showStatus(statusCode)}`,
icon: 'none'
})
}
}
} catch (e) {
stateRef.current.success = false
stateRef.current.error = true
stateRef.current.msg = e.errMsg
console.log('后台错误信息::',e.errMsg)
: {
data: options.type?.toUpperCase() == 'FORMDATA' ? qs.stringify(stateRef.current.query) : stateRef.current.query,
}),
}
const result = await Taro.request(q as any)
const { statusCode } = result
const { code, msg, data } = result.data
if (statusCode === 200) {
stateRef.current.success = code === 0 ? true : false
stateRef.current.code = code
stateRef.current.msg = msg
stateRef.current.data = data
stateRef.current.total = data?.list ? data?.total : 0
if (code !== 0) {
options.apiMsgStatus !== false &&
Taro.showToast({
title: `${msg}`,
icon: 'none',
})
console.log('错误::', msg)
}
stateRef.current.error = false
stateRef.current.loading = false
setState(() => ({...stateRef.current}))
return stateRef.current
} else {
if (statusCode === 401) {
removeToken()
removeSessionKey()
removeUserInfo()
login()
} else {
Taro.showToast({
title: `错误:${showStatus(statusCode)}`,
icon: 'none',
})
}
}
} catch (e) {
stateRef.current.success = false
stateRef.current.error = true
stateRef.current.msg = e.errMsg
console.log('后台错误信息::', e.errMsg)
}
stateRef.current.error = false
stateRef.current.loading = false
setState(() => ({ ...stateRef.current }))
return stateRef.current
}
return {
fetchData,
state,
}
}
return {
fetchData,
state,
}
}
+124 -127
View File
@@ -1,137 +1,134 @@
import useUserInfo from "./useUserInfo"
import Taro, { useDidShow, useRouter } from "@tarojs/taro"
import { GetWxUserInfoApi, GetAdminUserInfoApi, GetPhoneNumberApi, BindingCompanyApi } from "@/api/user"
import useLoginRequest from "./useLoginRequest"
import { SHARE_SCENE } from "@/common/enum"
import { GetShortCodeApi } from "@/api/share"
import { alert } from "@/common/common"
import { LoginApi } from "@/api/login"
import { IMG_CND_Prefix } from "@/common/constant"
import useUserInfo from './useUserInfo'
import Taro, { useDidShow, useRouter } from '@tarojs/taro'
import { GetWxUserInfoApi, GetAdminUserInfoApi, GetPhoneNumberApi, BindingCompanyApi } from '@/api/user'
import useLoginRequest from './useLoginRequest'
import { SHARE_SCENE } from '@/common/enum'
import { GetShortCodeApi } from '@/api/share'
import { alert } from '@/common/common'
import { LoginApi } from '@/api/login'
import { IMG_CND_Prefix } from '@/common/constant'
export default () => {
const {setUserInfo, setAdminUserInfo, setSortCode, userInfo} = useUserInfo()
const { setUserInfo, setAdminUserInfo, setSortCode, userInfo } = useUserInfo()
useDidShow(() => {
checkLogin()
useDidShow(() => {
checkLogin()
})
//登录请求
const { login } = useLoginRequest()
// const {fetchData:login} = LoginApi()
const wxLogin = async () => {
try {
await login()
getAdminUserInfo()
} catch (e) {
console.log('登录失败::', e)
}
}
//获取用户信息
const { fetchData: useFetchData } = GetAdminUserInfoApi()
const getAdminUserInfo = async () => {
let res = await useFetchData()
setAdminUserInfo({ ...res.data })
getShortCode(res.data.user_id)
}
//登录加checkLogin检查
const checkLogin = () => {
return new Promise(async (reslove) => {
if (!userInfo.token) {
await wxLogin()
reslove(true)
} else {
//这个东西不要打开,checkSession有调用频率问题
// Taro.checkSession({
// success: async () => {
// reslove(true)
// if(!userInfo.adminUserInfo) getAdminUserInfo()
// },
// fail: async () => {
// await wxLogin()
// reslove(true)
// }
// })
}
})
}
//登录请求
const {login} = useLoginRequest()
// const {fetchData:login} = LoginApi()
const wxLogin = async () => {
try {
await login()
//获取用户头像等信息数据
const { fetchData: fetchDataUserInfo } = GetWxUserInfoApi()
const getSelfUserInfo = async () => {
return new Promise((reslove, reject) => {
if (userInfo.adminUserInfo?.is_authorize_name) {
reslove(true)
return true
}
Taro.getUserProfile({
desc: '用于完善会员资料',
success: async (res) => {
if (!userInfo.session_key) {
await wxLogin()
}
const user_res = await fetchDataUserInfo({
session_key: userInfo.session_key,
raw_data: res.rawData,
signature: res.signature,
encrypted_data: res.encryptedData,
iv: res.iv,
})
if (user_res.success) {
setUserInfo({ ...user_res.data })
getAdminUserInfo()
} catch(e) {
console.log('登录失败::',e)
}
}
reslove(true)
} else {
reject(user_res.msg)
}
},
fail: (e) => {
console.log('授权失败::', e)
reject(e.errMsg)
},
})
})
}
//获取用户信息
const {fetchData: useFetchData} = GetAdminUserInfoApi()
const getAdminUserInfo = async () => {
let res = await useFetchData()
setAdminUserInfo({...res.data})
getShortCode(res.data.user_id)
}
//登录加checkLogin检查
const checkLogin = () => {
return new Promise( async (reslove) => {
if(!userInfo.token) {
await wxLogin()
reslove(true)
} else {
//这个东西不要打开,checkSession有调用频率问题
// Taro.checkSession({
// success: async () => {
// reslove(true)
// if(!userInfo.adminUserInfo) getAdminUserInfo()
// },
// fail: async () => {
// await wxLogin()
// reslove(true)
// }
// })
}
})
}
//获取手机号码
const { fetchData: fetchDataUserPhone } = GetPhoneNumberApi()
const { fetchData: fetchBindingCompany } = BindingCompanyApi()
const getPhoneNumber = (code) => {
return new Promise(async (reslove, reject) => {
if (userInfo.adminUserInfo?.is_authorize_phone) {
reslove(true)
return true
}
const res = await fetchDataUserPhone({ code })
if (res.success) {
setUserInfo({ ...userInfo.userInfo, phone: res.data.phone_number })
await fetchBindingCompany()
getAdminUserInfo()
reslove(res.data)
} else {
reject(res.msg)
}
})
}
//获取用户头像等信息数据
const {fetchData: fetchDataUserInfo} = GetWxUserInfoApi()
const getSelfUserInfo = async () => {
return new Promise((reslove, reject) => {
if(userInfo.adminUserInfo?.is_authorize_name) {
reslove(true)
return true
}
Taro.getUserProfile({
desc: '用于完善会员资料',
success: async (res) => {
if(!userInfo.session_key) {
await wxLogin()
}
const user_res = await fetchDataUserInfo({
session_key: userInfo.session_key,
raw_data: res.rawData,
signature: res.signature,
encrypted_data: res.encryptedData,
iv: res.iv
})
if(user_res.success) {
setUserInfo({...user_res.data})
getAdminUserInfo()
reslove(true)
} else {
reject(user_res.msg)
}
},
fail:(e) => {
console.log('授权失败::',e)
reject(e.errMsg)
}
})
})
}
//获取分享码(右上角分享码)
const { SharePage } = SHARE_SCENE
const { fetchData: fetchDataShortCode } = GetShortCodeApi()
const getShortCode = async (user_id) => {
const { data: resPage } = await fetchDataShortCode({ share_user_id: user_id, type: SharePage.value })
setSortCode({ ...userInfo.sort_code, shareShortPage: { title: '打造面料爆品 专注客户服务', code: resPage.md5_key, img: IMG_CND_Prefix + '/mall/share_img_01.png' } })
}
//获取手机号码
const {fetchData: fetchDataUserPhone} = GetPhoneNumberApi()
const {fetchData: fetchBindingCompany} = BindingCompanyApi()
const getPhoneNumber = (code) => {
return new Promise( async (reslove, reject) => {
if(userInfo.adminUserInfo?.is_authorize_phone) {
reslove(true)
return true
}
const res = await fetchDataUserPhone({code})
if(res.success) {
setUserInfo({...userInfo.userInfo, phone:res.data.phone_number})
await fetchBindingCompany()
getAdminUserInfo()
reslove(res.data)
} else {
reject(res.msg)
}
})
}
//获取分享码(右上角分享码)
const {SharePage} = SHARE_SCENE
const {fetchData: fetchDataShortCode} = GetShortCodeApi()
const getShortCode = async (user_id) => {
const {data: resPage} = await fetchDataShortCode({"share_user_id": user_id, type:SharePage.value})
setSortCode({...userInfo.sort_code, shareShortPage: {title: '打造面料爆品 专注客户服务', code: resPage.md5_key, img:IMG_CND_Prefix + '/mall/share_img_01.png'}})
}
return {
checkLogin,
wxLogin,
getSelfUserInfo,
getPhoneNumber,
userInfo,
getAdminUserInfo
}
return {
checkLogin,
wxLogin,
getSelfUserInfo,
getPhoneNumber,
userInfo,
getAdminUserInfo,
}
}
+139 -149
View File
@@ -1,165 +1,155 @@
import Taro from '@tarojs/taro';
import {UPLOAD_CDN_URL } from '@/common/constant'
import Taro from '@tarojs/taro'
import { UPLOAD_CDN_URL } from '@/common/constant'
import { GetSignApi } from '@/api/cdn'
export default () => {
const { fetchData: GetSign, state } = GetSignApi()
const { fetchData: GetSign, state} = GetSignApi()
// 上传图片 获取auth,Policy
/*
// 上传图片 获取auth,Policy
/*
scene 场景值,区分上传文件的根路径
type 类型值,区分上传业务bucket
*/
const getSecret = (scene, type) => {
return new Promise(async (resolve, reject) => {
const getSecret = (scene, type) => {
return new Promise(async (resolve, reject) => {
const SAVE_PATH = `/${scene}/{filemd5}{day}{hour}{min}{sec}{.suffix}`
const SAVE_PATH = `/${scene}/{filemd5}{day}{hour}{min}{sec}{.suffix}`;
let params = {
method: 'post',
save_key: SAVE_PATH,
}
// 获取签名
let res = await GetSign(params)
if (res.success) {
resolve(res.data)
} else {
reject({
code: res.code || '9999',
msg: res.msg,
})
}
})
}
const getFileType = (name) => {
if (!name) return false
var imgType = ['gif', 'jpeg', 'jpg', 'bmp', 'png']
var videoType = ['avi', 'wmv', 'mkv', 'mp4', 'mov', 'rm', '3gp', 'flv', 'mpg', 'rmvb', 'quicktime']
let params = {
'method': 'post',
'save_key': SAVE_PATH
}
// 获取签名
let res = await GetSign(params)
if (res.success) {
resolve(res.data)
if (RegExp('.?(' + imgType.join('|') + ')$', 'i').test(name.toLowerCase())) {
return 'image'
} else if (RegExp('.(' + videoType.join('|') + ')$', 'i').test(name.toLowerCase())) {
return 'video'
} else {
return false
}
}
/**
*
* @param {*} file 传入文件
* @param {String} secene 传入 'product'
* @param {String} type 传入 'product'
* @returns
*/
const uploadCDNImg = (file, secene, type) => {
let filetype = file.path
console.log('filetype::', filetype)
if (!getFileType(filetype)) {
Taro.showToast({
title: '上传文件类型错误',
icon: 'none',
duration: 3800,
})
return false
}
return new Promise((resolve, reject) => {
getSecret(secene, type)
.then((result) => {
let res: any = result
console.log('bucket', res.bucket)
var formdata = {
authorization: res.authorization,
policy: res.policy,
}
const uploadTask = Taro.uploadFile({
url: `${UPLOAD_CDN_URL}${res.bucket}`,
formData: formdata,
filePath: file.path,
name: 'file',
success: (res) => {
resolve(JSON.parse(`${res.data}`))
},
fail: (err) => {
console.log(err)
reject(err)
},
})
uploadTask.progress((res) => {
console.log('上传进度', res.progress)
if (res.progress < 100) {
Taro.showLoading({
title: '上传中...',
})
} else {
reject({
code: res.code || '9999',
msg: res.msg
});
Taro.hideLoading()
}
})
})
}
const getFileType = (name) => {
if (!name) return false;
var imgType = ["gif", "jpeg", "jpg", "bmp", "png"];
var videoType = ["avi", "wmv", "mkv", "mp4", "mov", "rm", "3gp", "flv", "mpg", "rmvb", "quicktime"];
if (RegExp("\.?(" + imgType.join("|") + ")$", "i").test(name.toLowerCase())) {
return 'image';
} else if (RegExp("\.(" + videoType.join("|") + ")$", "i").test(name.toLowerCase())) {
return 'video';
} else {
return false;
}
}
/**
*
* @param {*} file 传入文件
* @param {String} secene 传入 'product'
* @param {String} type 传入 'product'
* @returns
*/
const uploadCDNImg = (file, secene, type) => {
let filetype = file.path
console.log('filetype::',filetype)
if (!getFileType(filetype)) {
Taro.showToast({
title: "上传文件类型错误",
icon: "none",
duration: 3800
})
return false
}
return new Promise((resolve, reject) => {
getSecret(secene, type)
.then(result => {
let res:any = result
console.log('bucket', res.bucket);
var formdata = {
'authorization': res.authorization,
'policy': res.policy,
}
const uploadTask = Taro.uploadFile({
url: `${UPLOAD_CDN_URL}${res.bucket}`,
formData: formdata,
filePath: file.path,
name: 'file',
success: res => {
resolve(JSON.parse(`${res.data}`))
},
fail: err => {
console.log(err)
reject(err)
}
})
uploadTask.progress(res => {
console.log('上传进度', res.progress);
if (res.progress < 100) {
Taro.showLoading({
title: '上传中...'
})
} else {
Taro.hideLoading()
}
})
})
.catch(result => {
reject(result)
Taro.showToast({
title: "获取密钥失败!",
icon: "none",
duration: 3800
})
})
.catch((result) => {
reject(result)
Taro.showToast({
title: '获取密钥失败!',
icon: 'none',
duration: 3800,
})
})
}
})
}
// product 产品相关,图片、纹理图等 全平台
// after-sale 售后(申请退货、退款)相关的、图片、视频 全平台
// mall 电子商城相关的 全平台
// logistics 物流(发货、提货)相关的、图片、视频 全平台
type cdn_upload_type_Param = 'product'|'after-sale'|'mall'|'logistics'
/**
* 上传手机图片
* @param cdn_upload_type 场景值
* @param count // 1时返回一张图片信息, 大于1时返回图片数组
* @returns
*/
const getWxPhoto = (cdn_upload_type: cdn_upload_type_Param, count: number = 1) => {
return new Promise((resolve, reject) => {
let list:any[] = []
Taro.chooseImage({
count: count,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: async function (res) {
try {
if(count > 1) {
for(let i = 0; i < res.tempFiles.length; i++) {
let data = await uploadCDNImg(res.tempFiles[i], cdn_upload_type, cdn_upload_type)
list.push(data)
}
resolve(list)
} else {
//兼容以前上传一张的情况
let data = await uploadCDNImg(res.tempFiles[0], cdn_upload_type, cdn_upload_type)
resolve(data)
}
} catch(res) {
reject(res)
}
}
})
})
}
return {
uploadCDNImg,
getWxPhoto
}
// product 产品相关,图片、纹理图等 全平台
// after-sale 售后(申请退货、退款)相关的、图片、视频 全平台
// mall 电子商城相关的 全平台
// logistics 物流(发货、提货)相关的、图片、视频 全平台
type cdn_upload_type_Param = 'product' | 'after-sale' | 'mall' | 'logistics'
/**
* 上传手机图片
* @param cdn_upload_type 场景值
* @param count // 1时返回一张图片信息, 大于1时返回图片数组
* @returns
*/
const getWxPhoto = (cdn_upload_type: cdn_upload_type_Param, count: number = 1) => {
return new Promise((resolve, reject) => {
let list: any[] = []
Taro.chooseImage({
count: count,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: async function (res) {
try {
if (count > 1) {
for (let i = 0; i < res.tempFiles.length; i++) {
let data = await uploadCDNImg(res.tempFiles[i], cdn_upload_type, cdn_upload_type)
list.push(data)
}
resolve(list)
} else {
//兼容以前上传一张的情况
let data = await uploadCDNImg(res.tempFiles[0], cdn_upload_type, cdn_upload_type)
resolve(data)
}
} catch (res) {
reject(res)
}
},
})
})
}
return {
uploadCDNImg,
getWxPhoto,
}
}
+41 -41
View File
@@ -1,51 +1,51 @@
import { useDispatch, useSelector } from 'react-redux'
import { CLEAR_SESSIONKEY, SET_USERINFO, SET_TOKEN, SET_SESSIONKEY, CLEAR_USERINFO, CLEAR_TOKEN, SET_ADMINUSERINFO, SET_SORTCODE} from '@/constants/userInfo'
import {DataParam, UserParam, UserAdminParam, SortCodeParam} from '@/reducers/userInfo'
import { CLEAR_SESSIONKEY, SET_USERINFO, SET_TOKEN, SET_SESSIONKEY, CLEAR_USERINFO, CLEAR_TOKEN, SET_ADMINUSERINFO, SET_SORTCODE } from '@/constants/userInfo'
import { DataParam, UserParam, UserAdminParam, SortCodeParam } from '@/reducers/userInfo'
export default () => {
const userInfo = useSelector((state:DataParam) => state.userInfo) as DataParam
const dispatch = useDispatch()
const setToken = (token: string) => {
dispatch({type:SET_TOKEN, data:{token}})
}
const userInfo = useSelector((state: DataParam) => state.userInfo) as DataParam
const dispatch = useDispatch()
const setSessionKey = (sessionkey: string) => {
dispatch({type:SET_SESSIONKEY, data:{session_key: sessionkey}})
}
const setToken = (token: string) => {
dispatch({ type: SET_TOKEN, data: { token } })
}
const setUserInfo = (userInfo: UserParam) => {
dispatch({type:SET_USERINFO, data:{userInfo}})
}
const setSessionKey = (sessionkey: string) => {
dispatch({ type: SET_SESSIONKEY, data: { session_key: sessionkey } })
}
const setAdminUserInfo = (adminUserInfo: UserAdminParam) => {
dispatch({type:SET_ADMINUSERINFO, data:{adminUserInfo}})
}
const setUserInfo = (userInfo: UserParam) => {
dispatch({ type: SET_USERINFO, data: { userInfo } })
}
const setSortCode = (sortCode:SortCodeParam) => {
dispatch({type:SET_SORTCODE, data:{sort_code:sortCode}})
}
const setAdminUserInfo = (adminUserInfo: UserAdminParam) => {
dispatch({ type: SET_ADMINUSERINFO, data: { adminUserInfo } })
}
const removeUserInfo = () => {
dispatch({type:CLEAR_USERINFO})
}
const setSortCode = (sortCode: SortCodeParam) => {
dispatch({ type: SET_SORTCODE, data: { sort_code: sortCode } })
}
const removeToken = () => {
dispatch({type:CLEAR_TOKEN})
}
const removeUserInfo = () => {
dispatch({ type: CLEAR_USERINFO })
}
const removeSessionKey = () => {
dispatch({type:CLEAR_SESSIONKEY})
}
const removeToken = () => {
dispatch({ type: CLEAR_TOKEN })
}
return {
setToken,
setUserInfo,
setAdminUserInfo,
setSessionKey,
removeUserInfo,
removeToken,
removeSessionKey,
setSortCode,
userInfo, //响应式数据返回
}
}
const removeSessionKey = () => {
dispatch({ type: CLEAR_SESSIONKEY })
}
return {
setToken,
setUserInfo,
setAdminUserInfo,
setSessionKey,
removeUserInfo,
removeToken,
removeSessionKey,
setSortCode,
userInfo, //响应式数据返回
}
}