refactor: migrate to WeChat cloud development
- 新增 cloud-functions/ 目录(6个云函数:auth/device/subscription/treatment/user/admin) - 云函数使用 wx-server-sdk + 云数据库(不再依赖 MySQL) - auth 云函数通过 cloud.getWXContext() 自动获取 openid,无需手动 wx.login - request.js 改为通过 wx.cloud.callFunction() 调用云函数 - 登录流程简化:点击授权 → 直接调 auth 云函数 → 获取用户信息 - 保留 HTTP 模式切换能力(USE_CLOUD 变量控制)
这个提交包含在:
+13
-20
@@ -9,6 +9,13 @@ App({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onLaunch: function () {
|
onLaunch: function () {
|
||||||
|
if (!wx.cloud) {
|
||||||
|
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wx.cloud.init({
|
||||||
|
traceUser: true
|
||||||
|
})
|
||||||
this.checkLogin()
|
this.checkLogin()
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -28,30 +35,16 @@ App({
|
|||||||
self.globalData.userId = String(profile.user_id)
|
self.globalData.userId = String(profile.user_id)
|
||||||
}).catch(function () {
|
}).catch(function () {
|
||||||
wx.removeStorageSync('token')
|
wx.removeStorageSync('token')
|
||||||
wx.reLaunch({ url: '/pages/login/login' })
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
doLogin: function () {
|
doLogin: function () {
|
||||||
return new Promise(function (resolve, reject) {
|
return http.post('/api/v1/auth/login', {}).then(function (data) {
|
||||||
wx.login({
|
wx.setStorageSync('token', data.token)
|
||||||
success: function (res) {
|
var app = getApp()
|
||||||
if (!res.code) {
|
app.globalData.userInfo = data.user_info
|
||||||
reject({ message: 'wx.login failed' })
|
app.globalData.userId = data.user_id
|
||||||
return
|
return data
|
||||||
}
|
|
||||||
http.post('/api/v1/auth/login', {
|
|
||||||
code: res.code
|
|
||||||
}).then(function (data) {
|
|
||||||
wx.setStorageSync('token', data.token)
|
|
||||||
var app = getApp()
|
|
||||||
app.globalData.userInfo = data.user_info
|
|
||||||
app.globalData.userId = data.user_id
|
|
||||||
resolve(data)
|
|
||||||
}).catch(reject)
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const { action } = event
|
||||||
|
|
||||||
|
if (action === 'dashboard') {
|
||||||
|
const deviceCount = await db.collection('bindings').where({ status: 'active' }).count()
|
||||||
|
const userCount = await db.collection('users').count()
|
||||||
|
const treatmentCount = await db.collection('treatment_records').count()
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
device_count: deviceCount.total,
|
||||||
|
user_count: userCount.total,
|
||||||
|
treatment_count: treatmentCount.total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const wxContext = cloud.getWXContext()
|
||||||
|
const openid = wxContext.OPENID
|
||||||
|
|
||||||
|
if (event.action === 'login') {
|
||||||
|
let userRecord = await db.collection('users').where({ openid }).get()
|
||||||
|
|
||||||
|
if (userRecord.data.length === 0) {
|
||||||
|
const newUser = {
|
||||||
|
openid,
|
||||||
|
nickname: '',
|
||||||
|
avatar_url: '',
|
||||||
|
phone: '',
|
||||||
|
gender: 0,
|
||||||
|
created_at: db.serverDate()
|
||||||
|
}
|
||||||
|
await db.collection('users').add({ data: newUser })
|
||||||
|
userRecord = await db.collection('users').where({ openid }).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = userRecord.data[0]
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
token: openid + '_' + Date.now(),
|
||||||
|
user_id: user._id,
|
||||||
|
user_info: {
|
||||||
|
user_id: user._id,
|
||||||
|
nickname: user.nickname || '用户' + openid.slice(-4),
|
||||||
|
avatar_url: user.avatar_url || '',
|
||||||
|
phone: user.phone || '',
|
||||||
|
gender: user.gender || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.action === 'refresh') {
|
||||||
|
const userRecord = await db.collection('users').where({ openid }).get()
|
||||||
|
if (userRecord.data.length === 0) {
|
||||||
|
return { code: 1001, message: '用户不存在' }
|
||||||
|
}
|
||||||
|
return { code: 0, data: { token: openid + '_' + Date.now() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "auth",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
const _ = db.command
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const wxContext = cloud.getWXContext()
|
||||||
|
const openid = wxContext.OPENID
|
||||||
|
const { action } = event
|
||||||
|
|
||||||
|
if (action === 'bind') {
|
||||||
|
const { device_id } = event.data
|
||||||
|
if (!device_id) return { code: -1, message: '缺少设备ID' }
|
||||||
|
|
||||||
|
const existBind = await db.collection('bindings').where({ openid, status: 'active' }).count()
|
||||||
|
if (existBind.total > 0) {
|
||||||
|
const exist = await db.collection('bindings').where({ openid, status: 'active' }).get()
|
||||||
|
return { code: 2001, message: '已绑定设备', data: { device_id: exist.data[0].device_id } }
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.collection('bindings').add({
|
||||||
|
data: {
|
||||||
|
openid,
|
||||||
|
device_id,
|
||||||
|
status: 'active',
|
||||||
|
bind_time: db.serverDate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const subExist = await db.collection('subscriptions').where({ openid, status: 'active' }).count()
|
||||||
|
if (subExist.total === 0) {
|
||||||
|
await db.collection('subscriptions').add({
|
||||||
|
data: {
|
||||||
|
openid,
|
||||||
|
plan_type: 'trial',
|
||||||
|
status: 'active',
|
||||||
|
start_time: db.serverDate(),
|
||||||
|
end_time: new Date(Date.now() + 7 * 24 * 3600 * 1000),
|
||||||
|
remaining_days: 7
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
device_id,
|
||||||
|
bind_token: 'bt_' + Date.now(),
|
||||||
|
subscription: { plan_type: 'trial', remaining_days: 7 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'unbind') {
|
||||||
|
await db.collection('bindings').where({ openid, status: 'active' }).update({ data: { status: 'inactive' } })
|
||||||
|
return { code: 0, data: {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'list') {
|
||||||
|
const bindings = await db.collection('bindings').where({ openid, status: 'active' }).get()
|
||||||
|
const devices = bindings.data.map(b => ({
|
||||||
|
device_id: b.device_id,
|
||||||
|
name: '我的光面膜',
|
||||||
|
status: 'online',
|
||||||
|
bind_time: b.bind_time
|
||||||
|
}))
|
||||||
|
return { code: 0, data: { devices, total: devices.length } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'detail') {
|
||||||
|
const { device_id } = event.data
|
||||||
|
const bindings = await db.collection('bindings').where({ openid, device_id, status: 'active' }).get()
|
||||||
|
if (bindings.data.length === 0) return { code: -1, message: '设备未绑定' }
|
||||||
|
const b = bindings.data[0]
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
device_id: b.device_id,
|
||||||
|
name: '我的光面膜',
|
||||||
|
firmware_version: '1.0.0',
|
||||||
|
battery_level: 85,
|
||||||
|
status: 'online',
|
||||||
|
bind_time: b.bind_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "device",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const wxContext = cloud.getWXContext()
|
||||||
|
const openid = wxContext.OPENID
|
||||||
|
const { action } = event
|
||||||
|
|
||||||
|
if (action === 'status') {
|
||||||
|
const subs = await db.collection('subscriptions').where({ openid, status: 'active' }).get()
|
||||||
|
if (subs.data.length === 0) {
|
||||||
|
return { code: 0, data: { plan_type: 'none', status: 'inactive', remaining_days: 0 } }
|
||||||
|
}
|
||||||
|
const sub = subs.data[0]
|
||||||
|
const now = new Date()
|
||||||
|
const end = new Date(sub.end_time)
|
||||||
|
const remain = Math.max(0, Math.ceil((end - now) / (24 * 3600 * 1000)))
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
plan_type: sub.plan_type,
|
||||||
|
status: remain > 0 ? 'active' : 'expired',
|
||||||
|
remaining_days: remain,
|
||||||
|
start_time: sub.start_time,
|
||||||
|
end_time: sub.end_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'purchase') {
|
||||||
|
const { plan_type } = event.data
|
||||||
|
const price = plan_type === 'monthly' ? 99 : 899
|
||||||
|
const days = plan_type === 'monthly' ? 30 : 365
|
||||||
|
|
||||||
|
await db.collection('subscriptions').where({ openid, status: 'active' }).update({ data: { status: 'expired' } })
|
||||||
|
|
||||||
|
await db.collection('subscriptions').add({
|
||||||
|
data: {
|
||||||
|
openid,
|
||||||
|
plan_type,
|
||||||
|
status: 'active',
|
||||||
|
start_time: db.serverDate(),
|
||||||
|
end_time: new Date(Date.now() + days * 24 * 3600 * 1000),
|
||||||
|
remaining_days: days,
|
||||||
|
price
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return { code: 0, data: { order_id: 'ORD' + Date.now(), plan_type, status: 'paid' } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'verify') {
|
||||||
|
return { code: 0, data: { valid: true } }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "subscription",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
const _ = db.command
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const wxContext = cloud.getWXContext()
|
||||||
|
const openid = wxContext.OPENID
|
||||||
|
const { action } = event
|
||||||
|
|
||||||
|
if (action === 'sync') {
|
||||||
|
const d = event.data
|
||||||
|
await db.collection('treatment_records').add({
|
||||||
|
data: {
|
||||||
|
openid,
|
||||||
|
session_id: d.session_id || 'S' + Date.now(),
|
||||||
|
device_id: d.device_id || '',
|
||||||
|
regions: d.regions || 0,
|
||||||
|
total_duration_ms: d.total_duration_ms || 0,
|
||||||
|
mode: d.mode || 0,
|
||||||
|
avg_pd: d.avg_pd || 0,
|
||||||
|
created_at: db.serverDate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { code: 0, data: { session_id: d.session_id || 'S' + Date.now() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'history') {
|
||||||
|
const { page = 1, page_size = 20 } = event.data || {}
|
||||||
|
const totalRes = await db.collection('treatment_records').where({ openid }).count()
|
||||||
|
const records = await db.collection('treatment_records')
|
||||||
|
.where({ openid })
|
||||||
|
.orderBy('created_at', 'desc')
|
||||||
|
.skip((page - 1) * page_size)
|
||||||
|
.limit(page_size)
|
||||||
|
.get()
|
||||||
|
|
||||||
|
return { code: 0, data: { records: records.data, total: totalRes.total } }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "treatment",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
const cloud = require('wx-server-sdk')
|
||||||
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||||
|
const db = cloud.database()
|
||||||
|
|
||||||
|
exports.main = async (event, context) => {
|
||||||
|
const wxContext = cloud.getWXContext()
|
||||||
|
const openid = wxContext.OPENID
|
||||||
|
const { action } = event
|
||||||
|
|
||||||
|
if (action === 'profile') {
|
||||||
|
const users = await db.collection('users').where({ openid }).get()
|
||||||
|
if (users.data.length === 0) return { code: 1001, message: '用户不存在' }
|
||||||
|
const user = users.data[0]
|
||||||
|
const binds = await db.collection('bindings').where({ openid, status: 'active' }).count()
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
data: {
|
||||||
|
user_id: user._id,
|
||||||
|
nickname: user.nickname || '用户' + openid.slice(-4),
|
||||||
|
avatar_url: user.avatar_url || '',
|
||||||
|
phone: user.phone || '',
|
||||||
|
gender: user.gender || 0,
|
||||||
|
device_count: binds.total,
|
||||||
|
created_at: user.created_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'update') {
|
||||||
|
const updates = {}
|
||||||
|
if (event.data.nickname) updates.nickname = event.data.nickname
|
||||||
|
if (event.data.avatar_url) updates.avatar_url = event.data.avatar_url
|
||||||
|
if (event.data.gender !== undefined) updates.gender = event.data.gender
|
||||||
|
await db.collection('users').where({ openid }).update({ data: updates })
|
||||||
|
return { code: 0, data: {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { code: -1, message: '未知操作' }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "user",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"wx-server-sdk": "~2.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ Page({
|
|||||||
wx.switchTab({ url: '/pages/index/index' })
|
wx.switchTab({ url: '/pages/index/index' })
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
self.setData({ loading: false })
|
self.setData({ loading: false })
|
||||||
wx.showToast({ title: '登录失败', icon: 'none' })
|
wx.showToast({ title: err.message || '登录失败', icon: 'none' })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
"libVersion": "3.15.2",
|
"libVersion": "3.15.2",
|
||||||
"appid": "wxc4045074ef298510",
|
"appid": "wxc4045074ef298510",
|
||||||
"projectname": "hox-beauty",
|
"projectname": "hox-beauty",
|
||||||
|
"cloudfunctionRoot": "cloud-functions/",
|
||||||
"condition": {},
|
"condition": {},
|
||||||
"simulatorPluginLibVersion": {},
|
"simulatorPluginLibVersion": {},
|
||||||
"editorSetting": {}
|
"editorSetting": {}
|
||||||
|
|||||||
+54
-5
@@ -1,13 +1,35 @@
|
|||||||
var API_BASE = 'https://api.lightmask.com'
|
var USE_CLOUD = true
|
||||||
var USE_MOCK = true
|
|
||||||
|
function callCloud(funcName, action, data) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
wx.cloud.callFunction({
|
||||||
|
name: funcName,
|
||||||
|
data: { action: action, data: data }
|
||||||
|
}).then(function (res) {
|
||||||
|
if (res.result && res.result.code === 0) {
|
||||||
|
resolve(res.result.data)
|
||||||
|
} else if (res.result && (res.result.code === 1001 || res.result.code === 1002)) {
|
||||||
|
wx.removeStorageSync('token')
|
||||||
|
wx.reLaunch({ url: '/pages/login/login' })
|
||||||
|
reject(res.result)
|
||||||
|
} else {
|
||||||
|
reject(res.result || { code: -1, message: '请求失败' })
|
||||||
|
}
|
||||||
|
}).catch(function (err) {
|
||||||
|
reject({ code: 2002, message: err.errMsg || '网络异常' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var mock = null
|
var mock = null
|
||||||
if (USE_MOCK) {
|
if (!USE_CLOUD) {
|
||||||
mock = require('./mock')
|
mock = require('./mock')
|
||||||
}
|
}
|
||||||
|
|
||||||
function request(options) {
|
var API_BASE = 'https://api.lightmask.com'
|
||||||
if (USE_MOCK && mock && mock.enabled) {
|
|
||||||
|
function httpRequest(options) {
|
||||||
|
if (mock && mock.enabled) {
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var result = mock.handle(options.method || 'GET', options.path, options.data)
|
var result = mock.handle(options.method || 'GET', options.path, options.data)
|
||||||
@@ -49,6 +71,33 @@ function request(options) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var FUNC_MAP = {
|
||||||
|
'/api/v1/auth/login': { fn: 'auth', action: 'login' },
|
||||||
|
'/api/v1/auth/refresh': { fn: 'auth', action: 'refresh' },
|
||||||
|
'/api/v1/user/profile': { fn: 'user', action: 'profile' },
|
||||||
|
'/api/v1/user/update': { fn: 'user', action: 'update' },
|
||||||
|
'/api/v1/device/bind': { fn: 'device', action: 'bind' },
|
||||||
|
'/api/v1/device/unbind': { fn: 'device', action: 'unbind' },
|
||||||
|
'/api/v1/device/list': { fn: 'device', action: 'list' },
|
||||||
|
'/api/v1/device/detail': { fn: 'device', action: 'detail' },
|
||||||
|
'/api/v1/subscription/status': { fn: 'subscription', action: 'status' },
|
||||||
|
'/api/v1/subscription/purchase': { fn: 'subscription', action: 'purchase' },
|
||||||
|
'/api/v1/subscription/verify': { fn: 'subscription', action: 'verify' },
|
||||||
|
'/api/v1/treatment/sync': { fn: 'treatment', action: 'sync' },
|
||||||
|
'/api/v1/treatment/history': { fn: 'treatment', action: 'history' }
|
||||||
|
}
|
||||||
|
|
||||||
|
function request(options) {
|
||||||
|
if (USE_CLOUD) {
|
||||||
|
var mapping = FUNC_MAP[options.path]
|
||||||
|
if (mapping) {
|
||||||
|
return callCloud(mapping.fn, mapping.action, options.data)
|
||||||
|
}
|
||||||
|
return Promise.reject({ code: -1, message: '未映射的接口' })
|
||||||
|
}
|
||||||
|
return httpRequest(options)
|
||||||
|
}
|
||||||
|
|
||||||
function get(path, data) {
|
function get(path, data) {
|
||||||
return request({ path: path, method: 'GET', data: data })
|
return request({ path: path, method: 'GET', data: data })
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户