提交 46ebd587 编写于 作者: study夏羽's avatar study夏羽

更新依赖插件

上级 e61834ce
{
"bsonType": "object",
"required": [],
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"mobile": {
"bsonType": "string",
"description": "手机号码"
},
"email": {
"bsonType": "string",
"description": "邮箱"
},
"code": {
"bsonType": "string",
"description": "验证码"
},
"type": {
"bsonType": "string",
"description": "验证类型:login, bind, unbind, pay"
},
"state": {
"bsonType": "int",
"description": "验证状态:0 未验证、1 已验证、2 已作废"
},
"ip": {
"bsonType": "string",
"description": "请求时客户端IP地址"
},
"created_at": {
"bsonType": "timestamp",
"description": "创建时间"
},
"expired_at": {
"bsonType": "timestamp",
"description": "过期时间"
}
}
}
{
"bsonType": "object",
"required": ["user_id"],
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"user_id": {
"bsonType": "string",
"description": "用户id,参考uni-id-users表"
},
"ua": {
"bsonType": "string",
"description": "userAgent"
},
"device_uuid": {
"bsonType": "string",
"description": "设备唯一标识(需要加密存储)"
},
"type": {
"bsonType": "string",
"enum": ["login", "logout"],
"description": "登录类型"
},
"state": {
"bsonType": "int",
"description": "结果:0 失败、1 成功"
},
"ip": {
"bsonType": "string",
"description": "ip地址"
},
"create_date": {
"bsonType": "timestamp",
"description": "创建时间",
"forceDefaultValue": {
"$env": "now"
}
}
}
}
{
"bsonType": "object",
"required": ["permission_id", "permission_name"],
"properties": {
"_id": {
"description": "存储文档 ID,系统自动生成"
},
"permission_id": {
"bsonType": "string",
"description": "权限唯一标识,不可修改,不允许重复",
"label": "权限标识",
"trim": "both",
"title": "权限ID",
"component": {
"name": "input"
}
},
"permission_name": {
"bsonType": "string",
"description": "权限名称",
"label": "权限名称",
"title": "权限名称",
"trim": "both",
"component": {
"name": "input"
}
},
"comment": {
"bsonType": "string",
"description": "备注",
"label": "备注",
"title": "备注",
"trim": "both",
"component": {
"name": "textarea"
}
},
"create_date": {
"bsonType": "timestamp",
"description": "创建时间",
"forceDefaultValue": {
"$env": "now"
}
}
}
}
{
"bsonType": "object",
"required": ["role_id"],
"permission": {
"read": false,
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {
"description": "存储文档 ID,系统自动生成"
},
"role_id": {
"title": "唯一ID",
"bsonType": "string",
"description": "角色唯一标识,不可修改,不允许重复",
"trim": "both"
},
"role_name": {
"title": "名称",
"bsonType": "string",
"description": "角色名称",
"trim": "both"
},
"permission": {
"title": "权限",
"bsonType": "array",
"foreignKey": "uni-id-permissions.permission_id",
"description": "角色拥有的权限列表"
},
"comment": {
"title": "备注",
"bsonType": "string",
"description": "备注",
"trim": "both"
},
"create_date": {
"bsonType": "timestamp",
"description": "创建时间",
"forceDefaultValue": {
"$env": "now"
}
}
}
}
{
"bsonType": "object",
"required": [],
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"username": {
"bsonType": "string",
"title": "用户名",
"description": "用户名,不允许重复",
"trim": "both"
},
"password": {
"bsonType": "password",
"title": "密码",
"description": "密码,加密存储",
"trim": "both"
},
"password_secret_version": {
"bsonType": "int",
"permission":{
"read":false
},
"title": "passwordSecret",
"description": "密码使用的passwordSecret版本"
},
"nickname": {
"bsonType": "string",
"permission":{
"read":false
},
"title": "昵称",
"description": "用户昵称",
"trim": "both"
},
"gender": {
"bsonType": "int",
"permission":{
"read":false
},
"title": "性别",
"description": "用户性别:0 未知 1 男性 2 女性",
"defaultValue": 0,
"enum": [{
"text": "未知",
"value": 0
},
{
"text": "男",
"value": 1
},
{
"text": "女",
"value": 2
}
]
},
"status": {
"bsonType": "int",
"permission":{
"read":false
},
"description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝",
"title": "用户状态",
"defaultValue": 0,
"enum": [{
"text": "正常",
"value": 0
},
{
"text": "禁用",
"value": 1
},
{
"text": "审核中",
"value": 2
},
{
"text": "审核拒绝",
"value": 3
}
]
},
"mobile": {
"bsonType": "string",
"permission":{
"read":false
},
"title": "手机号码",
"description": "手机号码",
"pattern": "^\\+?[0-9-]{3,20}$",
"trim": "both"
},
"mobile_confirmed": {
"bsonType": "int",
"permission":{
"read":false
},
"description": "手机号验证状态:0 未验证 1 已验证",
"title": "手机号验证状态",
"defaultValue": 0,
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
]
},
"email": {
"bsonType": "string",
"permission":{
"read":false
},
"format": "email",
"title": "邮箱",
"description": "邮箱地址",
"trim": "both"
},
"email_confirmed": {
"bsonType": "int",
"permission":{
"read":false
},
"description": "邮箱验证状态:0 未验证 1 已验证",
"title": "邮箱验证状态",
"defaultValue": 0,
"enum": [{
"text": "未验证",
"value": 0
},
{
"text": "已验证",
"value": 1
}
]
},
"avatar": {
"bsonType": "string",
"permission":{
"read":false
},
"title": "头像地址",
"description": "头像地址",
"trim": "both"
},
"department_id": {
"bsonType": "array",
"permission":{
"read":false
},
"description": "部门ID",
"title": "部门",
"enumType": "tree",
"enum": {
"collection": "opendb-department",
"orderby": "name asc",
"field": "_id as value, name as text"
}
},
"role": {
"bsonType": "array",
"permission":{
"read":false
},
"title": "角色",
"description": "用户角色",
"enum": {
"collection": "uni-id-roles",
"field": "role_id as value, role_name as text"
},
"foreignKey": "uni-id-roles.role_id",
"permission": {
"write": false
}
},
"wx_unionid": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "微信unionid"
},
"wx_openid": {
"bsonType": "object",
"permission":{
"read":false
},
"description": "微信各个平台openid",
"properties": {
"app-plus": {
"bsonType": "string",
"description": "app平台微信openid"
},
"mp-weixin": {
"bsonType": "string",
"description": "微信小程序平台openid"
}
}
},
"ali_openid": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "支付宝平台openid"
},
"apple_openid": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "苹果登录openid"
},
"comment": {
"bsonType": "string",
"permission":{
"read":false
},
"title": "备注",
"description": "备注",
"trim": "both"
},
"realname_auth": {
"bsonType": "object",
"permission":{
"read":false
},
"description": "实名认证信息",
"required": [
"type",
"auth_status"
],
"properties": {
"type": {
"bsonType": "int",
"minimum": 0,
"maximum": 1,
"description": "用户类型:0 个人用户 1 企业用户"
},
"auth_status": {
"bsonType": "int",
"minimum": 0,
"maximum": 3,
"description": "认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败"
},
"auth_date": {
"bsonType": "timestamp",
"description": "认证通过时间"
},
"real_name": {
"bsonType": "string",
"description": "真实姓名/企业名称"
},
"identity": {
"bsonType": "string",
"description": "身份证号码/营业执照号码"
},
"id_card_front": {
"bsonType": "string",
"description": "身份证正面照 URL"
},
"id_card_back": {
"bsonType": "string",
"description": "身份证反面照 URL"
},
"in_hand": {
"bsonType": "string",
"description": "手持身份证照片 URL"
},
"license": {
"bsonType": "string",
"description": "营业执照 URL"
},
"contact_person": {
"bsonType": "string",
"description": "联系人姓名"
},
"contact_mobile": {
"bsonType": "string",
"description": "联系人手机号码"
},
"contact_email": {
"bsonType": "string",
"description": "联系人邮箱"
}
}
},
"register_date": {
"bsonType": "timestamp",
"permission":{
"read":false
},
"description": "注册时间",
"forceDefaultValue": {
"$env": "now"
}
},
"register_ip": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "注册时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"last_login_date": {
"bsonType": "timestamp",
"permission":{
"read":false
},
"description": "最后登录时间"
},
"last_login_ip": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "最后登录时 IP 地址"
},
"token": {
"bsonType": "array",
"permission":{
"read":false
},
"description": "用户token"
},
"inviter_uid": {
"bsonType": "array",
"permission":{
"read":false
},
"description": "用户全部上级邀请者",
"trim": "both"
},
"my_invite_code": {
"bsonType": "string",
"permission":{
"read":false
},
"description": "用户自身邀请码"
}
}
}
\ No newline at end of file
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
{
"schedule": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
"tasks": ["accessToken"]
}
}
},
"ipWhiteList": ["0.0.0.0"]
}
## 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.2",
"version": "0.0.3",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
......@@ -11,11 +11,7 @@
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云函数模板"
],
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
......@@ -32,7 +28,8 @@
"data": "无",
"permissions": "无"
},
"npmurl": ""
"npmurl": "",
"type": "unicloud-template-function"
},
"directories": {
"example": "../../../scripts/dist"
......@@ -73,6 +70,10 @@
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
......@@ -8,28 +8,28 @@
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app-plus": {
"app": {
"tokenExpiresIn": 2592000,
"oauth" : {
"weixin" : {
"appid" : "weixin appid",
"appsecret" : "weixin appsecret"
"oauth": {
"weixin": {
"appid": "weixin appid",
"appsecret": "weixin appsecret"
}
}
},
"mp-weixin": {
"oauth" : {
"weixin" : {
"appid" : "weixin appid",
"appsecret" : "weixin appsecret"
"oauth": {
"weixin": {
"appid": "",
"appsecret": ""
}
}
},
"mp-alipay": {
"oauth" : {
"alipay" : {
"appid" : "alipay appid",
"privateKey" : "alipay privateKey"
"oauth": {
"alipay": {
"appid": "alipay appid",
"privateKey": "alipay privateKey"
}
}
},
......
{
"schedule": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
"tasks": ["accessToken"]
}
}
},
"ipWhiteList": ["0.0.0.0"]
}
## 1.0.8(2022-09-16)
- 可以使用 uni-scss 控制主题色
## 1.0.7(2022-07-06)
- 优化 pc端图标位置不正确的问题
## 1.0.6(2022-07-05)
......
......@@ -318,9 +318,9 @@
padding-right: 5px;
overflow: hidden;
height: 35px;
/* #ifdef APP-NVUE */
/* #endif */
/* #ifndef APP-NVUE */
box-sizing: border-box;
/* #endif */
}
.input-value-border {
......
......@@ -177,7 +177,9 @@
}
}
</script>
<style >
<style lang="scss">
$uni-primary: #007aff !default;
.uni-data-pickerview {
flex: 1;
/* #ifndef APP-NVUE */
......@@ -265,11 +267,11 @@
}
.selected-item-active {
border-bottom: 2px solid #007aff;
border-bottom: 2px solid $uni-primary;
}
.selected-item-text {
color: #007aff;
color: $uni-primary;
}
.tab-c {
......@@ -319,7 +321,7 @@
.check {
margin-right: 5px;
border: 2px solid #007aff;
border: 2px solid $uni-primary;
border-left: 0;
border-top: 0;
height: 12px;
......
{
"id": "uni-data-picker",
"displayName": "uni-data-picker 数据驱动的picker选择器",
"version": "1.0.7",
"version": "1.0.8",
"description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
"keywords": [
"uni-ui",
......@@ -18,11 +18,7 @@
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
......@@ -39,7 +35,8 @@
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [
......@@ -56,7 +53,7 @@
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
......
## 2.2.11(2022-09-19)
- 修复,支付宝小程序样式错乱,[详情](https://github.com/dcloudio/uni-app/issues/3861)
## 2.2.10(2022-09-19)
- 修复,反向选择日期范围,日期显示异常,[详情](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false)
## 2.2.9(2022-09-16)
- 可以使用 uni-scss 控制主题色
## 2.2.8(2022-09-08)
- 修复 close事件无效的 bug
## 2.2.7(2022-09-05)
......
......@@ -62,6 +62,8 @@
</script>
<style lang="scss" >
$uni-primary: #007aff !default;
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
......@@ -78,7 +80,7 @@
font-size: 14px;
// font-family: Lato-Bold, Lato;
font-weight: bold;
color: #455997;
color: darken($color: $uni-primary, $amount: 40%);
}
.uni-calendar-item__weeks-lunar-text {
......@@ -138,7 +140,7 @@
}
.uni-calendar-item__weeks-box .uni-calendar-item--checked {
background-color: #007aff;
background-color: $uni-primary;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #fff;
......@@ -159,7 +161,7 @@
.uni-calendar-item--multiple .uni-calendar-item--before-checked,
.uni-calendar-item--multiple .uni-calendar-item--after-checked {
background-color: #409eff;
background-color: $uni-primary;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #F6F7FC;
......
......@@ -74,7 +74,9 @@
:hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
</time-picker>
</view>
<uni-icons type="arrowthinright" color="#999" style="line-height: 50px;"></uni-icons>
<view style="line-height: 50px;">
<uni-icons type="arrowthinright" color="#999"></uni-icons>
</view>
<view class="uni-date-changed--time-end">
<view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
<time-picker type="time" :end="reactEndTime" v-model="timeRange.endTime" :border="false"
......@@ -551,8 +553,16 @@
this.cale.setMultiple(this.calendar.fullDate, true)
this.weeks = this.cale.weeks
this.tempSingleDate = this.calendar.fullDate
this.tempRange.before = this.cale.multipleStatus.before
this.tempRange.after = this.cale.multipleStatus.after
const beforeStatus = this.cale.multipleStatus.before
const beforeDate = new Date(this.cale.multipleStatus.before).getTime()
const afterDate = new Date(this.cale.multipleStatus.after).getTime()
if (beforeDate > afterDate && afterDate) {
this.tempRange.before = this.cale.multipleStatus.after
this.tempRange.after = this.cale.multipleStatus.before
} else {
this.tempRange.before = this.cale.multipleStatus.before
this.tempRange.after = this.cale.multipleStatus.after
}
this.change()
},
/**
......@@ -609,6 +619,8 @@
</script>
<style lang="scss" >
$uni-primary: #007aff !default;
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
......@@ -719,7 +731,7 @@
text-align: center;
width: 100px;
font-size: 14px;
color: #007aff;
color: $uni-primary;
/* #ifndef APP-NVUE */
letter-spacing: 3px;
/* #endif */
......@@ -898,7 +910,7 @@
border-radius: 100px;
height: 40px;
line-height: 40px;
background-color: #007aff;
background-color: $uni-primary;
color: #fff;
font-size: 16px;
letter-spacing: 2px;
......
......@@ -770,7 +770,9 @@
}
</script>
<style>
<style lang="scss">
$uni-primary: #007aff !default;
.uni-datetime-picker {
/* #ifndef APP-NVUE */
/* width: 100%; */
......@@ -804,7 +806,7 @@
.uni-datetime-picker-btn-text {
font-size: 14px;
color: #007AFF;
color: $uni-primary;
}
.uni-datetime-picker-btn-group {
......@@ -889,6 +891,7 @@
.uni-datetime-picker-text {
font-size: 14px;
line-height: 50px
}
.uni-datetime-picker-sign {
......
......@@ -783,7 +783,9 @@
}
</script>
<style>
<style lang="scss">
$uni-primary: #007aff !default;
.uni-date {
/* #ifndef APP-NVUE */
width: 100%;
......@@ -942,14 +944,14 @@
}
.popup-x-footer text:hover {
color: #007aff;
color: $uni-primary;
cursor: pointer;
opacity: 0.8;
}
.popup-x-footer .confirm {
margin-left: 20px;
color: #007aff;
color: $uni-primary;
}
.uni-date-changed {
......
{
"id": "uni-datetime-picker",
"displayName": "uni-datetime-picker 日期选择器",
"version": "2.2.8",
"version": "2.2.11",
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
"keywords": [
"uni-datetime-picker",
......
## 1.1.3(2022-09-22)
- 修复,引入 uni.scss 引入默认主题色报错的问题
## 1.1.2(2022-09-22)
- 增加主题色 primaryColor 配置选项
## 1.1.1(2022-09-19)
- 修复,输入后回车,change 事件触发两次,[详情](https://ask.dcloud.net.cn/question/152149)
## 1.1.4(2022-10-27)
- 修复 props 中背景颜色无默认值的bug
## 1.1.0(2022-06-30)
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- 新增 clear 事件,点击右侧叉号图标触发
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
-
## 1.0.5(2022-06-07)
- 优化 clearable 显示策略
## 1.0.4(2022-06-07)
- 优化 clearable 显示策略
## 1.0.3(2022-05-20)
- 修复 关闭图标某些情况下无法取消的bug
- 修复 关闭图标某些情况下无法取消的 bug
## 1.0.2(2022-04-12)
- 修复 默认值不生效的bug
- 修复 默认值不生效的 bug
## 1.0.1(2022-04-02)
- 修复 value不能为0的bug
- 修复 value 不能为 0 的 bug
## 1.0.0(2021-11-19)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
## 0.1.4(2021-08-20)
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
## 0.1.3(2021-08-11)
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
## 0.1.2(2021-07-30)
- 优化 vue3下事件警告的问题
- 优化 vue3 下事件警告的问题
## 0.1.1
- 优化 errorMessage 属性支持 Boolean 类型
## 0.1.0(2021-07-13)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 0.0.16(2021-06-29)
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
## 0.0.15(2021-06-21)
- 修复 passwordIcon 属性拼写错误的 bug
## 0.0.14(2021-06-18)
- 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标
- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标
- 修复 confirmType 属性不生效的问题
## 0.0.13(2021-06-04)
- 修复 disabled 状态可清出内容的 bug
## 0.0.12(2021-05-12)
- 新增 组件示例地址
## 0.0.11(2021-05-07)
- 修复 input-border 属性不生效的问题
## 0.0.10(2021-04-30)
- 修复 ios 遮挡文字、显示一半的问题
## 0.0.9(2021-02-05)
- 调整为uni_modules目录规范
- 调整为 uni_modules 目录规范
- 优化 兼容 nvue 页面
{
"id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框",
"version": "1.1.3",
"version": "1.1.4",
"description": "Easyinput 组件是对原生input组件的增强",
"keywords": [
"uni-ui",
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
{
"passwordSecret": "passwordSecret-demo",
"tokenSecret": "tokenSecret-demo",
"tokenExpiresIn": 7200,
"tokenExpiresThreshold": 600,
"passwordErrorLimit": 6,
"bindTokenToDevice": true,
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app": {
"tokenExpiresIn": 2592000,
"oauth": {
"weixin": {
"appid": "weixin appid",
"appsecret": "weixin appsecret"
}
}
},
"mp-weixin": {
"oauth": {
"weixin": {
"appid": "",
"appsecret": ""
}
}
},
"mp-alipay": {
"oauth": {
"alipay": {
"appid": "alipay appid",
"privateKey": "alipay privateKey"
}
}
},
"service": {
"sms": {
"name": "DCloud",
"codeExpiresIn": 300,
"smsKey": "your sms key",
"smsSecret": "your sms secret"
}
}
}
{
"schedule": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
"tasks": ["accessToken"]
}
}
},
"ipWhiteList": ["0.0.0.0"]
}
## 1.0.31(2022-11-16)
- uni-id-co 修复 验证码可能无法收到的bug
## 1.0.30(2022-11-11)
- uni-id-co 修复 用户只有openid时绑定微信/QQ报错
## 1.0.29(2022-11-10)
- uni-id-co 支持URL化方式请求 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#adapter-http)
## 1.0.28(2022-11-09)
- uni-id-co 升级密码加密算法,支持hmac-sha256加密 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary.html#password-safe)
- uni-id-co 新增 开发者可以自定义密码加密规则 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary.html#custom-password-encrypt)
- uni-id-co 新增 支持将其他系统用户迁移至uni-id [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary.html#move-users-to-uni-id)
## 1.0.27(2022-10-26)
- uni-id-co 新增 secureNetworkHandshakeByWeixin 接口,用于建立和微信小程序的安全网络连接
## 1.0.26(2022-10-18)
- 修复 uni-id-pages 导入时异常的Bug
## 1.0.25(2022-10-14)
- uni-id-co 增加 微信授权手机号登录方式 [文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin-mobile)
- uni-id-co 增加 解绑第三方平台账号 [文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-third-account)
......
{
"id": "uni-id-pages",
"displayName": "uni-id-pages",
"version": "1.0.27",
"version": "1.0.31",
"description": "云端一体简单、统一、可扩展的用户中心页面模版",
"keywords": [
"用户管理",
......
......@@ -35,7 +35,8 @@ const ERROR = {
UNBIND_NOT_SUPPORTED: 'uni-id-unbind-not-supported',
UNBIND_UNIQUE_LOGIN: 'uni-id-unbind-unique-login',
UNBIND_PASSWORD_NOT_EXISTS: 'uni-id-unbind-password-not-exists',
UNBIND_MOBILE_NOT_EXISTS: 'uni-id-unbind-mobile-not-exists'
UNBIND_MOBILE_NOT_EXISTS: 'uni-id-unbind-mobile-not-exists',
UNSUPPORTED_REQUEST: 'uni-id-unsupported-request'
}
function isUniIdError (errCode) {
......
const { ERROR } = require('./error')
function getHttpClientInfo () {
const requestId = this.getUniCloudRequestId()
const { clientIP, userAgent, source, secretType = 'none' } = this.getClientInfo()
const { clientInfo = {} } = JSON.parse(this.getHttpInfo().body)
return {
...clientInfo,
clientIP,
userAgent,
source,
secretType,
requestId
}
}
function getHttpUniIdToken () {
const { uniIdToken = '' } = JSON.parse(this.getHttpInfo().body)
return uniIdToken
}
function verifyHttpMethod () {
const { headers, httpMethod } = this.getHttpInfo()
if (!/^application\/json/.test(headers['content-type']) || httpMethod.toUpperCase() !== 'POST') {
throw {
errCode: ERROR.UNSUPPORTED_REQUEST,
errMsg: 'unsupported request'
}
}
}
function universal () {
if (this.getClientInfo().source === 'http') {
verifyHttpMethod.call(this)
this.getParams()[0] = JSON.parse(this.getHttpInfo().body).params
this.getUniversalClientInfo = getHttpClientInfo.bind(this)
this.getUniversalUniIdToken = getHttpUniIdToken.bind(this)
} else {
this.getUniversalClientInfo = this.getClientInfo
this.getUniversalUniIdToken = this.getUniIdToken
}
}
module.exports = universal
......@@ -12,6 +12,7 @@ const {
isUniIdError
} = require('./common/error')
const middleware = require('./middleware/index')
const universal = require('./common/universal')
const {
registerAdmin,
......@@ -81,7 +82,10 @@ const {
module.exports = {
async _before () {
const clientInfo = this.getClientInfo()
// 支持 callFunction 与 URL化
universal.call(this)
const clientInfo = this.getUniversalClientInfo()
/**
* 检查clientInfo,无appId和uniPlatform时本云对象无法正常运行
* 此外需要保证用到的clientInfo字段均经过类型检查
......@@ -581,5 +585,5 @@ module.exports = {
/**
* 安全网络握手,目前仅处理微信小程序安全网络握手
*/
secureNetworkHandshakeByWeixin
secureNetworkHandshakeByWeixin
}
......@@ -40,7 +40,8 @@ const sentence = {
'uni-id-unbind-failed': 'Please bind first and then unbind',
'uni-id-unbind-not-supported': 'Unbinding is not supported',
'uni-id-unbind-mobile-not-exists': 'This is the only way to login at the moment, please bind your phone number and then try to unbind',
'uni-id-unbind-password-not-exists': 'Please set a password first'
'uni-id-unbind-password-not-exists': 'Please set a password first',
'uni-id-unsupported-request': 'Unsupported request'
}
module.exports = {
......
......@@ -40,7 +40,8 @@ const sentence = {
'uni-id-unbind-failed': '请先绑定后再解绑',
'uni-id-unbind-not-supported': '不支持解绑',
'uni-id-unbind-mobile-not-exists': '这是当前唯一登录方式,请绑定手机号后再尝试解绑',
'uni-id-unbind-password-not-exists': '请先设置密码在尝试解绑'
'uni-id-unbind-password-not-exists': '请先设置密码在尝试解绑',
'uni-id-unsupported-request': '不支持的请求方式'
}
module.exports = {
......
......@@ -39,7 +39,7 @@ async function getNeedCaptcha ({
const {
data: recentRecord
} = await uniIdLogCollection.where({
ip: this.getClientInfo().clientIP,
ip: this.getUniversalClientInfo().clientIP,
...userIdentifier,
type,
create_date: dbCmd.gt(now - limitDuration)
......@@ -61,7 +61,7 @@ async function verifyCaptcha (params = {}) {
}
}
const payload = await this.uniCaptcha.verify({
deviceId: this.getClientInfo().deviceId,
deviceId: this.getUniversalClientInfo().deviceId,
captcha,
scene
})
......
......@@ -17,7 +17,7 @@ async function realPreLogin (params = {}) {
const {
user
} = params
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const userMatched = await findUser({
userQuery: user,
authorizedApp: appId
......@@ -66,7 +66,7 @@ async function preLoginWithPassword (params = {}) {
} = this.config
const {
clientIP
} = this.getClientInfo()
} = this.getUniversalClientInfo()
// 根据ip地址,密码错误次数过多,锁定登录
let loginIPLimit = userRecord.login_ip_limit || []
// 清理无用记录
......@@ -78,6 +78,8 @@ async function preLoginWithPassword (params = {}) {
}
}
const passwordUtils = new PasswordUtils({
userRecord,
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
})
......@@ -85,9 +87,7 @@ async function preLoginWithPassword (params = {}) {
success: checkPasswordSuccess,
refreshPasswordInfo
} = passwordUtils.checkUserPassword({
password,
passwordHash: userRecord.password,
passwordSecretVersion: userRecord.password_secret_version
password
})
if (!checkPasswordSuccess) {
// 更新用户ip对应的密码错误记录
......@@ -179,7 +179,7 @@ async function postLogin (params = {}) {
const {
clientIP,
uniIdToken
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const uid = user._id
const updateData = {
last_login_date: Date.now(),
......
......@@ -5,11 +5,11 @@ const {
userCollection
} = require('../../common/constants')
async function logout() {
async function logout () {
const {
uniIdToken,
deviceId
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const {
uid
} = await this.uniIdCommon.checkToken(
......@@ -44,4 +44,4 @@ async function logout() {
module.exports = {
logout
}
\ No newline at end of file
}
......@@ -2,37 +2,160 @@ const {
getType
} = require('../../common/utils')
const crypto = require('crypto')
const createConfig = require('uni-config-center')
const shareConfig = createConfig({
pluginId: 'uni-id'
})
let customPassword = {}
if (shareConfig.hasFile('custom-password.js')) {
customPassword = shareConfig.requireFile('custom-password.js') || {}
}
const passwordAlgorithmMap = {
UNI_ID_HMAC_SHA1: 'hmac-sha1',
UNI_ID_HMAC_SHA256: 'hmac-sha256',
UNI_ID_CUSTOM: 'custom'
}
const passwordAlgorithmKeyMap = Object.keys(passwordAlgorithmMap).reduce((res, item) => {
res[passwordAlgorithmMap[item]] = item
return res
}, {})
const passwordExtMethod = {
[passwordAlgorithmMap.UNI_ID_HMAC_SHA1]: {
verify ({ password }) {
const { password_secret_version: passwordSecretVersion } = this.userRecord
const passwordSecret = this._getSecretByVersion({
version: passwordSecretVersion
})
const { passwordHash } = this.encrypt({
password,
passwordSecret
})
return passwordHash === this.userRecord.password
},
encrypt ({ password, passwordSecret }) {
const { value: secret, version } = passwordSecret
const hmac = crypto.createHmac('sha1', secret.toString('ascii'))
hmac.update(password)
return {
passwordHash: hmac.digest('hex'),
version
}
}
},
[passwordAlgorithmMap.UNI_ID_HMAC_SHA256]: {
verify ({ password }) {
const parse = this._parsePassword()
const passwordHash = crypto.createHmac(parse.algorithm, parse.salt).update(password).digest('hex')
return passwordHash === parse.hash
},
encrypt ({ password, passwordSecret }) {
const { version } = passwordSecret
// 默认使用 sha256 加密算法
const salt = crypto.randomBytes(10).toString('hex')
const sha256Hash = crypto.createHmac(passwordAlgorithmMap.UNI_ID_HMAC_SHA256.substring(5), salt).update(password).digest('hex')
const algorithm = passwordAlgorithmKeyMap[passwordAlgorithmMap.UNI_ID_HMAC_SHA256]
// B 为固定值,对应 PasswordMethodMaps 中的 sha256算法
// hash 格式 $[PasswordMethodFlagMapsKey]$[salt size]$[salt][Hash]
const passwordHash = `$${algorithm}$${salt.length}$${salt}${sha256Hash}`
return {
passwordHash,
version
}
}
},
[passwordAlgorithmMap.UNI_ID_CUSTOM]: {
verify ({ password, passwordSecret }) {
if (!customPassword.verifyPassword) throw new Error('verifyPassword method not found in custom password file')
// return true or false
return customPassword.verifyPassword({
password,
passwordSecret,
userRecord: this.userRecord,
clientInfo: this.clientInfo
})
},
encrypt ({ password, passwordSecret }) {
if (!customPassword.encryptPassword) throw new Error('encryptPassword method not found in custom password file')
const PasswordHashMethod = {
'hmac-sha1': function (content, secret) {
const hmac = crypto.createHmac('sha1', secret.toString('ascii'))
hmac.update(content)
return hmac.digest('hex')
// return object<{passwordHash: string, version: number}>
return customPassword.encryptPassword({
password,
passwordSecret,
clientInfo: this.clientInfo
})
}
}
}
class PasswordUtils {
constructor ({
userRecord = {},
clientInfo,
passwordSecret
} = {}) {
const passwordSecretType = getType(passwordSecret)
if (passwordSecretType === 'array') {
this.passwordSecret = passwordSecret.sort((a, b) => {
return a.version - b.version
if (!clientInfo) throw new Error('Invalid clientInfo')
if (!passwordSecret) throw new Error('Invalid password secret')
this.clientInfo = clientInfo
this.userRecord = userRecord
this.passwordSecret = this.prePasswordSecret(passwordSecret)
}
/**
* passwordSecret 预处理
* @param passwordSecret
* @return {*[]}
*/
prePasswordSecret (passwordSecret) {
const newPasswordSecret = []
if (getType(passwordSecret) === 'string') {
newPasswordSecret.push({
value: passwordSecret,
type: passwordAlgorithmMap.UNI_ID_HMAC_SHA1
})
} else if (passwordSecretType === 'string') {
this.passwordSecret = [{ value: passwordSecret }]
} else if (getType(passwordSecret) === 'array') {
for (const secret of passwordSecret.sort((a, b) => a.version - b.version)) {
newPasswordSecret.push({
...secret,
// 没有 type 设置默认 type hmac-sha1
type: secret.type || passwordAlgorithmMap.UNI_ID_HMAC_SHA1
})
}
} else {
throw new Error('Invalid password secret')
}
return newPasswordSecret
}
getSecretByVersion (params = {}) {
const {
version
} = params
/**
* 获取最新加密密钥
* @return {*}
* @private
*/
_getLastestSecret () {
return this.passwordSecret[this.passwordSecret.length - 1]
}
_getOldestSecret () {
return this.passwordSecret[0]
}
_getSecretByVersion ({ version } = {}) {
if (!version && version !== 0) {
return this.getOldestSecret()
return this._getOldestSecret()
}
if (this.passwordSecret.length === 1) {
return this.passwordSecret[0]
......@@ -40,77 +163,99 @@ class PasswordUtils {
return this.passwordSecret.find(item => item.version === version)
}
getLastestSecret () {
return this.passwordSecret[this.passwordSecret.length - 1]
/**
* 获取密码的验证/加密方法
* @param passwordSecret
* @return {*[]}
* @private
*/
_getPasswordExt (passwordSecret) {
const ext = passwordExtMethod[passwordSecret.type]
if (!ext) {
throw new Error(`暂不支持 ${passwordSecret.type} 类型的加密算法`)
}
const passwordExt = Object.create(null)
for (const key in ext) {
passwordExt[key] = ext[key].bind(Object.assign(this, Object.keys(ext).reduce((res, item) => {
if (item !== key) {
res[item] = ext[item].bind(this)
}
return res
}, {})))
}
return passwordExt
}
getOldestSecret () {
return this.passwordSecret[0]
_parsePassword () {
const [algorithmKey = '', cost = 0, hashStr = ''] = this.userRecord.password.split('$').filter(key => key)
const algorithm = passwordAlgorithmMap[algorithmKey] ? passwordAlgorithmMap[algorithmKey].substring(5) : null
const salt = hashStr.substring(0, Number(cost))
const hash = hashStr.substring(Number(cost))
return {
algorithm,
salt,
hash
}
}
checkUserPassword (params = {}) {
const {
/**
* 生成加密后的密码
* @param {String} password 密码
*/
generatePasswordHash ({ password }) {
if (!password) throw new Error('Invalid password')
const passwordSecret = this._getLastestSecret()
const ext = this._getPasswordExt(passwordSecret)
const { passwordHash, version } = ext.encrypt({
password,
passwordHash: passwordHashToCheck,
passwordSecretVersion,
autoRefresh = true
} = params
const currentPasswordSecret = this.getSecretByVersion({
version: passwordSecretVersion
passwordSecret
})
if (!currentPasswordSecret) {
throw new Error('Invalid password version')
return {
passwordHash,
version
}
const {
value: passwordSecret
} = currentPasswordSecret
const {
passwordHash
} = this.generatePasswordHash({
password,
passwordSecret,
passwordSecretVersion
}
/**
* 密码校验
* @param {String} password
* @param {Boolean} autoRefresh
* @return {{refreshPasswordInfo: {version: *, passwordHash: *}, success: boolean}|{success: boolean}}
*/
checkUserPassword ({ password, autoRefresh = true }) {
if (!password) throw new Error('Invalid password')
const { password_secret_version: passwordSecretVersion } = this.userRecord
const passwordSecret = this._getSecretByVersion({
version: passwordSecretVersion
})
if (passwordHashToCheck !== passwordHash) {
const ext = this._getPasswordExt(passwordSecret)
const success = ext.verify({ password, passwordSecret })
if (!success) {
return {
success: false
}
}
let refreshPasswordInfo
if (autoRefresh && passwordSecretVersion !== this.getLastestSecret().version) {
refreshPasswordInfo = this.generatePasswordHash({
password
})
if (autoRefresh && passwordSecretVersion !== this._getLastestSecret().version) {
refreshPasswordInfo = this.generatePasswordHash({ password })
}
return {
success: true,
refreshPasswordInfo
}
}
generatePasswordHash (params = {}) {
let {
password,
passwordSecret,
passwordSecretVersion
} = params
if (getType(password) !== 'string') {
throw new Error('Invalid password')
}
password = password && password.trim()
if (!password) {
throw new Error('Invalid password')
}
if (!passwordSecret) {
const lastestSecret = this.getLastestSecret()
passwordSecret = lastestSecret.value
passwordSecretVersion = lastestSecret.version
}
return {
passwordHash: PasswordHashMethod['hmac-sha1'](password, passwordSecret),
version: passwordSecretVersion
}
}
}
module.exports = PasswordUtils
......@@ -5,7 +5,7 @@ const {
ERROR
} = require('../../common/error')
function getQQPlatform() {
function getQQPlatform () {
const platform = this.clientPlatform
switch (platform) {
case 'app':
......@@ -18,7 +18,7 @@ function getQQPlatform() {
}
}
async function saveQQUserKey({
async function saveQQUserKey ({
openid,
sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken
......@@ -26,7 +26,7 @@ async function saveQQUserKey({
} = {}) {
// 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。
// 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const qqPlatform = getQQPlatform.call(this)
const keyObj = {
dcloudAppid: appId,
......@@ -45,9 +45,9 @@ async function saveQQUserKey({
await this.uniOpenBridge.setUserAccessToken(keyObj, {
access_token: accessToken,
access_token_expired: accessTokenExpired
}, accessTokenExpired ?
Math.floor((accessTokenExpired - Date.now()) / 1000) :
30 * 24 * 60 * 60
}, accessTokenExpired
? Math.floor((accessTokenExpired - Date.now()) / 1000)
: 30 * 24 * 60 * 60
)
break
default:
......@@ -55,7 +55,7 @@ async function saveQQUserKey({
}
}
function generateQQCache({
function generateQQCache ({
sessionKey, // QQ小程序用户sessionKey
accessToken, // App端QQ用户accessToken
accessTokenExpired // App端QQ用户accessToken过期时间
......@@ -84,11 +84,11 @@ function generateQQCache({
}
}
function getQQOpenid({
function getQQOpenid ({
userRecord
} = {}) {
const qqPlatform = getQQPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const qqOpenidObj = userRecord.qq_openid
if (!qqOpenidObj) {
return
......@@ -96,7 +96,7 @@ function getQQOpenid({
return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform]
}
async function getQQCacheFallback({
async function getQQCacheFallback ({
userRecord,
key
} = {}) {
......@@ -109,13 +109,13 @@ async function getQQCacheFallback({
return qqCache && qqCache[key]
}
async function getQQCache({
async function getQQCache ({
uid,
userRecord,
key
} = {}) {
const qqPlatform = getQQPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
if (!userRecord) {
const getUserRes = await userCollection.doc(uid).get()
......
......@@ -18,13 +18,13 @@ const {
const PasswordUtils = require('./password')
const merge = require('lodash.merge')
async function realPreRegister(params = {}) {
async function realPreRegister (params = {}) {
const {
user
} = params
const userMatched = await findUser({
userQuery: user,
authorizedApp: this.getClientInfo().appId
authorizedApp: this.getUniversalClientInfo().appId
})
if (userMatched.length > 0) {
throw {
......@@ -33,7 +33,7 @@ async function realPreRegister(params = {}) {
}
}
async function preRegister(params = {}) {
async function preRegister (params = {}) {
try {
await realPreRegister.call(this, params)
} catch (error) {
......@@ -45,7 +45,7 @@ async function preRegister(params = {}) {
}
}
async function preRegisterWithPassword(params = {}) {
async function preRegisterWithPassword (params = {}) {
const {
user,
password
......@@ -54,6 +54,7 @@ async function preRegisterWithPassword(params = {}) {
user
})
const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
})
const {
......@@ -72,7 +73,7 @@ async function preRegisterWithPassword(params = {}) {
}
}
async function thirdPartyRegister({
async function thirdPartyRegister ({
user = {}
} = {}) {
return {
......@@ -81,7 +82,7 @@ async function thirdPartyRegister({
}
}
async function postRegister(params = {}) {
async function postRegister (params = {}) {
const {
user,
extraData = {},
......@@ -98,7 +99,7 @@ async function postRegister(params = {}) {
clientIP,
osName,
uniIdToken
} = this.getClientInfo()
} = this.getUniversalClientInfo()
merge(user, extraData)
......@@ -162,7 +163,7 @@ async function postRegister(params = {}) {
if (beforeRegister) {
userRecord = await beforeRegister({
userRecord,
clientInfo: this.getClientInfo()
clientInfo: this.getUniversalClientInfo()
})
}
......
......@@ -29,7 +29,7 @@ async function preBind ({
} = {}) {
const userMatched = await findUser({
userQuery: bindAccount,
authorizedApp: this.getClientInfo().appId
authorizedApp: this.getUniversalClientInfo().appId
})
if (userMatched.length > 0) {
await this.middleware.uniIdLog({
......
......@@ -17,7 +17,7 @@ async function realPreUnifiedLogin (params = {}) {
user,
type
} = params
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const userMatched = await findUser({
userQuery: user,
authorizedApp: appId
......
......@@ -13,7 +13,7 @@ async function getPhoneNumber ({
}
return uniCloud.getPhoneNumber({
provider: 'univerify',
appid: this.getClientInfo().appId,
appid: this.getUniversalClientInfo().appId,
apiKey: univerifyConfig.apiKey,
apiSecret: univerifyConfig.apiSecret,
// eslint-disable-next-line camelcase
......
......@@ -23,7 +23,7 @@ async function setVerifyCode ({
scene,
code: code || getVerifyCode(),
state: 0,
ip: this.getClientInfo().clientIP,
ip: this.getUniversalClientInfo().clientIP,
created_date: now,
expired_date: now + expiresIn * 1000
}
......
......@@ -12,7 +12,7 @@ const {
openDataCollection
} = require('../../common/constants')
function decryptWeixinData({
function decryptWeixinData ({
encryptedData,
sessionKey,
iv
......@@ -37,9 +37,9 @@ function decryptWeixinData({
return decoded
}
function getWeixinPlatform() {
function getWeixinPlatform () {
const platform = this.clientPlatform
const userAgent = this.getClientInfo().userAgent
const userAgent = this.getUniversalClientInfo().userAgent
switch (platform) {
case 'app':
case 'app-plus':
......@@ -54,7 +54,7 @@ function getWeixinPlatform() {
}
}
async function saveWeixinUserKey({
async function saveWeixinUserKey ({
openid,
sessionKey, // 微信小程序用户sessionKey
accessToken, // App端微信用户accessToken
......@@ -64,7 +64,7 @@ async function saveWeixinUserKey({
// 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。
// 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const weixinPlatform = getWeixinPlatform.call(this)
const keyObj = {
dcloudAppid: appId,
......@@ -91,7 +91,7 @@ async function saveWeixinUserKey({
}
}
async function saveSecureNetworkCache({
async function saveSecureNetworkCache ({
code,
openid,
unionid,
......@@ -99,7 +99,7 @@ async function saveSecureNetworkCache({
}) {
const {
appId
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const key = `uni-id:${appId}:weixin-mp:code:${code}:secure-network-cache`
const value = JSON.stringify({
openid,
......@@ -120,7 +120,7 @@ async function saveSecureNetworkCache({
}
}
function generateWeixinCache({
function generateWeixinCache ({
sessionKey, // 微信小程序用户sessionKey
accessToken, // App端微信用户accessToken
refreshToken, // App端微信用户refreshToken
......@@ -153,11 +153,11 @@ function generateWeixinCache({
}
}
function getWeixinOpenid({
function getWeixinOpenid ({
userRecord
} = {}) {
const weixinPlatform = getWeixinPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const wxOpenidObj = userRecord.wx_openid
if (!wxOpenidObj) {
return
......@@ -165,7 +165,7 @@ function getWeixinOpenid({
return wxOpenidObj[`${weixinPlatform}_${appId}`] || wxOpenidObj[weixinPlatform]
}
async function getWeixinCacheFallback({
async function getWeixinCacheFallback ({
userRecord,
key
} = {}) {
......@@ -178,13 +178,13 @@ async function getWeixinCacheFallback({
return weixinCache && weixinCache[key]
}
async function getWeixinCache({
async function getWeixinCache ({
uid,
userRecord,
key
} = {}) {
const weixinPlatform = getWeixinPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
if (!userRecord) {
const getUserRes = await userCollection.doc(uid).get()
userRecord = getUserRes.data[0]
......@@ -212,9 +212,9 @@ async function getWeixinCache({
})
}
async function getWeixinAccessToken() {
async function getWeixinAccessToken () {
const weixinPlatform = getWeixinPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const cache = await this.uniOpenBridge.getAccessToken({
dcloudAppid: appId,
......
......@@ -2,7 +2,7 @@ module.exports = async function () {
if (this.authInfo) { // 多次执行auth时如果第一次成功后续不再执行
return
}
const token = this.getUniIdToken()
const token = this.getUniversalUniIdToken()
const payload = await this.uniIdCommon.checkToken(token)
if (payload.errCode) {
throw payload
......
......@@ -19,7 +19,7 @@ module.exports = async function ({
clientIP,
deviceId,
userAgent
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const logData = {
appid: appId,
device_id: deviceId,
......
......@@ -79,7 +79,7 @@ module.exports = async function (params = {}) {
userQuery: {
email
},
authorizedApp: [this.getClientInfo().appId]
authorizedApp: [this.getUniversalClientInfo().appId]
})
if (userMatched.length === 0) {
throw {
......@@ -95,6 +95,7 @@ module.exports = async function (params = {}) {
passwordHash,
version
} = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
}).generatePasswordHash({
password
......
......@@ -79,7 +79,7 @@ module.exports = async function (params = {}) {
userQuery: {
mobile
},
authorizedApp: [this.getClientInfo().appId]
authorizedApp: [this.getUniversalClientInfo().appId]
})
if (userMatched.length === 0) {
throw {
......@@ -95,6 +95,7 @@ module.exports = async function (params = {}) {
passwordHash,
version
} = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
}).generatePasswordHash({
password
......
......@@ -32,16 +32,18 @@ module.exports = async function (params = {}) {
newPassword
} = params
const passwordUtils = new PasswordUtils({
userRecord,
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
})
const {
success: checkPasswordSuccess
} = passwordUtils.checkUserPassword({
password: oldPassword,
passwordHash: userRecord.password,
passwordSecretVersion: userRecord.password_secret_version,
autoRefresh: false
})
if (!checkPasswordSuccess) {
throw {
errCode: ERROR.PASSWORD_ERROR
......
......@@ -83,6 +83,7 @@ module.exports = async function (params = {}) {
}
}
const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
})
const {
......
......@@ -107,6 +107,7 @@ module.exports = async function (params = {}) {
if (password) {
const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret
})
const {
......
......@@ -56,7 +56,7 @@ module.exports = async function (params = {}) {
} = params
const {
appId
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const qqApi = initQQ.call(this)
const qqPlatform = getQQPlatform.call(this)
let apiName
......
......@@ -44,7 +44,7 @@ module.exports = async function (params = {}) {
} = params
const {
appId
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const weixinApi = initWeixin.call(this)
const weixinPlatform = getWeixinPlatform.call(this)
let apiName
......
......@@ -38,7 +38,7 @@ module.exports = async function (params = {}) {
}).limit(1).get()
if (getAdminRes.data.length > 0) {
const [admin] = getAdminRes.data
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
if (!admin.dcloud_appid || (admin.dcloud_appid && admin.dcloud_appid.includes(appId))) {
return {
......
......@@ -49,7 +49,7 @@ module.exports = async function (params = {}) {
accessTokenExpired
} = params
const qqPlatform = getQQPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const qqApi = initQQ.call(this)
const clientPlatform = this.clientPlatform
const apiName = clientPlatform === 'mp-qq' ? 'code2Session' : 'getOpenidByToken'
......@@ -78,7 +78,7 @@ module.exports = async function (params = {}) {
const bindAccount = {
qq_openid: {
[clientPlatform]: openid
[qqPlatform]: openid
},
qq_unionid: unionid
}
......
......@@ -34,7 +34,7 @@ module.exports = async function (params = {}) {
code
} = params
const weixinPlatform = getWeixinPlatform.call(this)
const appId = this.getClientInfo().appId
const appId = this.getUniversalClientInfo().appId
const weixinApi = initWeixin.call(this)
const clientPlatform = this.clientPlatform
......@@ -64,7 +64,7 @@ module.exports = async function (params = {}) {
const bindAccount = {
wx_openid: {
[clientPlatform]: openid
[weixinPlatform]: openid
},
wx_unionid: unionid
}
......
......@@ -16,7 +16,7 @@ const {
*/
module.exports = async function () {
const { uid } = this.authInfo
const { appId } = this.getClientInfo()
const { appId } = this.getUniversalClientInfo()
const qqPlatform = getQQPlatform.call(this)
await preUnBind.call(this, {
......
......@@ -7,7 +7,7 @@ module.exports = async function () {
token,
tokenExpired
} = await this.uniIdCommon.refreshToken({
token: this.getUniIdToken()
token: this.getUniversalUniIdToken()
})
return {
errCode: 0,
......
......@@ -25,7 +25,7 @@ async function setOpendbDevice ({
screenHeight,
romName,
romVersion
} = this.getClientInfo()
} = this.getUniversalClientInfo()
const platform = this.clientPlatform
const now = Date.now()
......@@ -80,7 +80,7 @@ module.exports = async function (params = {}) {
deviceId,
appId,
osName
} = this.getClientInfo()
} = this.getUniversalClientInfo()
let platform = this.clientPlatform
if (platform === 'app') {
platform += osName
......
......@@ -18,7 +18,7 @@ module.exports = async function (params = {}) {
}
this.middleware.validate(params, schema)
const deviceId = this.getClientInfo().deviceId
const deviceId = this.getUniversalClientInfo().deviceId
const {
scene
} = params
......
......@@ -18,7 +18,7 @@ module.exports = async function (params = {}) {
}
this.middleware.validate(params, schema)
const deviceId = this.getClientInfo().deviceId
const deviceId = this.getUniversalClientInfo().deviceId
const {
scene
} = params
......
......@@ -23,26 +23,26 @@ module.exports = async function (params = {}) {
scene: 'string'
}
this.middleware.validate(params, schema)
const {
email,
captcha,
scene
} = params
if (!(Object.values(EMAIL_SCENE).includes(scene))) {
throw {
errCode: ERROR.INVALID_PARAM
}
}
await verifyCaptcha.call(this, {
scene: 'send-email-code',
captcha
})
// -- 测试代码
require('../../lib/utils/verify-code')
await require('../../lib/utils/verify-code')
.setEmailVerifyCode.call(this, {
email,
code: '123456',
......@@ -54,7 +54,7 @@ module.exports = async function (params = {}) {
errMsg: `已启动测试模式,直接使用:123456作为邮箱验证码即可。\n如果是正式项目,需自行实现发送邮件的相关功能`
}
// -- 测试代码
//发送邮件--需自行实现
}
......@@ -50,7 +50,7 @@ module.exports = async function (params = {}) {
this.config.service.sms.scene &&
this.config.service.sms.scene[scene]) || {}
if (!templateId) {
require('../../lib/utils/verify-code')
await require('../../lib/utils/verify-code')
.setMobileVerifyCode.call(this, {
mobile: params.mobile,
code: '123456',
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
......@@ -8,7 +8,7 @@
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app-plus": {
"app": {
"tokenExpiresIn": 2592000,
"oauth": {
"weixin": {
......
{
"schedule": {
"__UNI__HelloUniCloud": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
......@@ -8,7 +8,7 @@
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app-plus": {
"app": {
"tokenExpiresIn": 2592000,
"oauth": {
"weixin": {
......
{
"schedule": {
"__UNI__HelloUniCloud": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
......@@ -8,7 +8,7 @@
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app-plus": {
"app": {
"tokenExpiresIn": 2592000,
"oauth": {
"weixin": {
......
{
"schedule": {
"__UNI__HelloUniCloud": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
......@@ -8,7 +8,7 @@
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
"app-plus": {
"app": {
"tokenExpiresIn": 2592000,
"oauth": {
"weixin": {
......
{
"name": "uni-id-co",
"version": "1.0.27",
"version": "1.0.31",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "uni-id-co",
"version": "1.0.27",
"version": "1.0.31",
"description": "",
"main": "index.js",
"keywords": [],
......
## 3.3.29(2022-10-20)
- 使用[uni-open-bridge-common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge.html#common)存储用户三方凭证,以便其他服务使用。
## 3.3.28(2022-07-27)
- 修复 app端微信登录返回的accessToken过期时间(expired)不正确的Bug
## 3.3.27(2022-07-27)
......
{
"id": "uni-id",
"displayName": "uni-id",
"version": "3.3.28",
"version": "3.3.29",
"description": "简单、统一、可扩展的用户中心",
"keywords": [
"uniid",
......@@ -14,7 +14,7 @@
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
......@@ -35,7 +35,7 @@
"type": "unicloud-template-function"
},
"uni_modules": {
"dependencies": ["uni-config-center"],
"dependencies": ["uni-config-center", "uni-open-bridge-common"],
"encrypt": [],
"platforms": {
"cloud": {
......@@ -65,21 +65,21 @@
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
"vue2": "y",
"vue3": "u"
}
}
}
}
}
\ No newline at end of file
}
{
"name": "uni-id",
"version": "3.3.28",
"version": "3.3.29",
"description": "uni-id for uniCloud",
"main": "index.js",
"homepage": "https://uniapp.dcloud.io/uniCloud/uni-id",
......@@ -11,6 +11,7 @@
"author": "",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-open-bridge-common": "file:../../../../../uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common"
}
}
\ No newline at end of file
## 1.2.5(2022-11-15)
- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug
## 1.2.4(2022-11-15)
- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug
## 1.2.3(2022-11-14)
- uni-list-chat 新增 avatar 支持 fileId
## 1.2.2(2022-11-11)
- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor
## 1.2.1(2022-03-30)
- 删除无用文件
## 1.2.0(2021-11-23)
......
......@@ -7,7 +7,7 @@
<view class="uni-list-chat__container">
<view class="uni-list-chat__header-warp">
<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatar" mode="aspectFill"></image>
<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
</view>
<!-- 头像组 -->
<view v-else class="uni-list-chat__header">
......@@ -24,7 +24,10 @@
<view class="uni-list-chat__content">
<view class="uni-list-chat__content-main">
<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
<text class="uni-list-chat__content-note uni-ellipsis">{{ note }}</text>
<view style="flex-direction: row;">
<text class="draft" v-if="isDraft">[草稿]</text>
<text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14,-1):note}}</text>
</view>
</view>
<view class="uni-list-chat__content-extra">
<slot>
......@@ -121,6 +124,9 @@
},
// inject: ['list'],
computed: {
isDraft(){
return this.note.slice(0,14) == '[uni-im-draft]'
},
isSingle() {
if (this.badgeText === 'dot') {
return 'uni-badge--dot';
......@@ -146,12 +152,32 @@
}
}
},
watch: {
avatar:{
handler(avatar) {
if(avatar.includes('://')){
uniCloud.getTempFileURL({
fileList: [avatar]
}).then(res=>{
// console.log(res);
// 兼容uniCloud私有化部署
let fileList = res.fileList || res.result.fileList
this.avatarUrl = fileList[0].tempFileURL
})
}else{
this.avatarUrl = avatar
}
},
immediate: true
}
},
data() {
return {
isFirstChild: false,
border: true,
// avatarList: 3,
imageWidth: 50
imageWidth: 50,
avatarUrl:''
};
},
mounted() {
......@@ -445,13 +471,20 @@
overflow: hidden;
}
.uni-list-chat__content-note {
.draft ,.uni-list-chat__content-note {
margin-top: 3px;
color: $note-color;
font-size: $note-size;
font-weight: $title-weight;
overflow: hidden;
}
.draft{
color: #eb3a41;
/* #ifndef APP-NVUE */
flex-shrink: 0;
/* #endif */
padding-right: 3px;
}
.uni-list-chat__content-extra {
/* #ifndef APP-NVUE */
......
<template>
<!-- #ifdef APP-NVUE -->
<cell>
<cell keep-scroll-position>
<!-- #endif -->
<view :class="{ 'uni-list-item--disabled': disabled }"
<view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
class="uni-list-item" @click="onClick">
<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
<view class="uni-list-item__container"
:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column' }">
:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
:style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
<slot name="header">
<view class="uni-list-item__header">
<view v-if="thumb" class="uni-list-item__icon">
......@@ -96,7 +96,7 @@
default: ''
},
ellipsis: {
type: [Number,String],
type: [Number, String],
default: 0
},
disabled: {
......@@ -139,7 +139,7 @@
type: String,
default: 'success'
},
badgeStyle:{
badgeStyle: {
type: Object,
default () {
return {}
......@@ -174,12 +174,60 @@
border: {
type: Boolean,
default: true
},
customStyle: {
type: Object,
default () {
return {
padding: '',
backgroundColor: '#FFFFFF'
}
}
}
},
watch: {
'customStyle.padding': {
handler(padding) {
if(typeof padding == 'number'){
padding += ''
}
let paddingArr = padding.split(' ')
if (paddingArr.length === 1) {
this.padding = {
"top": padding,
"right": padding,
"bottom": padding,
"left": padding
}
} else if (paddingArr.length === 2) {
this.padding = {
"top": padding[0],
"right": padding[1],
"bottom": padding[0],
"left": padding[1]
}
} else if (paddingArr.length === 4) {
this.padding = {
"top": padding[0],
"right": padding[1],
"bottom": padding[2],
"left": padding[3]
}
}
},
immediate: true
}
},
// inject: ['list'],
data() {
return {
isFirstChild: false
isFirstChild: false,
padding: {
top: "",
right: "",
bottom: "",
left: ""
}
};
},
mounted() {
......@@ -255,7 +303,7 @@
uni.switchTab(callback)
break
default:
uni.navigateTo(callback)
uni.navigateTo(callback)
}
}
}
......@@ -275,6 +323,7 @@
$uni-bg-color-hover:#f1f1f1;
$uni-text-color-grey:#999;
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
.uni-list-item {
/* #ifndef APP-NVUE */
display: flex;
......@@ -289,12 +338,15 @@
cursor: pointer;
/* #endif */
}
.uni-list-item--disabled {
opacity: 0.3;
}
.uni-list-item--hover {
background-color: $uni-bg-color-hover;
}
.uni-list-item__container {
position: relative;
/* #ifndef APP-NVUE */
......@@ -307,9 +359,11 @@
overflow: hidden;
// align-items: center;
}
.container--right {
padding-right: 0;
}
// .border--left {
// margin-left: $uni-spacing-row-lg;
// }
......@@ -324,6 +378,7 @@
border-top-width: 0.5px;
/* #endif */
}
/* #ifndef APP-NVUE */
.uni-list--border:after {
position: absolute;
......@@ -336,6 +391,7 @@
transform: scaleY(0.5);
background-color: $uni-border-color;
}
/* #endif */
.uni-list-item__content {
/* #ifndef APP-NVUE */
......@@ -349,20 +405,24 @@
justify-content: space-between;
overflow: hidden;
}
.uni-list-item__content--center {
justify-content: center;
}
.uni-list-item__content-title {
font-size: $uni-font-size-base;
color: #3b4144;
overflow: hidden;
}
.uni-list-item__content-note {
margin-top: 6rpx;
color: $uni-text-color-grey;
font-size: $uni-font-size-sm;
overflow: hidden;
}
.uni-list-item__extra {
// width: 25%;
/* #ifndef APP-NVUE */
......@@ -372,6 +432,7 @@
justify-content: flex-end;
align-items: center;
}
.uni-list-item__header {
/* #ifndef APP-NVUE */
display: flex;
......@@ -379,12 +440,14 @@
flex-direction: row;
align-items: center;
}
.uni-list-item__icon {
margin-right: 18rpx;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-list-item__icon-img {
/* #ifndef APP-NVUE */
display: block;
......@@ -393,6 +456,7 @@
width: $uni-img-size-base;
margin-right: 10px;
}
.uni-icon-wrapper {
/* #ifndef APP-NVUE */
display: flex;
......@@ -400,33 +464,40 @@
align-items: center;
padding: 0 10px;
}
.flex--direction {
flex-direction: column;
/* #ifndef APP-NVUE */
align-items: initial;
/* #endif */
}
.flex--justify {
/* #ifndef APP-NVUE */
justify-content: initial;
/* #endif */
}
.uni-list--lg {
height: $uni-img-size-lg;
width: $uni-img-size-lg;
}
.uni-list--base {
height: $uni-img-size-base;
width: $uni-img-size-base;
}
.uni-list--sm {
height: $uni-img-size-sm;
width: $uni-img-size-sm;
}
.uni-list-item__extra-text {
color: $uni-text-color-grey;
font-size: $uni-font-size-sm;
}
.uni-ellipsis-1 {
/* #ifndef APP-NVUE */
overflow: hidden;
......@@ -435,9 +506,10 @@
/* #endif */
/* #ifdef APP-NVUE */
lines: 1;
text-overflow:ellipsis;
text-overflow: ellipsis;
/* #endif */
}
.uni-ellipsis-2 {
/* #ifndef APP-NVUE */
overflow: hidden;
......@@ -448,7 +520,7 @@
/* #endif */
/* #ifdef APP-NVUE */
lines: 2;
text-overflow:ellipsis;
text-overflow: ellipsis;
/* #endif */
}
</style>
</style>
\ No newline at end of file
......@@ -7,102 +7,117 @@
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
<list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
loadmoreoffset="15">
<slot />
</list>
<!-- #endif -->
</template>
<script>
/**
* List 列表
* @description 列表组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
* @property {String} border = [true|false] 标题
*/
export default {
name: 'uniList',
'mp-weixin': {
options: {
multipleSlots: false
}
},
props: {
enableBackToTop: {
type: [Boolean, String],
default: false
/**
* List 列表
* @description 列表组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
* @property {String} border = [true|false] 标题
*/
export default {
name: 'uniList',
'mp-weixin': {
options: {
multipleSlots: false
}
},
scrollY: {
type: [Boolean, String],
default: false
props: {
stackFromEnd:{
type: Boolean,
default:false
},
enableBackToTop: {
type: [Boolean, String],
default: false
},
scrollY: {
type: [Boolean, String],
default: false
},
border: {
type: Boolean,
default: true
},
renderReverse:{
type: Boolean,
default: false
}
},
border: {
type: Boolean,
default: true
}
},
// provide() {
// return {
// list: this
// };
// },
created() {
this.firstChildAppend = false;
},
methods: {
loadMore(e) {
this.$emit('scrolltolower');
// provide() {
// return {
// list: this
// };
// },
created() {
this.firstChildAppend = false;
},
methods: {
loadMore(e) {
this.$emit('scrolltolower');
},
scroll(e) {
this.$emit('scroll', e);
}
}
}
};
};
</script>
<style lang="scss" >
$uni-bg-color:#ffffff;
$uni-border-color:#e5e5e5;
.uni-list {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
background-color: $uni-bg-color;
position: relative;
flex-direction: column;
}
<style lang="scss">
$uni-bg-color:#ffffff;
$uni-border-color:#e5e5e5;
.uni-list--border {
position: relative;
/* #ifdef APP-NVUE */
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 0.5px;
border-bottom-color: $uni-border-color;
border-bottom-style: solid;
border-bottom-width: 0.5px;
/* #endif */
z-index: -1;
}
.uni-list {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
background-color: $uni-bg-color;
position: relative;
flex-direction: column;
}
/* #ifndef APP-NVUE */
.uni-list--border {
position: relative;
/* #ifdef APP-NVUE */
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 0.5px;
border-bottom-color: $uni-border-color;
border-bottom-style: solid;
border-bottom-width: 0.5px;
/* #endif */
z-index: -1;
}
.uni-list--border-top {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
background-color: $uni-border-color;
z-index: 1;
}
/* #ifndef APP-NVUE */
.uni-list--border-bottom {
position: absolute;
bottom: 0;
right: 0;
left: 0;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
background-color: $uni-border-color;
}
.uni-list--border-top {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
background-color: $uni-border-color;
z-index: 1;
}
/* #endif */
.uni-list--border-bottom {
position: absolute;
bottom: 0;
right: 0;
left: 0;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
background-color: $uni-border-color;
}
/* #endif */
</style>
{
"id": "uni-list",
"displayName": "uni-list 列表",
"version": "1.2.1",
"version": "1.2.5",
"description": "List 组件 ,帮助使用者快速构建列表。",
"keywords": [
"",
......@@ -18,11 +18,7 @@
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
......@@ -39,7 +35,8 @@
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [
......
{
"name": "uni-config-center",
"version": "0.0.2",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
......
{
"schedule": {
"__UNI__XXXXXX": {
"enable": true,
"weixin-mp": {
"enable": true,
"tasks": ["accessToken"]
}
}
},
"ipWhiteList": ["0.0.0.0"]
}
## 1.2.4(2022-09-19)
- 修复,未对主题色设置默认色,导致未引入 uni-scss 变量文件报错。
- 修复,未对移动端当前页文字做主题色适配。
## 1.2.3(2022-09-15)
- 修复未使用 uni-scss 主题色的 bug。
## 1.2.2(2022-07-06)
- 修复 es 语言 i18n 错误
## 1.2.1(2021-11-22)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册