提交 1f8e06ea 编写于 作者: M MicroMilo

重构用户和小队管理,编写验证码代码,尚未测试!

上级 01a1e4fa
......@@ -244,40 +244,44 @@
"style": {
"navigationBarTitleText": "用户日志"
}
}, {
"path": "mustgo-user/add",
"style": {
"navigationBarTitleText": "新增",
"navigationStyle": "default"
}
}, {
"path": "mustgo-user/edit",
"style": {
"navigationBarTitleText": "编辑"
}
}, {
"path": "mustgo-user/list",
"style": {
"navigationBarTitleText": "列表"
}
}, {
"path": "mustgo-team/add",
"style": {
"navigationBarTitleText": "新增"
}
}, {
"path": "mustgo-team/edit",
"style": {
"navigationBarTitleText": "编辑"
}
}, {
"path": "mustgo-team/list",
"style": {
"navigationBarTitleText": "列表"
}
}
]
},
{
"root": "pages/content",
"pages": [{
"path": "mustgo-user/add",
"style": {
"navigationBarTitleText": "新增",
"navigationStyle": "default"
}
}, {
"path": "mustgo-user/edit",
"style": {
"navigationBarTitleText": "编辑"
}
}, {
"path": "mustgo-user/list",
"style": {
"navigationBarTitleText": "列表"
}
}, {
"path": "mustgo-team/add",
"style": {
"navigationBarTitleText": "新增"
}
}, {
"path": "mustgo-team/edit",
"style": {
"navigationBarTitleText": "编辑"
}
}, {
"path": "mustgo-team/list",
"style": {
"navigationBarTitleText": "列表"
}
}]
},
{
"root": "pages/uni-stat",
"pages": [{
......
<template>
<view class="uni-container">
<uni-forms ref="form" :model="formData" validateTrigger="bind">
<uni-forms-item name="icon" label="队标" @click="avatarChoose">
<image :src="formData.icon" style="width: 120px; height: 80px;"></image>
</uni-forms-item>
<uni-forms-item name="name" label="队名">
<uni-easyinput placeholder="小队名称" v-model="formData.name"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="owner_id" label="发起人id">
<uni-easyinput placeholder="小队发起人id" v-model="formData.owner_id"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="description" label="描述">
<uni-easyinput placeholder="小队描述" v-model="formData.description"></uni-easyinput>
</uni-forms-item>
<view class="uni-button-group">
<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
<navigator open-type="navigateBack" style="margin-left: 15px;">
<button class="uni-button" style="width: 100px;">返回</button>
</navigator>
</view>
</uni-forms>
</view>
</template>
<script>
import {
validator
} from '../../../js_sdk/validator/mustgo-team.js';
const db = uniCloud.database();
const dbCmd = db.command;
const dbCollectionName = 'mustgo-team';
function getValidator(fields) {
let result = {}
for (let key in validator) {
if (fields.includes(key)) {
result[key] = validator[key]
}
}
return result
}
export default {
data() {
let formData = {
"icon": "https://mp-6f6feaec-a026-4402-8e8d-18f7572890da.cdn.bspapp.com/cloudstorage/0510a534-dd8d-41f0-8341-601aa677e243.jpg",
"name": "",
"owner_id": "",
"description": ""
}
return {
formData,
formOptions: {},
rules: {
...getValidator(Object.keys(formData))
}
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
methods: {
/**
* 验证表单并提交
*/
submit() {
uni.showLoading({
mask: true
})
this.$refs.form.validate().then((res) => {
return this.submitForm(res)
}).catch(() => {}).finally(() => {
uni.hideLoading()
})
},
avatarChoose() {
let that = this;
console.log("upload image loading")
uniCloud.chooseAndUploadFile({
type: 'image',
success(res) {
that.formData.icon = res["tempFiles"][0]["url"]
console.log(res)
},
fail() {
console.log("upload icon failed")
},
complete() {}
});
},
/**
* 提交表单
*/
submitForm(value) {
// 使用 clientDB 提交数据
return db.collection(dbCollectionName).add(value).then((res) => {
uni.showToast({
title: '新增成功'
})
this.getOpenerEventChannel().emit('refreshData')
setTimeout(() => uni.navigateBack(), 500)
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
}
}
}
</script>
\ No newline at end of file
<template>
<view class="uni-container">
<uni-forms ref="form" :model="formData" validateTrigger="bind">
<uni-forms-item name="icon" label="队标" @click="avatarChoose">
<image :src="formData.icon" style="width: 120px; height: 80px;"></image>
</uni-forms-item>
<uni-forms-item name="name" label="队名">
<uni-easyinput placeholder="小队名称" v-model="formData.name"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="owner_id" label="发起人id">
<uni-easyinput placeholder="小队发起人id" v-model="formData.owner_id"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="description" label="描述">
<uni-easyinput placeholder="小队描述" v-model="formData.description"></uni-easyinput>
</uni-forms-item>
<view class="uni-button-group">
<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
<navigator open-type="navigateBack" style="margin-left: 15px;">
<button class="uni-button" style="width: 100px;">返回</button>
</navigator>
</view>
</uni-forms>
</view>
</template>
<script>
import {
validator
} from '../../../js_sdk/validator/mustgo-team.js';
const db = uniCloud.database();
const dbCmd = db.command;
const dbCollectionName = 'mustgo-team';
function getValidator(fields) {
let result = {}
for (let key in validator) {
if (fields.includes(key)) {
result[key] = validator[key]
}
}
return result
}
export default {
data() {
let formData = {
"icon": "",
"name": "",
"owner_id": "",
"description": ""
}
return {
formData,
formOptions: {},
rules: {
...getValidator(Object.keys(formData))
}
}
},
onLoad(e) {
if (e.id) {
const id = e.id
this.formDataId = id
this.getDetail(id)
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
methods: {
/**
* 验证表单并提交
*/
submit() {
uni.showLoading({
mask: true
})
this.$refs.form.validate().then((res) => {
return this.submitForm(res)
}).catch(() => {}).finally(() => {
uni.hideLoading()
})
},
/**
* 提交表单
*/
submitForm(value) {
// 使用 clientDB 提交数据
return db.collection(dbCollectionName).doc(this.formDataId).update(value).then((res) => {
uni.showToast({
title: '修改成功'
})
this.getOpenerEventChannel().emit('refreshData')
setTimeout(() => uni.navigateBack(), 500)
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
},
avatarChoose() {
let that = this;
console.log("upload image loading")
uniCloud.chooseAndUploadFile({
type: 'image',
success(res) {
that.formData.icon = res["tempFiles"][0]["url"]
console.log(res)
},
fail() {
console.log("upload icon failed")
},
complete() {}
});
},
/**
* 获取表单数据
* @param {Object} id
*/
getDetail(id) {
uni.showLoading({
mask: true
})
db.collection(dbCollectionName).doc(id).field("icon,name,owner_id,description").get().then((res) => {
const data = res.result.data[0]
if (data) {
this.formData = data
}
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
}
}
}
</script>
\ No newline at end of file
......@@ -28,7 +28,7 @@
<uni-th align="center">操作</uni-th>
</uni-tr>
<uni-tr v-for="(item,index) in data" :key="index">
<uni-td align="center">{{item.icon}}</uni-td>
<uni-td align="center"><image :src="item.icon" style="width: 120px; height: 80px;"></image></uni-td>
<uni-td align="center">{{item.name}}</uni-td>
<uni-td align="center">{{item.owner_id}}</uni-td>
<uni-td align="center">{{item.description}}</uni-td>
......
......@@ -4,14 +4,8 @@
<uni-forms-item name="name" label="用户名">
<uni-easyinput v-model="formData.name"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="icon" label="用户头像">
<image :src="formData.icon" mode="grid"></image>
<uni-file-picker
v-model="icon"
fileMediatype="image"
mode="grid"
/>
<uni-easyinput v-model="formData.icon" :clearable="false"/>
<uni-forms-item name="icon" label="用户头像" @click="avatarChoose">
<image :src="formData.icon" style="width: 120px; height: 80px;"></image>
</uni-forms-item>
<uni-forms-item name="gender" label="性别">
<uni-easyinput v-model="formData.gender"></uni-easyinput>
......@@ -37,7 +31,6 @@
<uni-forms-item name="total_walking_distance" label="健走总距离">
<uni-easyinput type="number" v-model="formData.total_walking_distance"></uni-easyinput>
</uni-forms-item>
<button @click="smsSend">发短信啦!</button>
<view class="uni-button-group">
<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
<navigator open-type="navigateBack" style="margin-left: 15px;">
......@@ -82,9 +75,9 @@
"total_walking_distance": 0
}
return {
icon: [
],
// icon: [
// ],
formData,
formOptions: {},
rules: {
......@@ -102,25 +95,12 @@
onReady() {
this.$refs.form.setRules(this.rules)
},
watch: {
icon(newIcon, oldIcon) {
this.formData.icon = newIcon[0].url
}
},
// watch: {
// icon(newIcon, oldIcon) {
// this.formData.icon = newIcon[0].url
// }
// },
methods: {
smsSend() {
uniCloud.callFunction({
name: 'fe-retrievePassword',
data: {
phone: '15860855025',
password: '123456'
}
})
.then(res => {
console.log(res);
console.log("demodemodmeodmeodmeod")
});
},
/**
* 验证表单并提交
*/
......@@ -153,7 +133,21 @@
})
})
},
avatarChoose() {
let that = this;
console.log("upload image loading")
uniCloud.chooseAndUploadFile({
type: 'image',
success(res) {
that.formData.icon = res["tempFiles"][0]["url"]
console.log(res)
},
fail() {
console.log("upload icon failed")
},
complete() {}
});
},
/**
* 获取表单数据
* @param {Object} id
......@@ -164,7 +158,7 @@
})
db.collection(dbCollectionName).doc(id).field(
"name,icon,gender,password,phone_num,team_id,school,type,total_running_distance,total_walking_distance"
).get().then((res) => {
).get().then((res) => {
const data = res.result.data[0]
if (data) {
this.formData = data
......
......@@ -25,6 +25,8 @@
<uni-table ref="table" :loading="loading" :emptyText="error.message || '没有更多数据'" border stripe
type="selection" @selection-change="selectionChange">
<uni-tr>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'icon')"
sortable @sort-change="sortChange($event, 'icon')">头像</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'name')"
sortable @sort-change="sortChange($event, 'name')">用户名</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'gender')"
......@@ -35,16 +37,22 @@
sortable @sort-change="sortChange($event, 'phone_num')">手机号</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'school')"
sortable @sort-change="sortChange($event, 'school')">学校</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'type[0].identity')"
sortable @sort-change="sortChange($event, 'type[0].identity')">身份</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'total_running_distance')"
sortable @sort-change="sortChange($event, 'total_running_distance')">跑步总量</uni-th>
<uni-th align="center" filter-type="search" @filter-change="filterChange($event, 'total_walking_distance')"
sortable @sort-change="sortChange($event, 'total_walking_distance')">健走总量</uni-th>
<uni-th align="center" filter-type="search"
@filter-change="filterChange($event, 'type[0].identity')" sortable
@sort-change="sortChange($event, 'type[0].identity')">身份</uni-th>
<uni-th align="center" filter-type="search"
@filter-change="filterChange($event, 'total_running_distance')" sortable
@sort-change="sortChange($event, 'total_running_distance')">跑步总量</uni-th>
<uni-th align="center" filter-type="search"
@filter-change="filterChange($event, 'total_walking_distance')" sortable
@sort-change="sortChange($event, 'total_walking_distance')">健走总量</uni-th>
<uni-th align="center">操作</uni-th>
</uni-tr>
<uni-tr v-for="(item,index) in data" :key="index">
<uni-td align="center">
<image :src="item.icon" style="width: 120px; height: 80px;"></image>
</uni-td>
<uni-td align="center">{{item.name}}</uni-td>
<uni-td align="center">{{item.gender}}</uni-td>
<uni-td align="center">{{item.password}}</uni-td>
......@@ -80,35 +88,17 @@
filterToWhere
} from '../../../js_sdk/validator/mustgo-user.js';
// uniCloud.callFunction({
// name: 'fe-sport-walk-rank',
// data: {
// startTime: "2023-04-28 11:13:54",
// duration: 1000,
// feelings: "good",
// userId: "644a643a0c801ca878983559",
// distance: 5.98,
// pace: 5.1,
// startPoint: {
// "longitude": 116.39,
// "latitude": 39.9
// },
// endPoint: {
// "longitude": 117.9891,
// "latitude": 40.98
// },
// pathLine: [{
// "longitude": 116.39,
// "latitude": 39.9
// }, {
// "longitude": 117.9891,
// "latitude": 40.98
// }]
// }
// })
// .then(res => {
// console.log(res);
// });
uniCloud.callFunction({
name: 'fe-retrievePassword',
data: {
phone: "13950014724",
code: "",
password: "12345678"
}
})
.then(res => {
console.log(res);
});
const db = uniCloud.database()
// 表查询配置
......
<template>
<view class="uni-container">
<uni-forms ref="form" :model="formData" validateTrigger="bind">
<uni-forms-item name="icon" label="队标">
<uni-easyinput placeholder="小队队标" v-model="formData.icon"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="name" label="队名">
<uni-easyinput placeholder="小队名称" v-model="formData.name"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="owner_id" label="发起人id">
<uni-easyinput placeholder="小队发起人id" v-model="formData.owner_id"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="description" label="描述">
<uni-easyinput placeholder="小队描述" v-model="formData.description"></uni-easyinput>
</uni-forms-item>
<view class="uni-button-group">
<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
<navigator open-type="navigateBack" style="margin-left: 15px;">
<button class="uni-button" style="width: 100px;">返回</button>
</navigator>
</view>
</uni-forms>
</view>
</template>
<script>
import { validator } from '../../../js_sdk/validator/mustgo-team.js';
const db = uniCloud.database();
const dbCmd = db.command;
const dbCollectionName = 'mustgo-team';
function getValidator(fields) {
let result = {}
for (let key in validator) {
if (fields.includes(key)) {
result[key] = validator[key]
}
}
return result
}
export default {
data() {
let formData = {
"icon": "",
"name": "",
"owner_id": "",
"description": ""
}
return {
formData,
formOptions: {},
rules: {
...getValidator(Object.keys(formData))
}
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
methods: {
/**
* 验证表单并提交
*/
submit() {
uni.showLoading({
mask: true
})
this.$refs.form.validate().then((res) => {
return this.submitForm(res)
}).catch(() => {
}).finally(() => {
uni.hideLoading()
})
},
/**
* 提交表单
*/
submitForm(value) {
// 使用 clientDB 提交数据
return db.collection(dbCollectionName).add(value).then((res) => {
uni.showToast({
title: '新增成功'
})
this.getOpenerEventChannel().emit('refreshData')
setTimeout(() => uni.navigateBack(), 500)
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
}
}
}
</script>
<template>
<view class="uni-container">
<uni-forms ref="form" :model="formData" validateTrigger="bind">
<uni-forms-item name="icon" label="队标">
<uni-easyinput placeholder="小队队标" v-model="formData.icon"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="name" label="队名">
<uni-easyinput placeholder="小队名称" v-model="formData.name"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="owner_id" label="发起人id">
<uni-easyinput placeholder="小队发起人id" v-model="formData.owner_id"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="description" label="描述">
<uni-easyinput placeholder="小队描述" v-model="formData.description"></uni-easyinput>
</uni-forms-item>
<view class="uni-button-group">
<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
<navigator open-type="navigateBack" style="margin-left: 15px;">
<button class="uni-button" style="width: 100px;">返回</button>
</navigator>
</view>
</uni-forms>
</view>
</template>
<script>
import { validator } from '../../../js_sdk/validator/mustgo-team.js';
const db = uniCloud.database();
const dbCmd = db.command;
const dbCollectionName = 'mustgo-team';
function getValidator(fields) {
let result = {}
for (let key in validator) {
if (fields.includes(key)) {
result[key] = validator[key]
}
}
return result
}
export default {
data() {
let formData = {
"icon": "",
"name": "",
"owner_id": "",
"description": ""
}
return {
formData,
formOptions: {},
rules: {
...getValidator(Object.keys(formData))
}
}
},
onLoad(e) {
if (e.id) {
const id = e.id
this.formDataId = id
this.getDetail(id)
}
},
onReady() {
this.$refs.form.setRules(this.rules)
},
methods: {
/**
* 验证表单并提交
*/
submit() {
uni.showLoading({
mask: true
})
this.$refs.form.validate().then((res) => {
return this.submitForm(res)
}).catch(() => {
}).finally(() => {
uni.hideLoading()
})
},
/**
* 提交表单
*/
submitForm(value) {
// 使用 clientDB 提交数据
return db.collection(dbCollectionName).doc(this.formDataId).update(value).then((res) => {
uni.showToast({
title: '修改成功'
})
this.getOpenerEventChannel().emit('refreshData')
setTimeout(() => uni.navigateBack(), 500)
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
},
/**
* 获取表单数据
* @param {Object} id
*/
getDetail(id) {
uni.showLoading({
mask: true
})
db.collection(dbCollectionName).doc(id).field("icon,name,owner_id,description").get().then((res) => {
const data = res.result.data[0]
if (data) {
this.formData = data
}
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
}
}
}
</script>
// 发送单条短信示例
'use strict';
function random() {
let min = 100000;
let max = 999999;
return Math.floor(Math.random() * (max - min)) + min;
}
exports.main = async (event, context) => {
const db = uniCloud.database();
const collection = db.collection('mustgo-verify-code');
let smsCode = random();
let res = await collection.add({
phone: event.phone,
code: smsCode,
expire: Date.now() + 300
})
console.log(res)
if (res.id.length == 0) {
return {
code: 500,
message: "验证码发送失败",
data: {
}
}
}
try {
const res = await uniCloud.sendSms({
appid: '__UNI__2A45DD3',
smsKey: 'b4d94cfbbb60074d7f2675f640fb60ca',
smsSecret: 'b53adc6b88bb62031e67f60c1f52570d',
phone: event.phone,
templateId: 'uni_sms_test', // 请替换为自己申请的模板id
data: {
name: 'DCloud',
code: smsCode,
expMinute: '3',
}
})
console.log(res)
// 调用成功,请注意这时不代表发送成功
return res
} catch (err) {
// 调用失败
console.log(err.errCode)
console.log(err.errMsg)
return {
code: err.errCode,
msg: err.errMsg
}
}
};
\ No newline at end of file
{
"name": "fe-retrievePassword",
"dependencies": {},
"extensions": {
"uni-cloud-jql": {}
}
}
\ No newline at end of file
// 发送单条短信示例
'use strict';
exports.main = async (event, context) => {
try {
const res = await uniCloud.sendSms({
appid: '__UNI__2A45DD3',
smsKey: 'b4d94cfbbb60074d7f2675f640fb60ca',
smsSecret: 'b53adc6b88bb62031e67f60c1f52570d',
phone: '13950014724',
templateId: 'uni_sms_test', // 请替换为自己申请的模板id
data: {
name: 'DCloud',
code: '123456',
expMinute: '3',
}
})
console.log(res)
// 调用成功,请注意这时不代表发送成功
return res
} catch(err) {
// 调用失败
console.log(err.errCode)
console.log(err.errMsg)
return {
code: err.errCode,
msg: err.errMsg
}
}
//event为客户端上传的参数
console.log('event : ', event)
const db = uniCloud.database();
let collection = db.collection('mustgo-verify-code');
let res = await collection.where({
phone: event.phone
}).orderBy("expire", "desc").get()
console.log(res.data[0])
if (res.data[0]["expire"] < Date.now() && res.data[0]["code"] == event.code) {
// userID
collection = db.collection('mustgo-user');
res = await collection.where({
phone_num: event.phone
}).get()
// console.log(res)
res = await collection.doc(event.userId).update({
password: res.data[0]["password"],
})
if (res.updated > 0)
return {
code: 200,
message: "修改成功",
data: {}
}
return {
code: 500,
message: "服务器错误",
data: {}
}
}
//返回数据给客户端
return {
code: 400,
message: "验证码错误或超时",
data: {}
}
};
\ No newline at end of file
{
"name": "fe-retrievePassword",
"name": "fe-changePassword",
"dependencies": {},
"extensions": {
"uni-cloud-jql": {}
......
'use strict';
exports.main = async (event, context) => {
/**
* 根据搜索记录,设定时间间隔来归纳出热搜数据并存储在热搜表中
*/
const SEARCHHOT = 'opendb-search-hot'; // 热搜数据库名称
const SEARCHLOG = 'opendb-search-log'; // 搜索记录数据库名称
const SEARCHLOG_timeZone = 604800000; // 归纳搜索记录时间间隔,毫秒数,默认为最近7天
const SEARCHHOT_size = 10; // 热搜条数
const DB = uniCloud.database();
const DBCmd = DB.command;
const $ = DB.command.aggregate;
const SEARCHHOT_db = DB.collection(SEARCHHOT);
const SEARCHLOG_db = DB.collection(SEARCHLOG);
const timeEnd = Date.now() - SEARCHLOG_timeZone;
let {
data: searchHotData
} = await SEARCHLOG_db
.aggregate()
.match({
create_date: DBCmd.gt(timeEnd)
})
.group({
_id: {
'content': '$content',
},
count: $.sum(1)
})
.replaceRoot({
newRoot: $.mergeObjects(['$_id', '$$ROOT'])
})
.project({
_id: false
})
.sort({
count: -1
})
.end();
let now = Date.now();
searchHotData.map(item => {
item.create_date = now;
return item;
}).slice(0, SEARCHHOT_size);
// searchHotData = searchHotData.sort((a, b) => b.count - a.count).slice(0, SEARCHHOT_size);
return searchHotData.length ? await SEARCHHOT_db.add(searchHotData) : ''
};
{
"name": "uni-analyse-searchhot",
"version": "1.0.0",
"description": "定时归纳热搜",
"main": "index.js",
"dependencies": {},
"cloudfunction-config": {
"triggers": [{
"name": "analyse-searchHot",
"type": "timer",
"config": "0 0 */2 * * * *"
}]
}
}
module.exports = (templateData, user) => {
const data = {}
for (const template of templateData) {
const isDynamic = /\{.*?\}/.test(template.value)
// 仅支持uni-id-users
if (isDynamic) {
const [collection, field] = template.value.replace(/\{|\}/g, '').split('.')
data[template.field] = collection === 'uni-id-users' ? user[field] || template.value: template.value
} else {
data[template.field] = template.value
}
// switch (template.type) {
// case 'static':
// data[template.field] = template.value
// break
// case 'dynamic':
// data[template.field] = user[template.value] || ''
// break
// default:
// throw new Error(`template type [${template.type}] not supported`)
// }
}
return data
}
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
const createConfig = require('uni-config-center')
const buildTemplateData = require('./build-template-data')
const { parserDynamicField } = require('./utils')
const schemaNameAdapter = require('./schema-name-adapter')
const {presetCondition, conditionConvert} = require("./preset-condition")
const uniSmsCo = uniCloud.importObject('uni-sms-co')
const db = uniCloud.database()
const smsConfig = createConfig({
pluginId: 'uni-sms-co'
}).config()
function errCode(code) {
return 'uni-sms-co-' + code
}
const tableNames = {
template: 'opendb-sms-template',
task: 'opendb-sms-task',
log: 'opendb-sms-log'
}
module.exports = {
_before: async function () { // 通用预处理器
if (!smsConfig.smsKey || smsConfig.smsKey.length <= 20 || !smsConfig.smsSecret || smsConfig.smsSecret.length <= 20) {
throw new Error('请先配置smsKey和smsSecret')
}
this.tableNames = tableNames
/**
* 优化 schema 的命名规范,需要兼容 uni-admin@2.1.6 以下版本
* 如果是在uni-admin@2.1.6版本以上创建的项目可以将其注释
* */
await schemaNameAdapter.call(this)
},
_after: function (error, result) {
if (error) {
console.error(error)
if (error instanceof Error) {
return {
errCode: 'error',
errMsg: error.message
}
}
if (error.errCode) {
return error
}
throw error
}
return result
},
/**
* 创建短信任务
* @param {{receiver: *[], type: string}} to
* @param {String} to.type=user to.all=true时用来区分发送类型
* @param {Array} to.receiver 用户ID's / 用户标签ID's
* @param {Object} to.condition 用户筛选条件
* @param {String} templateId 短信模板ID
* @param {Array} templateData 短信模板数据
* @param {Object} options
* @param {String} options.taskName 任务名称
*/
async createSmsTask(to, templateId, templateData, options = {}) {
if (!templateId) {
return {
errCode: errCode('template-id-required'),
errMsg: '缺少templateId'
}
}
if (!to.condition && (!to.receiver || to.receiver.length <= 0)) {
return {
errCode: errCode('send-users-is-null'),
errMsg: '请选择要发送的用户'
}
}
const clientInfo = this.getClientInfo()
const {data: templates} = await db.collection(this.tableNames.template).where({_id: templateId}).get()
if (templates.length <= 0) {
return {
errCode: errCode('template-not-found'),
errMsg: '短信模板不存在'
}
}
const [template] = templates
// 预设条件
if (presetCondition[to.condition]) {
to.condition = typeof presetCondition[to.condition] === "function" ? presetCondition[to.condition]() : presetCondition[to.condition]
}
// 创建短信任务
const task = await db.collection(this.tableNames.task).add({
app_id: clientInfo.appId,
name: options.taskName,
template_id: templateId,
template_content: template.content,
vars: templateData,
to,
send_qty: 0,
success_qty: 0,
fail_qty: 0,
create_date: Date.now()
})
uniSmsCo.createUserSmsMessage(task.id)
return new Promise(resolve => setTimeout(() => resolve({
errCode: 0,
errMsg: '任务创建成功',
taskId: task.id
}), 300))
},
async createUserSmsMessage(taskId, execData = {}) {
const parallel = 100
let beforeId
const { data: tasks } = await db.collection(this.tableNames.task).where({ _id: taskId }).get()
if (tasks.length <= 0) {
return {
errCode: errCode('task-id-not-found'),
errMsg: '任务ID不存在'
}
}
const [task] = tasks
let query = {
mobile: db.command.exists(true)
}
// 指定用户发送
if (task.to.type === 'user' && task.to.receiver.length > 0 && !task.to.condition) {
let index = 0
if (execData.beforeId) {
const i = task.to.receiver.findIndex(id => id === execData.beforeId)
index = i !== -1 ? i + 1 : 0
}
const receiver = task.to.receiver.slice(index, index + parallel)
query._id = db.command.in(receiver)
beforeId = receiver[receiver.length - 1]
}
// 指定用户标签
if (task.to.type === 'userTags') {
query.tags = db.command.in(task.to.receiver)
}
// 自定义条件
if (task.to.condition) {
const condition = conditionConvert(task.to.condition, db.command)
query = {
...query,
...condition
}
}
if ((task.to.condition || task.to.type === "userTags") && execData.beforeId) {
query._id = db.command.gt(execData.beforeId)
}
// 动态数据仅支持uni-id-users表字段
const dynamicField = parserDynamicField(task.vars)
const userFields = dynamicField['uni-id-users'] ? dynamicField['uni-id-users'].reduce((res, field) => {
res[field] = true
return res
}, {}): {}
const { data: users } = await db.collection('uni-id-users')
.where(query)
.field({
mobile: true,
...userFields
})
.limit(parallel)
.orderBy('_id', 'asc')
.get()
if (users.length <= 0) {
// 更新要发送的短信数量
const count = await db.collection(this.tableNames.log).where({ task_id: taskId }).count()
await db.collection(this.tableNames.task).where({ _id: taskId }).update({
send_qty: count.total
})
// 开始发送
uniSmsCo.sendSms(taskId)
return new Promise(resolve => setTimeout(() => resolve({
errCode: 0,
errMsg: '创建完成'
}), 500))
}
if (!beforeId) {
beforeId = users[users.length - 1]._id
}
let docs = []
for (const user of users) {
const varData = await buildTemplateData(task.vars, user)
docs.push({
uid: user._id,
task_id: taskId,
mobile: user.mobile,
var_data: varData,
status: 0,
create_date: Date.now()
})
}
await db.collection(this.tableNames.log).add(docs)
uniSmsCo.createUserSmsMessage(taskId, { beforeId })
return new Promise(resolve => setTimeout(() => resolve(), 500))
},
async sendSms(taskId) {
const { data: tasks } = await db.collection(this.tableNames.task).where({ _id: taskId }).get()
if (tasks.length <= 0) {
console.warn(`task [${taskId}] not found`)
return
}
const [task] = tasks
const isStaticTemplate = !task.vars.length
let sendData = {
appId: task.app_id,
smsKey: smsConfig.smsKey,
smsSecret: smsConfig.smsSecret,
templateId: task.template_id,
data: {}
}
const { data: records } = await db.collection(this.tableNames.log)
.where({ task_id: taskId, status: 0 })
.limit(isStaticTemplate ? 50 : 1)
.field({ mobile: true, var_data: true })
.get()
if (records.length <= 0) {
return {
errCode: 0,
errMsg: '发送完成'
}
}
if (isStaticTemplate) {
sendData.phoneList = records.reduce((res, user) => {
res.push(user.mobile)
return res
}, [])
} else {
const [record] = records
sendData.phone = record.mobile
sendData.data = record.var_data
}
try {
// await sendSms(sendData)
await uniCloud.sendSms(sendData)
// 修改发送状态为已发送
await db.collection(this.tableNames.log).where({
_id: db.command.in(records.map(record => record._id))
}).update({
status: 1,
send_date: Date.now()
})
// 更新任务的短信成功数
await db.collection(this.tableNames.task).where({ _id: taskId })
.update({
success_qty: db.command.inc(records.length)
})
} catch (e) {
console.error('[sendSms Fail]', e)
// 修改发送状态为发送失败
await db.collection(this.tableNames.log).where({
_id: db.command.in(records.map(record => record._id))
}).update({
status: 2,
reason: e.errMsg || '未知原因',
send_date: Date.now()
})
// 更新任务的短信失败数
await db.collection(this.tableNames.task).where({ _id: taskId })
.update({
fail_qty: db.command.inc(records.length)
})
}
uniSmsCo.sendSms(taskId)
return new Promise(resolve => setTimeout(() => resolve(), 500))
},
async template() {
const {data: templates = []} = await db.collection(this.tableNames.template).get()
return templates
},
async task (id) {
const {data: tasks} = await db.collection(this.tableNames.task).where({_id: id}).get()
if (tasks.length <= 0) {
return null
}
return tasks[0]
},
async updateTemplates (templates) {
if (templates.length <= 0) {
return {
errCode: errCode('template-is-null'),
errMsg: '缺少模板信息'
}
}
let group = []
for (const template of templates) {
group.push(
db.collection(this.tableNames.template).doc(String(template.templateId)).set({
name: template.templateName,
content: template.templateContent,
type: template.templateType,
sign: template.templateSign
})
)
}
await Promise.all(group)
return {
errCode: 0,
errMsg: '更新成功'
}
},
/**
* @param to
* @param templateId
* @param templateData
* @param options {Object}
* @param options.condition 群发条件
* */
async preview (to, templateId, templateData, options = {}) {
const count = 1
let query = {
mobile: db.command.exists(true)
}
// 指定用户发送
if (to.type === 'user' && to.receiver.length > 0 && !to.condition) {
// const receiver = to.receiver.slice(0, 10)
query._id = db.command.in(to.receiver)
}
// 指定用户标签
if (to.type === 'userTags') {
query.tags = db.command.in(to.receiver)
}
// 自定义条件
let condition = to.condition
if (presetCondition[to.condition]) {
condition = typeof presetCondition[to.condition] === "function" ? presetCondition[to.condition]() : presetCondition[to.condition]
}
if (condition) {
query = {
...query,
...conditionConvert(condition, db.command)
}
}
const {data: users} = await db.collection('uni-id-users').where(query).limit(count).get()
const {total} = await db.collection('uni-id-users').where(query).count()
if (users.length <= 0) {
return {
errCode: errCode('users-is-null'),
errMsg: '请添加要发送的用户'
}
}
const {data: templates} = await db.collection(this.tableNames.template).where({_id: templateId}).get()
if (templates.length <= 0) {
return {
errCode: errCode('template-not-found'),
errMsg: '模板不存在'
}
}
const [template] = templates
let docs = []
for (const user of users) {
const varData = buildTemplateData(templateData, user)
const content = template.content.replace(/\$\{(.*?)\}/g, ($1, param) => varData[param] || $1)
docs.push(`【${template.sign}${content}`)
}
return {
errCode: 0,
errMsg: '',
list: docs,
total
}
}
}
{
"name": "uni-sms-co",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "uni-sms-co"
}
}
}
{
"name": "uni-sms-co",
"dependencies": {
"uni-config-center": "file:../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
},
"extensions": {
"uni-cloud-sms": {},
"uni-cloud-jql": {}
}
}
const presetCondition = {
all: {},
'7-day-offline-users': () => ({
last_login_date: {
type: 'lt',
value: Date.now() - (7 * 24 * 60 * 60 * 1000)
}
}),
'15-day-offline-users': () => ({
last_login_date: {
type: 'lt',
value: Date.now() - (15 * 24 * 60 * 60 * 1000)
}
}),
'30-day-offline-users': () => ({
last_login_date: {
type: 'lt',
value: Date.now() - (30 * 24 * 60 * 60 * 1000)
}
})
}
function conditionConvert(condition, command) {
const newCondition = {}
for (const key in condition) {
const field = condition[key]
switch (field.type) {
case 'search':
newCondition[key] = new RegExp(field.value)
break
case 'select':
if (field.value.length) {
newCondition[key] = command.or(
field.value.map(value => command.eq(value))
)
}
break
case 'range':
if (field.value.length) {
const [gt, lt] = field.value
newCondition[key] = command.and([
command.gte(gt),
command.lte(lt)
])
}
break
case 'date':
if (field.value.length) {
const [startTimestamp, endTimestamp] = field.value
const startDate = new Date(startTimestamp)
const endDate = new Date(endTimestamp)
newCondition[key] = command.and([
command.gte(startDate),
command.lte(endDate)
])
}
break
case 'timestamp':
if (field.value.length) {
const [startDate, endDate] = field.value
newCondition[key] = command.and([
command.gte(startDate),
command.lte(endDate)
])
}
break
case 'lt':
newCondition[key] = command.lt(field.value)
break
}
}
return newCondition
}
module.exports.presetCondition = presetCondition
module.exports.conditionConvert = conditionConvert
const db = uniCloud.database()
module.exports = async function () {
try {
const count = await db.collection('batch-sms-template').count()
if (count.total > 0) {
this.tableNames = {
template: 'batch-sms-template',
task: 'batch-sms-task',
log: 'batch-sms-result'
}
}
} catch (e) {}
}
exports.chunk = function (arr, num) {
const list = []
let current = []
for (const item of arr) {
current.push(item);
if (current.length === num) {
list.push(current)
current = []
}
}
if (current.length) list.push(current)
return list
}
exports.checkIsStaticTemplate = function (data = []) {
let isStatic = data.length <= 0
for (const template of data) {
if (template.type === 'static') {
isStatic = true
break
}
}
return isStatic
}
exports.parserDynamicField = function (templateData) {
return templateData.reduce((res, template) => {
if (/\{.*?\}/.test(template.value)) {
const [collection, field] = template.value.replace(/\{|\}/g, '').split('.')
if (!res[collection]) {
res[collection] = []
}
res[collection].push(field)
}
return res
}, {})
}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"id":{"bsonType":"int","title":"活动状态id","description":"活动状态id"},"status":{"bsonType":"string","title":"活动状态","description":"活动状态"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"id":{"bsonType":"int","title":"活动状态id","description":"活动状态id"},"status":{"bsonType":"string","title":"活动状态","description":"活动状态"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"id":{"bsonType":"int","title":"活动状态id","description":"活动状态id"},"status":{"bsonType":"string","title":"活动状态","description":"活动状态"}}}
\ No newline at end of file
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"description":"ID,系统自动生成"}}}
\ No newline at end of file
<<<<<<< HEAD
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
}
}
}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"content":{"bsonType":"string","title":"内容","description":"帖子内容"},"date":{"bsonType":"string","title":"发布时间","description":"帖子发布时间"},"likes":{"bsonType":"int","title":"点赞数","description":"帖子点赞数"},"owner_id":{"bsonType":"string","title":"发帖人id","description":"发帖人id","foreignKey":"mustgo-user._id"},"check_status":{"bsonType":"bool","title":"审核状态","description":"帖子审核状态"},"comment_num":{"bsonType":"int","title":"评论数","description":"帖子评论数"},"url":{"bsonType":"array","title":"图片url","description":"帖子中图片url的数组"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"content":{"bsonType":"string","title":"内容","description":"帖子内容"},"date":{"bsonType":"string","title":"发布时间","description":"帖子发布时间"},"likes":{"bsonType":"int","title":"点赞数","description":"帖子点赞数"},"owner_id":{"bsonType":"string","title":"发帖人id","description":"发帖人id","foreignKey":"mustgo-user._id"},"check_status":{"bsonType":"bool","title":"审核状态","description":"帖子审核状态"},"comment_num":{"bsonType":"int","title":"评论数","description":"帖子评论数"},"url":{"bsonType":"array","title":"图片url","description":"帖子中图片url的数组"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"team_activity_id":{"bsonType":"string","foreignKey":"mustgo-team-activity._id","title":"小队活动id","description":"报名信息所属小队活动id"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"用户id","description":"报名者id"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"team_activity_id":{"bsonType":"string","foreignKey":"mustgo-team-activity._id","title":"小队活动id","description":"报名信息所属小队活动id"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"用户id","description":"报名者id"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"team_activity_id":{"bsonType":"string","foreignKey":"mustgo-team-activity._id","title":"小队活动id","description":"报名信息所属小队活动id"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"用户id","description":"报名者id"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"identity":{"bsonType":"string","title":"身份","description":"用户身份"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"identity":{"bsonType":"string","title":"身份","description":"用户身份"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"identity":{"bsonType":"string","title":"身份","description":"用户身份"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"start_date":{"bsonType":"string","title":"开始时间","description":"运动开始时间"},"duration":{"bsonType":"int","title":"持续时间","description":"运动持续时间"},"feelings":{"bsonType":"string","title":"感受","description":"运动感受"},"owner_id":{"bsonType":"string","title":"用户id","description":"用户id","foreignKey":"mustgo-user._id"},"distance":{"bsonType":"double","title":"距离","description":"运动距离"},"pace":{"bsonType":"double","title":"配速","description":"运动配速"},"start_point":{"bsonType":"string","title":"起始地点","description":"运动起始地点"},"end_point":{"bsonType":"string","title":"结束地点","description":"运动结束地点"},"path_line":{"bsonType":"array","title":"路线","description":"运动路线"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"start_date":{"bsonType":"string","title":"开始时间","description":"运动开始时间"},"duration":{"bsonType":"int","title":"持续时间","description":"运动持续时间"},"feelings":{"bsonType":"string","title":"感受","description":"运动感受"},"owner_id":{"bsonType":"string","title":"用户id","description":"用户id","foreignKey":"mustgo-user._id"},"distance":{"bsonType":"double","title":"距离","description":"运动距离"},"pace":{"bsonType":"double","title":"配速","description":"运动配速"},"start_point":{"bsonType":"object","title":"起始地点","description":"运动起始地点,经纬度"},"end_point":{"bsonType":"object","title":"结束地点","description":"运动结束地点,经纬度"},"path_line":{"bsonType":"array","title":"路线","description":"运动路线"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"start_date":{"bsonType":"string","title":"开始时间","description":"运动开始时间"},"duration":{"bsonType":"int","title":"持续时间","description":"运动持续时间"},"feelings":{"bsonType":"string","title":"感受","description":"运动感受"},"owner_id":{"bsonType":"string","title":"用户id","description":"用户id","foreignKey":"mustgo-user._id"},"distance":{"bsonType":"double","title":"距离","description":"运动距离"},"pace":{"bsonType":"double","title":"配速","description":"运动配速"},"start_point":{"bsonType":"object","title":"起始地点","description":"运动起始地点,经纬度"},"end_point":{"bsonType":"object","title":"结束地点","description":"运动结束地点,经纬度"},"path_line":{"bsonType":"array","title":"路线","description":"运动路线"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"校园活动标题"},"content":{"bsonType":"string","title":"内容","description":"校园活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"校园活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"校园活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"校园活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"校园活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"校园活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"校园活动状态"},"contact":{"bsonType":"string","title":"联系方式","description":"校园活动发布者联系方式"},"invitee":{"bsonType":"string","title":"面向对象","description":"校园活动面向对象"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"校园活动标题"},"content":{"bsonType":"string","title":"内容","description":"校园活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"校园活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"校园活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"校园活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"校园活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"校园活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"校园活动状态"},"contact":{"bsonType":"string","title":"联系方式","description":"校园活动发布者联系方式"},"invitee":{"bsonType":"string","title":"面向对象","description":"校园活动面向对象"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"校园活动标题"},"content":{"bsonType":"string","title":"内容","description":"校园活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"校园活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"校园活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"校园活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"校园活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"校园活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"校园活动状态"},"contact":{"bsonType":"string","title":"联系方式","description":"校园活动发布者联系方式"},"invitee":{"bsonType":"string","title":"面向对象","description":"校园活动面向对象"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"小队活动标题"},"content":{"bsonType":"string","title":"内容","description":"小队活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"小队活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"小队活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"小队活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"小队活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"小队活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"小队活动状态"},"participants":{"bsonType":"int","title":"参与人数","description":"小队活动参与人数"},"contact":{"bsonType":"string","title":"联系方式","description":"小队活动发布者联系方式"},"team_id":{"bsonType":"string","foreignKey":"mustgo-team._id","title":"小队id","description":"活动所属小队id"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"小队活动标题"},"content":{"bsonType":"string","title":"内容","description":"小队活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"小队活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"小队活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"小队活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"小队活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"小队活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"小队活动状态"},"participants":{"bsonType":"int","title":"参与人数","description":"小队活动参与人数"},"contact":{"bsonType":"string","title":"联系方式","description":"小队活动发布者联系方式"},"team_id":{"bsonType":"string","foreignKey":"mustgo-team._id","title":"小队id","description":"活动所属小队id"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"title":{"bsonType":"string","title":"标题","description":"小队活动标题"},"content":{"bsonType":"string","title":"内容","description":"小队活动内容"},"start_date":{"bsonType":"string","title":"开始时间","description":"小队活动开始时间"},"end_date":{"bsonType":"string","title":"结束时间","description":"小队活动结束时间"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发布者id","description":"小队活动发布者id"},"background_picture":{"bsonType":"string","title":"背景图片","description":"小队活动背景图片"},"place":{"bsonType":"string","title":"地点","description":"小队活动地点"},"status":{"bsonType":"int","foreignKey":"mustgo-activity-status.id","title":"活动状态","description":"小队活动状态"},"participants":{"bsonType":"int","title":"参与人数","description":"小队活动参与人数"},"contact":{"bsonType":"string","title":"联系方式","description":"小队活动发布者联系方式"},"team_id":{"bsonType":"string","foreignKey":"mustgo-team._id","title":"小队id","description":"活动所属小队id"}}}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"icon":{"bsonType":"string","title":"队标","description":"小队队标"},"name":{"bsonType":"string","title":"队名","description":"小队名称"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发起人id","description":"小队发起人id"},"description":{"bsonType":"string","title":"描述","description":"小队描述"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"icon":{"bsonType":"string","title":"队标","description":"小队队标"},"name":{"bsonType":"string","title":"队名","description":"小队名称"},"owner_id":{"bsonType":"string","foreignKey":"mustgo-user._id","title":"发起人id","description":"小队发起人id"},"description":{"bsonType":"string","title":"描述","description":"小队描述"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": true,
"update": true,
"delete": true
},
"properties": {
"_id": {
"title": "id",
"description": "ID,系统自动生成"
},
"icon": {
"bsonType": "string",
"title": "队标",
"description": "小队队标",
"defaultValue": "https://mp-6f6feaec-a026-4402-8e8d-18f7572890da.cdn.bspapp.com/cloudstorage/0510a534-dd8d-41f0-8341-601aa677e243.jpg"
},
"name": {
"bsonType": "string",
"title": "队名",
"description": "小队名称"
},
"owner_id": {
"bsonType": "string",
"foreignKey": "mustgo-user._id",
"title": "发起人id",
"description": "小队发起人id"
},
"description": {
"bsonType": "string",
"title": "描述",
"description": "小队描述"
}
}
}
\ No newline at end of file
<<<<<<< HEAD
{"bsonType":"object","required":[],"permission":{"read":false,"create":true,"update":false,"delete":false},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"name":{"bsonType":"string","title":"姓名","description":"用户姓名"},"icon":{"bsonType":"string","title":"头像","description":"用户头像"},"gender":{"bsonType":"string","title":"性别","description":"用户性别"},"password":{"bsonType":"string","title":"密码","description":"用户密码"},"phone_num":{"bsonType":"string","title":"手机号码","description":"用户手机号码"},"team_id":{"bsonType":"string","defaultValue":"","title":"小队id","description":"用户所属小队id"},"school":{"bsonType":"string","title":"学校","description":"用户所属学校"},"type":{"bsonType":"string","foreignKey":"mustgo-role._id","title":"类型","description":"用户类型"},"total_running_distance":{"bsonType":"double","defaultValue":0,"title":"总跑步距离","description":"用户总跑步距离"},"total_walking_distance":{"bsonType":"double","defaultValue":0,"title":"总健走距离","description":"用户总健走距离"}}}
=======
{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"title":"id","description":"ID,系统自动生成"},"name":{"bsonType":"string","title":"姓名","description":"用户姓名"},"icon":{"bsonType":"string","title":"头像","description":"用户头像"},"gender":{"bsonType":"string","title":"性别","description":"用户性别"},"password":{"bsonType":"string","title":"密码","description":"用户密码"},"phone_num":{"bsonType":"string","title":"手机号码","description":"用户手机号码"},"team_id":{"bsonType":"string","defaultValue":"","title":"小队id","description":"用户所属小队id"},"school":{"bsonType":"string","title":"学校","description":"用户所属学校"},"type":{"bsonType":"string","foreignKey":"mustgo-role._id","title":"类型","description":"用户类型"},"total_running_distance":{"bsonType":"double","defaultValue":0,"title":"总跑步距离","description":"用户总跑步距离"},"total_walking_distance":{"bsonType":"double","defaultValue":0,"title":"总健走距离","description":"用户总健走距离"}}}
>>>>>>> ade9e7a5a1b72c66f17e4899b4a2e9ae73e61a42
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": true,
"update": true,
"delete": true
},
"properties": {
"_id": {
"title": "id",
"description": "ID,系统自动生成"
},
"name": {
"bsonType": "string",
"title": "姓名",
"description": "用户姓名"
},
"icon": {
"bsonType": "string",
"title": "头像",
"description": "用户头像",
"defaultValue": "https://mp-6f6feaec-a026-4402-8e8d-18f7572890da.cdn.bspapp.com/cloudstorage/0510a534-dd8d-41f0-8341-601aa677e243.jpg"
},
"gender": {
"bsonType": "string",
"title": "性别",
"description": "用户性别"
},
"password": {
"bsonType": "string",
"title": "密码",
"description": "用户密码"
},
"phone_num": {
"bsonType": "string",
"title": "手机号码",
"description": "用户手机号码"
},
"team_id": {
"bsonType": "string",
"defaultValue": "",
"title": "小队id",
"description": "用户所属小队id"
},
"school": {
"bsonType": "string",
"title": "学校",
"description": "用户所属学校"
},
"type": {
"bsonType": "string",
"foreignKey": "mustgo-role._id",
"title": "类型",
"description": "用户类型"
},
"total_running_distance": {
"bsonType": "double",
"defaultValue": 0,
"title": "总跑步距离",
"description": "用户总跑步距离"
},
"total_walking_distance": {
"bsonType": "double",
"defaultValue": 0,
"title": "总健走距离",
"description": "用户总健走距离"
}
}
}
\ No newline at end of file
{
"bsonType": "object",
"required": [],
"permission": {
"read": false,
"create": true,
"update": false,
"delete": false
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
}
}
}
\ No newline at end of file
'use strict';
const uniADConfig = require('uni-config-center')({
pluginId: 'uni-ad'
}).config()
const signIn = require('sign-in')
let ip = null
async function nextFn(data) {
//写自己的业务逻辑
switch (data.extra) {
case "uniSignIn": //签到
let {
user_id
} = data;
await signIn({
user_id,
ip
})
break;
default:
break;
}
return {
"isValid": true //如果不返回,广点通会2次调用本云函数
}
}
const crypto = require('crypto');
const db = uniCloud.database();
exports.main = async (event, context) => {
ip = context.CLIENTIP;
//event为客户端上传的参数
console.log('event : ', event);
const {
path,
queryStringParameters
} = event;
const data = {
adpid: event.adpid,
platform: event.platform,
provider: event.provider,
trans_id: event.trans_id,
sign: event.sign,
user_id: event.user_id,
extra: event.extra,
}
// 注意::必须验签请求来源
const trans_id = event.trans_id;
//去uni-config-center通过adpid获取secret
const secret = uniADConfig[event.adpid]
const sign2 = crypto.createHash('sha256').update(`${secret}:${trans_id}`).digest('hex');
if (event.sign !== sign2) {
console.log('验签失败');
return null;
}
//自己的逻辑
try {
return await nextFn(data)
} catch (e) {
console.error(e)
return {
"isValid": false
}
}
};
\ No newline at end of file
{
"name": "rewarded-video-ad-notify-url",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rewarded-video-ad-notify-url",
"version": "1.0.0",
"license": "ISC"
}
}
}
{
"name": "rewarded-video-ad-notify-url",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"sign-in": "file:../common/sign-in",
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"h5" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}
## 0.0.3(2022-11-11)
- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug
## 0.0.2(2021-04-16)
- 修改插件package信息
## 0.0.1(2021-03-15)
- 初始化项目
{
"id": "uni-config-center",
"displayName": "uni-config-center",
"version": "0.0.3",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
"配置中心"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "unicloud-template-function"
},
"directories": {
"example": "../../../scripts/dist"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
}
}
# 为什么使用uni-config-center
实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ ├─index.js
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b // plugin-b对应的目录
├─index.js
└─config.json // plugin-b对应的配置文件
```
假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ └─index.js
├─plugin-b // plugin-b对应的目录
│ └─index.js
└─uni-config-center
├─index.js // config-center入口文件
├─plugin-a
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b
└─config.json // plugin-b对应的配置文件
```
使用uni-config-center后的优势
- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
# 用法
在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
```js
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id', // 插件id
defaultConfig: { // 默认配置
tokenExpiresIn: 7200,
tokenExpiresThreshold: 600,
},
customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
// defaudltConfig 默认配置
// userConfig 用户配置
return Object.assign(defaultConfig, userConfig)
}
})
// 以如下配置为例
// {
// "tokenExpiresIn": 7200,
// "passwordErrorLimit": 6,
// "bindTokenToDevice": false,
// "passwordErrorRetryTime": 3600,
// "app-plus": {
// "tokenExpiresIn": 2592000
// },
// "service": {
// "sms": {
// "codeExpiresIn": 300
// }
// }
// }
// 获取配置
uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
// 获取文件绝对路径
uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
// 引用文件(require)
uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
// 判断是否包含某文件
uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
```
\ No newline at end of file
"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=vt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=vt(p,"Map"),J=vt(Object,"create"),K=function(){function t(){}return function(r){if(!xt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function X(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Z(t){var r=this.__data__=new X(t);this.size=r.size}function tt(t,r){var e=Ot(t),n=!e&&wt(t),o=!e&&!n&&At(t),i=!e&&!n&&!o&&Ft(t),u=e||n||o||i,c=u?function(t,r){for(var e=-1,n=Array(t);++e<t;)n[e]=r(e);return n}(t.length,String):[],a=c.length;for(var f in t)!r&&!F.call(t,f)||u&&("length"==f||o&&("offset"==f||"parent"==f)||i&&("buffer"==f||"byteLength"==f||"byteOffset"==f)||dt(f,a))||c.push(f);return c}function rt(t,r,e){(void 0!==e&&!jt(t[r],e)||void 0===e&&!(r in t))&&ot(t,r,e)}function et(t,r,e){var n=t[r];F.call(t,r)&&jt(n,e)&&(void 0!==e||r in t)||ot(t,r,e)}function nt(t,r){for(var e=t.length;e--;)if(jt(t[e][0],r))return e;return-1}function ot(t,r,e){"__proto__"==r&&R?R(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}Q.prototype.clear=function(){this.__data__=J?J(null):{},this.size=0},Q.prototype.delete=function(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r},Q.prototype.get=function(t){var r=this.__data__;if(J){var n=r[t];return n===e?void 0:n}return F.call(r,t)?r[t]:void 0},Q.prototype.has=function(t){var r=this.__data__;return J?void 0!==r[t]:F.call(r,t)},Q.prototype.set=function(t,r){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=J&&void 0===r?e:r,this},X.prototype.clear=function(){this.__data__=[],this.size=0},X.prototype.delete=function(t){var r=this.__data__,e=nt(r,t);return!(e<0)&&(e==r.length-1?r.pop():N.call(r,e,1),--this.size,!0)},X.prototype.get=function(t){var r=this.__data__,e=nt(r,t);return e<0?void 0:r[e][1]},X.prototype.has=function(t){return nt(this.__data__,t)>-1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=_t(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return _t(this,t).get(t)},Y.prototype.has=function(t){return _t(this,t).has(t)},Y.prototype.set=function(t,r){var e=_t(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return Ct(t)&&ct(t)==o}function ft(t){return!(!xt(t)||function(t){return!!U&&U in t}(t))&&(zt(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!xt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=yt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),xt(i))!function(t,r,e,n,o,i,u){var a=gt(t,e),f=gt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=Ot(f),_=!p&&At(f),v=!p&&!_&&Ft(f);l=f,p||_||v?Ot(a)?l=a:Ct(j=a)&&mt(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e<n;)r[e]=t[e];return r}(a):_?(h=!1,l=function(t,r){if(r)return t.slice();var e=t.length,n=$?$(e):new t.constructor(e);return t.copy(n),n}(f,!0)):v?(h=!1,d=f,y=!0?(g=d.buffer,b=new g.constructor(g.byteLength),new E(b).set(new E(g)),b):d.buffer,l=new d.constructor(y,d.byteOffset,d.length)):l=[]:function(t){if(!Ct(t)||ct(t)!=c)return!1;var r=D(t);if(null===r)return!0;var e=F.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&C.call(e)==I}(f)||wt(f)?(l=a,wt(a)?l=function(t){return function(t,r,e,n){var o=!e;e||(e={});var i=-1,u=r.length;for(;++i<u;){var c=r[i],a=n?n(e[c],t[c],c,e,t):void 0;void 0===a&&(a=t[c]),o?ot(e,c,a):et(e,c,a)}return e}(t,Ut(t))}(a):xt(a)&&!zt(a)||(l=function(t){return"function"!=typeof t.constructor||yt(t)?{}:K(D(t))}(f))):h=!1}var d,y,g,b;var j;h&&(u.set(f,l),o(l,f,n,i,u),u.delete(f));rt(t,e,l)}(t,r,u,e,lt,n,o);else{var a=n?n(gt(t,u),i,u+"",t,r,o):void 0;void 0===a&&(a=i),rt(t,u,a)}}),Ut)}function ht(t,r){return bt(function(t,r,e){return r=V(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=V(n.length-r,0),u=Array(i);++o<i;)u[o]=n[r+o];o=-1;for(var c=Array(r+1);++o<r;)c[o]=n[o];return c[r]=e(u),j(t,this,c)}}(t,r,Pt),t+"")}var pt=R?function(t,r){return R(t,"toString",{configurable:!0,enumerable:!1,value:(e=r,function(){return e}),writable:!0});var e}:Pt;function _t(t,r){var e,n,o=t.__data__;return("string"==(n=typeof(e=r))||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?o["string"==typeof r?"string":"hash"]:o.map}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return ft(e)?e:void 0}function dt(t,r){var e=typeof t;return!!(r=null==r?n:r)&&("number"==e||"symbol"!=e&&f.test(t))&&t>-1&&t%1==0&&t<r}function yt(t){var r=t&&t.constructor;return t===("function"==typeof r&&r.prototype||M)}function gt(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var bt=function(t){var r=0,e=0;return function(){var n=W(),o=16-(n-e);if(e=n,o>0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(pt);function jt(t,r){return t===r||t!=t&&r!=r}var wt=at(function(){return arguments}())?at:function(t){return Ct(t)&&F.call(t,"callee")&&!B.call(t,"callee")},Ot=Array.isArray;function mt(t){return null!=t&&Mt(t.length)&&!zt(t)}var At=G||function(){return!1};function zt(t){if(!xt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function Mt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function xt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function Ct(t){return null!=t&&"object"==typeof t}var Ft=b?function(t){return function(r){return t(r)}}(b):function(t){return Ct(t)&&Mt(t.length)&&!!s[ct(t)]};function Ut(t){return mt(t)?tt(t,!0):st(t)}var St,It=(St=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=St.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!xt(e))return!1;var n=typeof r;return!!("number"==n?mt(e)&&dt(r,e.length):"string"==n&&r in e)&&jt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e<n;){var u=r[e];u&&St(t,u,e,o)}return t})));function Pt(t){return t}t.exports=It}));const c=Object.prototype.hasOwnProperty,a=(t,r)=>c.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){if(!this._config){const t=this._getUserConfig();this._config=Array.isArray(t)?t:(this.customMerge||u)(this.defaultConfig,t)}let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;t<n.length;t++){const r=n[t];if(!a(i,r))return e;i=i[r]}return i}(e,t,r):e}}const s=new class{constructor(){this._configMap=new Map}plugin({pluginId:t,defaultConfig:r,customMerge:e,root:n=__dirname,cache:o=!0}){if(this._configMap.has(t)&&o)return this._configMap.get(t);const i=new f({pluginId:t,defaultConfig:r,customMerge:e,root:n});return o&&this._configMap.set(t,i),i}};var l=s.plugin.bind(s);module.exports=l;
{
"name": "uni-config-center",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
"author": "DCloud",
"license": "Apache-2.0"
}
\ No newline at end of file
## 1.0.16(2023-04-25)
- 新增maxTokenLength配置,用于限制数据库用户记录token数组的最大长度
## 1.0.15(2023-04-06)
- 修复部分语言国际化出错的Bug
## 1.0.14(2023-03-07)
- 修复 admin用户包含其他角色时未包含在token的Bug
## 1.0.13(2022-07-21)
- 修复 创建token时未传角色权限信息生成的token不正确的bug
## 1.0.12(2022-07-15)
- 提升与旧版本uni-id的兼容性(补充读取配置文件时回退平台app-plus、h5),但是仍推荐使用新平台名进行配置(app、web)
## 1.0.11(2022-07-14)
- 修复 部分情况下报`read property 'reduce' of undefined`的错误
## 1.0.10(2022-07-11)
- 将token存储在用户表的token字段内,与旧版本uni-id保持一致
## 1.0.9(2022-07-01)
- checkToken兼容token内未缓存角色权限的情况,此时将查库获取角色权限
## 1.0.8(2022-07-01)
- 修复clientDB默认依赖时部分情况下获取不到uni-id配置的Bug
## 1.0.7(2022-06-30)
- 修复config文件不合法时未抛出具体错误的Bug
## 1.0.6(2022-06-28)
- 移除插件内的数据表schema
## 1.0.5(2022-06-27)
- 修复使用多应用配置时报`Cannot read property 'appId' of undefined`的Bug
## 1.0.4(2022-06-27)
- 修复使用自定义token内容功能报错的Bug [详情](https://ask.dcloud.net.cn/question/147945)
## 1.0.2(2022-06-23)
- 对齐旧版本uni-id默认配置
## 1.0.1(2022-06-22)
- 补充对uni-config-center的依赖
## 1.0.0(2022-06-21)
- 提供uni-id token创建、校验、刷新接口,简化旧版uni-id公共模块
{
"id": "uni-id-common",
"displayName": "uni-id-common",
"version": "1.0.16",
"description": "包含uni-id token生成、校验、刷新功能的云函数公共模块",
"keywords": [
"uni-id-common",
"uniCloud",
"token",
"权限"
],
"repository": "https://gitcode.net/dcloud/uni-id-common",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "unicloud-template-function"
},
"uni_modules": {
"dependencies": ["uni-config-center"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
# uni-id-common
文档请参考:[uni-id-common](https://uniapp.dcloud.net.cn/uniCloud/uni-id-common.html)
\ No newline at end of file
"use strict";var e,t=(e=require("crypto"))&&"object"==typeof e&&"default"in e?e.default:e;const n={TOKEN_EXPIRED:"uni-id-token-expired",CHECK_TOKEN_FAILED:"uni-id-check-token-failed",PARAM_REQUIRED:"uni-id-param-required",ACCOUNT_EXISTS:"uni-id-account-exists",ACCOUNT_NOT_EXISTS:"uni-id-account-not-exists",ACCOUNT_CONFLICT:"uni-id-account-conflict",ACCOUNT_BANNED:"uni-id-account-banned",ACCOUNT_AUDITING:"uni-id-account-auditing",ACCOUNT_AUDIT_FAILED:"uni-id-account-audit-failed",ACCOUNT_CLOSED:"uni-id-account-closed"};function i(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}function r(e){if(!e)return;const t=e.match(/^(\d+).(\d+).(\d+)/);return t?t.slice(1,4).map(e=>parseInt(e)):void 0}function o(e,t){const n=r(e),i=r(t);return n?i?function(e,t){const n=Math.max(e.length,t.length);for(let i=0;i<n;i++){const n=e[i],r=t[i];if(n>r)return 1;if(n<r)return-1}return 0}(n,i):1:i?-1:0}const s={"uni-id-token-expired":30203,"uni-id-check-token-failed":30202};function c(e){const{errCode:t,errMsgValue:n}=e;e.errMsg=this._t(t,n),t in s&&(e.code=s[t]),delete e.errMsgValue}function a(e){return"object"===(i=e,Object.prototype.toString.call(i).slice(8,-1).toLowerCase())&&e.errCode&&(t=e.errCode,Object.values(n).includes(t))&&!!e.errCode;var t,i}let u={"zh-Hans":{"uni-id-token-expired":"登录状态失效,token已过期","uni-id-check-token-failed":"token校验未通过","uni-id-param-required":"缺少参数: {param}","uni-id-account-exists":"此账号已注册","uni-id-account-not-exists":"此账号未注册","uni-id-account-conflict":"用户账号冲突","uni-id-account-banned":"从账号已封禁","uni-id-account-auditing":"此账号正在审核中","uni-id-account-audit-failed":"此账号审核失败","uni-id-account-closed":"此账号已注销"},en:{"uni-id-token-expired":"The login status is invalid, token has expired","uni-id-check-token-failed":"Check token failed","uni-id-param-required":"Parameter required: {param}","uni-id-account-exists":"Account exists","uni-id-account-not-exists":"Account does not exists","uni-id-account-conflict":"User account conflict","uni-id-account-banned":"Account has been banned","uni-id-account-auditing":"Account audit in progress","uni-id-account-audit-failed":"Account audit failed","uni-id-account-closed":"Account has been closed"}};try{const e=require.resolve("uni-config-center/uni-id/lang/index.js");u=function(e,t){const n=Object.keys(e);n.push(...Object.keys(t));const i={};for(let r=0;r<n.length;r++){const o=n[r];i[o]=Object.assign({},e[o],t[o])}return i}(u,require(e))}catch(e){}var d=u;function l(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function h(e){return JSON.parse((t=function(e){var t=4-(e=e.toString()).length%4;if(4!==t)for(var n=0;n<t;++n)e+="=";return e.replace(/-/g,"+").replace(/_/g,"/")}(e),Buffer.from(t,"base64").toString("utf-8")));var t}function f(e){return l((t=JSON.stringify(e),Buffer.from(t,"utf-8").toString("base64")));var t}function p(e,n){return l(t.createHmac("sha256",n).update(e).digest("base64"))}const k=function(e,t){if("string"!=typeof e)throw new Error("Invalid token");const n=e.split(".");if(3!==n.length)throw new Error("Invalid token");const[i,r,o]=n;if(p(i+"."+r,t)!==o)throw new Error("Invalid token");const s=h(i);if("HS256"!==s.alg||"JWT"!==s.typ)throw new Error("Invalid token");const c=h(r);if(1e3*c.exp<Date.now()){const e=new Error("Token expired");throw e.name="TokenExpiredError",e}return c},g=function(e,t,n={}){const{expiresIn:i}=n;if(!i)throw new Error("expiresIn is required");const r=parseInt(Date.now()/1e3),o={...e,iat:r,exp:r+n.expiresIn},s=f({alg:"HS256",typ:"JWT"})+"."+f(o);return s+"."+p(s,t)},I=uniCloud.database(),_=I.command,C=I.collection("uni-id-users"),T=I.collection("uni-id-roles");class m{constructor({uniId:e}={}){this.uid=null,this.userRecord=null,this.userPermission=null,this.oldToken=null,this.oldTokenPayload=null,this.uniId=e,this.config=this.uniId._getConfig(),this.clientInfo=this.uniId._clientInfo,this.checkConfig()}checkConfig(){const{tokenExpiresIn:e,tokenExpiresThreshold:t}=this.config;if(t>=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");t>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:n.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:n.ACCOUNT_BANNED};case 2:throw{errCode:n.ACCOUNT_AUDITING};case 3:throw{errCode:n.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:n.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:n.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:n.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const t=await T.where({role_id:_.in(e)}).get(),n=(i=t.data.reduce((e,t)=>(t.permission&&e.push(...t.permission),e),[]),Array.from(new Set(i)));var i;return this.userPermission={role:e,permission:n},this.userPermission}async _createToken({uid:e,role:t,permission:i}={}){if(!t||!i){const e=await this.getUserPermission();t=e.role,i=e.permission}let r={uid:e,role:t,permission:i};if(this.uniId.interceptorMap.has("customToken")){const n=this.uniId.interceptorMap.get("customToken");if("function"!=typeof n)throw new Error("Invalid custom token file");r=await n({uid:e,role:t,permission:i})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.16"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const t=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*t.iat)return!1}catch(e){if(e.errCode===n.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:t,permission:i}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:t,permission:i});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{uid:i}=t,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:i,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:t}=this.config;let i;try{i=k(e,t)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:n.TOKEN_EXPIRED};throw{errCode:n.CHECK_TOKEN_FAILED}}return i}async checkToken(e,{autoRefresh:t=!0}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const i=this._checkToken(e);this.uid=i.uid,this.oldTokenPayload=i;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=i,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:t}=await this.getUserPermission();a.role=e,a.permission=t}if(!r||!t){const e={code:0,errCode:0,...i,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*i.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...i,...a,...d};return delete l.uniIdVersion,l}}var E=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:t=!0}={}){return new m({uniId:this}).checkToken(e,{autoRefresh:t})},createToken:async function({uid:e,role:t,permission:n}={}){return new m({uniId:this}).createToken({uid:e,role:t,permission:n})},refreshToken:async function({token:e}={}){return new m({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:t,config:n}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):t,this.config=n||this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,t){this.interceptorMap.set(e,t)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let t;switch("app-plus"===this._clientInfo.platform&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":t="h5";break;case"app":t="app-plus"}const n=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];t&&e[t]&&n.push(e[t]),n.push(e[this._clientInfo.platform]);const i=Object.assign(...n);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!i||!i[e])throw new Error(`Config parameter missing, ${e} is required`)}),i}_getConfig(){return this._getPlatformConfig()}}for(const e in E)x.prototype[e]=E[e];function y(e){const t=new x(e);return new Proxy(t,{get(e,t){if(t in e&&0!==t.indexOf("_")){if("function"==typeof e[t])return(n=e[t],function(){let e;try{e=n.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return i(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==t&&"config"!==t)return e[t]}var n}})}x.prototype.createInstance=y;const A={createInstance:y};module.exports=A;
{
"name": "uni-id-common",
"version": "1.0.16",
"description": "uni-id token生成、校验、刷新",
"main": "index.js",
"homepage": "https://uniapp.dcloud.io/uniCloud/uni-id-common.html",
"repository": {
"type": "git",
"url": "git+https://gitee.com/dcloud/uni-id-common.git"
},
"author": "DCloud",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册