Commit 3f5cb448 吴良建

第一次提交

0 个父辈
正在显示 186 个修改的文件 包含 4929 行增加0 行删除
node_modules/
unpackage/
dist/**
package/android/HBuilder-Integrate-AS/simpleDemo/src/main/assets/apps/**
package/android/HBuilder-Integrate-AS/simpleDemo/release/**
.project
.DS_Store
.hbuilderx/
.vite/
<script>
import common from '@/utils/common.js'
import http from '@/utils/http.js'
import app_config from '@/utils/app.js'
import loginHelper from '@/utils/loginHelper.js'
import {
transformImageCodeToUri
} from "@/utils/image_utils.js";
export default {
data() {
return {
common,
timer: null
}
},
onLaunch: async function() {
console.log('App Launch')
// #ifdef APP-PLUS
plus.screen.lockOrientation("portrait-primary") //关闭横屏
var code = common.getChannelCode();
app_config.app_info.PromoterId = code;
console.log(app_config.app_info.PromoterId);
// #endif
//获取导航栏高度
uni.getSystemInfo({
success: (e) => {
// #ifdef APP-PLUS
if (e.statusBarHeight === 0) {
common.statusBarH = 33
} else {
common.statusBarH = e.statusBarHeight
}
// #endif
// #ifdef H5
common.statusBarH = 10
// #endif
// #ifdef MP-WEIXIN
common.statusBarH = e.statusBarHeight + 20
// #endif
// if (e.platform === 'android' || e.platform === 'ios') {
// common.customBarH = e.statusBarHeight + 55
// } else {
// common.customBarH = e.statusBarHeight + 50
// }
}
})
//获取配置
// let local_ic = await uni.getStorageSync('info_config_key')
// if (local_ic.length > 0) {
// common.info_config = JSON.parse(local_ic)
// }
// console.debug('---0000------', common.info_config)
// let ic_res = await http.gql({
// query: 'query{info_config}'
// })
// let info_config = ic_res.data.info_config
// if (info_config) {
// common.info_config = info_config
// await uni.setStorageSync('info_config_key', JSON.stringify(info_config))
// console.log(common.info_config);
// } else {
// console.debug('---获取后台配置失败---')
// }
},
onShow: function() {
console.log('App Show')
// 检查当前上网环境
uni.getNetworkType({
complete: function(res) {
if (res.networkType == "none") {
setTimeout(() => {
uni.showToast({
icon: "none",
title: "网络异常,请检查网络设置!",
duration: 2000,
position: "bottom",
});
}, 200);
}
},
});
this.antoLogin();
this.timer = setInterval(this.antoLogin, 9 * 60 * 1000)
},
onHide: function() {
console.log('App Hide')
clearInterval(this.timer)
},
methods: {
async antoLogin() {
var appToken = loginHelper.getAppToken() || ""
console.log("antoLogin " + JSON.stringify(appToken))
if (appToken) {
var mac_code = uni.getSystemInfoSync().deviceId
var time = new Date().getTime() + ""
let query_data = `mutation{
ydn_auto_login(token:${JSON.stringify(appToken)},mac_code:${JSON.stringify(mac_code)},t:${JSON.stringify(time)})
}`;
console.log(query_data)
let result = await http.gql({
query: query_data
})
console.log(result)
if (result && result.data && result.data.ydn_auto_login) {
if (!result.data.ydn_auto_login.Error) {
result.data.ydn_auto_login.Result.FaceImageCode = transformImageCodeToUri(result.data
.ydn_auto_login.Result
.FaceImageCode);
loginHelper.login(result.data.ydn_auto_login
.Result,result.data.ydn_auto_login.AppToken)
} else {
loginHelper.logout()
}
}
} else {
loginHelper.logout()
}
}
}
}
</script>
<style>
/*每个页面公共css */
</style>
<template>
<view>
<!-- <web-view :src="url" fullscreen='false'></web-view> -->
</view>
</template>
<script>
import {
default as app_config
} from '@/utils/app.js';
import common from '@/utils/common.js'
import loginHelper from '../utils/loginHelper.js'
var wv; //计划创建的webview
var nwating;
export default {
name: "customWebview",
data() {
return {
url: this.src
};
},
props: {
src: {
type: String,
default: () => ""
},
top: {
type: Number,
default: () => 0
},
height: {
type: Number,
default: () => uni.getSystemInfoSync().windowHeight
}
},
created() {
uni.$on("loginStatus", function(arg) {
if(arg) {
wv.reload()
console.log("loginStatus:" + arg)
}
})
let appInfo = app_config.app_info;
let header = {
AppVersion: encodeURI(JSON.stringify(appInfo))
}
// #ifdef APP-PLUS
nwating = plus.nativeUI.showWaiting();
wv = plus.webview.create("", "normal_h5-webview", {
additionalHttpHeaders: {
header: header,
},
plusrequire: "none", //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止
'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
top: this.top,
height: this.height
})
let pages = getCurrentPages()
let currentPage = pages[pages.length - 1]
var currentWebview = currentPage.$getAppWebview() //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
currentWebview.append(wv);
console.log(header)
wv.loadURL(this.url, header);
wv.addEventListener('loaded', function () {
// wv.evalJS("$(\".header\").hide();");
console.log("load---")
nwating.close();
wv.show();
}, false);
var _this = this;
wv.overrideUrlLoading({
effect: "touchstart",
mode: "allow",
match: "^https:\/\/app\.ydniu\.com\/experts\/(kl8|sd|pl3|ssq|dlt|pl5|zq)\?zqe&app_header=true$"
// exclude: "redirect"
}, (e) => {
console.log('----请求拦截了------', e.url + "--" + _this.url)
if (e.url === _this.url) {
console.log("reload")
wv.reload();
} else if (e.url.indexOf("login") !== -1) {
// 前端检测到未登录,需要登录,说明当前登录信息已经失效,清除登录信息
loginHelper.logout()
console.log('-------拦截请求login', e.url)
uni.navigateTo({
url: `/pages/login_pwd/login_pwd`
})
} else if ((e.url.indexOf("?zq") !== -1 || e.url.indexOf("user/payment") !== -1) && e.url
.startsWith("http")) {
console.log('-------拦截请求?zq', e.url)
let tempData = {
url: e.url
}
uni.navigateTo({
url: `/pages/notitle_webview/notitle_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
} else if (e.url.indexOf("?ydn_back") !== -1 ||
e.url === 'https://app.ydniu.com/' ||
e.url === 'https://app.ydniu.com' ||
e.url === 'https://app.ydniu.com/sports' ||
e.url.startsWith("https://app.ydniu.com/?")) {
console.log('-------拦截请求ydn_back', e.url)
uni.navigateBack({})
} else if (e.url.startsWith("weixin") || e.url.startsWith("alipay")) {
console.log('-------拦截请求weixin', e.url)
plus.runtime.openURL(e.url, err => {
uni.showToast({
title: '打开失败!请检查是否已安装',
icon: 'none'
});
});
} else if (e.url.startsWith("ydncp")) {
var urlStr = e.url.substring("ydncp:".length, e.url.length);
let tempData = {
url: e.url,
}
uni.navigateTo({
url:'/pages/notitle_webview/notitle_webview'
})
uni.navigateTo({
url: `/pages/notitle_webview/notitle_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
} else {
console.log('-------拦截请求tempData', e.url)
let tempData = {
url: e.url,
}
uni.navigateTo({
url: `/pages/notitle_webview/notitle_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
}
console.log('----请求拦截了End------', e.url)
})
// #endif
},
mounted() {
},
methods: {
onRefreshInfo(data) {
console.log(data)
this.url = data
nwating = plus.nativeUI.showWaiting();
wv.loadURL(this.url)
}
}
}
</script>
<style>
</style>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
Vue.config.productionTip = false
App.mpType = 'app'
try {
function isPromise(obj) {
return (
!!obj &&
(typeof obj === "object" || typeof obj === "function") &&
typeof obj.then === "function"
);
}
// 统一 vue2 API Promise 化返回格式与 vue3 保持一致
uni.addInterceptor({
returnValue(res) {
if (!isPromise(res)) {
return res;
}
return new Promise((resolve, reject) => {
res.then((res) => {
if (res[0]) {
reject(res[0]);
} else {
resolve(res[1]);
}
});
});
},
});
} catch (error) { }
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
\ No newline at end of file
{
"name" : "ydnApp",
"appid" : "__UNI__B008CD1",
"description" : "一定牛",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {},
/* SDK配置 */
"sdkConfigs" : {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": false
}
}, {
"path": "pages/mine/mine",
"style": {
"navigationBarTitleText": "我的",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/open/open",
"style": {
"navigationBarTitleText": "开奖",
"enablePullDownRefresh": false
}
}, {
"path": "pages/expert/expert",
"style": {
"navigationBarTitleText": "专家",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/notitle_webview/notitle_webview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/normal_webview/normal_webview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/logout/logout",
"style": {
"navigationBarTitleText": "账号注销",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#FFFFFF"
}
},
{
"path": "pages/login_pwd/login_pwd",
"style": {
"navigationBarTitleText": "账号登录",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/login_yzm/login_yzm",
"style": {
"navigationBarTitleText": "验证码登录",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}
,{
"path" : "pages/settings/settings",
"style" :
{
"navigationBarTitleText": "设置",
"enablePullDownRefresh": false,
"backgroundColor": "#000000"
}
}
,{
"path" : "pages/xingqu/xingqu",
"style" :
{
"navigationBarTitleText": "选择感兴趣的内容",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"backgroundColor": "#F5F5F5"
}
}
,{
"path" : "pages/suggest/suggest",
"style" :
{
"navigationBarTitleText": "提建议",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}
,{
"path" : "pages/security_center/security_center",
"style" :
{
"navigationBarTitleText": "安全中心",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}
,{
"path" : "pages/number_book/number_book",
"style" :
{
"navigationBarTitleText": "号码本",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/bind_card/bind_card",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "一定牛",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"backgroundColor": "#F8F8F8",
"selectedColor": "#0a1b31",
"color": "#999999",
"list": [{
"text": "首页",
"iconPath": "static/tab_icons/bottom_home_normal.webp",
"selectedIconPath": "static/tab_icons/bottom_home_press.webp",
"pagePath": "pages/index/index"
},
{
"text": "开奖",
"iconPath": "static/tab_icons/bottom_open_normal.webp",
"selectedIconPath": "static/tab_icons/bottom_open_press.webp",
"pagePath": "pages/open/open"
},
{
"text": "专家",
"iconPath": "static/tab_icons/bottom_talk_normal.webp",
"selectedIconPath": "static/tab_icons/bottom_talk_press.webp",
"pagePath": "pages/expert/expert"
},
{
"text": "我的",
"iconPath": "static/tab_icons/bottom_user_normal.webp",
"selectedIconPath": "static/tab_icons/bottom_user_press.webp",
"pagePath": "pages/mine/mine"
}
]
},
"uniIdRouter": {}
}
<template>
<view style="background-color: #f5f5f5; height: 100vh;">
<view class="title_bg" :style="'padding-top:' + (common.statusBarH + 10)+ 'px; '">
<image style="width: 40rpx; height: 40rpx;" src='../../static/common/icon_back.png' @click="onBack()">
</image>
<text style="color: white; font-size: 36rpx; font-weight: 700; margin-left: 15rpx;">绑定身份证</text>
<image style="width: 40rpx; height: 40rpx;">
</image>
</view>
<view :style="'height: ' + titleHeight + 'px'"></view>
<view style="font-size: 32rpx; color: #393939; padding: 20rpx; margin-bottom: 3rpx; background-color: white;">
<text>用于实名认证,修改个人信息.非常非常重要。</text>
</view>
<view class="item">
<text class="text1">&nbsp;&nbsp;&nbsp;名:</text>
<view class="input-class">
<input placeholder="请填写真实姓名"/>
</view>
</view>
<view class="item">
<text class="text1">身份证:</text>
<view class="input-class" >
<input type="idcard" :value="idCard" placeholder="请填写身份证号" />
</view>
</view>
<button :class="userInfo.IdCard ? 'un-button-class' : 'button-class'">{{userInfo.IdCard ? "无法修改" : "修改"}}</button>
</view>
</template>
<script>
import common from '@/utils/common.js'
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
titleHeight: 60,
common,
idCard: "",
userInfo: {}
}
},
onReady() {
var this_ = this
uni.createSelectorQuery()
.in(this)
.select('.title_bg')
.boundingClientRect((rect) => {
if (rect) {
this_.titleHeight = rect.height
console.log("rect.height:" + rect.height)
}
})
.exec();
this.userInfo = loginHelper.getUserInfo()
this.idCard = this.userInfo.IdCard
},
methods: {
}
}
</script>
<style>
.title_bg {
background: linear-gradient(90deg, #FF6F38 0%, #FFA04B 100%);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24rpx;
padding-right: 24rpx;
padding-bottom: 20rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
}
.item {
display: flex;
align-items: center;
padding: 20rpx;
background-color: white;
}
.text1 {
color: #393939;
font-size: 32rpx;
}
.input-class {
border: 2px solid #F39801;
border-radius: 6rpx;
background-color: white;
flex: 1;
padding: 15rpx;
}
.button-class {
margin: 30rpx;
background-color: #F39801;
}
.un-button-class {
margin: 30rpx;
background-color: #7a7a7a;
}
</style>
<template>
<view>
<view :style="'height:' + common.statusBarH + 'px;'"></view>
<v-tabs class="tab_c" v-model="current" :tabs="tabs" @change="changeTab" :fixed="true" line-height="8rpx"
line-color="#04764E" color="#AAAAAA" activeColor="#04764E" height="88rpx"></v-tabs>
<customWebview :src="tabsUrl[current]" :top="webview_top" :height="webview_height" ref="Webview">
</customWebview>
</z-swiper>
</view>
</template>
<script>
import customWebview from '../../components/customWebview.vue'
import common from '@/utils/common.js'
export default {
components: {
customWebview
},
data() {
return {
common,
tabs: ["快乐8", "福彩3D", "排列3", "双色球", "大乐透", "排列5", "足球"],
current: 0,
webview_top: 0,
webview_height: uni.getSystemInfoSync().windowHeight,
tabsUrl: [
'https://app.ydniu.com/experts/kl8?zqe&app_header=true',
'https://app.ydniu.com/experts/sd?zqe&app_header=true',
'https://app.ydniu.com/experts/pl3?zqe&app_header=true',
'https://app.ydniu.com/experts/ssq?zqe&app_header=true',
'https://app.ydniu.com/experts/dlt?zqe&app_header=true',
'https://app.ydniu.com/experts/pl5?zqe&app_header=true',
'https://app.ydniu.com/experts/zq?zqe&app_header=true'
]
}
},
onLoad() {
this.webview_top = 88
this.webview_height = uni.getSystemInfoSync().safeArea.bottom - this.webview_top
},
methods: {
changeTab(index) {
console.log('当前选中的项:' + index)
var ref = this.$refs.Webview
this.current = index
console.log(this.$refs.Webview)
ref.onRefreshInfo(this.tabsUrl[this.current])
}
}
}
</script>
<style>
.tab_c {
/* position: fixed; */
z-index: 999;
}
</style>
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
<template>
<view>
<view class="head-bg" :style="{'padding-top': statusBarHeight +'px'}">
<view style="align-items: center; display: flex; width: 100v; height: 5vh;">
<image src="../../static/common/icon_back.png" style="width: 34rpx; height: 34rpx; padding: 25rpx;"
v-on:click="onBack()" />
<text style="margin-left: 10rpx; color: white; align-self: center; font-size: 40rpx;">账号密码登陆</text>
</view>
</view>
<view class="input-group" style="margin-left: 35rpx; margin-right: 35rpx;">
<view class="input-row border">
<input class="m-input" type="text" clearable focus v-model="username" placeholder="请输入用户名/手机号"
style="padding-top: 20rpx; padding-bottom: 20rpx;" />
<view style=" height: 1px; background: #C6C6C6; "></view>
</view>
<view class="input-row border" style="padding-top: 10rpx;">
<input type="password" displayable v-model="password" placeholder="请输入密码"
style="padding-top: 20rpx; padding-bottom: 20rpx;" />
<view style=" height: 1px; background: #C6C6C6; "></view>
</view>
</view>
<view style="margin-top: 15rpx; margin-left: 35rpx;" @click="gotoCodeLogin()">
<text style="color: #4169E1; font-size: 28rpx;">切换验证码登陆</text>
</view>
<view class="btn-row">
<button style="background-color: transparent; color: white; " :loading="loginBtnLoading" @tap="bindLogin">
登录
</button>
</view>
<view style=" margin-left: 35rpx; display: flex; margin-top: 35rpx; align-items: center;">
<view @click="checkboxSelected()" :checked="agreeState"
:class="agreeState === true ? 'checkbox-check' : 'checkbox-uncheck'" />
<text style="font-size: 28rpx; color: #333333;">阅读并同意</text>
<text style="color: #4d90ff; font-size: 28rpx;" @click="onUserAgreement()">用户协议</text>
<text style="font-size: 28rpx; color: #333333;"></text>
<text style="color: #4d90ff; font-size: 28rpx;" @click="onPrivacyPolicy()">隐私政策</text>
</view>
</view>
</template>
<script>
import {
transformImageCodeToUri
} from "@/utils/image_utils.js";
import {
default as http
} from "@/utils/http.js";
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
agreeState: false,
username: "",
password: "",
loginBtnLoading: false,
}
},
methods: {
async bindLogin() {
if (this.username.length < 3) {
uni.showToast({
icon: "none",
title: "账号最短为 3 个字符",
});
return;
}
if (this.password.length < 4) {
uni.showToast({
icon: "none",
title: "密码最短为 4 个字符",
});
return;
}
if (!this.agreeState) {
uni.showToast({
icon: "none",
title: "您还没有同意用户协议",
});
return;
}
this.loginBtnLoading = true;
let query_data = `mutation{
ydn_login(name:${JSON.stringify(this.username)},pass:${JSON.stringify(this.password)})
}`;
let result = await http.gql({
query: query_data
})
this.loginBtnLoading = false;
//处理返回请求
console.log("result:" + JSON.stringify(result))
if (result && result.data && result.data.ydn_login) {
if (!result.data.ydn_login.Error) {
result.data.ydn_login.Result.FaceImageCode = transformImageCodeToUri(result.data.ydn_login
.Result
.FaceImageCode);
loginHelper.login(result.data.ydn_login.Result , result.data.ydn_login.AppToken)
console.log("login")
uni.navigateBack();
return
} else {
uni.showToast({
icon: "none",
title: result.data.ydn_login.Error,
});
}
} else {
uni.showToast({
icon: "none",
title: "登录异常",
});
return;
}
},
onBack() {
uni.navigateBack()
},
gotoCodeLogin() {
uni.redirectTo({
url: '/pages/login_yzm/login_yzm'
})
},
checkboxSelected(e) {
this.agreeState = !this.agreeState;
},
onUserAgreement() {
let tempData = {
url: 'http://www.qianhaiyilan.cn/ppolicy_user.html',
title: "用户协议"
}
uni.navigateTo({
url: `/pages/normal_webview/normal_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
},
onPrivacyPolicy() {
let tempData = {
url: 'http://www.qianhaiyilan.cn/ppolicy_app.html',
title: "隐私政策"
}
uni.navigateTo({
url: `/pages/normal_webview/normal_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
}
}
}
</script>
<style>
</style>
<style>
.login-type-btn.act {
color: #ecab80;
border-bottom: solid 1px #ecab80;
}
.send-code-btn {
width: 120px;
text-align: center;
background-color: #ecab80;
color: #ffffff;
margin: 12px;
padding: 4px;
}
.action-row {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 15px;
}
.oauth-row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.oauth-image {
position: relative;
width: 50px;
height: 50px;
border: 1px solid #dddddd;
border-radius: 50px;
background-color: #ffffff;
}
.oauth-image image {
width: 30px;
height: 30px;
margin: 10px;
}
.oauth-image button {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.btn-row {
margin-top: 15px;
margin-left: 35rpx;
margin-right: 35rpx;
background: linear-gradient(to right, #58B8FF, #32CDFF);
border-radius: 15rpx;
}
.head-bg {
flex-direction: column;
background: url('~@/static/login/head_zm.webp');
background-color: transparent;
background-repeat: no-repeat;
background-size: 50% 100%;
width: 100vh;
height: 15vh;
display: flex;
}
.uni-status-bar {
// width: 750rpx;
height: 20px;
// height: var(--status-bar-height);
}
.checkbox-check {
background-image: url(../../static/common/authsdk_checkbox_checked_bg.png);
background-repeat: no-repeat;
background-size: cover;
margin-right: 15rpx;
width: 35rpx;
height: 35rpx;
}
.checkbox-uncheck {
background-image: url(../../static/common/authsdk_checkbox_uncheck_bg.png);
width: 35rpx;
height: 35rpx;
margin-right: 15rpx;
background-repeat: no-repeat;
background-size: cover;
}
.m-input::input-placeholder {
color: #0000EE;
}
</style>
<template>
<view>
<view class="head-bg" :style="{'padding-top': statusBarHeight +'px'}">
<view style="align-items: center; display: flex; width: 100vh; height: 5vh;">
<image src="../../static/common/icon_back.png" style="width: 34rpx; height: 34rpx; padding: 25rpx;"
v-on:click="onBack()" />
<text style="margin-left: 10rpx; color: white; font-size: 40rpx;">验证码登陆</text>
</view>
</view>
<view class="input-group" style="margin-left: 35rpx; margin-right: 35rpx;">
<view class="input-row border">
<input class="m-input" type="text" clearable focus v-model="phoneNumber" placeholder="请输入手机号"
style="padding-top: 20rpx; padding-bottom: 20rpx;" />
<view style=" height: 1px; background: #C6C6C6; "></view>
</view>
<view class="input-row border" style=" display: flex; padding-top: 30rpx; padding-bottom: 20rpx;">
<input type="number" displayable v-model="phone_code" placeholder="请输入验证码" />
<button size="mini" style="background-color: #787878; font-size: 20; color: #FFFFFF; "
@click="getPhoneCode()" :disabled="disabled">{{phoneCodeStr}}</button>
</view>
<view style="height: 1px; background: #C6C6C6;"></view>
</view>
<view style="margin-top: 15rpx; margin-left: 35rpx;" @click="gotoAccountLogin()">
<text style="color: #4169E1; font-size: 28rpx;">切换密码登陆</text>
</view>
<view class="btn-row">
<button style="background-color: transparent; color: white; " :loading="loginBtnLoading" @tap="bindLogin">
登录
</button>
</view>
<view style=" margin-left: 35rpx; display: flex; margin-top: 35rpx; align-items: center;">
<view @click="checkboxSelected()" :checked="agreeState"
:class="agreeState === true ? 'checkbox-check' : 'checkbox-uncheck'" />
<text style="font-size: 28rpx; color: #333333;">阅读并同意</text>
<text style="color: #4d90ff; font-size: 28rpx;" @click="onUserAgreement()">用户协议</text>
<text style="font-size: 28rpx; color: #333333;"></text>
<text style="color: #4d90ff; font-size: 28rpx;" @click="onPrivacyPolicy()">隐私政策</text>
</view>
</view>
</template>
<script>
import {
transformImageCodeToUri
} from "@/utils/image_utils.js";
import {
default as http
} from "@/utils/http.js";
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
disabled: false,
phoneCodeStr: "获取验证码",
phoneCodeTime: 60,
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
phoneNumber: "",
password: "",
phone_code: "",
loginBtnLoading: false,
timer: null,
agreeState: false,
}
},
methods: {
async getPhoneCode() {
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
var this_ = this;
if (this.phoneNumber.length != 11) {
uni.showToast({
icon: "none",
title: "请输入手机号码",
});
return;
}
if (!myreg.test(this.phoneNumber)) {
uni.showToast({
icon: "none",
title: "电话号码格式不对",
});
return;
}
this.phoneCodeTime = 60;
this.timer = setInterval(() => {
console.log(this_.phoneCodeTime)
if (this_.phoneCodeTime <= 0) {
clearInterval(this_.timer);
this_.phoneCodeStr = "获取验证码";
this_.disabled = false;
} else {
this_.phoneCodeStr = this_.phoneCodeTime + "s";
this_.phoneCodeTime--;
this_.disabled = true;
}
}, 1000);
this_.disabled = true;
let query_data = `query{
getMobileCode(mobile:${JSON.stringify(this.phoneNumber)},type:7)
}`;
let result = await http.gql({
query: query_data
})
console.info(result);
//处理返回请求
if (result && result.data && result.data.getMobileCode) {
if (result.data.getMobileCode.Error) {
clearInterval(this.timer);
this_.disabled = false;
uni.showToast({
icon: "none",
title: result.data.getMobileCode.Error,
});
} else {
}
} else {
clearInterval(this.timer);
this_.disabled = false;
uni.showToast({
icon: "none",
title: "请求异常",
});
return;
}
},
async bindLogin() {
if (this.phoneNumber.length < 11) {
uni.showToast({
icon: "none",
title: "请输入手机号码",
});
return;
}
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
if (!myreg.test(this.phoneNumber)) {
uni.showToast({
icon: "none",
title: "电话号码格式不对",
});
return;
}
if (this.phone_code.length <= 0) {
uni.showToast({
icon: "none",
title: "请输入验证码",
});
return;
}
if (!this.agreeState) {
uni.showToast({
icon: "none",
title: "您还没有同意用户协议",
});
return;
}
this.loginBtnLoading = true;
let query_data = `mutation{
ydn_sms_login(mobile:${JSON.stringify(this.phoneNumber)},code:${JSON.stringify(this.phone_code)},type:"web")
}`;
let result = await http.gql({
query: query_data
})
this.loginBtnLoading = false;
console.info(result);
//处理返回请求
if (result && result.data && result.data.ydn_sms_login) {
if (result.data.ydn_sms_login.Error) {
uni.showToast({
icon: "none",
title: result.data.ydn_sms_login.Error,
});
} else {
result.data.ydn_sms_login.Result.FaceImageCode = transformImageCodeToUri(result.data
.ydn_sms_login.Result
.FaceImageCode);
loginHelper.login(result.data.ydn_sms_login.Result,result.data.ydn_sms_login.AppToken)
uni.navigateBack();
}
} else {
uni.showToast({
icon: "none",
title: "登录异常",
});
return;
}
},
onBack() {
uni.navigateBack()
},
gotoAccountLogin() {
uni.redirectTo({
url: '/pages/login_pwd/login_pwd'
})
},
onUserAgreement() {
let tempData = {
url: 'http://www.qianhaiyilan.cn/ppolicy_user.html',
title: "用户协议"
}
uni.navigateTo({
url: `/pages/normal_webview/normal_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
},
onPrivacyPolicy() {
let tempData = {
url: 'http://www.qianhaiyilan.cn/ppolicy_app.html',
title: "隐私政策"
}
uni.navigateTo({
url: `/pages/normal_webview/normal_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
},
checkboxSelected(e) {
this.agreeState = !this.agreeState;
}
}
}
</script>
<style>
.action-row {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 15rpx;
}
.btn-row {
margin-top: 15rpx;
margin-left: 35rpx;
margin-right: 35rpx;
background: linear-gradient(to right, #FDB559, #FF7E31);
border-radius: 15rpx;
}
.head-bg {
flex-direction: column;
background-image: url('~@/static/login/head.png');
background-size: 50% 100%;
width: 100vh;
height: 15vh;
display: flex;
background-color: transparent;
background-repeat: no-repeat;
}
.checkbox-check {
background-image: url(../../static/common/authsdk_checkbox_checked_bg.png);
background-repeat: no-repeat;
background-size: cover;
margin-right: 15rpx;
width: 30rpx;
height: 30rpx;
}
.checkbox-uncheck {
background-image: url(../../static/common/authsdk_checkbox_uncheck_bg.png);
width: 30rpx;
height: 30rpx;
margin-right: 15rpx;
background-repeat: no-repeat;
background-size: cover;
}
</style>
<template>
<view style="padding-left: 4%; padding-right: 4%; padding-top: 4%;">
<view style="display: flex; ">
<text space="emsp" style="font-size: 35rpx;">手机号</text>
<text style="margin-left: 25rpx; font-size: 35rpx;">{{phoneNume}}</text>
</view>
<view style="height: 2rpx; background-color: #eeeeee; margin-top: 5rpx; margin-bottom: 20rpx;"></view>
<view style="display: flex; align-items: center;">
<text space="emsp" style="font-size: 35rpx;">密 码</text>
<input style="font-size: 35rpx; margin-left: 25rpx;" password type="text" v-model="pwd"
placeholder="请输入密码" />
</view>
<view style="height: 2rpx; background-color: #eeeeee; margin-top: 5rpx; margin-bottom: 20rpx;"></view>
<view style="align-content: center; width: 100%;">
<text style="color: #D4383D; font-size: 22rpx;">账号注销后该账户下所有信息将被清除</text>
</view>
<button style="margin-top: 8%; background-color: #2a0d5c; border-radius: 13rpx; color: white;"
@click="bindLogout()">确实注销</button>
</view>
</template>
<script>
import http from "@/utils/http";
import loginHelper from '../../utils/loginHelper.js'
export default {
data() {
return {
pwd: "",
phoneNume: ""
}
},
onLoad: function(){
console.info("onLoad")
this.phoneNume = "******" + loginHelper.getUserInfo().Mobile.substring(7);
},
methods: {
bindLogout() {
{
this.logoutLogin();
}
},
async logoutLogin() {
if (this.pwd.length <= 0) {
uni.showToast({
icon: "none",
title: "请输入密码",
});
return;
}
let query_data = `mutation{
info_update_user(user:{ user_status:"-1"})
{
error
success
error_type
}
}`;
console.info(query_data);
let result = await http.gql({
query: query_data
})
this.loginBtnLoading = false;
console.info(result);
//处理返回请求
if (result && result.data && result.data.info_update_user &&
!result.data.info_update_user.error) {
loginHelper.logout();
uni.navigateBack();
} else {
uni.showToast({
icon: "none",
title: "注销异常",
});
return;
}
}
}
}
</script>
<style>
</style>
此文件的差异被折叠, 点击展开。
<template>
<view>
<web-view :src="url"></web-view>
</view>
</template>
<script>
import { default as app_config } from '@/utils/app.js';
import common from '@/utils/common.js'
var wv;//计划创建的webview
export default {
data() {
return {
app_config,
url: '',
}
},
methods: {
},
onLoad(val) {
let data = JSON.parse(decodeURIComponent(val.info))
this.url = data.url
if (data.title) {
uni.setNavigationBarTitle({
title: data.title
})
}
},
onReady() {
let appInfo = app_config.app_info;
let header = {
AppVersion: encodeURI(JSON.stringify(appInfo))
}
// #ifdef APP-PLUS
var nwating = plus.nativeUI.showWaiting();
wv = plus.webview.create("", "normal_h5-webview", {
additionalHttpHeaders: {
header: header,
},
plusrequire: "none", //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止
'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
top: common.customBarH,
height: uni.getSystemInfoSync().windowHeight
})
let pages = getCurrentPages()
let currentPage = pages[pages.length - 1]
var currentWebview = currentPage.$getAppWebview() //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
currentWebview.append(wv);
wv.loadURL(this.url, header);
wv.addEventListener('loaded', function () {
// wv.evalJS("$(\".header\").hide();");
nwating.close();
wv.show();
}, false);
// #endif
}
}
</script>
<style>
</style>
<template>
<view>
<customWebview :src="url" :top="webview_top" :height="webview_height"></customWebview>
</view>
</template>
<script>
import customWebview from '../../components/customWebview.vue'
import {
default as app_config
} from '@/utils/app.js';
import common from '@/utils/common.js'
var wv; //计划创建的webview
export default {
components: {
customWebview
},
data() {
return {
url: '',
webview_top: 0,
webview_height: uni.getSystemInfoSync().windowHeight,
}
},
methods: {
},
onLoad(val) {
let data = JSON.parse(decodeURIComponent(val.info))
this.url = data.url
if (data.title) {
uni.setNavigationBarTitle({
title: data.title
})
}
if (uni.getSystemInfoSync().platform == "ios") {
/*
获取顶部安全区域的高度 安卓的顶部区域为0 ios的是实际大小
*/
let safeTopArea = uni.getSystemInfoSync().platform == 'ios' ? uni.getSystemInfoSync().safeAreaInsets.top :
0;
//获取底部安全区域的高度
let safeBoottom = uni.getSystemInfoSync().safeAreaInsets.bottom;
this.webview_top = - safeTopArea
this.webview_height = uni.getSystemInfoSync().windowHeight + safeBoottom + safeTopArea
console.log(this.webview_top)
} else {
this.webview_top = common.customBarH + uni.getSystemInfoSync().navigationBarHeight,
this.webview_height = uni.getSystemInfoSync().windowHeight
}
},
onReady() {
},
methods : {
}
}
</script>
<style>
</style>
<template>
<view>
<view class="title_bg" :style="'padding-top:' + (common.statusBarH + 10)+ 'px; '">
<image style="width: 40rpx; height: 40rpx;" src='../../static/common/icon_back.png' @click="onBack()">
</image>
<text style="color: white; font-size: 36rpx; font-weight: 700; margin-left: 15rpx;">我的号码本</text>
<image style="width: 40rpx; height: 40rpx;">
</image>
</view>
<view :style="'height: ' + titleHeight + 'px'"></view>
</view>
</template>
<script>
import common from '@/utils/common.js'
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
titleHeight: 60,
common,
idCard: "",
userInfo: {}
}
},
onReady() {
var this_ = this
uni.createSelectorQuery()
.in(this)
.select('.title_bg')
.boundingClientRect((rect) => {
if (rect) {
this_.titleHeight = rect.height
console.log("rect.height:" + rect.height)
}
})
.exec();
this.userInfo = loginHelper.getUserInfo()
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.title_bg {
background: linear-gradient(90deg, #FF6F38 0%, #FFA04B 100%);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24rpx;
padding-right: 24rpx;
padding-bottom: 20rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
}
</style>
<template>
<view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>
<template>
<view style="background-color: #f5f5f5; height: 100vh;">
<view class="title_bg" :style="'padding-top:' + (common.statusBarH + 10)+ 'px; '">
<image style="width: 40rpx; height: 40rpx;" src='../../static/common/icon_back.png' @click="onBack()">
</image>
<text style="color: white; font-size: 36rpx; font-weight: 700; margin-left: 15rpx;">安全中心</text>
<image style="width: 40rpx; height: 40rpx;">
</image>
</view>
<view :style="'height: ' + titleHeight + 'px'"></view>
<view class="data-item" @click="goToShare()">
<text>身份证</text>
<view style="display: flex; justify-content: center; align-items: center;">
<text :class="userInfo.IdCard ? 'text2' : 'text1'">{{userInfo.Mobile ? "已绑定" : "绑定身份证,账号更安全"}}</text>
<image style="width: 28rpx; height: 28rpx; margin-left: 15rpx;" src="../../static/arrow_right.png">
</image>
</view>
</view>
<view class="data-item" @click="goToShare()">
<text>手机</text>
<view style="display: flex; justify-content: center; align-items: center;">
<text :class="userInfo.Mobile ? 'text2' : 'text1'">{{userInfo.Mobile ? "已绑定" : "绑定手机"}}</text>
<image style="width: 28rpx; height: 28rpx; margin-left: 15rpx;" src="../../static/arrow_right.png">
</image>
</view>
</view>
<view class="data-item" @click="goToShare()">
<text>修改密码</text>
<view style="display: flex; justify-content: center; align-items: center;">
<text class="text1">修改登录密码</text>
<image style="width: 28rpx; height: 28rpx; margin-left: 15rpx;" src="../../static/arrow_right.png">
</image>
</view>
</view>
</view>
</template>
<script>
import common from '@/utils/common.js'
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
titleHeight: 80,
common,
userInfo: {}
}
},
onReady() {
var this_ = this
uni.createSelectorQuery()
.in(this)
.select('.title_bg')
.boundingClientRect((rect) => {
if (rect) {
this_.titleHeight = rect.height
console.log("rect.height:" + rect.height)
}
})
.exec();
this.userInfo = loginHelper.getUserInfo()
},
onShow() {
},
methods: {
}
}
</script>
<style>
.title_bg {
background: linear-gradient(90deg, #FF6F38 0%, #FFA04B 100%);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24rpx;
padding-right: 24rpx;
padding-bottom: 20rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
}
.data-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 110rpx;
background-color: white;
margin-top: 3rpx;
margin-bottom: 3rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.text1 {
font-size: 30rpx;
color: #B0B0B0;
}
.text2 {
font-size: 30rpx;
color: #666666;
}
</style>
<template>
<view>
<view class="data-item">
<text>弹窗开关</text>
<switch checked @change="switchChange"></switch>
</view>
<view v-show="isApp" class="data-item" @click="clearCache()">
<text>清理缓存</text>
<view>
<text style="margin-right: 30rpx;">{{currentSize}}</text>
<image style="width: 28rpx; height: 28rpx;" src="../../static/arrow_right.png"></image>
</view>
</view>
<view class="data-item" @click="goToShare()">
<text>好友分享</text>
<image style="width: 28rpx; height: 28rpx;" src="../../static/arrow_right.png"></image>
</view>
<view class="data-item" @click="goToStop()">
<text>店主认证资料</text>
<image style="width: 28rpx; height: 28rpx;" src="../../static/arrow_right.png"></image>
</view>
<view v-show="isApp" class="data-item" @click="showUpdateVersion()">
<text>版本检测和更新</text>
<view>
<text style="font-size: 27rpx; margin-right: 15rpx;">{{this.updateInfoStr}}</text>
<image style="width: 28rpx; height: 28rpx;" src="../../static/arrow_right.png"></image>
</view>
</view>
<button style="background-color: white; margin: 35rpx; color: #469bf4;" @click="bindLogout()">
{{ this.hasLogin ? "退出登录" : '登陆/注册' }}</button>
</view>
</template>
<script>
import {
default as http
} from "@/utils/http.js";
import {
updateUseModal,
compare
} from '@/utils/check_update.js';
import {
default as app_config
} from '@/utils/app.js';
import loginHelper from "../../utils/loginHelper.js"
export default {
data() {
return {
app_config,
hasLogin: false,
updateInfoStr: "已是最新版本",
versionData: null,
versionName: app_config.app_info.AppName,
currentSize: "",
isApp: false
}
},
onShow() {
this.hasLogin = loginHelper.hasLogin()
console.log("onShow");
// #ifdef APP
this.updateVersion();
this.getStorageSize()
this.isApp = true;
// #endif
},
methods: {
goToStop() {
if(this.hasLogin) {
let tempData = {
url: `${app_config.server_url.app_host}eshop/center/adv?zq`
}
uni.navigateTo({
url: `/pages/notitle_webview/notitle_webview?info=${encodeURIComponent(JSON.stringify(tempData))}`
})
} else {
uni.navigateTo({
url: '/pages/login_pwd/login_pwd',
});
}
},
goToShare() {
},
clearCache() {
let that = this;
let os = plus.os.name;
if (os == 'Android') {
let main = plus.android.runtimeMainActivity();
let sdRoot = main.getCacheDir();
let files = plus.android.invoke(sdRoot, "listFiles");
let len = files.length;
console.log(files, len)
for (let i = 0; i < len; i++) {
let filePath = '' + files[i]; // 没有找到合适的方法获取路径,这样写可以转成文件路径
plus.io.resolveLocalFileSystemURL(filePath, function(entry) {
if (entry.isDirectory) {
entry.removeRecursively(function(entry) { //递归删除其下的所有文件及子目录
that.files = []
uni.showToast({
title: '清除成功',
duration: 2000
});
that.getStorageSize(); // 重新计算缓存
}, function(e) {
console.log(e.message)
});
} else {
entry.remove();
}
}, function(e) {
console.log('文件路径读取失败')
});
}
} else { // ios
plus.cache.clear(function() {
uni.showToast({
title: '清除成功',
duration: 2000
});
that.getStorageSize();
});
}
},
// 获取本地缓存大小
getStorageSize() {
// #ifdef APP
let that = this;
plus.cache.calculate(function(size) {
let sizeCache = parseInt(size);
if (sizeCache == 0) {
that.currentSize = "0B";
} else if (sizeCache < 1024) {
that.currentSize = sizeCache + "B";
} else if (sizeCache < 1048576) {
that.currentSize = (sizeCache / 1024).toFixed(2) + "KB";
} else if (sizeCache < 1073741824) {
that.currentSize = (sizeCache / 1048576).toFixed(2) + "MB";
} else {
that.currentSize = (sizeCache / 1073741824).toFixed(2) + "GB";
}
});
// #endif
},
bindLogout() {
{
loginHelper.logout();
uni.reLaunch({
url: '/pages/mine/mine'
})
}
},
onLogout() {
if (!loginHelper.hasLogin()) {
uni.navigateTo({
url: '/pages/login_pwd/login_pwd',
});
} else {
uni.navigateTo({
url: "/pages/logout/logout",
});
}
},
showUpdateVersion() {
if (this.versionData) {
updateUseModal({
title: "更新",
contents: this.versionData.Version_Content || '',
is_mandatory: false,
url: this.versionData.Package_Url,
platform: 'android',
type: "pkg" // 安装包类型
});
}
},
async updateVersion() {
let appInfo = app_config.app_info;
// #ifdef APP-PLUS
let query_data = `query{
update_app_version(App_Code:${JSON.stringify(appInfo.Version)}) {
App_Code
App_Name
Sys_Code
Sys_Name
Version_Code
Version_Type
Version_Content
Package_Url
Package_Weight
Version_Num
Update_Way
Download_Way
Update_Time
Publish_Time
Sys_Version
Promoter_Id
}
}`;
console.info(query_data);
let result = await http.gql({
query: query_data
})
console.info(result);
//处理返回请求
if (result && result.data && result.data.update_app_version) {
if (result.data.update_app_version.Error) {
uni.showToast({
icon: "none",
title: result.data.update_app_version.Error,
});
} else {
this.versionData = result.data.update_app_version;
if (this.versionData && this.versionData.Package_Url) {
this.updateInfoStr = "更新版本";
} else {
this.updateInfoStr = "已是最新版本";
}
}
}
// #endif
// #ifdef MP-WEIXIN
this.versionName = app_config.app_info.AppName
this.updateInfoStr = appInfo.Version
// #endif
},
switchChange(e) {
}
}
}
</script>
<style>
.data-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 110rpx;
background-color: white;
margin-top: 3rpx;
margin-bottom: 3rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
</style>
<template>
<view style="background-color: #F5F5F5; min-height: 100vh; height: 100%;">
<view class="title_bg" :style="'padding-top:' + (common.statusBarH + 10)+ 'px; '">
<image style="width: 40rpx; height: 40rpx;" src='../../static/common/icon_back.png' @click="onBack()">
</image>
<text style="color: white; font-size: 36rpx; font-weight: 700;">提建议</text>
<text style="color: white; font-size: 32rpx;" v-on:click="commit()">提交</text>
</view>
<view :style="'height: ' + titleHeight + 'px'"></view>
<view class="input-c">
<textarea class="suggest-input" maxlength="-1" focus placeholder="请具体描述你的问题或建议(至少15字)"
placeholder-style="color:#999999" v-model="suggest_content" />
</view>
<view style="margin-top: 48rpx; margin-left: 22rpx;">
<text style="color: #999999; font-size: 28rpx;">我的建议</text>
</view>
<view v-for="(item, index) in suggestData" class="suggest-item">
<view v-for="(content, index) in item.Data">
<view v-if="!content.IsReply" class="suggest-content-text">
<text>{{content.Content}}</text>
</view>
<view v-else class="suggest-repet-content-text">
<text>{{content.Content}}</text>
<text>{{"回复时间:" + content.InitTime}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import common from '@/utils/common.js'
import http from "@/utils/http";
export default {
data() {
return {
titleHeight: 80,
common,
suggestData: [],
suggest_content: ""
}
},
async onLoad() {
let query_data = `query{
getMySuggest(pageSize:30,pageIndex:1,typeId:-1,orderExp:"Id desc",time:"Month|3")
}`;
console.log(query_data)
let result = await http.gql({
query: query_data
})
//处理返回请求
if (result && result.data && result.data.getMySuggest &&
result.data.getMySuggest.Result &&
!result.data.getMySuggest.error) {
var array = result.data.getMySuggest.Result.Rows
for (var i = 0; i < array.length; i++) {
this.getMySuggestById(array[i].Id)
}
}
},
onReady() {
var this_ = this
uni.createSelectorQuery()
.in(this)
.select('.title_bg')
.boundingClientRect((rect) => {
if (rect) {
this_.titleHeight = rect.height
}
})
.exec();
},
onShow() {
},
methods: {
onBack() {
uni.navigateBack()
},
async getMySuggestById(id) {
let query_data = `query{
getSuggestById(id:${id})
}`;
console.log(query_data)
let result = await http.gql({
query: query_data
})
//处理返回请求
if (result && result.data && result.data.getSuggestById &&
result.data.getSuggestById.Result &&
!result.data.getSuggestById.error) {
var bean = JSON.parse(result.data.getSuggestById.Result)
this.suggestData.push(bean)
}
},
async commit() {
console.log("commit")
if (this.suggest_content.length < 5) {
uni.showToast({
icon: "none",
title: "最短为 5 个字符",
});
return;
}
let query_data = `mutation{
user_suggest_info(content:${JSON.stringify(this.suggest_content)})
}`;
console.log(query_data)
let result = await http.gql({
query: query_data
})
console.info(result);
//处理返回请求
if (result && result.data && result.data.user_suggest_info &&
!result.data.user_suggest_info.error) {
uni.showToast({
icon: "none",
title: "提交成功",
});
uni.navigateBack()
} else {
uni.showToast({
icon: "none",
title: "提交失败",
});
}
}
}
}
</script>
<style>
.title_bg {
background: linear-gradient(90deg, #FF6F38 0%, #FFA04B 100%);
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 24rpx;
padding-right: 24rpx;
padding-bottom: 20rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
}
.input-c {
min-height: 300rpx;
background-color: white;
padding: 20rpx;
}
.suggest-input {
color: #616161;
font-size: 28rpx;
width: 100%;
}
.suggest-item {
padding: 15rpx;
background-color: white;
margin-top: 30rpx;
}
.suggest-content-text {
font-size: 28rpx;
color: #333333;
margin-top: 30rpx;
margin-left: 22rpx;
margin-right: 22rpx;
margin-bottom: 30rpx;
}
.suggest-repet-content-text {
font-size: 24rpx;
color: #999999;
margin-top: 26rpx;
margin-left: 22rpx;
margin-right: 22rpx;
margin-bottom: 26rpx;
display: flex;
flex-direction: column;
}
</style>
<template>
<view style="background-color: #F5F5F5; min-height: 100vh; height: 100%;">
<view :style="'height:' + common.statusBarH + 'px; background-color: white; '"></view>
<view style="display: flex; justify-content: space-between;
padding-top: 16rpx;
padding-left: 30rpx ; padding-right: 30rpx; background-color: white;
padding-bottom: 16rpx;">
<image style="width: 56rpx; height: 56rpx;" src="../../static/close_black.webp" @click="back()"></image>
<text style="color: #333333; font-size: 34rpx; height: 56rpx; line-height: 56rpx; ">选择感兴趣的内容</text>
<image style="width: 56rpx; height: 56rpx;"></image>
</view>
<radio-group @change="radioChange">
<view class="grid-container">
<label v-for="(item, index) in dataArray" class="grid-item">
<image style="width: 72rpx; height: 72rpx;" :src="item.pic"></image>
<text style="color: #333333; margin-top: 20rpx; margin-bottom: 20rpx;">{{item.name}}</text>
<radio :checked="item.checked" :value="item.code"> </radio>
</label>
</view>
</radio-group>
<view
style="display: flex; align-items: center; justify-content: center; margin-top: 20rpx; padding-bottom: 20rpx;">
<text style="font-size: 24rpx; color: #999999;">APP将在每次启动后打开您选择的页面</text>
</view>
</view>
</template>
<script>
import common from '@/utils/common.js'
export default {
data() {
return {
common,
dataArray: []
}
},
onLoad() {
var select = uni.getStorageSync("user_option_code")
if (!select) {
select = 'home'
uni.setStorageSync("user_option_code", select)
}
var array = common.info_config.app_open_option
for (var i = 0; i < array.length; i++) {
array[i].checked = (select === array[i].code)
}
this.dataArray = array
},
methods: {
back() {
uni.navigateBack()
},
radioChange(e) {
var select = e.detail.value
for (var i = 0; i < this.dataArray.length; i++) {
this.dataArray[i].checked = (select === this.dataArray.code)
}
uni.setStorageSync("user_option_code", select)
}
}
}
</script>
<style>
.grid-container {
margin: 40rpx;
display: grid;
grid-template-columns: repeat(3, 1fr);
/* 每列占据 1/3 的宽度 */
grid-gap: 28rpx;
/* 设置列间距 */
}
.grid-item {
border-radius: 6rpx;
background-color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 40rpx;
padding-bottom: 30rpx;
}
</style>
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
## 2.1.2(2023-06-12)
1. [新增]添加`z-index`参数控制层级大小,默认1993
2. [说明]以后该插件只更新`uni_modules`方式的,`zip`方式的不提供更新了
## 2.1.1(2022-09-16)
1. 将插件更新为`uni_modules`方式
## 2.1.0(2022-08-12)
1. 增加`disable`参数,控制是否可以点击,只能应用在数组对象中,见[disabled 的用法](#112-当tabs使用的数组对象的方式特定参数需要注意一下)
```js
export default {
data() {
return {
tabs: [{ id: 1, name: '' }]
}
}
}
```
## 2.0.10(2022-01-27)
1. 更新属性line-animation设置为false可以不要动画,这是好多朋友问到,特此加上
## 2.0.9(2020-10-12)
1. 修复 v-tabs 第一次可能出现第一个标签显示不完整的情况
2. 修改了 pages/tabs/order 示例文件
## 2.0.8(2020-09-21)
1. 修复添加 fixed 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 paddingItem 属性,设置选项左右边距(上下边距需要设置 height 属性,或者设置 padding 属性)
## 2.0.7(2020-09-17)
1. 紧急修复 bug,横向滑动不了的情况
## 2.0.6(2020-09-16)
1. 新增 fixed 属性,是否固定在顶部,示例地址:pages/tabs/tabs-static
2. 优化之前的页面结构
## 2.0.5(2020-09-09)
1. 修复 width 错误,dom 加载的时候没有及时获取到 data 属性导致的 。
## 2.0.4(2020-08-29)
1. 优化异步改变 tabs 后,下划线不初始化问题
2. github 地址上有图 2 的源码,需要的自行下载,页面路径:pages/tabs/order.vue
## 2.0.3(2020-08-20)
1. 优化 节点查询 和 选中渲染
2. 优化支付宝中 createSelectorQuery() 的影响
**特别说明:**
> 支付宝中平铺方法和其他方法不能在一个页面中出现,不然有一个显示错误(具体什么原因没查到,有好心的人发现了,望告知一下,感谢
## 2.0.2(2020-08-19)
1. 优化 change 事件触发机制
## 2.0.1(2020-08-16)
1. 修改默认高度为 70rpx
2. 新增属性 bgColor,可设置背景颜色,默认 #fff
3. 新增整个 tab 的 padding 属性,默认 0
## 2.0.0(2020-08-13)
1. 全新的 v-tabs 2.0
2. 支持 H5 小程序 APP
3. 属性高度可配置
## 1.3.2(2020-07-21)
1. 新增 auto 的配置,是否平铺 tab
2. 修复文档上的错误示例(感谢 lushgwe@163.com 的反馈)
## 1.3.0(2020-07-05)
1. 新增 padding 的可配置
2. 修复 v-model 双向绑定问题
3. 修复初始化下划线没定位的为题
## 1.2.0(2020-06-19)
1. 添加注释
2. 修复 bug
## 1.1.8(2020-06-11)
1. 添加 change 事件
2. 修复插件内容问题
3. 修复下划线不居中问题
## 1.1.6(2020-06-11)
1. 添加 change 事件
2. 修复插件内容问题
## 1.1.4(2020-06-11)
1. 添加 change 事件
2. 修复插件内容问题
## 1.1.2(2020-06-11)
1. 添加 change 事件
## 1.1.1(2020-06-09)
1. 修复小程序端选中的下划线不显示问题
2. 新增 tab 高度设置
3. lineHeight 修改为只支持 String 方式
## 1.1.0(2020-06-09)
1. 修复小程序端选中的下划线不显示问题
2. 新增 tab 高度设置
3. lineHeight 修改为只支持 String 方式
## 1.0.0(2020-06-04)
1. 更新插件1.0.0
\ No newline at end of file
<template>
<view :id="elId" class="v-tabs">
<scroll-view
id="scrollContainer"
:scroll-x="scroll"
:scroll-left="scroll ? scrollLeft : 0"
:scroll-with-animation="scroll"
:style="{ position: fixed ? 'fixed' : 'relative', zIndex }"
>
<view
class="v-tabs__container"
:style="{
display: scroll ? 'inline-flex' : 'flex',
whiteSpace: scroll ? 'nowrap' : 'normal',
background: bgColor,
height,
padding
}"
>
<view
:class="['v-tabs__container-item', { disabled: !!v.disabled }]"
v-for="(v, i) in tabs"
:key="i"
:style="{
color: current == i ? activeColor : color,
fontSize: current == i ? fontSize : fontSize,
fontWeight: bold && current == i ? 'bold' : '',
justifyContent: !scroll ? 'center' : '',
flex: scroll ? '' : 1,
padding: paddingItem
}"
@click="change(i)"
>
{{ field ? v[field] : v }}
</view>
<view
v-if="!pills"
:class="['v-tabs__container-line', { animation: lineAnimation }]"
:style="{
background: lineColor,
width: lineWidth + 'px',
height: lineHeight,
borderRadius: lineRadius,
left: lineLeft + 'px',
transform: `translateX(-${lineWidth / 2}px)`
}"
></view>
<view
v-else
:class="['v-tabs__container-pills', { animation: lineAnimation }]"
:style="{
background: pillsColor,
borderRadius: pillsBorderRadius,
left: pillsLeft + 'px',
width: currentWidth + 'px',
height
}"
></view>
</view>
</scroll-view>
<view
class="v-tabs__placeholder"
:style="{
height: fixed ? height : '0',
padding
}"
></view>
</view>
</template>
<script>
/**
* v-tabs
* @property {Number} value 选中的下标
* @property {Array} tabs tabs 列表
* @property {String} bgColor = '#fff' 背景颜色
* @property {String} color = '#333' 默认颜色
* @property {String} activeColor = '#2979ff' 选中文字颜色
* @property {String} fontSize = '28rpx' 默认文字大小
* @property {String} activeFontSize = '28rpx' 选中文字大小
* @property {Boolean} bold = [true | false] 选中文字是否加粗
* @property {Boolean} scroll = [true | false] 是否滚动
* @property {String} height = '60rpx' tab 的高度
* @property {String} lineHeight = '10rpx' 下划线的高度
* @property {String} lineColor = '#2979ff' 下划线的颜色
* @property {Number} lineScale = 0.5 下划线的宽度缩放比例
* @property {String} lineRadius = '10rpx' 下划线圆角
* @property {Boolean} pills = [true | false] 是否胶囊样式
* @property {String} pillsColor = '#2979ff' 胶囊背景色
* @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
* @property {String} field 如果是对象,显示的键名
* @property {Boolean} fixed = [true | false] 是否固定
* @property {String} paddingItem = '0 22rpx' 选项的边距
* @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
* @property {Number} zIndex = 1993 默认层级
*
* @event {Function(current)} change 改变标签触发
*/
export default {
props: {
value: {
type: Number,
default: 0
},
tabs: {
type: Array,
default () {
return []
}
},
bgColor: {
type: String,
default: '#fff'
},
padding: {
type: String,
default: '0'
},
color: {
type: String,
default: '#333'
},
activeColor: {
type: String,
default: '#2979ff'
},
fontSize: {
type: String,
default: '28rpx'
},
activeFontSize: {
type: String,
default: '32rpx'
},
bold: {
type: Boolean,
default: true
},
scroll: {
type: Boolean,
default: true
},
height: {
type: String,
default: '70rpx'
},
lineColor: {
type: String,
default: '#2979ff'
},
lineHeight: {
type: String,
default: '10rpx'
},
lineScale: {
type: Number,
default: 0.5
},
lineRadius: {
type: String,
default: '10rpx'
},
pills: {
type: Boolean,
default: false
},
pillsColor: {
type: String,
default: '#2979ff'
},
pillsBorderRadius: {
type: String,
default: '10rpx'
},
field: {
type: String,
default: ''
},
fixed: {
type: Boolean,
default: false
},
paddingItem: {
type: String,
default: '0 22rpx'
},
lineAnimation: {
type: Boolean,
default: true
},
zIndex: {
type: Number,
default: 1993
}
},
data () {
return {
elId: '',
lineWidth: 30,
currentWidth: 0, // 当前选项的宽度
lineLeft: 0, // 滑块距离左侧的位置
pillsLeft: 0, // 胶囊距离左侧的位置
scrollLeft: 0, // 距离左边的位置
containerWidth: 0, // 容器的宽度
current: 0 // 当前选中项
}
},
watch: {
value (newVal) {
this.current = newVal
this.$nextTick(() => {
this.getTabItemWidth()
})
},
current (newVal) {
this.$emit('input', newVal)
},
tabs (newVal) {
this.$nextTick(() => {
this.getTabItemWidth()
})
}
},
methods: {
// 产生随机字符串
randomString (len) {
len = len || 32
let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
let maxPos = $chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
},
// 切换事件
change (index) {
const isDisabled = !!this.tabs[index].disabled
if (this.current !== index && !isDisabled) {
this.current = index
this.$emit('change', index)
}
},
// 获取左移动位置
getTabItemWidth () {
let query = uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
// 获取容器的宽度
query
.select(`#scrollContainer`)
.boundingClientRect((data) => {
if (!this.containerWidth && data) {
this.containerWidth = data.width
}
})
.exec()
// 获取所有的 tab-item 的宽度
query
.selectAll('.v-tabs__container-item')
.boundingClientRect((data) => {
if (!data) {
return
}
let lineLeft = 0
let currentWidth = 0
if (data) {
for (let i = 0; i < data.length; i++) {
if (i < this.current) {
lineLeft += data[i].width
} else if (i == this.current) {
currentWidth = data[i].width
} else {
break
}
}
}
// 当前滑块的宽度
this.currentWidth = currentWidth
// 缩放后的滑块宽度
this.lineWidth = currentWidth * this.lineScale * 1
// 滑块作移动的位置
this.lineLeft = lineLeft + currentWidth / 2
// 胶囊距离左侧的位置
this.pillsLeft = lineLeft
// 计算滚动的距离左侧的位置
if (this.scroll) {
this.scrollLeft = this.lineLeft - this.containerWidth / 2
}
})
.exec()
}
},
mounted () {
this.elId = 'xfjpeter_' + this.randomString()
this.current = this.value
this.$nextTick(() => {
this.getTabItemWidth()
})
}
}
</script>
<style lang="scss" scoped>
.v-tabs {
width: 100%;
box-sizing: border-box;
overflow: hidden;
::-webkit-scrollbar {
display: none;
}
&__container {
min-width: 100%;
position: relative;
display: inline-flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
&-item {
display: flex;
align-items: center;
height: 100%;
position: relative;
z-index: 10;
// padding: 0 11px;
transition: all 0.3s;
white-space: nowrap;
&.disabled {
opacity: 0.5;
color: #999;
}
}
&-line {
position: absolute;
bottom: 0;
}
&-pills {
position: absolute;
z-index: 9;
}
&-line,
&-pills {
&.animation {
transition: all 0.3s linear;
}
}
}
}
</style>
{
"id": "v-tabs",
"displayName": "自定义 tab 选项卡 2",
"version": "2.1.2",
"description": "自定义 tab ,支持多种样式,支持 h5 小程序 app",
"keywords": [
"v-tabs",
"tab",
"选项卡"
],
"repository": "https://github.com/xfjpeter/uni-plugins",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": "1207791534"
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "n"
},
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "n",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
\ No newline at end of file
## 插件说明
> 这是 `v-tabs` 插件的升级版本,参数上有很大变动,支持 `H5` `小程序` `手机端`,如果是在之前的插件上升级的话,请注意参数的变更,触发的事件没有变更。
## 使用说明
### 1、最基本用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
current: 0,
tabs: ['军事', '国内', '新闻新闻', '军事', '国内', '新闻', '军事', '国内', '新闻']
}
},
methods: {
changeTab(index) {
console.log('当前选中的项:' + index)
}
}
}
```
### 2、平铺整个屏幕
- 视图文件
```html
<v-tabs v-model="activeTab" :scroll="false" :tabs="['全部', '进行中', '已完成']"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
activeTab: 0
}
}
}
```
### 3、胶囊用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" :pills="true" line-height="0" activeColor="#fff" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
data() {
return {
current: 2,
tabs: [
'军事',
'国内',
'新闻新闻',
'军事',
'国内',
'新闻',
'军事',
'国内',
'新闻',
],
},
methods: {
changeTab(index) {
console.log('当前选中索引:' + index)
}
}
}
```
## 文档说明
### 1、属性说明
| 参数 | 类型 | 默认值 | 说明 |
| :---------------: | :-----: | :-------: | :-----------------------------------------------------------------------: |
| tabs | Array | [] | 控制 tab 的列表 |
| value | Number | 0 | 必传(双向绑定的值) |
| color | String | '#333' | 默认文字颜色 |
| activeColor | String | '#2979ff' | 选中文字的颜色 |
| fontSize | String | '28rpx' | 默认文字大小(rpx 或 px)(弃用) |
| bold | Boolean | true | 是否加粗选中项 |
| scroll | Boolean | true | 是否显示滚动条,平铺设置 false |
| height | String | '70rpx' | tab 高度(rpx 或 px) |
| lineHeight | String | '10rpx' | 滑块高度(rpx 或 px) |
| lineColor | String | '#2979ff' | 滑块的颜色 |
| lineScale | Number | 0.5 | 滑块宽度缩放值 |
| lineRadius | String | '10rpx' | 滑块圆角宽度(rpx 或 px) |
| pills | Boolean | false | 是否开启胶囊 |
| pillsColor | String | '#2979ff' | 胶囊背景颜色(rpx 或 px) |
| pillsBorderRadius | String | '10rpx' | 胶囊圆角宽度(rpx 或 px) |
| field | String | '' | 如果 tabs 子项是对象,输入需要展示的键名 |
| bgColor | String | '#fff' | 背景色,支持 linear-gradient 渐变 |
| padding | String | '0' | 整个 tab padding 属性 |
| fixed | Boolean | false | 是否固定在顶部 |
| paddingItem | String | '0 22rpx' | 选项的边距(设置上下不生效,需要设置高度) |
| lineAnimation | Boolean | true | 是否需要 line 和 pills 的动画,在隐藏页面后默认移动到第一个的时候比较实用 |
| zIndex | Number | 1993 | 控制 tab 的层级,默认1993 |
### 1.1 `tabs`参数展开说明
#### 1.1.1 当`tabs`仅仅是单纯的数组时候,没有什么特别的地方
```js
export default {
data() {
return {
tabs: ['全部', '待付款', '待消费', '已完成', '已评价', '已过期', '已退款']
}
}
}
```
#### 1.1.2 当`tabs`使用的数组对象的方式,特定参数需要注意一下
- `disabled` 参数,可以控制按钮是否可以点击
```js
export default {
data() {
return {
tabs: [
{ id: 1, name: '待付款', disabled: false },
{ id: 2, name: '待收货', disabled: false },
{ id: 3, name: '待评价', disabled: false },
{ id: 4, name: '退款/售后', disabled: true },
{ id: 5, name: '我的订单', disabled: false }
]
}
}
}
```
### 2、事件说明
| 名称 | 参数 | 说明 |
| :----: | :---: | :--------------------------------: |
| change | index | 改变选中项触发, index 选中项的下标 |
## 更新日志
### 2.1.1(2022-09-16)
1. 将插件更新为`uni_modules`方式
### 2022-08-12
1. 增加`disable`参数,控制是否可以点击,只能应用在数组对象中,见[disabled 的用法](#112-当tabs使用的数组对象的方式特定参数需要注意一下)
```js
export default {
data() {
return {
tabs: [{ id: 1, name: '' }]
}
}
}
```
### 2022-01-27
1. 更新属性`line-animation`设置为`false`可以不要动画,这是好多朋友问到,特此加上
### 2020-09-24
1. 修复 `v-tabs` 第一次可能出现第一个标签显示不完整的情况
2. 修改了 `pages/tabs/order` 示例文件
### 2020-09-21
1. 修复添加 `fixed` 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 `paddingItem` 属性,设置选项左右边距(上下边距需要设置 `height` 属性,或者设置 `padding` 属性)
**写在最后:**
欢迎各位老铁反馈 bug ,本人后端 PHP 一枚,只是应为感兴趣前端,自己琢磨,自己搞。如果你在使用的过程中有什么不合理,需要优化的,都可以在下面评论(或加我 QQ: 1207791534),本人看见后回复、修正,感谢。
### 2020-09-17
1. 紧急修复 bug,横向滑动不了的情况
### 2020-09-16
1. 新增 `fixed` 属性,是否固定在顶部,示例地址:`pages/tabs/tabs-static`
2. 优化之前的页面结构
**注意:**
1. 使用 `padding` 属性的时候,尽量不要左右边距,会导致下划线位置不对
2. 如果不绑定 `v-model` 会导致 `change` 事件改变的时候,下划线不跟随问题
### 2020-09-09
1. 修复 `width` 错误,dom 加载的时候没有及时获取到 `data` 属性导致的。
### 2020-08-29
1. 优化异步改变 `tabs` 后,下划线不初始化问题
2. `github` 地址上有图 2 的源码,需要的自行下载,页面路径:`pages/tabs/order`
### 2020-08-20
1. 优化 `节点查询``选中渲染`
2. 优化支付宝中 `createSelectorQuery()` 的影响
### 2020-08-19
1. 优化 `change` 事件触发机制
### 2020-08-16
1. 修改默认高度为 `70rpx`
2. 新增属性 `bgColor`,可设置背景颜色,默认 `#fff`
3. 新增整个 `tab``padding` 属性,默认 `0`
### 2020-08-13
1. 全新的 `v-tabs 2.0`
2. 支持 `H5` `小程序` `APP`
3. 属性高度可配置
## 预览
![v-tabs 2.0.1.gif](https://tva1.sinaimg.cn/large/007S8ZIlgy1ghsv40mj76g30ai0i2tsd.gif)
![v-tabs 2.0.2.gif](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/42f3a920-a674-11ea-8a24-ffee00625e2e_1.png?v=1597912963)
MIT License
Copyright (c) 2022 zebra-ui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<p align="center">
<img alt="logo" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/logo.png" width="220" style="margin-bottom: 10px;">
</p>
<h1 align="center">ZebraSwiper</h1>
<p align="center">基于uniapp,全面对标swiper,并实现全端兼容。</p>
<p align="center">
🔥 <a href="https://swiper.zebraui.com/">文档网站</a>
&nbsp;
&nbsp;
🚀 <a href="https://zebraui.com/" target="_blank">zebraUI组件库</a>
</p>
## 介绍
[zebra-swiper](https://github.com/zebra-ui/zebra-uniapp-swiper) 是基于uniapp开发的一款移动端轮播组件,已实现swiper组件90%的功能。
[uniapp](https://uniapp.dcloud.io/README)[swiper](https://uniapp.dcloud.io/component/swiper)组件存在很大的局限性,无法完成一些复杂的轮播效果。
而zebra-swiper不仅可以实现一些3D轮播效果,还可以通过参数来定义你想要的效果。
## 特性
- 全面对标swiper,并实现全端兼容
- 兼容多端,小程序也可以实现3D轮播效果
- 可自定义3D效果
- 多种示例,总有一种适合你
## 安装
### npm方式
```bash
npm i @zebra-ui/swiper
```
```js
// pages.json
{
"easycom": {
"^z-(.*)": "@zebra-ui/swiper/components/z-$1/z-$1.vue"
},
"pages": [...],
"globalStyle": {...}
}
```
### uni_modules方式
[插件市场](https://ext.dcloud.net.cn/plugin?id=7273)直接导入即可
## 手机预览
<div>
<img alt="wx" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/wx.jpg" width="200" />
<img alt="ali" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/ali.jpg" width="200" />
<img alt="h5" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/h5.png" width="200" />
</div>
## 预览
<div style="display:flex;flex-wrap:wrap;margin-top:30px;">
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif1.gif" width="300" style="margin:20px;" />
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif2.gif" width="300" style="margin:20px;" />
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif3.gif" width="300" style="margin:20px;" />
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif4.gif" width="300" style="margin:20px;" />
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif5.gif" width="300" style="margin:20px;" />
<img alt="gif" src="https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/gif/gif6.gif" width="300" style="margin:20px;" />
</div>
## 群
QQ群:947159437
![image](https://assets-1256020106.cos.ap-beijing.myqcloud.com/zebra-swiper/zebra-swiper-group-code.png)
\ No newline at end of file
## 2.2.6(2023-02-20)
`2023-02-20`
**Feat**
- `panorama`全景切换效果新增`stretch`参数,用于控制slide之间的距离。
**Fix**
- 修复字节小程序3D样式失效的问题。
- 修复`panorama`切换效果参数无效的问题。
- 修复`autoHeight`高度自适应使用报错的问题。(`autoHeight`选项可以正常使用,且在大多数场景下可以正确获取高度)
## 2.2.5(2022-11-10)
`2022-11-10`
**Feat**
- `cards`卡片切换效果新增`perSlideRotate``perSlideOffset`参数用于控制卡片的偏移距离及旋转角度。
- 微信小程序中默认使用虚拟节点渲染,即`virtualHost`: `true`
**Fix**
- 修复`pagination`选项开启后,动态控制`swiper`禁用或启用报错的问题。
- 修复支付宝小程序3D样式失效的问题。
## 2.2.4(2022-09-23)
`2022-09-23`
**Feat**
- 新增`noSwiping`参数控制是否禁止触摸。当禁止触摸开启时,不可通过滑动切换。可通过自动切换,`slideTo`等方法切换。
**Fix**
- 修复`vue3``app`触摸无效的问题。
- 新增触摸事件`touchcancel`
## 2.2.3(2022-07-26)
`2022-07-26`
**Feat**
- 卡片切换效果`cards`新增`rotate`参数,用于控制卡片切换时是否发生旋转。
**Fix**
- 修复微信小程序使用`zebra-swiper`时,页面无法滚动。
- 修复`app`报错`toJSON`的问题。
- 修复`swiper``vue3`中无法自动播放的问题。
## 2.2.2(2022-07-01)
`2022-07-01`
**Feat**
- 兼容`PC`浏览器端。
- 初步兼容`VUE3`
**Fix**
- 修复使用`zebra-swiper`时,页面无法滚动。(`zebra-swiper`将不再默认阻止事件冒泡)。
## 2.2.1(2022-03-31)
`2022-03-31`
**Feat**
- 新增`changeDirection`方法,该方法用于动态改变swiper方向。
- `z-swiper-item`新增`swiperItemWidth` `swiperItemHeight` 属性,用于在swiper无法正确获取宽高的情况下设置swiper的宽高(如快手小程序)。
**Fix**
- 消除快手小程序itemPropWxs的警告。
## 2.2.0(2022-03-21)
`2022-03-21`
**本次更新调整了组件的整体架构及组件入口逻辑。主要为性能优化,不涉及新功能。**
不兼容性更新:
- `z-swiper``customStyle` 由字符串类型更改为Object类型(与`z-swiper-item`保持一致)。
- `z-swiper-item` 删除了加载的效果。
**Fix**
- 修复因数据改变而无法正确触发更新的问题。
- 修复方法 `disable` `enable` 提示未定义的问题。
**Perf**
- 组件首次渲染速度优化。
- loop模式处理数据后才开始加载swiper,确保数据的一致性。
- 部分同步方法更改为异步,体验更流畅。
## 2.1.4(2022-03-05)
`2022-03-05`
**Feat**
- 高级案例加入开屏页。[点击预览](https://swiper.zebraui.com/h5/pages/demos/paper/index)
**Fix**
- 修复百度小程序高度计算错误的问题。
## 2.1.3(2022-03-03)
`2022-03-03`
**Feat**
- 新增高级案例模块。
- 高级案例加入环游地球。[点击预览](https://swiper.zebraui.com/h5/pages/demos/travel-slider/index)
- 微信小程序,qq小程序使用wxs赋值样式。
## 2.1.2(2022-03-02)
`2022-03-02`
本次改版涉及所有开启loop的功能。请更新后删除手动拼接的数据。
**Feat**
- loop无限循环模式无需再手动拼接数据。
## 2.1.1(2022-03-01)
`2022-03-01`
**Fix**
- 修复字节小程序轮播内容不显示的问题。
- 修复字节小程序获取位置信息错误的问题。
**Docs**
- [文档新增事件。](https://swiper.zebraui.com/basic/events/)
## 2.1.0(2022-02-27)
`2022-02-27`
更新须知
使用组件时,需在z-swiper标签上以`v-model`的形式传入list数据,也就是要循环的列表数据,该属性为强制性,不加会导致意外错误。例:
之前的方式:
```vue
<z-swiper>
<z-swiper-item v-for="(item,index) in list" :key="index">
<image class="image" :src="item" mode="aspectFill">
</image>
</z-swiper-item>
</z-swiper>
```
现在的方式:
```vue
<z-swiper v-model="list"> //这里传入的需和下方循环的保持一致
<z-swiper-item v-for="(item,index) in list" :key="index">
<image class="image" :src="item" mode="aspectFill">
</image>
</z-swiper-item>
</z-swiper>
```
这个操作也为swiper接管数据操作铺垫,对后续很多新功能非常有用,也为loop无限循环的痛点提供了解决方案。
**Fix**
- 修复数据为空时报错。
- 修复请求数据时swiper提前初始化的问题。
**Feat**
- 新增滚动条功能。
## 2.0.1(2022-02-25)
`2022-02-25`
**Fix**
- 修复插槽内容class样式不生效问题。
**Feat**
- 新增缩略图功能。
## 2.0.0(2022-02-24)
`2022-02-24`
**Feat**
- 该版本为破坏性改版,无法兼容1.0。
- 代码重构,使用模块化将功能分割,大幅提升性能,方便后续维护。
- 全面对标swiper组件,并实现全端兼容。小程序也可实现炫酷的轮播效果。
- 所有切换效果全部支持loop无限循环。
- 新增全景切换效果。
- 新增轮播块功能,可自定义显示数量。
- 新增进度条指示器。
## 1.0.7(2022-01-25)
`2022-01-25`
**Feat**
- 新增轮播切换器功能,可使用默认切换或自定义切换。
- 示例项目新增切换器的使用及自定义切换器。
## 1.0.6(2022-01-24)
`2022-01-24`
**Chore**
- 示例项目新增指示器的使用及自定义指示器。
## 1.0.5(2022-01-21)
`2022-01-21`
**Docs**
- README.md新增手机预览,包含微信,支付宝小程序码,H5二维码。
## 1.0.4(2022-01-20)
`2022-01-20`
**Style**
- 示例项目首页px统一修改为rpx。
## 1.0.3(2022-01-19)
`2022-01-19`
**Fix**
- 修复轮播设置为纵向时,高度错误的问题。
- 修复在百度小程序中样式错乱的问题。
## 1.0.2(2022-01-18)
`2022-01-18`
**Docs**
- README.md新增gif预览图
- 修复因未知原因引起的uni_modules组件上传错误的问题。
`2022-01-14`
### [v1.0.1](https://github.com/zebra-ui/zebra-uniapp-swiper)
**Feature**
- 新增zebra-swiper,zebra-swiper-item组件。
- 新增多种3D切换效果。包括渐变,方块,3D流,翻转,卡片,创意性等多种切换效果。
- 新增[示例项目](https://swiper.zebraui.com),包含多种切换效果示例。
<template>
<!-- #ifndef MP-WEIXIN || MP-QQ -->
<view :class="['swiper-slide',slideClass]" :style="[itemStyle,customStyle]" @click.stop="onClickSlide">
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-QQ -->
<view :class="['swiper-slide',slideClass]" :style="[itemStyle,customStyle]" @click.stop="onClickSlide"
:swiperItemTransform="wxsItemTransform" :change:swiperItemTransform="zSwiperWxs.wxsItemTransformObserver">
<!-- #endif -->
<slot></slot>
</view>
</template>
<!-- #ifdef MP-WEIXIN || MP-QQ -->
<script src="../../wxs/z-swiper-wxs.wxs" module="zSwiperWxs" lang="wxs"></script>
<!-- #endif -->
<script>
import {
ChildrenMixin
} from '../../libs/mixins/relation.js';
import {
getRect
} from '../../libs/utils/utils.js';
export default {
name: "z-swipe-item",
// #ifdef MP-WEIXIN
options: {
virtualHost: true
},
// #endif
mixins: [ChildrenMixin('zSwipe')],
props: {
customStyle: {
type: Object,
default: () => {
return {};
}
},
swiperItemWidth: {
type: [String, Number],
default: 0
},
swiperItemHeight: {
type: [String, Number],
default: 0
},
},
data() {
return {
wxsItemTransform: "",
itemStyle: {},
offsetLeft: 0,
offsetTop: 0,
itemClass: [],
width: 0,
height: 0,
};
},
mounted() {
this.getSize();
},
computed: {
slideClass() {
return this.itemClass.join(" ");
}
},
watch: {
swiperItemWidth: {
handler(val) {
if (val) {
this.$set(this.itemStyle, 'width', this.unitFormat(val, "rpx"))
}
},
immediate: true
},
swiperItemHeight: {
handler(val) {
if (val) {
this.$set(this.itemStyle, 'height', this.unitFormat(val, "rpx"))
}
},
immediate: true
}
},
methods: {
unitFormat(val, type) {
if (type == "rpx") {
if (val.includes("rpx") || val.includes("px")) {
return val;
} else {
return val + 'px';
}
}
if (type == "number") {
if (val.includes("rpx")) {
return uni.upx2px(parseInt(val.replace("rpx", "")))
} else if (!val.includes("rpx") && val.includes("px")) {
return parseInt(val.replace("px", ""))
} else {
return val;
}
}
},
onClickSlide(event) {
this.$emit("click", {
event,
index: this.index
});
this.parent.swiper.updateClickedSlide(this.index);
this.parent.swiper.emit("slideClick", this.index);
},
transform(value) {
// #ifndef MP-WEIXIN || MP-QQ
this.$set(this.itemStyle, 'transform', value)
// #endif
// #ifdef MP-WEIXIN || MP-QQ
this.wxsItemTransform = value
// #endif
},
transition(value) {
// #ifdef MP-BAIDU
this.$set(this.itemStyle, 'transitionDuration', `${value}ms`)
// #endif
// #ifndef MP-BAIDU
this.$set(this.itemStyle, 'transition-duration', `${value}ms`)
// #endif
},
willChange(value) {
this.$set(this.itemStyle, 'will-change', value)
},
css(value) {
Object.keys(value).forEach((item) => {
this.$set(this.itemStyle, item, value[item])
})
},
transitionEnd(callback, duration) {
setTimeout(callback, duration)
},
getSize() {
const query = uni.createSelectorQuery().in(this);
return new Promise((resolve, reject) => {
query.select('.swiper-slide').boundingClientRect(data => {
if (this.swiperItemWidth) {
this.width = this.unitFormat(this.swiperItemWidth, "number");
this.height = data.height;
}
if (this.swiperItemHeight) {
this.width = data.width;
this.height = this.unitFormat(this.swiperItemHeight, "number");
}
if (!this.swiperItemWidth && !this.swiperItemHeight) {
this.width = data.width;
this.height = data.height;
}
resolve({
width: this.width,
height: this.height
})
}).exec();
})
},
addClass(value) {
this.itemClass = Array.from(new Set([...this.itemClass, ...value.split(" ")]));
},
removeClass(value) {
this.itemClass = this.itemClass.filter(item => !value.split(" ").includes(item));
},
hasClass(value) {
return this.itemClass.includes(value);
},
nextAll() {
return this.parent.children.filter((item) => {
return item.index > this.index
})
},
prevAll() {
return this.parent.children.filter((item) => {
return item.index < this.index
}).reverse()
},
}
}
</script>
<style scoped lang="scss">
@import '../../libs/core.scss';
</style>
<!-- uni_modules发布插件时,components中必须有一个和父级名称一致的组件,否则提示指定目录不存在,这样做的具体原因未知。故此文件为无用文件,仅做为上传插件时消除错误使用。 -->
<template>
</template>
<script>
</script>
<style>
</style>
import Swiper from "./libs/core.js";
import Autoplay from './modules/autoplay/autoplay.js';
import FreeMode from './modules/free-mode/free-mode.js';
import EffectFade from './modules/effect-fade/effect-fade.js';
import EffectCube from './modules/effect-cube/effect-cube.js';
import EffectCoverflow from './modules/effect-coverflow/effect-coverflow.js';
import EffectFlip from './modules/effect-flip/effect-flip.js';
import EffectCards from './modules/effect-cards/effect-cards.js';
import EffectCreative from './modules/effect-creative/effect-creative.js';
import EffectPanorama from './modules/effect-panorama/effect-panorama.js';
import EffectCarousel from './modules/effect-carousel/effect-carousel.js';
import Navigation from './modules/navigation/navigation.js';
import Pagination from './modules/pagination/pagination.js';
import Thumbs from './modules/thumbs/thumbs.js';
import Scrollbar from './modules/scrollbar/scrollbar.js';
import Virtual from './modules/virtual/virtual.js';
import WillChange from './modules/will-change/will-change.js';
export {
default as Swiper,
default
}
from './libs/core.js';
const modules = [Autoplay, FreeMode, EffectFade, EffectCube, EffectCoverflow, EffectFlip, EffectCards, EffectCreative,
EffectPanorama, EffectCarousel, Navigation, Pagination, Thumbs, Scrollbar, WillChange, Virtual
];
Swiper.use(modules);
function checkOverflow() {
const swiper = this;
const {
isLocked: wasLocked,
params
} = swiper;
const {
slidesOffsetBefore
} = params;
if (slidesOffsetBefore) {
const lastSlideIndex = swiper.slides.length - 1;
const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] +
slidesOffsetBefore * 2;
swiper.isLocked = swiper.size > lastSlideRightEdge;
} else {
swiper.isLocked = swiper.snapGrid.length === 1;
}
if (params.allowSlideNext === true) {
swiper.allowSlideNext = !swiper.isLocked;
}
if (params.allowSlidePrev === true) {
swiper.allowSlidePrev = !swiper.isLocked;
}
if (wasLocked && wasLocked !== swiper.isLocked) {
swiper.isEnd = false;
}
if (wasLocked !== swiper.isLocked) {
swiper.emit(swiper.isLocked ? 'lock' : 'unlock');
}
}
export default {
checkOverflow
};
function prepareClasses(entries, prefix) {
const resultClasses = [];
entries.forEach(item => {
if (typeof item === 'object') {
Object.keys(item).forEach(classNames => {
if (item[classNames]) {
resultClasses.push(prefix + classNames);
}
});
} else if (typeof item === 'string') {
resultClasses.push(prefix + item);
}
});
return resultClasses;
}
export default function addClasses() {
const swiper = this;
const {
classNames,
params,
rtl,
$el,
device,
support
} = swiper; // prettier-ignore
const suffixes = prepareClasses(['initialized', params.direction, {
'pointer-events': !support.touch
}, {
'free-mode': swiper.params.freeMode && params.freeMode.enabled
}, {
'autoheight': params.autoHeight
}, {
'rtl': rtl
}, {
'grid': params.grid && params.grid.rows > 1
}, {
'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'
}, {
'android': device.android
}, {
'ios': device.ios
}, {
'css-mode': params.cssMode
}, {
'centered': params.cssMode && params.centeredSlides
}], params.containerModifierClass);
classNames.push(...suffixes);
$el.addClass([...classNames].join(' '));
swiper.emitContainerClasses();
}
\ No newline at end of file
import addClasses from './addClasses.js';
import removeClasses from './removeClasses.js';
export default {
addClasses,
removeClasses
};
\ No newline at end of file
export default function removeClasses() {
const swiper = this;
const {
$el,
classNames
} = swiper;
$el.removeClass(classNames.join(' '));
swiper.emitContainerClasses();
}
\ No newline at end of file
$themeColor: #007aff !default;
:root {
--swiper-theme-color: #{$themeColor};
}
.swiper {
margin-left: auto;
margin-right: auto;
position: relative;
overflow: hidden;
list-style: none;
padding: 0;
/* Fix of Webkit flickering */
z-index: 1;
}
.swiper-vertical > .swiper-wrapper {
flex-direction: column;
}
.swiper-wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
transition-property: transform;
box-sizing: content-box;
}
.swiper-android .swiper-slide,
.swiper-wrapper {
transform: translate3d(0px, 0, 0);
}
.swiper-pointer-events {
touch-action: pan-y;
&.swiper-vertical {
touch-action: pan-x;
}
}
.swiper-slide {
flex-shrink: 0;
width: 100%;
height: 100%;
position: relative;
transition-property: transform;
}
.swiper-slide-invisible-blank {
visibility: hidden;
}
/* Auto Height */
.swiper-autoheight {
&,
.swiper-slide {
height: auto;
}
.swiper-wrapper {
align-items: flex-start;
transition-property: transform, height;
}
}
.swiper-slide-3d{
transform-style: preserve-3d;
}
/* 3D Effects */
.swiper-3d {
&,
&.swiper-css-mode .swiper-wrapper {
perspective: 1200px;
}
.swiper-wrapper,
.swiper-slide,
.swiper-slide-shadow,
.swiper-slide-shadow-left,
.swiper-slide-shadow-right,
.swiper-slide-shadow-top,
.swiper-slide-shadow-bottom,
.swiper-cube-shadow {
transform-style: preserve-3d;
}
.swiper-slide-shadow,
.swiper-slide-shadow-left,
.swiper-slide-shadow-right,
.swiper-slide-shadow-top,
.swiper-slide-shadow-bottom {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
}
.swiper-slide-shadow {
background: rgba(0, 0, 0, 0.15);
}
.swiper-slide-shadow-left {
background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-slide-shadow-right {
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-slide-shadow-top {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-slide-shadow-bottom {
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
}
/* CSS Mode */
.swiper-css-mode {
> .swiper-wrapper {
overflow: auto;
scrollbar-width: none; /* For Firefox */
-ms-overflow-style: none; /* For Internet Explorer and Edge */
&::-webkit-scrollbar {
display: none;
}
}
> .swiper-wrapper > .swiper-slide {
scroll-snap-align: start start;
}
}
.swiper-horizontal.swiper-css-mode {
> .swiper-wrapper {
scroll-snap-type: x mandatory;
}
}
.swiper-vertical.swiper-css-mode {
> .swiper-wrapper {
scroll-snap-type: y mandatory;
}
}
.swiper-centered {
> .swiper-wrapper::before {
content: '';
flex-shrink: 0;
order: 9999;
}
&.swiper-horizontal {
> .swiper-wrapper > .swiper-slide:first-child {
margin-inline-start: var(--swiper-centered-offset-before);
}
> .swiper-wrapper::before {
height: 100%;
width: var(--swiper-centered-offset-after);
}
}
&.swiper-vertical {
> .swiper-wrapper > .swiper-slide:first-child {
margin-block-start: var(--swiper-centered-offset-before);
}
> .swiper-wrapper::before {
width: 100%;
height: var(--swiper-centered-offset-after);
}
}
> .swiper-wrapper > .swiper-slide {
scroll-snap-align: center center;
}
}
@import "../modules/effect-fade/effect-fade.scss";
@import "../modules/effect-cube/effect-cube.scss";
@import "../modules/effect-coverflow/effect-coverflow.scss";
@import "../modules/effect-flip/effect-flip.scss";
@import "../modules/effect-cards/effect-cards.scss";
@import "../modules/effect-creative/effect-creative.scss";
@import "../modules/effect-panorama/effect-panorama.scss";
@import "../modules/effect-carousel/effect-carousel.scss";
@import "../modules/navigation/navigation.scss";
@import "../modules/pagination/pagination.scss";
@import "../modules/thumbs/thumbs.scss";
@import "../modules/scrollbar/scrollbar.scss";
\ No newline at end of file
export default {
init: true,
direction: 'horizontal',
touchEventsTarget: 'wrapper',
initialSlide: 0,
speed: 300,
cssMode: false,
updateOnWindowResize: true,
resizeObserver: true,
nested: false,
createElements: false,
enabled: true,
focusableElements: 'input, select, option, textarea, button, video, label',
// Overrides
width: null,
height: null,
//
preventInteractionOnTransition: false,
// ssr
userAgent: null,
url: null,
// To support iOS's swipe-to-go-back gesture (when being used in-app).
edgeSwipeDetection: false,
edgeSwipeThreshold: 20,
// Autoheight
autoHeight: false,
// Set wrapper width
setWrapperSize: false,
// Virtual Translate
virtualTranslate: false,
virtualList: [],
virtualIndexList: [],
// Effects
effect: 'slide',
// 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
// Breakpoints
breakpoints: undefined,
breakpointsBase: 'window',
// Slides grid
spaceBetween: 0,
slidesPerView: 1,
slidesPerGroup: 1,
slidesPerGroupSkip: 0,
slidesPerGroupAuto: false,
centeredSlides: false,
centeredSlidesBounds: false,
slidesOffsetBefore: 0,
// in px
slidesOffsetAfter: 0,
// in px
normalizeSlideIndex: true,
centerInsufficientSlides: false,
// Disable swiper and hide navigation when container not overflow
watchOverflow: true,
// Round length
roundLengths: false,
// Touches
touchRatio: 1,
touchAngle: 45,
simulateTouch: true,
shortSwipes: true,
longSwipes: true,
longSwipesRatio: 0.5,
longSwipesMs: 300,
followFinger: true,
allowTouchMove: true,
threshold: 0,
touchMoveStopPropagation: false,
touchStartPreventDefault: true,
touchStartForcePreventDefault: false,
touchReleaseOnEdges: false,
// Unique Navigation Elements
uniqueNavElements: true,
// Resistance
resistance: true,
resistanceRatio: 0.85,
// Progress
watchSlidesProgress: false,
// Cursor
grabCursor: false,
// Clicks
preventClicks: true,
preventClicksPropagation: true,
slideToClickedSlide: false,
// Images
preloadImages: true,
updateOnImagesReady: true,
// loop
loop: false,
loopAdditionalSlides: 0,
loopedSlides: null,
loopFillGroupWithBlank: false,
loopPreventsSlide: true,
// rewind
rewind: false,
// Swiping/no swiping
allowSlidePrev: true,
allowSlideNext: true,
swipeHandler: null,
// '.swipe-handler',
noSwiping: false,
noSwipingClass: 'swiper-no-swiping',
noSwipingSelector: null,
// Passive Listeners
passiveListeners: true,
// NS
containerModifierClass: 'swiper-',
// NEW
slideClass: 'swiper-slide',
slideBlankClass: 'swiper-slide-invisible-blank',
slideActiveClass: 'swiper-slide-active',
slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
slideVisibleClass: 'swiper-slide-visible',
slideDuplicateClass: 'swiper-slide-duplicate',
slideNextClass: 'swiper-slide-next',
slideDuplicateNextClass: 'swiper-slide-duplicate-next',
slidePrevClass: 'swiper-slide-prev',
slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
wrapperClass: 'swiper-wrapper',
slideThumbsClass: 'swiper-slide-thumb',
// Callbacks
runCallbacksOnInit: true,
// Internals
_emitClasses: false,
willChange: false
};
/* eslint-disable no-underscore-dangle */
export default {
on(events, handler, priority) {
const self = this;
if (typeof handler !== 'function') return self;
const method = priority ? 'unshift' : 'push';
events.split(' ').forEach(event => {
if (!self.eventsListeners[event]) self.eventsListeners[event] = [];
self.eventsListeners[event][method](handler);
});
return self;
},
once(events, handler, priority) {
const self = this;
if (typeof handler !== 'function') return self;
function onceHandler(...args) {
self.off(events, onceHandler);
if (onceHandler.__emitterProxy) {
delete onceHandler.__emitterProxy;
}
handler.apply(self, args);
}
onceHandler.__emitterProxy = handler;
return self.on(events, onceHandler, priority);
},
onAny(handler, priority) {
const self = this;
if (typeof handler !== 'function') return self;
const method = priority ? 'unshift' : 'push';
if (self.eventsAnyListeners.indexOf(handler) < 0) {
self.eventsAnyListeners[method](handler);
}
return self;
},
offAny(handler) {
const self = this;
if (!self.eventsAnyListeners) return self;
const index = self.eventsAnyListeners.indexOf(handler);
if (index >= 0) {
self.eventsAnyListeners.splice(index, 1);
}
return self;
},
off(events, handler) {
const self = this;
if (!self.eventsListeners) return self;
events.split(' ').forEach(event => {
// self.native.off(event, handler);
if (typeof handler === 'undefined') {
self.eventsListeners[event] = [];
} else if (self.eventsListeners[event]) {
self.eventsListeners[event].forEach((eventHandler, index) => {
if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler
.__emitterProxy === handler) {
self.eventsListeners[event].splice(index, 1);
}
});
}
});
return self;
},
emit(...args) {
const self = this;
if (!self.eventsListeners) return self;
let events;
let data;
let context;
if (typeof args[0] === 'string' || Array.isArray(args[0])) {
events = args[0];
data = args.slice(1, args.length);
context = self;
} else {
events = args[0].events;
data = args[0].data;
context = args[0].context || self;
}
data.unshift(context);
const eventsArray = Array.isArray(events) ? events : events.split(' ');
eventsArray.forEach(event => {
// console.log(event)
if (self.eventsAnyListeners && self.eventsAnyListeners.length) {
self.eventsAnyListeners.forEach(eventHandler => {
eventHandler.apply(context, [event, ...data]);
});
}
if (self.eventsListeners && self.eventsListeners[event]) {
self.eventsListeners[event].forEach(eventHandler => {
eventHandler.apply(context, data);
});
}
});
return self;
}
};
import onTouchStart from './onTouchStart.js';
import onTouchMove from './onTouchMove.js';
import onTouchEnd from './onTouchEnd.js';
import onResize from './onResize.js';
import onClick from './onClick.js';
import onScroll from './onScroll.js';
let dummyEventAttached = false;
function dummyEventListener() {}
const events = (swiper, method) => {
const {
params,
touchEvents,
wrapperEl,
device,
support
} = swiper;
let el = swiper.native;
const capture = !!params.nested;
const domMethod = method === 'on' ? 'on' : 'off';
const swiperMethod = method;
if (!support.touch) {
let desktopMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
if (document.querySelector(`#${swiper.$el.swiperElId}`)) {
document.querySelector(`#${swiper.$el.swiperElId}`)[desktopMethod](touchEvents.start, swiper
.onTouchStart,
false);
}
document[desktopMethod](touchEvents.move, swiper.onTouchMove, capture);
document[desktopMethod](touchEvents.end, swiper.onTouchEnd, false);
} else {
const passiveListener = touchEvents.start === 'touchstart' && support.passiveListener && params
.passiveListeners ? {
passive: true,
capture: false
} : false;
}
};
function attachEvents() {
const swiper = this;
const {
params,
support
} = swiper;
swiper.onTouchStart = onTouchStart.bind(swiper);
swiper.onTouchMove = onTouchMove.bind(swiper);
swiper.onTouchEnd = onTouchEnd.bind(swiper);
if (params.cssMode) {
swiper.onScroll = onScroll.bind(swiper);
}
swiper.onClick = onClick.bind(swiper);
events(swiper, 'on');
}
function detachEvents() {
const swiper = this;
events(swiper, 'off');
}
export default {
attachEvents,
detachEvents
};
export default function onClick(e) {
const swiper = this;
if (!swiper.enabled) return;
if (!swiper.allowClick) {
if (swiper.params.preventClicks) e.preventDefault();
if (swiper.params.preventClicksPropagation && swiper.animating) {
e.stopPropagation();
e.stopImmediatePropagation();
}
}
}
\ No newline at end of file
export default function onResize() {
const swiper = this;
const {
params,
el
} = swiper;
if (el && el.offsetWidth === 0) return;
if (params.breakpoints) {
swiper.setBreakpoint();
}
const {
allowSlideNext,
allowSlidePrev,
snapGrid
} = swiper;
swiper.allowSlideNext = true;
swiper.allowSlidePrev = true;
swiper.updateSize();
swiper.updateSlides();
swiper.updateSlidesClasses();
if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {
swiper.slideTo(swiper.slides.length - 1, 0, false, true);
} else {
swiper.slideTo(swiper.activeIndex, 0, false, true);
}
if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
swiper.autoplay.run();
}
swiper.allowSlidePrev = allowSlidePrev;
swiper.allowSlideNext = allowSlideNext;
if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
swiper.checkOverflow();
}
}
\ No newline at end of file
export default function onScroll() {
const swiper = this;
const {
wrapperEl,
rtlTranslate,
enabled
} = swiper;
if (!enabled) return;
swiper.previousTranslate = swiper.translate;
if (swiper.isHorizontal()) {
swiper.translate = -wrapperEl.scrollLeft;
} else {
swiper.translate = -wrapperEl.scrollTop;
} // eslint-disable-next-line
if (swiper.translate === -0) swiper.translate = 0;
swiper.updateActiveIndex();
swiper.updateSlidesClasses();
let newProgress;
const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
if (translatesDiff === 0) {
newProgress = 0;
} else {
newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff;
}
if (newProgress !== swiper.progress) {
swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate);
}
swiper.emit('setTranslate', swiper.translate, false);
}
\ No newline at end of file
import {
now,
nextTick
} from '../../shared/utils.js';
export default function onTouchEnd(event) {
const swiper = this;
const data = swiper.touchEventsData;
const {
params,
touches,
rtlTranslate: rtl,
slidesGrid,
enabled
} = swiper;
if (!enabled) return;
let e = event;
if (e.originalEvent) e = e.originalEvent;
if (data.allowTouchCallbacks) {
swiper.emit('touch-end', e);
}
data.allowTouchCallbacks = false;
if (!data.isTouched) {
if (data.isMoved && params.grabCursor) {
swiper.setGrabCursor(false);
}
data.isMoved = false;
data.startMoving = false;
return;
}
if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper
.allowSlidePrev === true)) {
swiper.setGrabCursor(false);
}
const touchEndTime = now();
const timeDiff = touchEndTime - data.touchStartTime; // Tap, doubleTap, Click
if (swiper.allowClick) {
const pathTree = e.path || e.composedPath && e.composedPath();
// swiper.updateClickedSlide(pathTree && pathTree[0] || e.target);
swiper.emit('tap click', e);
if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) {
swiper.emit('doubleTap doubleClick', e);
}
}
data.lastClickTime = now();
nextTick(() => {
if (!swiper.destroyed) swiper.allowClick = true;
});
if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate ===
data.startTranslate) {
data.isTouched = false;
data.isMoved = false;
data.startMoving = false;
return;
}
data.isTouched = false;
data.isMoved = false;
data.startMoving = false;
let currentPos;
if (params.followFinger) {
currentPos = rtl ? swiper.translate : -swiper.translate;
} else {
currentPos = -data.currentTranslate;
}
if (params.cssMode) {
return;
}
if (swiper.params.freeMode && params.freeMode.enabled) {
swiper.freeMode.onTouchEnd({
currentPos
});
return;
}
let stopIndex = 0;
let groupSize = swiper.slidesSizesGrid[0];
for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) {
const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
if (typeof slidesGrid[i + increment] !== 'undefined') {
if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {
stopIndex = i;
groupSize = slidesGrid[i + increment] - slidesGrid[i];
}
} else if (currentPos >= slidesGrid[i]) {
stopIndex = i;
groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
}
}
const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
if (timeDiff > params.longSwipesMs) {
if (!params.longSwipes) {
swiper.slideTo(swiper.activeIndex);
return;
}
if (swiper.swipeDirection === 'next') {
if (ratio >= params.longSwipesRatio) swiper.slideTo(stopIndex + increment);
else swiper.slideTo(stopIndex);
}
if (swiper.swipeDirection === 'prev') {
if (ratio > 1 - params.longSwipesRatio) swiper.slideTo(stopIndex + increment);
else swiper.slideTo(stopIndex);
}
} else {
if (!params.shortSwipes) {
swiper.slideTo(swiper.activeIndex);
return;
}
const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper
.navigation.prevEl);
if (!isNavButtonTarget) {
if (swiper.swipeDirection === 'next') {
swiper.slideTo(stopIndex + increment);
}
if (swiper.swipeDirection === 'prev') {
swiper.slideTo(stopIndex);
}
} else if (e.target === swiper.navigation.nextEl) {
swiper.slideTo(stopIndex + increment);
} else {
swiper.slideTo(stopIndex);
}
}
}
import {
now
} from '../../shared/utils.js';
export default function onTouchMove(event) {
const swiper = this;
const data = swiper.touchEventsData;
const {
params,
touches,
rtlTranslate: rtl,
enabled
} = swiper;
if (!enabled) return;
let e = event;
if (e.originalEvent) e = e.originalEvent;
if (!data.isTouched) {
if (data.startMoving && data.isScrolling) {
swiper.emit('touchMoveOpposite', e);
}
return;
}
if (data.isTouchEvent && e.type !== 'touchmove' && e.type !== 'touchMove' && e.type !== 'onTouchmove') return;
const targetTouch = (e.type === 'touchmove' || e.type === 'touchMove' || e.type === 'onTouchmove') && e.touches && (
e.touches[0] || e
.changedTouches[0]);
const pageX = (e.type === 'touchmove' || e.type === 'touchMove' || e.type === 'onTouchmove') ? targetTouch.pageX : e
.pageX;
const pageY = (e.type === 'touchmove' || e.type === 'touchMove' || e.type === 'onTouchmove') ? targetTouch.pageY : e
.pageY;
if (e.preventedByNestedSwiper) {
touches.startX = pageX;
touches.startY = pageY;
return;
}
if (!swiper.allowTouchMove) {
swiper.allowClick = false;
if (data.isTouched) {
Object.assign(touches, {
startX: pageX,
startY: pageY,
currentX: pageX,
currentY: pageY
});
data.touchStartTime = now();
}
return;
}
if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {
if (swiper.isVertical()) {
if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper
.translate >= swiper.minTranslate()) {
data.isTouched = false;
data.isMoved = false;
return;
}
} else if (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX &&
swiper.translate >= swiper.minTranslate()) {
return;
}
}
// if (data.isTouchEvent && document.activeElement) {
// if (e.target === document.activeElement && $(e.target).is(data.focusableElements)) {
// data.isMoved = true;
// swiper.allowClick = false;
// return;
// }
// }
if (data.allowTouchCallbacks) {
swiper.emit('touch-move', e);
}
if (e.touches && e.touches.length > 1) return;
touches.currentX = pageX;
touches.currentY = pageY;
const diffX = touches.currentX - touches.startX;
const diffY = touches.currentY - touches.startY;
if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return;
if (typeof data.isScrolling === 'undefined') {
let touchAngle;
if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX ===
touches.startX) {
data.isScrolling = false;
} else {
if (diffX * diffX + diffY * diffY >= 25) {
touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI;
data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params
.touchAngle;
}
}
}
if (data.isScrolling) {
swiper.emit('touchMoveOpposite', e);
}
if (typeof data.startMoving === 'undefined') {
if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
data.startMoving = true;
}
}
if (data.isScrolling) {
data.isTouched = false;
return;
}
if (!data.startMoving) {
return;
}
swiper.allowClick = false;
if (!params.cssMode && e.cancelable) {
e.preventDefault();
}
if (params.touchMoveStopPropagation && !params.nested) {
e.stopPropagation();
}
if (!data.isMoved) {
if (params.loop && !params.cssMode) {
swiper.loopFix();
}
data.startTranslate = swiper.getTranslate();
swiper.setTransition(0);
if (swiper.animating) {
swiper.$wrapperEl.emit('transitionend', [swiper]);
}
data.allowMomentumBounce = false;
if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
swiper.setGrabCursor(true);
}
swiper.emit('sliderFirstMove', e);
}
swiper.emit('sliderMove', e);
data.isMoved = true;
let diff = swiper.isHorizontal() ? diffX : diffY;
touches.diff = diff;
diff *= params.touchRatio;
if (rtl) diff = -diff;
swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
data.currentTranslate = diff + data.startTranslate;
let disableParentSwiper = true;
let resistanceRatio = params.resistanceRatio;
if (params.touchReleaseOnEdges) {
resistanceRatio = 0;
}
if (diff > 0 && data.currentTranslate > swiper.minTranslate()) {
disableParentSwiper = false;
if (params.resistance) data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data
.startTranslate + diff) ** resistanceRatio;
} else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {
disableParentSwiper = false;
if (params.resistance) data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data
.startTranslate - diff) ** resistanceRatio;
}
if (disableParentSwiper) {
e.preventedByNestedSwiper = true;
}
if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
data.currentTranslate = data.startTranslate;
}
if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
data.currentTranslate = data.startTranslate;
}
if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {
data.currentTranslate = data.startTranslate;
}
if (params.threshold > 0) {
if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
if (!data.allowThresholdMove) {
data.allowThresholdMove = true;
touches.startX = touches.currentX;
touches.startY = touches.currentY;
data.currentTranslate = data.startTranslate;
touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches
.startY;
return;
}
} else {
data.currentTranslate = data.startTranslate;
return;
}
}
if (!params.followFinger || params.cssMode) return;
if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {
swiper.updateActiveIndex();
swiper.updateSlidesClasses();
}
if (swiper.params.freeMode && params.freeMode.enabled && swiper.freeMode) {
swiper.freeMode.onTouchMove();
}
swiper.updateProgress(data.currentTranslate);
swiper.setTranslate(data.currentTranslate);
}
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
此文件的差异被折叠, 点击展开。
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!