提交 1882983f 编写于 作者: DCloud_JSON's avatar DCloud_JSON

调整结构,新增个人资料修改

上级 43e66bab
......@@ -4,41 +4,72 @@
export default {
globalData: {
searchText: '',
appVersion:{}
appVersion: {}
},
onLaunch: function() {
console.log('App Launch')
initApp();
// #ifdef APP-PLUS
checkIsAgree();
// #endif
//#ifdef APP-NVUE || H5
//预加载设置页面
uni.preloadPage({
url: "/pages/ucenter/settings/settings",
complete:e=>{
complete: e => {
// console.log(e);
}
});
//#endif
// #ifdef APP-PLUS
//预加载一键登录
plus.oauth.getServices(oauthServices=>{
plus.oauth.getServices(oauthServices => {
// console.log(oauthServices);
oauthServices.forEach(({_id},item)=>{
if(_id=='provider'){
oauthServices.forEach(({
_id
}, item) => {
if (_id == 'provider') {
uni.preLogin({
provider:item,
complete:e=>{
provider: item,
complete: e => {
console.log(e);
}
})
}
})
uni.preloadPage({url: "/uni_modules/uni-login-page/pages/index/index"});
},err=>{
uni.preloadPage({
url: "/pages/ucenter/login-page/index/index"
});
}, err => {
console.error('获取服务供应商失败:' + JSON.stringify(err));
})
// #endif
//clientDB的错误提示
const db = uniCloud.database()
function onDBError({
code, // 错误码详见https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=returnvalue
message
}) {
// 处理错误
console.log(code,message);
if([
'TOKEN_INVALID_INVALID_CLIENTID',
'TOKEN_INVALID',
'TOKEN_INVALID_TOKEN_EXPIRED',
'TOKEN_INVALID_WRONG_TOKEN',
'TOKEN_INVALID_ANONYMOUS_USER',
].includes(code)){
uni.navigateTo({
url:'/pages/ucenter/login-page/index/index'
})
}
}
// 绑定clientDB错误事件
db.on('error', onDBError)
// 解绑clientDB错误事件
//db.off('error', onDBError)
},
onShow: function() {
console.log('App Show')
......@@ -51,7 +82,7 @@
<style>
/*每个页面公共css */
.border-test{
.border-test {
/* #ifdef APP-NVUE */
border-width: 1rpx;
border-color: #DD524D;
......@@ -61,15 +92,23 @@
box-sizing: border-box;
/* #endif */
}
/* #ifndef APP-NVUE */
view,scroll-view,text,
image,switch,navigator,icons {
view,
scroll-view,
text,
image,
switch,
navigator,
icons {
display: flex;
box-sizing: border-box;
flex-direction: column;
}
scroll-view{
scroll-view {
-webkit-overflow-scrolling: touch;
}
/* #endif */
</style>
module.exports = {
"h5":{
"url":"https://static-76ce2c5e-31c7-4d81-8fcf-ed1541ecbc6e.bspapp.com",// 前端网页托管的域名
"openApp":{ // 在h5端全局悬浮引导用户下载app的功能 更多自定义要求在/common/openApp.js中修改
"openUrl":'https://sj.qq.com/myapp/detail.htm?apkName=com.tencent.android.qqdownloader&info=6646FD239A6EBA9E2DEE5DFC7E18D867',
"h5": {
"url": "https://static-76ce2c5e-31c7-4d81-8fcf-ed1541ecbc6e.bspapp.com", // 前端网页托管的域名
"openApp": { // 在h5端全局悬浮引导用户下载app的功能 更多自定义要求在/common/openApp.js中修改
"openUrl": 'https://sj.qq.com/myapp/detail.htm?apkName=com.tencent.android.qqdownloader&info=6646FD239A6EBA9E2DEE5DFC7E18D867',
"appname": 'base-app',
"logo": './static/logo.png',
}
},
"mp":{
"weixin":{
"id":"gh_33446d7f7a26"
"mp": {
"weixin": {
"id": "gh_33446d7f7a26"
}
},
"router":{
"needLogin":[ //配置需要路由拦截的页面地址,在打开这些页面之前会自动检查(不联网)uni_id_token的值是否存在/过期等
"/uni_modules/uni-id-users/pages/uni-id-users/edit",
"router": {
"needLogin": [ //配置需要路由拦截的页面地址,在打开这些页面之前会自动检查(不联网)uni_id_token的值是否存在/过期等
"/pages/ucenter/edit/edit",
"/uni_modules/uni-news-favorite/pages/uni-news-favorite/list",
"/pages/ucenter/edit/uploadCutImageToUnicloud"
],
"login":["univerify","smsCode","username","weixin","apple"] //默认就是短信验证码登陆
"login": ["univerify", "smsCode", "username", "weixin", "apple"] //默认就是短信验证码登陆
},
"about":{
"appName":"base-app",
"logo":"/static/logo.png",
"company":"数字天堂(北京)网络技术有限公司",
"slogan":"为开发而生",
"agreements":[
{
"title":"用户服务协议",
"url":"https://ask.dcloud.net.cn/protocol.html"
"about": {
"appName": "base-app",
"logo": "/static/logo.png",
"company": "数字天堂(北京)网络技术有限公司",
"slogan": "为开发而生",
"agreements": [{
"title": "用户服务协议",
"url": "https://ask.dcloud.net.cn/protocol.html"
},
{
"title":"隐私政策",
"url":"https://ask.dcloud.net.cn/protocol.html"
"title": "隐私政策",
"url": "https://ask.dcloud.net.cn/protocol.html"
}
],
"download":"https://m3w.cn/uniapp"
"download": "https://m3w.cn/uniapp"
}
}
......@@ -31,12 +31,12 @@ export default function() {
icon: 'none'
})
uni.navigateTo({
url: "/uni_modules/uni-login-page/pages/index/index"
url: "/pages/ucenter/login-page/index/index"
})
return false
}
//控制登陆优先级
if (url == '/uni_modules/uni-login-page/pages/index/index') {
if (url == '/pages/ucenter/login-page/index/index') {
//一键登录(univerify)、密码登陆(username)、快捷登录&验证码登陆(!univerify&password)
if (login[0] == 'univerify') {
// console.log(e.url,url);
......@@ -45,7 +45,7 @@ export default function() {
}
e.url += "univerify_first=true"
} else if (login[0] == 'username') {
e.url = "/uni_modules/uni-login-page/pages/pwd-login/pwd-login"
e.url = "/pages/ucenter/login-page/pwd-login/pwd-login"
} else {
//默认即是
}
......@@ -132,6 +132,7 @@ function initAppVersion() {
// 设备网络状态变化事件
function eventListenerNetwork() {
/*
//网络掉线
uni.getNetworkType({
success:res=>{
......@@ -169,7 +170,7 @@ function eventListenerNetwork() {
function showNetworkErrPage(){
let pages = getCurrentPages();
console.log('pages.length',pages.length);
if(pages.length===0|| pages[pages.length - 1].route!='/pages/networkErr/networkErr.vue'){
if(pages.length===0 || pages[pages.length - 1].route!='/pages/networkErr/networkErr.vue'){
uni.navigateTo({
url:'/pages/networkErr/networkErr'
})
......@@ -204,6 +205,7 @@ function openAppPermissionSetting(){
intent.setData(uri);
mainActivity.startActivity(intent);
}
*/
}
/*
uni.addInterceptor(item, {
......
<template>
<view class="quick-login-box">
<view class="item" v-for="(item,index) in servicesList" :key="index" @click="item.path?to(item.path):login(item.id,false)">
<view class="item" v-for="(item,index) in servicesList" :key="index"
@click="item.path?to(item.path):login(item.id,false)">
<image class="logo" :src="item.logo" mode="widthFix"></image>
<text class="login-title">{{item.text}}</text>
</view>
</view>
</template>
<script>
import {mapGetters,mapMutations} from 'vuex';
import {
mapGetters,
mapMutations
} from 'vuex';
//前一个窗口的页面地址。控制点击切换快捷登陆方式是创建还是返回
import loginSuccess from 'uni_modules/uni-login-page/common/loginSuccess.js';
import loginSuccess from '@/pages/ucenter/login-page/common/loginSuccess.js';
export default {
data() {
return {
servicesList: [{
"text": "账号登陆",
"logo": "/static/uni-quick-login/user.png",
"path": "/pages/ucenter/login-page/pwd-login/pwd-login"
},
{
"text": "短信验证码",
"logo": "/static/uni-quick-login/sms.png",
"path": "/pages/ucenter/login-page/index/index"
}
]
}
},
props: {
config: {
type: Object,
default () {
return {
"weixin": {
"text": "微信登陆",
"logo": "../../static/login/weixin.png",
"isChecked":true
"logo": "/static/uni-quick-login/wechat.png",
"isChecked": true
},
"apple": {
"text": "苹果登陆",
"logo": "../../static/login/apple.png",
"isChecked":true
"logo": "/static/uni-quick-login/apple.png",
"isChecked": true
},
"univerify": {
"text": "一键登陆",
"logo": "../../static/login/univerify.png",
"isChecked":true
"logo": "/static/uni-quick-login/univerify.png",
"isChecked": true
},
"qq": {
"text": "QQ登陆",
"logo": "../../static/login/qq.png",
"isChecked":false //暂未提供该登陆方式的接口示例
"logo": "/static/uni-quick-login/univerify.png",
"isChecked": false //暂未提供该登陆方式的接口示例
},
"xiaomi": {
"text": "小米登陆",
"logo": "../../static/login/qq.png",
"isChecked":false //暂未提供该登陆方式的接口示例
"logo": "/static/uni-quick-login/univerify.png",
"isChecked": false //暂未提供该登陆方式的接口示例
},
"sinaweibo": {
"text": "微博登录",
"logo": "../../static/login/weibo.png",
"isChecked":false //暂未提供该登陆方式的接口示例
"logo": "/static/uni-quick-login/univerify.png",
"isChecked": false //暂未提供该登陆方式的接口示例
}
}
},
servicesList:[
{
"text": "账号登陆",
"logo": "../../static/login/db.png",
"path":"/uni_modules/uni-login-page/pages/pwd-login/pwd-login"
},
{
"text": "短信登陆",
"logo": "../../static/login/smsCode.png",
"path":"/uni_modules/uni-login-page/pages/index/index"
}
],
univerifyStyle: { //一键登陆弹出窗的样式配置参数
},
univerifyStyle: {
type: Object,
default () {
return { //一键登陆弹出窗的样式配置参数
"fullScreen": true, // 是否全屏显示,true表示全屏模式,false表示非全屏模式,默认值为false。
"backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff
}
}
},
},
created() {
let servicesList = this.servicesList
//去掉当前页面对应的登陆选项
for (var i = 0; i < servicesList.length; i++) {
if(servicesList[i].path == this.getRoute(1)){
servicesList.splice(i,1)
if (servicesList[i].path == this.getRoute(1)) {
servicesList.splice(i, 1)
}
}
},
mounted() {
//获取当前环境能用的快捷登陆方式
// #ifdef APP-PLUS
plus.oauth.getServices(oauthServices=>{
plus.oauth.getServices(oauthServices => {
this.oauthServices = oauthServices
oauthServices.forEach(({id})=>{
if(this.config[id].isChecked){
this.servicesList.push({...this.config[id],id})
oauthServices.forEach(({
id
}) => {
if (this.config[id].isChecked) {
this.servicesList.push({
...this.config[id],
id
})
}
})
// console.log(oauthServices);
},err=>{
}, err => {
uni.hideLoading()
uni.showModal({
title: '获取服务供应商失败:' +JSON.stringify(err),
title: '获取服务供应商失败:' + JSON.stringify(err),
showCancel: false,
confirmText: '知道了'
});
......@@ -98,34 +118,42 @@
...mapMutations({
setUserInfo: 'user/login'
}),
getRoute(n=0){
getRoute(n = 0) {
let pages = getCurrentPages();
console.log('route-pages-length',pages.length);
if(n>pages.length){ return '' }
return '/'+pages[pages.length - n].route
console.log('route-pages-length', pages.length);
if (n > pages.length) {
return ''
}
return '/' + pages[pages.length - n].route
},
to(path){
console.log('比较',this.getRoute(2),path)
if(this.getRoute(2)==path){ // 控制路由是重新打开还是返回,避免重复打开页面
to(path) {
console.log('比较', this.getRoute(2), path)
if (this.getRoute(2) == path) { // 控制路由是重新打开还是返回,避免重复打开页面
uni.navigateBack();
}else{
uni.navigateTo({url:path})
} else {
uni.navigateTo({
url: path
})
}
},
login(type,navigateBack=true) {
login(type, navigateBack = true) {
console.log(arguments);
console.log('services',services);
console.log('services', services);
let oauthService = this.oauthServices.find((service) => service.id == type)
console.log(type);
// #ifdef APP-PLUS
//请勿直接使用前端获取的unionid或openid直接用于登陆,前端的数据都是不可靠的
if(type=='weixin'){
return oauthService.authorize(({code})=>{
if (type == 'weixin') {
return oauthService.authorize(({
code
}) => {
console.log(code);
this.quickLogin({code},type)
this.quickLogin({
code
}, type)
},
err=>{
err => {
uni.hideLoading()
console.log(err);
})
......@@ -134,38 +162,42 @@
uni.login({
"provider": type,
"univerifyStyle":this.univerifyStyle,
success:async e => {
"univerifyStyle": this.univerifyStyle,
success: async e => {
console.log(e);
if(type=='apple'){
let res = await this.getUserInfo({provider:"apple"})
Object.assign(e.authResult,res.userInfo)
if (type == 'apple') {
let res = await this.getUserInfo({
provider: "apple"
})
Object.assign(e.authResult, res.userInfo)
}
this.quickLogin(e.authResult,type)
this.quickLogin(e.authResult, type)
},
fail: (err) => {
uni.hideLoading()
console.log(err);
if(type=='univerify'){
if(err.metadata.error_data){
if (type == 'univerify') {
if (err.metadata.error_data) {
uni.showToast({
title: "一键登陆:"+err.metadata.error_data,
title: "一键登陆:" + err.metadata.error_data,
icon: 'none'
});
}
switch (err.errCode){
switch (err.errCode) {
case 30002:
console.log('在一键登陆界面,点击其他登陆方式');
break;
case 30003:
console.log('关闭了登陆');
if(navigateBack){ uni.navigateBack() }
if (navigateBack) {
uni.navigateBack()
}
break;
case 30006:
uni.showModal({
title: "登陆服务初始化错误",
content:err.metadata.error_data,
content: err.metadata.error_data,
showCancel: false,
confirmText: '知道了',
});
......@@ -177,12 +209,12 @@
}
})
},
quickLogin(params,type){//联网验证登陆
console.log(params,type);
this.request('user-center/login_by_'+type,params,(data,result)=>{
quickLogin(params, type) { //联网验证登陆
console.log(params, type);
this.request('user-center/login_by_' + type, params, (data, result) => {
console.log(result);
if(result.code === 0){
if(type=='univerify'){
if (result.code === 0) {
if (type == 'univerify') {
uni.closeAuthView()
}
uni.hideLoading()
......@@ -190,10 +222,12 @@
delete result.userInfo.token
this.setUserInfo(result.userInfo)
}
},{showLoading:true})
}, {
showLoading: true
})
},
async getUserInfo(e){
return new Promise((resolve, reject)=>{
async getUserInfo(e) {
return new Promise((resolve, reject) => {
uni.getUserInfo({
...e,
success: (res) => {
......@@ -219,6 +253,7 @@
width: 750rpx;
justify-content: space-around;
}
.item {
flex-direction: column;
justify-content: center;
......@@ -232,6 +267,7 @@
}
.login-title {
margin-top: 4px;
font-size: 26rpx;
}
</style>
......@@ -20,13 +20,10 @@ export default function request(name,params,callback=false,{showLoading=false,lo
return new Promise((resolve,reject)=>{
uniCloud.callFunction({name,data:{action,params},
success(e){
// console.log(e);
console.log(e);
const {result:{data,code}} = e
console.log(data,code);
if (code === 0 ) {
resolve(e)
return callback(data,e.result,e)
}
if (code != 0 ) {
if(debug){
uni.showModal({
content: JSON.stringify(e),
......@@ -34,6 +31,9 @@ export default function request(name,params,callback=false,{showLoading=false,lo
confirmText: '知道了'
})
}
}
resolve(e)
return callback(data,e.result,e)
},
fail(err){
reject(err)
......
......@@ -8,20 +8,6 @@
"enablePullDownRefresh": true
}
},
// #ifdef APP-PLUS
{
"path": "pages/networkErr/networkErr",
"style": {
"navigationStyle": "custom",
"backgroundColor": "transparent",
"app-plus": {
"animationType": "fade-in",
"background": "transparent",
"popGesture": "none"
}
}
},
// #endif
{
"path": "pages/list/news-list",
"style": {
......@@ -39,7 +25,7 @@
//#endif
}
}, {
"path": "uni_modules/uni-login-page/pages/index/index",
"path": "pages/ucenter/login-page/index/index",
"style": {
"navigationBarTitleText": "",
"app-plus": {
......@@ -73,13 +59,18 @@
},
"navigationBarTitleText": "文章详情"
}
}, {
"path": "pages/ucenter/edit/bind-mobile/bind-mobile",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/ucenter/ucenter",
"style": {
"navigationStyle": "custom"
}
}, {
},{
"path": "uni_modules/uni-feedback/pages/opendb-feedback/list",
"style": {
"navigationBarTitleText": "常见问题"
......@@ -156,9 +147,9 @@
}
}, {
"path": "uni_modules/uni-id-users/pages/uni-id-users/edit",
"path": "pages/ucenter/edit/edit",
"style": {
"navigationBarTitleText": "编辑资料"
"navigationBarTitleText": "个人资料"
}
}, {
"path": "pages/ucenter/edit/uploadCutImageToUnicloud",
......@@ -166,17 +157,17 @@
"navigationStyle": "custom"
}
}, {
"path": "uni_modules/uni-login-page/pages/pwd-login/pwd-login",
"path": "pages/ucenter/login-page/pwd-login/pwd-login",
"style": {
"navigationBarTitleText": ""
}
}, {
"path": "uni_modules/uni-login-page/pages/pwd-retrieve/pwd-retrieve",
"path": "pages/ucenter/login-page/pwd-retrieve/pwd-retrieve",
"style": {
"navigationBarTitleText": ""
}
}, {
"path": "uni_modules/uni-login-page/pages/phone-code/phone-code",
"path": "pages/ucenter/login-page/phone-code/phone-code",
"style": {
"navigationBarTitleText": ""
}
......@@ -196,7 +187,7 @@
}
}, {
"path": "uni_modules/uni-login-page/pages/register/register",
"path": "pages/ucenter/login-page/register/register",
"style": {
"navigationBarTitleText": "注册",
"enablePullDownRefresh": false
......@@ -222,7 +213,7 @@
"path": "pages/list/list"
},
{
"path": "uni_modules/uni-login-page/pages/index/index"
"path": "pages/ucenter/login-page/index/index"
},
{
"path": "pages/test/test"
......
......@@ -53,7 +53,7 @@
import uParse from '@/components/u-parse/parse.vue';
const db = uniCloud.database();
const dbCollectionName = 'opendb-news-favorite';
const newsFavoriteTable = db.collection('opendb-news-favorite')
import { mapGetters } from 'vuex';
export default {
components: {
......@@ -80,7 +80,8 @@
return `_id =="${this.id}"`
},
...mapGetters({
'userInfo':'user/info'
'userInfo':'user/info',
'hasLogin':'user/hasLogin'
})
},
onLoad(event) {
......@@ -114,8 +115,8 @@
},
methods: {
setFavorite(){
if(!this.userInfo)return
db.collection(dbCollectionName).where({
if(!this.has)return
newsFavoriteTable.where({
article_id:this.id,
user_id:this.userInfo._id
})
......@@ -128,9 +129,9 @@
update_date:Date.now()
}
if(res.result.data.length == 0){
return db.collection(dbCollectionName).add(value)
return newsFavoriteTable.add(value)
} else {
return db.collection(dbCollectionName).where({
return newsFavoriteTable.where({
article_id:this.id,
user_id:this.userInfo._id
})
......
<template>
<view class="box">
<view class="content">
<text class="networkErr">网络连接不可用</text>
<button type="default" @click="toSet">去设置</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight:0
}
},
mounted() {
uni.onNetworkStatusChange(res=> {
console.log(res.isConnected);
console.log(res.networkType);
if(res.networkType!='none'){
uni.showToast({
title:'当前网络类型:'+res.networkType,
icon:'none',
duration:3000
})
uni.navigateBack({
animationType:'fade-out'
})
}
});
},
methods: {
toSet(){
if (uni.getSystemInfoSync().platform == "ios") {
plus.runtime.launchApplication({
action: 'App-Prefs:root=WIFI'
}, function(e) {
console.log(JSON.stringify(e));
});
} else {
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass("android.content.Intent");
var mIntent = new Intent('android.settings.DATA_ROAMING_SETTINGS');
main.startActivity(mIntent);
}
}
},
}
</script>
<style >
page {
background: transparent;
}
.box{
display: flex;
width: 750rpx;
height: 100vh;
justify-content: center;
align-items: center;
}
.content{
height: 100px;
width: 400rpx;
background-color: #DD524D;
}
</style>
......@@ -8,15 +8,16 @@
<text>应用相关权限</text>
<button type="default" @click="openAppPermissionSetting">打开</button>
<button type="default" @click="iosSetting">iosSetting</button> -->
<button type="default" @click="openCamera">打开相机</button>
<button type="default" @click="open=1">打开</button>
<web-view v-if="open" style="height: 1px;" src="https://ur.alipay.com/2tZMWI"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
open:0
}
},
onLoad() {
......@@ -24,6 +25,9 @@
// 1.先检测手机的该模块是否打开
// 2.检测当前应用是否被授权了该模块对应的权限
// 提示,并点击跳转到设置
// plus.runtime.openURL('https://ur.alipay.com/2tZMWI',e=>{
// console.log(e);
// })
},
methods: {
openCamera(){
......
<template>
<view class="box">
<!-- 登录框 (选择手机号所属国家和地区需要另行实现) -->
<uni-easyinput focus type="number" class="phone-input-box" :inputBorder="false" v-model="formData.phone"
maxlength="11" placeholder="请输入手机号"></uni-easyinput>
<uni-easyinput type="number" class="phone-input-box" :inputBorder="false" v-model="formData.code" maxlength="6"
placeholder="请输入验证码">
<template slot="right">
<login-short-code ref="shortCode" :phone="formData.phone"></login-short-code>
</template>
</uni-easyinput>
<button class="send-btn-box" type="primary" @click="submit">提交</button>
</view>
</template>
<script>
import {
mapMutations,
mapGetters
} from 'vuex';
export default {
data() {
return {
currenPhoneArea: '',
formData: {
phone:"",
code:""
}
}
},
computed: {
tipText() {
return `验证码已通过短信发送至${this.currenPhoneArea} ${this.formData.phone}。密码为6 - 20位`
},
canSubmit() {
return this.isPhone && this.isPwd && this.isCode;
}
},
onLoad(event) {
},
onReady() {
},
methods: {
...mapMutations({
setUserInfo: 'user/login'
}),
/**
* 完成并提交
*/
submit() {
console.log(this.formData);
this.request('user-center/bind_mobile_by_sms', {
"mobile": this.formData.phone,
"code": this.formData.code
}, (data, result) => {
console.log(result);
this.setUserInfo({"mobile":result.mobile})
uni.showToast({
title: result.msg,
icon: 'none'
});
if (result.code === 0) {
uni.navigateBack()
}
})
}
}
}
</script>
<style>
.box {
align-items: center;
justify-content: center;
padding-top: 10px;
}
.box /deep/ .uni-easyinput__content {
height: 45px;
}
.phone-input-box {
width: 650rpx;
height: 50px;
margin-top: 16px;
background-color: #f9f9f9;
border-radius: 6rpx;
flex-direction: row;
flex-wrap: nowrap;
}
.send-btn-box {
width: 650rpx;
margin-top: 15px;
}
</style>
<template>
<view>
<uni-list>
<uni-list-item class="item" link>
<view @click="setAvatar" slot="body" class="item">
<text>头像</text>
<image class="avatarUrl" :src="userInfo.avatar||nullAvatarUrl" mode="widthFix"></image>
</view>
</uni-list-item>
<uni-list-item class="item" @click="setNickname()" title="昵称" :rightText="userInfo.nickname||'未设置'" link></uni-list-item>
<uni-list-item class="item" @click="bindMobile" title="手机号" :rightText="userInfo.mobile||'未绑定'" link></uni-list-item>
</uni-list>
<uni-popup ref="dialog" type="dialog">
<uni-popup-dialog mode="input" :value="userInfo.nickname" @confirm="setNickname" title="设置昵称" placeholder="请输入要设置的昵称">
</uni-popup-dialog>
</uni-popup>
</view>
</template>
<script>
import {
mapMutations,
mapGetters
} from 'vuex';
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
export default {
data() {
return {
nullAvatarUrl: '/static/uni-center/logo.png',
univerifyStyle: {
authButton: {
"title": "本机号码一键绑定", // 授权按钮文案
},
otherLoginButton: {
"title": "其他号码绑定",
}
}
}
},
computed: {
...mapGetters({
userInfo: 'user/info',
login: 'user/hasLogin'
})
},
methods: {
...mapMutations({
setUserInfo: 'user/login'
}),
bindMobile() {
// #ifdef APP-PLUS
uni.preLogin({
provider: 'univerify',
success: this.univerify(), //预登录成功
fail(res) { // 预登录失败
// 不显示一键登录选项(或置灰)
console.log(res)
}
})
// #endif
// #ifndef APP-PLUS
this.bindMobileBySmsCode()
//...去用验证码绑定
// #endif
},
univerify() {
uni.login({
"provider": 'univerify',
"univerifyStyle": this.univerifyStyle,
success: async e => {
console.log(e.authResult);
this.request('user-center/bind_mobile_by_univerify',
e.authResult,
(data, result) =>
{
console.log(result);
if(result.code===0){
this.setUserInfo({"mobile":result.mobile})
uni.closeAuthView()
}else{
uni.showModal({
content: JSON.stringify(result.msg),
showCancel: false,
complete() {
uni.closeAuthView()
}
});
}
}
)
},
fail: (err) => {
console.log(err);
this.bindMobileBySmsCode()
}
})
},
bindMobileBySmsCode() {
uni.navigateTo({
url:'/pages/ucenter/edit/bind-mobile/bind-mobile'
})
},
setNickname(nickname) {
console.log(nickname);
if (nickname) {
usersTable.where('_id==$env.uid').update({
nickname
}).then(e => {
console.log(e);
if (e.result.updated) {
uni.showToast({
title: '更新成功',
icon: 'none'
});
this.setUserInfo({
nickname
});
} else {
uni.showToast({
title: '没有变化',
icon: 'none'
});
}
})
this.$refs.dialog.close()
} else {
this.$refs.dialog.open()
}
},
setAvatar() {
console.log('点击编辑信息');
uni.chooseImage({
count: 1,
success: (res) => {
// 头像剪裁尺寸
let options = {
width: 600,
height: 600
}
// 剪裁并上传头像
uni.navigateTo({
url: '/pages/ucenter/edit/uploadCutImageToUnicloud?path=' +
res
.tempFilePaths[0] +
`&options=${JSON.stringify(options)}`,
animationType: "fade-in",
events: {
uploadAvatarAfter: ({
url
}) => {
console.log(url);
// 使用 clientDB 提交数据
usersTable.where('_id==$env.uid').update({
avatar: url
}).then((res) => {
console.log(res);
uni.showToast({
icon: 'none',
title: '修改成功'
})
this.setUserInfo({
avatar: url
});
}).catch((err) => {
uni.showModal({
content: err.message ||
'请求服务失败',
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
}
}
});
}
})
},
}
}
</script>
<style>
.item {
width: 750rpx;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 60px;
}
.avatarUrl {
width: 50px;
height: 50px;
border-radius: 6px;
}
</style>
......@@ -5,7 +5,6 @@ page {
flex: 1;
height: 100%;
}
/* #endif */
.wrap {
/* #ifndef APP-NVUE */
......
......@@ -41,7 +41,7 @@
<script>
var univerify_first,currentWebview;//是否一键登陆优先
import baseappConfig from '@/baseapp.config.js';
import mixin from '../../common/loginPage.mixin.js';
import mixin from '../common/loginPage.mixin.js';
var currentPage;
export default {
mixins:[mixin],
......@@ -131,7 +131,7 @@ import mixin from '../../common/loginPage.mixin.js';
</script>
<style>
@import url("../../common/loginPage.css");
@import url("../common/loginPage.css");
.content-top-title {
text-align: center;
......
......@@ -28,7 +28,7 @@
</template>
<script>
import mixin from '../../common/loginPage.mixin.js';
import mixin from '../common/loginPage.mixin.js';
export default {
mixins:[mixin],
data() {
......@@ -101,7 +101,7 @@
</script>
<style>
@import url("../../common/loginPage.css");
@import url("../common/loginPage.css");
.phone-input-box{
margin-top: 10px;
}
......
......@@ -22,7 +22,8 @@
<uni-easyinput type="password" class="phone-input-box" :inputBorder="false"
v-model="formData.pwd" placeholder="请输入密码"></uni-easyinput>
</uni-forms-item>
<button class="send-btn-box" type="primary" @click="pwdLogin">登录</button>
<button class="send-btn-box" :disabled="!canLogin" :type="canLogin?'primary':'default'"
@click="pwdLogin">登录</button>
</uni-forms>
<!-- 忘记密码 -->
<view class="auth-box">
......@@ -36,7 +37,7 @@
</template>
<script>
import mixin from '../../common/loginPage.mixin.js';
import mixin from '../common/loginPage.mixin.js';
export default {
mixins:[mixin],
data() {
......@@ -47,7 +48,7 @@
},
computed: {
canLogin() {
return this.isPhone && this.isPwd;
return this.formData.phone.length && this.isPwd;
}
},
methods: {
......@@ -55,12 +56,12 @@
* 页面跳转,找回密码
*/
toRetrievePwd() {
if (!this.isPhone) return uni.showToast({
title: '请输入正确的手机号',
icon: 'none'
});
// if (!this.isPhone) return uni.showToast({
// title: '请输入正确的手机号',
// icon: 'none'
// });
uni.navigateTo({
url: '../pwd-retrieve/pwd-retrieve?phoneNumber=' + this.formData.phone + '&phoneArea=' + this.currenPhoneArea
url: '../pwd-retrieve/pwd-retrieve?phoneNumber=' + (this.isPhone?this.formData.phone:'') + '&phoneArea=' + this.currenPhoneArea
})
},
/**
......@@ -119,7 +120,7 @@
toRegister(e){
console.log(e);
uni.navigateTo({
url:'/uni_modules/uni-login-page/pages/register/register'
url:'/pages/ucenter/login-page/register/register'
})
}
}
......@@ -127,7 +128,7 @@
</script>
<style>
@import url("../../common/loginPage.css");
@import url("../common/loginPage.css");
.phone-input-box {
margin-top: 20rpx;
}
......
......@@ -8,11 +8,12 @@
<!-- 登录框 (选择手机号所属国家和地区需要另行实现) -->
<uni-forms ref="form" :value="formData" :rules="rules">
<uni-forms-item name="phone">
<uni-easyinput type="number" class="phone-input-box" :inputBorder="false"
<!-- focus规则如果上一页携带来“手机号码”数据就focus验证码输入框,否则focus手机号码输入框 -->
<uni-easyinput :focus="!formData.phone.length" type="number" class="phone-input-box" :inputBorder="false"
v-model="formData.phone" maxlength="11" placeholder="请输入手机号"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="code">
<uni-easyinput type="number" class="phone-input-box" :inputBorder="false"
<uni-easyinput :focus="formData.phone.length" type="number" class="phone-input-box" :inputBorder="false"
v-model="formData.code" maxlength="6" placeholder="请输入验证码">
<template slot="right">
<login-short-code ref="shortCode" :phone="formData.phone"></login-short-code>
......@@ -36,7 +37,7 @@
</template>
<script>
import mixin from '../../common/loginPage.mixin.js';
import mixin from '../common/loginPage.mixin.js';
export default {
mixins:[mixin],
data() {
......@@ -60,7 +61,7 @@ import mixin from '../../common/loginPage.mixin.js';
},
onReady() {
if(this.formData.phone){
// this.$refs.shortCode.start();
this.$refs.shortCode.start();
}
},
methods: {
......@@ -91,7 +92,7 @@ import mixin from '../../common/loginPage.mixin.js';
</script>
<style>
@import url("../../common/loginPage.css");
@import url("../common/loginPage.css");
.phone-input-box{
margin-top: 20rpx;
}
......
<template>
<view class="uni-container">
<uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="undertext">
<uni-forms-item name="username" label="用户名" required>
<uni-easyinput placeholder="请输入用户名" v-model="formData.username" trim="both" />
<uni-forms-item name="username" required>
<uni-easyinput :inputBorder="false" class="phone-input-box" placeholder="请输入用户名" v-model="formData.username" trim="both" />
</uni-forms-item>
<uni-forms-item name="nickname" label="昵称">
<uni-easyinput placeholder="请输入用户昵称" v-model="formData.nickname" trim="both" />
<uni-forms-item name="nickname">
<uni-easyinput :inputBorder="false" class="phone-input-box" placeholder="请输入用户昵称" v-model="formData.nickname" trim="both" />
</uni-forms-item>
<uni-forms-item name="password" label="密码" v-model="formData.password" required>
<uni-easyinput placeholder="请输入6-20位密码" type="password" v-model="formData.password" trim="both" />
<uni-forms-item name="password" v-model="formData.password" required>
<uni-easyinput :inputBorder="false" class="phone-input-box" placeholder="请输入6-20位密码" type="password" v-model="formData.password" trim="both" />
</uni-forms-item>
<uni-forms-item name="pwd2" label="确认密码" v-model="formData.pwd2" required>
<uni-easyinput placeholder="再次输入密码" type="password" v-model="formData.pwd2" trim="both" />
<uni-forms-item name="pwd2" v-model="formData.pwd2" required>
<uni-easyinput :inputBorder="false" class="phone-input-box" placeholder="再次输入密码" type="password" v-model="formData.pwd2" trim="both" />
</uni-forms-item>
<view class="uni-button-group">
<button type="primary" class="uni-button" @click="submit">注册并登陆</button>
</view>
<login-ikonw class="login-iknow" :link="link" text="登录即表示同意用户协议和隐私政策"></login-ikonw>
<button class="send-btn-box" type="primary" @click="submit">注册并登陆</button>
</uni-forms>
</view>
</template>
<script>
import rules from './validator.js';
import mixin from '../../common/loginPage.mixin.js';
import mixin from '../common/loginPage.mixin.js';
export default {
mixins:[mixin],
data() {
......@@ -69,6 +68,7 @@ import mixin from '../../common/loginPage.mixin.js';
</script>
<style>
@import url("../common/loginPage.css");
.uni-container {
padding: 15px;
}
......@@ -102,7 +102,6 @@ import mixin from '../../common/loginPage.mixin.js';
}
.uni-button {
width: 184px;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
......
<template>
<view class="content">
<!-- 功能列表 -->
<uni-list :border="false" class="mb10" v-for="(sublist,index) in agreeList">
<uni-list-item :border="false" class="mb1" v-for="(item,i) in sublist" :key="i" :title="item.title"
<uni-list :border="false" class="mt10" v-for="(sublist,index) in agreeList">
<uni-list-item :border="false" class="list-item" v-for="(item,i) in sublist" :key="i" :title="item.title"
:clickable="true" @click="itemClick(item)" :showSwitch="item.showSwitch" :switchChecked="item.isChecked"
:link="!item.showSwitch"></uni-list-item>
:link="!item.showSwitch"
v-if="item.event!='changePwd'||hasLogin"
></uni-list-item>
</uni-list>
<!-- 退出按钮 -->
<view class="bottom-back" @click="clickLogout">
<text class="bottom-back-text" v-if="userInfo">退出登录</text>
<text class="bottom-back-text" v-if="hasLogin">退出登录</text>
<text class="bottom-back-text" v-else>登录</text>
</view>
</view>
......@@ -56,7 +58,8 @@
},
computed: {
...mapGetters({
'userInfo': 'user/info'
'userInfo': 'user/info',
'hasLogin': 'user/hasLogin',
})
},
onLoad() {
......@@ -71,13 +74,14 @@
}),
toEdit() {
uni.navigateTo({
url: '/uni_modules/uni-id-users/pages/uni-id-users/edit'
url: '/pages/ucenter/edit/edit'
});
},
changePwd() {
uni.navigateTo({
url: '/uni_modules/uni-login-page/pages/pwd-retrieve/pwd-retrieve?phoneNumber=' + (this
.userInfo && this.userInfo.phone ? this.userInfo.phone : '') + '&phoneArea=+86',
url: '/pages/ucenter/login-page/pwd-retrieve/pwd-retrieve?phoneNumber='
+ (this.userInfo && this.userInfo.phone ? this.userInfo.phone : '')
+ '&phoneArea=+86',
fail: err => {
console.log(err);
}
......@@ -185,7 +189,7 @@
})
},
clickLogout() {
if (this.userInfo) {
if (this.hasLogin) {
uni.showModal({
title: '提示',
content: '是否退出登录',
......@@ -202,7 +206,7 @@
});
} else {
uni.navigateTo({
url: '/uni_modules/uni-login-page/pages/index/index'
url: '/pages/ucenter/login-page/index/index'
});
}
},
......@@ -314,15 +318,16 @@
font-size: 33rpx;
}
.mb10 {
margin-bottom: 10px;
.mt10 {
margin-top: 10px;
}
.content /deep/ .uni-list {
background-color: #F9F9F9;
}
.mb1 {
.list-item {
height: 50px;
margin-bottom: 1px;
}
</style>
<template>
<view class="center">
<view class="userInfo" @click="toEdit">
<image class="logo-img" :src="login ? (userInfo.avatar || avatarUrl) :avatarUrl"></image>
<view class="userInfo" @click="toUserInfo">
<image class="logo-img" :src="userInfo.avatar||avatarUrl"></image>
<view class="logo-title">
<text class="uer-name">{{login ? userInfo.nickname||userInfo.username||userInfo.mobile : '未登录'}}</text>
<text class="uer-name">{{userInfo.nickname||userInfo.username||userInfo.mobile||'未登录'}}</text>
<text class="go-login-navigat-arrow navigat-arrow" v-if="!login">&#xe65e;</text>
</view>
</view>
......@@ -83,7 +83,8 @@
}, {
title: '设置',
to: '/pages/ucenter/settings/settings'
}, {
}],
[{
title: '关于',
to: '/pages/ucenter/about/about'
}]
......@@ -92,7 +93,7 @@
},
onLoad() {
//#ifdef APP-PLUS
this.ucenterList[this.ucenterList.length - 1].unshift({
this.ucenterList[this.ucenterList.length - 2].unshift({
title: '检查更新',
rightText: this.appVersion.version + '-' + this.appVersion.versionCode,
event: 'checkVersion',
......@@ -106,7 +107,8 @@
login: 'user/hasLogin'
})
// #ifdef APP-PLUS
,appVersion() {
,
appVersion() {
return getApp().appVersion
}
// #endif
......@@ -131,7 +133,7 @@
async checkVersion() {
let res = await callCheckVersion()
console.log(res);
if(res.result.code == 0){
if (res.result.code == 0) {
uni.showToast({
title: res.result.message,
icon: 'none'
......@@ -139,54 +141,10 @@
}
checkUpdate()
},
toEdit() {
console.log('点击编辑信息');
// uni.navigateTo({
// url: '/uni_modules/uni-id-users/pages/uni-id-users/edit'
// })
const token = uni.getStorageSync('uni_id_token')
if(token){
uni.chooseImage({
count:1,
success:(res)=> {
// 头像剪裁尺寸
let options = {
width:600,
height:600
}
// 剪裁并上传头像
uni.navigateTo({
url:'/pages/ucenter/edit/uploadCutImageToUnicloud?path=' + res.tempFilePaths[0] + `&options=${JSON.stringify(options)}`,
animationType:"fade-in",
events:{
uploadAvatarAfter:({url})=>{
console.log(url);
// 使用 clientDB 提交数据
db.collection('uni-id-users').where('_id==$env.uid').update({avatar:url}).then((res) => {
console.log(res);
uni.showToast({
icon: 'none',
title: '修改成功'
})
this.setUserInfo({avatar:url});
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
}
}
});
}
})
}else{
toUserInfo() {
uni.navigateTo({
url:'/uni_modules/uni-login-page/pages/index/index'
url: '/pages/ucenter/edit/edit'
})
}
},
tapGrid(index) {
uni.showToast({
......@@ -233,11 +191,6 @@
title: msg,
icon: 'none'
});
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
......@@ -254,11 +207,9 @@
font-style: normal;
src: url('~@/static/text-icon.ttf') format('truetype');
}
page {
background-color: #f8f8f8;
}
/* #endif*/
/* 解决头条小程序字体图标不显示问题,因为头条运行时自动插入了span标签,且有全局字体 */
......@@ -266,15 +217,12 @@
text :not(view) {
font-family: texticons;
}
/* #endif */
.center {
flex: 1;
flex-direction: column;
background-color: #f8f8f8;
}
.userInfo {
width: 750rpx;
padding: 20rpx;
......@@ -283,25 +231,18 @@
flex-direction: column;
align-items: center;
}
/* .logo-hover {
opacity: 0.8;
} */
.logo-img {
width: 150rpx;
height: 150rpx;
border-radius: 150rpx;
border: solid 1px #FFFFFF;
}
.logo-title {
height: 150rpx;
flex: 1;
align-items: center;
justify-content: space-between;
flex-direction: row;
margin-left: 20rpx;
}
.uer-name {
......
// 上次启动时的用户信息
let userHistory = uni.getStorageSync('userInfo') || null;
let userHistory = uni.getStorageSync('userInfo') || {};
let state = {
/**
* 是否需要强制登录
*/
/* 是否需要强制登录 */
forcedLogin: false,
hasLogin: Boolean(userHistory),
info: userHistory
......@@ -22,20 +20,18 @@ let state = {
let _info = state.info;
state.info = Object.assign({}, _info, info);
state.hasLogin = true;
uni.setStorageSync('userInfo', info);
uni.setStorageSync('userInfo', state.info);
},
logout(state) {
state.info = null;
state.info = {};
state.hasLogin = false;
uni.setStorageSync('userInfo', null);
uni.setStorageSync('userInfo', {});
uni.setStorageSync('uni_id_token', '');
}
},
actions = {
}
export default {
state,
getters,
......
'use strict';
let uniID = require('uni-id')
const uniCaptcha = require('uni-captcha')
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id'
})._config
const db = uniCloud.database()
const dbCmd = db.command
exports.main = async (event, context) => {
......@@ -84,7 +88,7 @@ exports.main = async (event, context) => {
} : {
state: 0
})
if(res.type == 'register'){
if (res.type == 'register') {
await registerSuccess(res.uid)
}
return await uniIdLogCollection.add(logData)
......@@ -94,6 +98,46 @@ exports.main = async (event, context) => {
let res = {}
switch (event.action) {
case 'bind_mobile_by_univerify':
let {
appid, apiKey, apiSecret
} = uniIdConfig.service.univerify
let univerifyRes = await uniCloud.getPhoneNumber({
provider: 'univerify',
appid,
apiKey,
apiSecret,
access_token: params.access_token,
openid: params.openid
})
if (univerifyRes.code === 0) {
res = await uniID.bindMobile({
uid: params.uid,
mobile: univerifyRes.phoneNumber
})
res.mobile = univerifyRes.phoneNumber
}
break;
case 'bind_mobile_by_sms':
console.log({
uid: params.uid,
mobile: params.mobile,
code: params.code
});
let verifyCode = await uniID.verifyCode({
mobile: params.mobile,
code: params.code
})
if (verifyCode.code === 0) {
res = await uniID.bindMobile({
uid: params.uid,
mobile: params.mobile
})
} else {
res = verifyCode
}
console.log(res, verifyCode);
break;
case 'register':
let {
username, password, gender, nickname
......@@ -165,6 +209,14 @@ exports.main = async (event, context) => {
res = await uniID.logout(event.uniIdToken)
break;
case 'sendSmsCode':
//123546
return uniID.setVerifyCode({
mobile: params.mobile,
code:'123456'
})
// 简单限制一下客户端调用频率
const ipLimit = await db.collection('uni-verify').where({
ip: context.CLIENTIP,
......
{
"name": "user-center",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"uni-captcha": "file:../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"uni-config-center": "file:../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id": "file:../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id"
}
},
"../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha": {
"version": "0.1.0",
"license": "Apache-2.0"
},
"../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center": {
"version": "0.0.2",
"license": "Apache-2.0"
},
"../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id": {
"version": "3.0.12",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
},
"node_modules/uni-captcha": {
"resolved": "../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"link": true
},
"node_modules/uni-config-center": {
"resolved": "../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"link": true
},
"node_modules/uni-id": {
"resolved": "../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id",
"link": true
}
},
"dependencies": {
"uni-captcha": {
"version": "file:../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha"
},
"uni-config-center": {
"version": "file:../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
},
"uni-id": {
"version": "file:../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id",
"requires": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}
}
}
......@@ -9,8 +9,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"uni-captcha": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id": "file:../../../../uni-id/uniCloud/cloudfunctions/common/uni-id"
"uni-captcha": "file:../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"uni-config-center": "file:../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id": "file:../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id"
}
}
{
"name": "user",
"version": "1.0.0",
"lockfileVersion": 1,
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"uni-captcha": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id": "file:../../../../uni-id/uniCloud/cloudfunctions/common/uni-id"
}
},
"../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha": {},
"../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center": {},
"../../../../uni-id/uniCloud/cloudfunctions/common/uni-id": {
"dependencies": {
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
},
"../../../../uni-id/uniCloud/cloudfunctions/common/uni-id/node_modules/uni-config-center": {
"resolved": "../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"link": true
},
"node_modules/uni-captcha": {
"resolved": "../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"link": true
},
"node_modules/uni-config-center": {
"resolved": "../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"link": true
},
"node_modules/uni-id": {
"resolved": "../../../../uni-id/uniCloud/cloudfunctions/common/uni-id",
"link": true
}
},
"dependencies": {
"uni-captcha": {
"version": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha"
......
......@@ -2,7 +2,7 @@
"bsonType": "object",
"required": ["user_id", "title", "content"],
"permission": {
"read": "doc.uid == auth.uid && doc.article_status == 0 || doc.article_status == 1",
"read": "doc.article_status == 0 || doc.article_status == 1",
"create": "auth.uid != null",
"update": "doc.uid == auth.uid",
"delete": "doc.uid == auth.uid"
......
......@@ -8,9 +8,9 @@
</view>
</template>
</uni-forms-item>
<uni-forms-item name="gender" label="性别" required>
<!-- <uni-forms-item name="gender" label="性别" required>
<uni-data-checkbox v-model="formData.gender" :localdata="formOptions.gender_localdata" />
</uni-forms-item>
</uni-forms-item> -->
<uni-forms-item name="mobile" label="手机号码" v-if="formData.mobile">
<uni-easyinput placeholder="手机号码" :disabled="true" v-model="formData.mobile" trim="both" />
</uni-forms-item>
......
{
"id": "uni-login-page",
"displayName": "uni-login-page",
"version": "1.0.0",
"description": "uni-login-page",
"keywords": [
"uni-login-page"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"前端页面模板",
"前端页面模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"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"
}
}
}
}
}
\ No newline at end of file
# uni-login-page
\ No newline at end of file
{
"name": "user-center",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"uni-captcha": {
"version": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha"
},
"uni-config-center": {
"version": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
},
"uni-id": {
"version": "file:../../../../uni-id/uniCloud/cloudfunctions/common/uni-id",
"requires": {
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
},
"dependencies": {
"uni-config-center": {
"version": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}
}
}
}
## 1.3.0(2021-04-13)
修复某些情况下uni-popup-dialog输入框的值获取失败的问题
## 1.2.9(2021-02-05)
- 优化 组件引用关系,通过uni_modules引用组件
## 1.2.8(2021-02-05)
......
......@@ -5,7 +5,7 @@
</view>
<view class="uni-dialog-content">
<text class="uni-dialog-content-text" v-if="mode === 'base'">{{content}}</text>
<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus">
<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" >
</view>
<view class="uni-dialog-button-group">
<view class="uni-dialog-button" @click="close">
......@@ -15,19 +15,11 @@
<text class="uni-dialog-button-text uni-button-color">确定</text>
</view>
</view>
<view v-if="popup.isDesktop" class="uni-popup-dialog__close" @click="close">
<span class="uni-popup-dialog__close-icon "></span>
</view>
<!-- #ifdef H5 -->
<keypress @esc="close" @enter="onOk"/>
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress.js'
// #endif
/**
* PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式
......@@ -50,11 +42,6 @@
export default {
name: "uniPopupDialog",
components: {
// #ifdef H5
keypress
// #endif
},
props: {
value: {
type: [String, Number],
......@@ -139,10 +126,11 @@
* 点击确认按钮
*/
onOk() {
this.$emit('confirm', () => {
if (this.mode === 'input'){
this.$emit('confirm', this.val)
}else{
this.popup.close()
if (this.mode === 'input') this.val = this.value
}, this.mode === 'input' ? this.val : '')
}
},
/**
* 点击取消按钮
......@@ -160,10 +148,10 @@
}
</script>
<style lang="scss" scoped>
<style scoped>
.uni-popup-dialog {
width: 300px;
border-radius: 5px;
border-radius: 15px;
background-color: #fff;
}
......@@ -217,9 +205,6 @@
justify-content: center;
align-items: center;
height: 45px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-border-left {
......@@ -233,7 +218,7 @@
}
.uni-button-color {
color: $uni-color-primary;
color: #007aff;
}
.uni-dialog-input {
......@@ -242,49 +227,18 @@
}
.uni-popup__success {
color: $uni-color-success;
color: #4cd964;
}
.uni-popup__warn {
color: $uni-color-warning;
color: #f0ad4e;
}
.uni-popup__error {
color: $uni-color-error;
color: #dd524d;
}
.uni-popup__info {
color: #909399;
}
.uni-popup-dialog__close {
/* #ifndef APP-NVUE */
display: block;
cursor: pointer;
/* #endif */
position: absolute;
top: 9px;
right: 17px;
}
.uni-popup-dialog__close-icon {
/* #ifndef APP-NVUE */
display: inline-block;
/* #endif */
width: 13px;
height: 1px;
background: #909399;
transform: rotate(45deg);
}
.uni-popup-dialog__close-icon::after {
/* #ifndef APP-NVUE */
content: '';
display: block;
/* #endif */
width: 13px;
height: 1px;
background: #909399;
transform: rotate(-90deg);
}
</style>
\ No newline at end of file
......@@ -31,7 +31,12 @@
bottomData: [{
text: '微信',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
name: 'weixin'
name: 'wx'
},
{
text: '支付宝',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
name: 'wx'
},
{
text: 'QQ',
......@@ -41,12 +46,17 @@
{
text: '新浪',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
name: 'sinaweibo'
name: 'sina'
},
{
text: '复制链接',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
text: '百度',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
name: 'copy'
},
{
text: '其他',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
name: 'more'
}
]
}
......
{
"id": "uni-popup",
"displayName": "PopUp 弹出层",
"version": "1.2.9",
"version": "1.3.0",
"description": " Popup 组件,提供常用的弹层",
"keywords": [
"popup",
......
## 1.1.0(2021-04-22)
- 新增 通过方法自定义动画
- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
- 优化 动画触发逻辑,使动画更流畅
- 优化 支持单独的动画类型
- 优化 文档示例
## 1.0.2(2021-02-05)
- 调整为uni_modules目录规范
// const defaultOption = {
// duration: 300,
// timingFunction: 'linear',
// delay: 0,
// transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation')
// #endif
class MPAnimation {
constructor(options, _this) {
this.options = options
this.animation = uni.createAnimation(options)
this.currentStepAnimates = {}
this.next = 0
this.$ = _this
}
_nvuePushAnimates(type, args) {
let aniObj = this.currentStepAnimates[this.next]
let styles = {}
if (!aniObj) {
styles = {
styles: {},
config: {}
}
} else {
styles = aniObj
}
if (animateTypes1.includes(type)) {
if (!styles.styles.transform) {
styles.styles.transform = ''
}
let unit = ''
if(type === 'rotate'){
unit = 'deg'
}
styles.styles.transform += `${type}(${args+unit}) `
} else {
styles.styles[type] = `${args}`
}
this.currentStepAnimates[this.next] = styles
}
_animateRun(styles = {}, config = {}) {
let ref = this.$.$refs['ani'].ref
if (!ref) return
return new Promise((resolve, reject) => {
nvueAnimation.transition(ref, {
styles,
...config
}, res => {
resolve()
})
})
}
_nvueNextAnimate(animates, step = 0, fn) {
let obj = animates[step]
if (obj) {
let {
styles,
config
} = obj
this._animateRun(styles, config).then(() => {
step += 1
this._nvueNextAnimate(animates, step, fn)
})
} else {
this.currentStepAnimates = {}
typeof fn === 'function' && fn()
this.isEnd = true
}
}
step(config = {}) {
// #ifndef APP-NVUE
this.animation.step(config)
// #endif
// #ifdef APP-NVUE
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
this.next++
// #endif
return this
}
run(fn) {
// #ifndef APP-NVUE
this.$.animationData = this.animation.export()
this.$.timer = setTimeout(() => {
typeof fn === 'function' && fn()
}, this.$.durationTime)
// #endif
// #ifdef APP-NVUE
this.isEnd = false
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
this.next = 0
// #endif
}
}
const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
'translateZ'
]
const animateTypes2 = ['opacity', 'backgroundColor']
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
MPAnimation.prototype[type] = function(...args) {
// #ifndef APP-NVUE
this.animation[type](...args)
// #endif
// #ifdef APP-NVUE
this._nvuePushAnimates(type, args)
// #endif
return this
}
})
export function createAnimation(option, _this) {
if(!_this) return
clearTimeout(_this.timer)
return new MPAnimation(option, _this)
}
<template>
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
@click="change">
<slot></slot>
</view>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
/**
import { createAnimation } from './createAnimation'
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
......@@ -25,7 +21,7 @@
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
*/
export default {
export default {
name: 'uniTransition',
props: {
show: {
......@@ -33,9 +29,9 @@
default: false
},
modeClass: {
type: Array,
default () {
return []
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
......@@ -44,19 +40,24 @@
},
styles: {
type: Object,
default () {
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
ani: { in: '',
active: ''
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
};
},
watch: {
show: {
......@@ -64,217 +65,212 @@
if (newVal) {
this.open()
} else {
// 避免上来就执行 close,导致动画错乱
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
// 生成样式数据
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transfrom = ''
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transfrom += line + ':' + styles[i] + ';'
transform += line + ':' + styles[i] + ';'
}
return transfrom
return transform
},
// 初始化动画条件
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
// this.timer = null
// this.nextTick = (time = 50) => new Promise(resolve => {
// clearTimeout(this.timer)
// this.timer = setTimeout(resolve, time)
// return this.timer
// });
// 动画默认配置
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
change() {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj))
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
open() {
clearTimeout(this.timer)
this.isShow = true
this.transform = ''
this.ani.in = ''
for (let i in this.getTranfrom(false)) {
if (i === 'opacity') {
this.ani.in = 'fade-in'
} else {
this.transform += `${this.getTranfrom(false)[i]} `
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return
for (let i in obj) {
try {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
} catch (e) {
console.error(`方法 ${i} 不存在`)
}
this.$nextTick(() => {
setTimeout(() => {
this._animation(true)
}, 50)
})
}
this.animation.step(config)
return this
},
close(type) {
clearTimeout(this.timer)
this._animation(false)
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
this.animation.run(fn)
},
_animation(type) {
let styles = this.getTranfrom(type)
// #ifdef APP-NVUE
if(!this.$refs['ani']) return
animation.transition(this.$refs['ani'].ref, {
styles,
duration: this.duration, //ms
timingFunction: 'ease',
needLayout: false,
delay: 0 //ms
}, () => {
if (!type) {
this.isShow = false
// 开始过度动画
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
this.$nextTick(() => {
// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
this.timer = setTimeout(() => {
this.animation = createAnimation(this.config, this)
this.tranfromInit(false).step()
this.animation.run()
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
// #endif
// #ifndef APP-NVUE
this.transform = ''
for (let i in styles) {
if (i === 'opacity') {
this.ani.in = `fade-${type?'out':'in'}`
} else {
this.transform += `${styles[i]} `
}
}
this.timer = setTimeout(() => {
if (!type) {
},
// 关闭过度动画
close(type) {
if (!this.animation) return
this.tranfromInit(true)
.step()
.run(() => {
this.isShow = false
}
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
}, this.duration)
// #endif
})
},
getTranfrom(type) {
// 处理动画开始前的默认样式
styleInit(type) {
let styles = {
transform: ''
}
this.modeClass.forEach((mode) => {
switch (mode) {
case 'fade':
styles.opacity = type ? 1 : 0
break;
case 'slide-top':
styles.transform += `translateY(${type?'0':'-100%'}) `
break;
case 'slide-right':
styles.transform += `translateX(${type?'0':'100%'}) `
break;
case 'slide-bottom':
styles.transform += `translateY(${type?'0':'100%'}) `
break;
case 'slide-left':
styles.transform += `translateX(${type?'0':'-100%'}) `
break;
case 'zoom-in':
styles.transform += `scale(${type?1:0.8}) `
break;
case 'zoom-out':
styles.transform += `scale(${type?1:1.2}) `
break;
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
_modeClassArr(type) {
let mode = this.modeClass
if (typeof(mode) !== "string") {
let modestr = ''
mode.forEach((item) => {
modestr += (item + '-' + type + ',')
})
return modestr.substr(0, modestr.length - 1)
// 处理内置组合动画
tranfromInit(type) {
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
return mode + '-' + type
}
},
// getEl(el) {
// console.log(el || el.ref || null);
// return el || el.ref || null
// },
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
}
}
}
</script>
<style>
.uni-transition {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: transform, opacity;
z-index: 998;
}
.fade-in {
opacity: 0;
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
.fade-active {
opacity: 1;
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
.slide-top-in {
/* transition-property: transform, opacity; */
transform: translateY(-100%);
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
.slide-top-active {
transform: translateY(0);
/* opacity: 1; */
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
.slide-right-in {
transform: translateX(100%);
}
.slide-right-active {
transform: translateX(0);
this.animation[this.animationMode()[mode]](aniNum)
}
.slide-bottom-in {
transform: translateY(100%);
}
.slide-bottom-active {
transform: translateY(0);
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
.slide-left-in {
transform: translateX(-100%);
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
.slide-left-active {
transform: translateX(0);
opacity: 1;
},
// 内置动画类型与实际动画对应字典
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
.zoom-in-in {
transform: scale(0.8);
},
// 驼峰转中横线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
.zoom-out-active {
transform: scale(1);
}
}
</script>
.zoom-out-in {
transform: scale(1.2);
}
</style>
<style></style>
{
"id": "uni-transition",
"displayName": "Transition 过渡动画",
"version": "1.0.2",
"version": "1.1.0",
"description": "元素的简单过渡动画",
"keywords": [
"动画",
......
## Transition 过渡动画
> **组件名:uni-transition**
> 代码块: `uTransition`
元素的简单过渡动画,组件名:`uni-transition`
元素过渡动画
> **注意事项**
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
> - 组件需要依赖 `sass` 插件 ,请自行手动安装
> - rotate 旋转动画不需要填写 deg 单位,在小程序上填写单位动画不会执行
> - NVUE 下修改宽高动画,不能定位到中心点
> - 百度小程序下修改宽高 ,可能会影响其他动画,需注意
> - nvue 不支持 costom-class , 请使用 styles
> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
### 安装方式
......@@ -19,18 +30,13 @@
```html
<template>
<view>
<button type="primary">fade</button>
<uni-transition :mode-class="['fade']" :styles="{'width':'100px','height':'100px';'backgroundColor':'red'}" :show="show" @change="change" />
<button type="primary" @click="open">fade</button>
<uni-transition mode-class="fade" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" @change="change" />
</view>
</template>
```
``` javascript
import uniTransition from '@/components/uni-transition/uni-transition.vue'
<script>
export default {
components: {
uniTransition
},
data() {
return {
show: false,
......@@ -45,22 +51,135 @@ export default {
console.log('触发动画')
}
}
}
</script>
```
### 样式覆盖
**注意:`nvue` 不支持 `custom-class` 属性 ,需要使用 `styles` 属性进行兼容**
使用 `custom-class` 属性绑定样式,可以自定义 `uni-transition` 的样式
```html
<template>
<view class="content">
<uni-transition custom-class="custom-transition" mode-class="fade" :duration="0" :show="true" />
</view>
</template>
<style>
/* 常规样式覆盖 */
.content >>> .custom-transition {
width:100px;
height:100px;
background-color:red;
}
</style>
<style lang="scss">
/* 如果使用 scss 需要使用 /deep/ */
.content /deep/ .custom-transition {
width:100px;
height:100px;
background-color:red;
}
</style>
```
如果使用 `styles` 注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
```html
<template>
<view class="content">
<uni-transition :styles="styles" mode-class="fade" :duration="0" :show="true" />
</view>
</template>
<script>
export default {
data() {
return {
styles:{
'width':'100px',
'height':'100px',
'backgroundColor':'red'
}
}
}
}
</script>
```
### 自定义动画
当内置动画类型不能满足需求的时候 ,可以使用 `step()``run()` 自定义动画,入参以及具体用法参考下方属性说明
`init()` 方法可以覆盖默认配置
```html
<template>
<view>
<button type="primary" @click="run">执行动画</button>
<uni-transition ref="ani" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" />
</view>
</template>
<script>
export default {
data() {
return {
show: true,
}
},
onReady() {
this.$refs.ani.init({
duration: 1000,
timingFunction: 'linear',
transformOrigin: '50% 50%',
delay: 500
})
},
methods: {
run() {
// 同时右平移到 100px,旋转 360 读
this.$refs.ani.step({
translateX: '100px',
rotate: '360'
})
// 上面的动画执行完成后,等待200毫秒平移到 0px,旋转到 0 读
this.$refs.ani.step({
translateX: '0px',
rotate: '0'
},
{
timingFunction: 'ease-in',
duration: 200
})
// 开始执行动画
this.$refs.ani.run(()=>{
console.log('动画支持完毕')
})
}
}
}
</script>
```
## API
### Transition Props
|属性名 |类型 |默认值 |说明 |
|:-: |:-: |:-: |:-:|
|show |Boolean|false |控制组件显示或隐藏, |
|modeClass |Array |- |过渡动画类型 |
|show |Boolean|false |控制组件显示或隐藏 |
|mode-class |Array/String |- |内置过渡动画类型 |
|custom-class |String |- |自定义类名 |
|duration |Number |300 |过渡动画持续时间 |
|styles |Object |- |组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red` |
#### modeClass 类型说明
**格式为**`['fade','slide-top']`
#### mode-class 内置过渡动画类型说明
**格式为**`'fade'` 或者 `['fade','slide-top']`
|属性名 |说明 |
|:-: |:-: |
......@@ -78,7 +197,211 @@ export default {
### Transition Events
|事件称名 |说明 |返回值 |
|事件 |说明 |返回值 |
|:-: |:-: |:-: |
|click |点击组件触发 |- |
|change |过渡动画结束时触发 | e = {detail:true} |
### Transition Methons
|方法名|说明|参数|
|:-:|:-:|:-:|
|init()|手动初始化配置|Function(OBJECT:config)|
|step()|动画队列|Function(OBJECT:type,OBJECT:config)|
|run()|执行动画|Function(FUNCTION:callback) |
### init(OBJECT:config)
**通过 ref 调用方法**
手动设置动画配置,需要在页面渲染完毕后调用
```javascript
this.$refs.ani.init({
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### step(OBJECT:type,OBJECT:config) 动画队列
**通过 ref 调用方法**
调用 `step()` 来表示一组动画完成,`step` 第一个参数可以传入任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。`step` 第二个参数可以传入一个跟 `uni.createAnimation()` 一样的配置参数用于指定当前组动画的配置。
Tips
- 第一个参数支持的动画参考下面的 `支持的动画`
- 第二个参数参考下面的 `动画配置`,可省略,如果省略继承`init`的配置
```javascript
this.$refs.ani.step({
translateX: '100px'
},{
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### run(FUNCTION:callback) 执行动画
**通过 ref 调用方法**
在执行 `step()` 后,需要调用 `run()` 来运行动画 ,否则动画会一直等待
`run()` 方法可以传入一个 `callback` 函数 ,会在所有动画执行完毕后回调
```javascript
this.$refs.ani.step({
translateX: '100px'
})
this.$refs.ani.run(()=>{
console.log('动画执行完毕')
})
```
### 动画配置
动画配置 , `init()``step()` 第二个参数配置相同 ,如果配置`step() `第二个参数,将会覆盖 `init()` 的配置
|属性名|值|必填|默认值|说明|平台差异|
|:-:|:-:|:-:|:-:|:-:|:-:|
|duration|Number|否|400|动画持续时间,单位ms|-|
|timingFunction|String|否|"linear"|定义动画的效果|-|
|delay|Number|否|0|动画延迟时间,单位 ms|-|
|needLayout|Boolean|否|false |动画执行是否影响布局|仅 nvue 支持|
|transformOrigin|String |否|"center center"|设置 [transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)|-|
### timingFunction 属性说明
|值|说明|平台差异|
|:-:|:-:|:-:|
|linear|动画从头到尾的速度是相同的|-|
|ease|动画以低速开始,然后加快,在结束前变慢|-|
|ease-in| 动画以低速开始|-|
|ease-in-out| 动画以低速开始和结束|-|
|ease-out|动画以低速结束|-|
|step-start|动画第一帧就跳至结束状态直到结束|nvue不支持|
|step-end|动画一直保持开始状态,最后一帧跳到结束状态|nvue不支持|
```javascript
// init 配置
this.$refs.ani.init({
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
// step 配置
this.$refs.ani.step({
translateX: '100px'
},{
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### 支持的动画
动画方法
如果同一个动画方法有多个值,多个值使用数组分隔
```javascript
this.$refs.ani.step({
width:'100px',
scale: [1.2,0.8],
})
```
**样式:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|opacity|value|透明度,参数范围 0~1|-|
|backgroundColor|color|颜色值|-|
|width|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
|height|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
|top|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
|left|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
|bottom|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
|right|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
```javascript
this.$refs.ani.step({
opacity: 1,
backgroundColor: '#ff5a5f',
widht:'100px',
height:'50rpx',
})
```
**旋转:**
旋转属性的值不需要填写单位
|属性名|值|说明|平台差异 |
|:-:|:-:|:-:|:-:|
|rotate|deg|deg的范围-180~180,从原点顺时针旋转一个deg角度 |-|
|rotateX|deg|deg的范围-180~180,在X轴旋转一个deg角度 |-|
|rotateY|deg|deg的范围-180~180,在Y轴旋转一个deg角度 |-|
|rotateZ|deg|deg的范围-180~180,在Z轴旋转一个deg角度 |nvue不支持|
|rotate3d|x,y,z,deg| 同 [transform-function rotate3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d()) |nvue不支持|
```javascript
this.$refs.ani.step({
rotateX: 45,
rotateY: 45
})
```
**缩放:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-: |:-:|
|scale|sx,[sy]|一个参数时,表示在X轴、Y轴同时缩放sx倍数;两个参数时表示在X轴缩放sx倍数,在Y轴缩放sy倍数|-|
|scaleX|sx|在X轴缩放sx倍数|-|
|scaleY|sy|在Y轴缩放sy倍数|-|
|scaleZ|sz|在Z轴缩放sy倍数|nvue不支持|
|scale3d|sx,sy,sz|在X轴缩放sx倍数,在Y轴缩放sy倍数,在Z轴缩放sz倍数|nvue不支持|
```javascript
this.$refs.ani.step({
scale: [1.2,0.8]
})
```
**偏移:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|translate|tx,[ty]|一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。|-|
|translateX|tx| 在X轴偏移tx,单位px|-|
|translateY|ty| 在Y轴偏移tx,单位px|-|
|translateZ|tz| 在Z轴偏移tx,单位px|nvue不支持|
|translate3d|tx,ty,tz| 在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px|nvue不支持|
```javascript
this.$refs.ani.step({
translateX: '100px'
})
```
**倾斜:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|skew|ax,[ay]|参数范围-180~180;一个参数时,Y轴坐标不变,X轴坐标延顺时针倾斜ax度;两个参数时,分别在X轴倾斜ax度,在Y轴倾斜ay度|nvue不支持|
|skewX|ax| 参数范围-180~180;Y轴坐标不变,X轴坐标延顺时针倾斜ax度|nvue不支持|
|skewY|ay| 参数范围-180~180;X轴坐标不变,Y轴坐标延顺时针倾斜ay度|nvue不支持|
**矩阵变形:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|matrix|(a,b,c,d,tx,ty)|同 [transform-function matrix](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix())|nvue不支持|
|matrix3d|同 [transform-function matrix3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d())|nvue不支持|
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册