提交 f51d6a5b 编写于 作者: guangjun.yang's avatar guangjun.yang

新建PC端项目

上级
# nuxt-ssr
> nuxt ssr layout
## Build Setup
``` bash
# install dependencies
$ npm run install
# serve with hot reload at localhost:3000
$ npm run dev
# build for production and launch server
# 有环境变量 非本地打包请自行带上ENV => dev, test, uat, prod
$ ENV=上一行的变量 npm run build // eg: ENV=dev npm run build
$ npm run start // 对于 start 命令,可以根据需求自行 更改PORT (有部署冲突的时候会改)
# generate static project // 暂时用不到
$ npm run generate
```
\ No newline at end of file
# ASSETS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
html,body {
background: #fff;
}
input {
outline: none;
-webkit-appearance: none;
border: none;
}
\ No newline at end of file
# COMPONENTS
**This directory is not required, you can delete it if you don't want to use it.**
The components directory contains your Vue.js Components.
_Nuxt.js doesn't supercharge these components._
<template>
<div
:class="{ 'button-dis': buttonInfo.isDisabled }"
class="button-container"
@click="submit"
>
{{ buttonInfo.buttonText }}
</div>
</template>
<script>
export default {
name: 'ButtonComponent',
props: {
buttonInfo: {
type: Object,
default: () => {
return {
buttonText: '下一步', //按钮文案
isDisabled: true //按钮是否可以点击
};
}
}
},
methods: {
submit() {
if (this.buttonInfo.isDisabled) {
return;
}
this.$emit('handlerClick'); //点击按钮的操作,触发父组件相应的方法
}
}
};
</script>
<style scoped lang="less">
.button-container {
/*按钮本身样式没有设置margin,可根据具体页面的ui在父页面中进行设置*/
width: 325px;
height: 44px;
background: #449284;
border-radius: 22px;
color: #fff;
font-size: 16px;
font-weight: 700;
line-height: 44px;
text-align: center;
margin: 0 auto;
}
.button-dis {
opacity: 0.5;
}
</style>
<template>
<section class="dialog-wrap">
<div class="dialog-content">
<div class="info">
<p class="title">{{dialogInfos.title}}</p>
<div class="text" v-html="dialogInfos.content"></div>
</div>
<div class="operation">
<div class="left" @click="cancel"> {{dialogInfos.cancelText}}</div>
<div class="right" @click="submit">{{dialogInfos.affirmText}}</div>
</div>
</div>
</section>
</template>
<script>
export default {
name: "Mydialog",
props: {
dialogInfos: {
type: Object,
default: () => {
return {
title: '提醒',
content: '',
cancelText: '取消',
affirmText: '确定'
}
}
}
},
methods: {
cancel() { //取消操作
this.$emit('cancelBtn')
},
submit() { // 确定操作
this.$emit('submitBtn')
}
}
}
</script>
<style scoped lang="less">
.dialog-wrap {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background:rgba(55,56,57,.6);
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
.dialog-content {
width: 300px;
background: #fff;
border-radius: 3px;
.info {
padding: 30px;
.title {
color: #333333;
font-size: 18px;
line-height: 18px;
text-align: center;
margin-bottom: 14px;
}
.text {
font-size: 14px;
line-height: 21px;
color: #676869;
}
}
.operation {
height: 50px;
position: relative;
display: flex;
display: -webkit-flex;
div {
font-size: 17px;
width: 300px;
line-height: 50px;
text-align: center;
}
.left {
width: 299px;
border-right: 1px solid #F0F1F2;
color: #979899;
}
.right {
color: #449284;
}
}
.operation:before {
position: absolute;
content: " ";
left: 0;
top: 0;
right: 0;
height: 1Px;
border-top: 1Px solid #F0F1F2;
-webkit-transform-origin: 0 100%;
-ms-transform-origin: 0 100%;
transform-origin: 0 100%;
-webkit-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
}
</style>
\ No newline at end of file
<template>
<div class="input-phone-container">
<div class="input-content" @click.stop="showDelete=true">
<input
:placeholder="placeholderText"
type="tel"
maxlength="13"
v-model="mobilePhone"
@keyup="dealPhoneNumber"
id="inputs"
:autofocus="isAutofocus"
/>
<img
v-show="showDelete&&this.mobilePhone.length"
src="~/assets/img/icon-del.png"
@click="reset"
/>
</div>
</div>
</template>
<script>
import { setCookie, getCookie, delCookie } from '@/utils/cookieFun';
export default {
name: 'InputPhone',
props: {
placeholderText: {
type: String,
default: '请输入'
},
defaultMobile: {
type: String,
default: ''
}
},
data() {
return {
mobilePhone: '',
showDelete: false,
isAutofocus: true
}
},
mounted() {
const _this = this;
if(_this.defaultMobile) {
this.mobilePhone = this.defaultMobile.replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3');
} else if(localStorage.getItem('mobile')) {
this.mobilePhone = localStorage.getItem('mobile').replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3');
}
document.querySelector('html').addEventListener('click', function () {
// document.getElementById('inputs').focus()
this.isAutofocus = true;
});
document.querySelector('html').click();
},
methods: {
dealPhoneNumber(e) {
let value = this.mobilePhone.replace(/\D/g, '').substr(0, 11) // 不允许输入非数字字符,超过11位数字截取前11位
let len = value.length
if (len > 3 && len < 8) {
value = value.replace(/^(\d{3})/g, '$1 ')
} else if (len >= 8) {
value = value.replace(/^(\d{3})(\d{4})/g, '$1 $2 ')
}
this.mobilePhone = value
//this.mobilePhone = this.mobilePhone.replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3');
this.$emit('getPhone',this.mobilePhone.replace(/\s/g,""))
},
reset() {
this.mobilePhone = '';
this.$emit('getPhone',this.mobilePhone.replace(/\s/g,""))
},
},
watch: {
mobilePhone: {
handler(val) {
this.$emit('getPhone', val.replace(/\s/g,""));
if(val.length) {
this.showDelete = true;
}
},
deep: true
}
}
};
</script>
<style scoped lang="less">
.input-phone-container {
position: relative;
width: 325px;
margin: 0 auto;
padding-bottom: 16px;
.input-content {
position: relative;
width: 325px;
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
input {
width: 300px;
color: #373839;
font-size: 18px;
}
input::-webkit-input-placeholder {
/* WebKit browsers */
color: #C7C8C9;
}
input::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #C7C8C9;
}
input:-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #C7C8C9;
}
input:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #C7C8C9;
}
img {
width: 16px;
height: 16px;
margin-left: auto;
}
}
}
.input-phone-container:after {
position: absolute;
content: ' ';
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e6e6e6;
color: #e6e6e6;
-webkit-transform-origin: 0 100%;
-ms-transform-origin: 0 100%;
transform-origin: 0 100%;
-webkit-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
transform: scaleY(0.5);
}
</style>
<template>
<section class="loading-wrap">
<div class="loading-content">
<van-loading color="#4C4C4C" type="spinner"/>
</div>
</section>
</template>
<script>
export default {
data() {
return {
name: 'about'
}
}
}
</script>
<style lang="less" scoped>
.loading-wrap {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
.loading-content {
width: 60px;
height: 60px;
background: #E4E4E4;
border-radius: 4px;
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
justify-content: center;
-webkit-justify-content: center;
}
}
</style>
\ No newline at end of file
<template>
<div class="login-types-container">
<div
class="item"
v-for="(item, index) in arrayData"
:key="index"
v-if="item.url != '/wxLogin' || is_Wx"
@click="goToTarget(item)"
>
<img :src="item.img" alt="">
<p>{{item.content}}</p>
</div>
</div>
</template>
<script>
export default {
name: "login-types",
props: {
arrayData: {
type: Array,
default: () => {
return []
}
},
is_Wx: {
type: Boolean,
default: () => {
return false
}
}
},
methods: {
goToTarget(item) {
this.$emit('goToTarget', item)
}
}
}
</script>
<style scoped lang="less">
.login-types-container {
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
.item {
margin: 0 30px;
}
.item:first-child {
margin-left: 0;
}
.item:last-child {
margin-right: 0;
}
img {
display: block;
width: 45px;
height: 45px;
margin: 0 auto;
}
p {
width: 100%;
color: #676869;
font-size: 11px;
line-height: 15px;
margin-top: 8.5px;
text-align: center;
}
}
</style>
\ No newline at end of file
<template>
<div class="msg-code-wrap">
<label class="simple-input-content" for="currentCode">
<span
v-for="(item, index) in tempArr"
:key="index"
:class="eachSpanClass(index)">
{{ currentCode.slice(index, index+1) }}
</span>
</label>
<input
class="code-input"
id="currentCode"
v-model.trim="currentCode"
autofocus="autofocus"
type="tel"
maxlength="6"
placeholder="请输入六位数字验证码"
/>
</div>
</template>
<script>
import Loading from '@/components/loading';
import { sendEncryptRequest } from '@/utils/encrypt';
import { msgCodeLogin, wxBindMobile, signAgreements } from "@/service";
import { setCookie, getCookie, delCookie } from '@/utils/cookieFun';
export default {
name: "msg-code",
components: {
Loading,
},
props: {
codeInfo: {
type: Object,
default: () => {
return {
fromType: '', //页面来源
};
}
}
},
data() {
return {
currentCode: "",
tempArr: [1, 2, 3, 4, 5, 6],
}
},
watch: {
currentCode(val) {
console.log('val>>>> ', val);
// 触发验证码登录
if ( val && val.length == 6 ) {
const checkIng = this.$toast({
duration: 0, // 持续展示 toast
forbidClick: true,
message: '验证中...'
})
console.log('调接口 去验证...')
let fromType = this.codeInfo.fromType;
if (fromType == 0) { // 0 验证码登录
this.handleMsgCodeLogin(checkIng);
} else if (fromType == 2) { //2 微信登录手机号绑定
this.handleWechatLogin(checkIng);
}
}
}
},
mounted() {
this.$nextTick(() => {
document.getElementById("currentCode").focus();
});
},
methods: {
eachSpanClass(index) {
let msgCodeLength = this.currentCode.length;
if ( msgCodeLength == 0 && index == 0 ) {
return "highlight focus";
} else {
if ( index < msgCodeLength ) {
return "highlight";
}
if ( index == msgCodeLength ) {
return "highlight focus";
}
}
},
handleMsgCodeLogin(checkIng) {
let data = {
mobile: localStorage.getItem('mobile'),
authCode: this.currentCode,
}
sendEncryptRequest(data, params => {
msgCodeLogin(params).then( res => {
checkIng.clear(); // 手动清除 Toast
if(res.code == '000000') {
this.$toast('验证成功');
// 验证成功回调
this.handleLoginSuccess(res);
} else {
this.currentCode = '';
this.$toast(res.message);
}
})
});
},
handleWechatLogin(checkIng) {
let data = {
mobile: localStorage.getItem('mobile'),
authCode: this.currentCode,
unionId: this.$store.state.unionId,
};
sendEncryptRequest(data, params => {
wxBindMobile(params).then( res => {
checkIng.clear(); // 手动清除 Toast
if(res.code == '000000') {
this.$toast('验证成功');
// 验证成功回调
this.handleLoginSuccess(res);
} else {
this.currentCode = '';
this.$toast(res.message);
}
})
});
},
handleLoginSuccess(res) {
delCookie('token');
setCookie('token', res.data.token);
this.signAnAgreements();
if(sessionStorage.getItem('target_url')) {
const target_url = decodeURIComponent(sessionStorage.getItem('target_url'));
window.location.replace(target_url);
} else {
console.log('登录成功,后面跳转页面>>>>>>'); // 此行代码测试用,后续上线前删掉 -----------------------------------------------
}
},
signAnAgreements() {
signAgreements({}).then(res => {
if(res.code != '000000') {
this.$toast(res.message)
}
})
}
},
}
</script>
<style lang="less">
.msg-code-wrap {
overflow: hidden;
.simple-input-content {
span {
display: block;
float: left;
width: 44px;
height: 42px;
font-size: 18px;
text-align: center;
line-height: 42px;
margin-right: 10px;
border-bottom: 1PX solid #c7c8c9;
&:last-child {
margin: 0;
}
&.highlight {
border-color: #449284;
}
}
.focus {
position: relative;
border-color: #449284 !important;
}
.focus:after {
position: absolute;
content: "";
display: inline-block;
width: 2px;
height: 20px;
top: 50%;
left: 49%;
transform: translateY(-50%);
animation: blink 1s infinite steps(1, start);
}
@keyframes blink {
0%,
50% {
background-color: transparent;
}
100% {
background-color: #373839;
}
}
}
.code-input{
position: absolute; left:-9999px;
}
}
</style>
\ No newline at end of file
<template>
<div class="password-input-wrap">
<input :type="pwdInfo.inputType" v-model="pwdInfo.password" @keyup="updatePassword" placeholder="请输入登录密码"/>
<img src="~/assets/img/icon-del.png" alt="" v-show="showDelete" class="close-btn" @click="handleClear" v-bp="{ component_tag: '908#908002'}" />
<img :src="getPasswordShow" alt="" class="password-show" @click="changeVisible" v-bp="{ component_tag: '908#908002'}" />
</div>
</template>
<script>
import iconVisible from "@/assets/img/icon-visible.png";
import iconInvisible from "@/assets/img/icon-invisible.png";
export default {
name: "password-input",
props: {
pwdInfo: {
type: Object,
default: () => {
return {
inputType: 'password', // 默认输入框类型(password / text)
password: '',
}
}
},
},
data() {
return {
showDelete: false
}
},
computed: {
getPasswordShow() {
return this.pwdInfo.inputType == 'text' ? iconVisible : iconInvisible;
},
},
methods: {
// 清空密码
handleClear() {
this.pwdInfo.password = '';
this.$emit('updatePassword');
this.showDelete = false;
},
// 更改密码显示方式
changeVisible() {
if (this.pwdInfo.inputType == 'text') {
this.pwdInfo.inputType = 'password';
} else {
this.pwdInfo.inputType = 'text';
}
},
updatePassword() {
this.$emit('updatePassword');
},
},
watch: {
["pwdInfo.password"]: {
handler(val) {
if(val.length) {
this.showDelete = true;
}
},
deep: true
}
}
}
</script>
<style lang="less">
.password-input-wrap {
width: 325px;
margin: 0 auto;
border-bottom: 1PX solid #C7C8C9;
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
color: #373839;
padding-bottom: 16px;
input{
width: 270px;
font-size: 18px;
}
input::-webkit-input-placeholder {
/* WebKit browsers */
color: #C7C8C9;
}
input:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #C7C8C9;
}
input::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #C7C8C9;
}
input:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #C7C8C9;
}
.close-btn{
width: 16px; height: 16px;
/*padding: 18px 5px;*/
margin-left: auto;
}
.password-show{
width: 20px; height: 20px;
//aass padding: 16px 0 16px 6px;
margin-left: auto;
}
}
</style>
\ No newline at end of file
<template>
<div ref="dragDiv" class="slide-to-check-wrap" :class="{'slide-ok':confirmSuccess}" >
<div class="drag_bg"></div>
<div
ref="moveDiv"
class="handler handler_bg"
:class="{'handler_ok_bg':confirmSuccess}"
@touchstart="mousedownFn($event)">
</div>
</div>
</template>
<script>
export default {
name: "slide-to-check",
data() {
return {
beginClientX: 0, //距离屏幕左端距离
mouseMoveStata: false, //触发拖动状态 判断
maxwidth: "" , //拖动最大宽度,依据滑块宽度算出来的
confirmSuccess: false //验证成功判断
};
},
mounted() {
let htmlEle = document.getElementsByTagName("html")[0];
this.maxwidth = this.$refs.dragDiv.clientWidth - this.$refs.moveDiv.clientWidth - 4;
htmlEle.addEventListener("touchmove", this.mouseMoveFn);
htmlEle.addEventListener("touchend", this.moseUpFn);
},
methods: {
mousedownFn: function(evt) {
if (!this.confirmSuccess) {
evt.preventDefault && evt.preventDefault(); //阻止文字选中等默认事件
this.mouseMoveStata = true;
this.beginClientX = evt.changedTouches[0].clientX;
}
},
mouseMoveFn(evt) {
if (this.mouseMoveStata) {
let width = evt.changedTouches[0].clientX - this.beginClientX;
if (width > 0 && width <= this.maxwidth) {
document.getElementsByClassName("handler")[0].style.left = width + "px";
document.getElementsByClassName("drag_bg")[0].style.width = width + "px";
} else if (width > this.maxwidth) {
this.successHandle();
}
}
},
successHandle() {
this.confirmSuccess = true;
if (window.addEventListener) {
let htmlEle = document.getElementsByTagName("html")[0];
htmlEle.removeEventListener("touchmove", this.mouseMoveFn);
htmlEle.removeEventListener("touchend", this.moseUpFn);
} else {
htmlEle.removeEventListener("touchend", () => {});
}
document.getElementsByClassName("handler")[0].style.left = this.maxwidth + "px";
document.getElementsByClassName("drag_bg")[0].style.width = this.maxwidth + "px";
this.$emit('slideCallback')
},
moseUpFn(evt) {
this.mouseMoveStata = false;
let width = evt.changedTouches[0].clientX - this.beginClientX;
if (width < this.maxwidth) {
document.getElementsByClassName("handler")[0].style.left = 0 + "px";
document.getElementsByClassName("drag_bg")[0].style.width = 0 + "px";
}
}
},
};
</script>
<style lang="less">
.slide-to-check-wrap {
position: relative;
background-color: #e7e8e9;
margin: 0 auto;
width: 325px;
height: 40px;
border-radius:4px;
line-height: 40px;
text-align: center;
&.slide-ok{
background: #449284;
}
.handler {
width: 36px;
height: 36px;
position: absolute;top: 0px;left: 0px;
cursor: move;
margin: 2px;
}
.handler_bg {
background: url('../assets/img/slide-icon.png') no-repeat center ;
background-size: 100% 100%;
}
.handler_ok_bg {
background: url('../assets/img/slide-ok.png') no-repeat center ;
background-size: 100% 100%;
}
.drag_bg {
background-color: #449284;
border-radius: 4px 0 0 4px;
height: 40px;
width: 0px;
}
}
</style>
\ No newline at end of file
module.exports = {
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1',
'^~/(.*)$': '<rootDir>/$1',
'^vue$': 'vue/dist/vue.common.js'
},
moduleFileExtensions: ['js', 'vue', 'json'],
transform: {
'^.+\\.js$': 'babel-jest',
'.*\\.(vue)$': 'vue-jest'
},
'collectCoverage': true,
'collectCoverageFrom': [
'<rootDir>/components/**/*.vue',
'<rootDir>/pages/**/*.vue'
]
}
# LAYOUTS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your Application Layouts.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
<template>
<div>
<nuxt />
</div>
</template>
<style>
</style>
# MIDDLEWARE
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your application middleware.
Middleware let you define custom functions that can be run before rendering either a page or a group of pages.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).
module.exports = {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: '云鹊医登录',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui' },
{ name: 'screen-orientation', content: 'portrait' },
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
{ name: 'format-detection', content: 'telephone=no' },
{ name: 'full-screen', content: 'yes' },
{ name: 'x5-fullscreen', content: 'true' },
{ name: 'referrer', content: 'never' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
// { rel: 'stylesheet', href: '/css/common.css' }
],
style: [
{ cssText: `
@charset "utf-8";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html *{outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:PingFangSC-Regular,-apple-system-font,Source Han Sans,Helvetica Neue,sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}
`, type: 'text/css' }
],
__dangerouslyDisableSanitizers: ['script'],
script: [
{ innerHTML: `
!function(a,b){function c(){var b=f.getBoundingClientRect().width;b/i>540&&(b=540*i);var c=b/10;f.style.fontSize=c+"px",k.rem=a.rem=c}var d,e=a.document,f=e.documentElement,g=e.querySelector('meta[name="viewport"]'),h=e.querySelector('meta[name="flexible"]'),i=0,j=0,k=b.flexible||(b.flexible={});if(g){console.warn("将根据已有的meta标签来设置缩放比例");var l=g.getAttribute("content").match(/initial\-scale=([\d\.]+)/);l&&(j=parseFloat(l[1]),i=parseInt(1/j))}else if(h){var m=h.getAttribute("content");if(m){var n=m.match(/initial\-dpr=([\d\.]+)/),o=m.match(/maximum\-dpr=([\d\.]+)/);n&&(i=parseFloat(n[1]),j=parseFloat((1/i).toFixed(2))),o&&(i=parseFloat(o[1]),j=parseFloat((1/i).toFixed(2)))}}if(!i&&!j){var p=(a.navigator.appVersion.match(/android/gi),a.navigator.appVersion.match(/iphone/gi)),q=a.devicePixelRatio;i=p?q>=3&&(!i||i>=3)?3:q>=2&&(!i||i>=2)?2:1:1,j=1/i}if(f.setAttribute("data-dpr",i),!g)if(g=e.createElement("meta"),g.setAttribute("name","viewport"),g.setAttribute("content","initial-scale="+j+", maximum-scale="+j+", minimum-scale="+j+", user-scalable=no"),f.firstElementChild)f.firstElementChild.appendChild(g);else{var r=e.createElement("div");r.appendChild(g),e.write(r.innerHTML)}a.addEventListener("resize",function(){clearTimeout(d),d=setTimeout(c,300)},!1),a.addEventListener("pageshow",function(a){a.persisted&&(clearTimeout(d),d=setTimeout(c,300))},!1),"complete"===e.readyState?e.body.style.fontSize=12*i+"px":e.addEventListener("DOMContentLoaded",function(){e.body.style.fontSize=12*i+"px"},!1),c(),k.dpr=a.dpr=i,k.refreshRem=c,k.rem2px=function(a){var b=parseFloat(a)*this.rem;return"string"==typeof a&&a.match(/rem$/)&&(b+="px"),b},k.px2rem=function(a){var b=parseFloat(a)/this.rem;return"string"==typeof a&&a.match(/px$/)&&(b+="rem"),b}}(window,window.lib||(window.lib={}));
`, type: 'text/javascript', charset: 'utf-8'},
{ src: 'https://file.yunqueyi.com/h5/js/jquery.js'}
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
'~/assets/styles/global.less',
'vant/lib/index.css'
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{
src: '~/plugins/vue-inject',
ssr: false
}, {
src: '~/plugins/vueComponent',
ssr: false
}, {
src: '~/plugins/slide',
ssr: false
}
],
/*
** Nuxt.js modules
*/
modules: [],
/*
** Build configuration
*/
router: {
base: '/pica_login/' //上下文根据自己的需求自行打开修改
},
build: {
postcss: {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*']
}
}
},
extractCSS: true,
filenames: {
app: ({ isDev }) => isDev ? '[name].js' : '[name].[chunkhash:7].js',
chunk: ({ isDev }) => isDev ? '[name].js' : '[name].[chunkhash:7].js',
css: ({ isDev }) => isDev ? '[name].css' : '[name].[contenthash:7].css',
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[name].[hash:7].[ext]',
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[name].[hash:7].[ext]',
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[name].[hash:7].[ext]'
},
/*
** You can extend webpack config here
*/
extend(config, ctx) {
config.devtool = ['dev', 'test'].indexOf(process.env.NUXT_ENV_APP) !== -1 ? 'source-map' : false;
}
}
}
\ No newline at end of file
因为 它太大了无法显示 源差异 。您可以改为 查看blob
{
"name": "pica-login",
"version": "1.0.0",
"description": "pica-login",
"author": "souse",
"private": true,
"scripts": {
"test": "jest",
"dev": "cross-env NODE_ENV=development NUXT_ENV_APP=dev HOST=0.0.0.0 PORT=3015 nodemon server/index.js --watch server",
"build": "NUXT_ENV_APP=${ENV} nuxt build",
"start": "cross-env NUXT_ENV_APP=${ENV} HOST=0.0.0.0 PORT=3015 NODE_ENV=production node server/index.js",
"generate": "nuxt generate"
},
"dependencies": {
"cookie-universal": "^2.0.16",
"cross-env": "^5.2.0",
"jsencrypt": "^3.0.0-rc.1",
"koa": "^2.6.2",
"lodash": "^4.17.15",
"nuxt": "^2.0.0",
"vant": "^2.0.9",
"vue-infinite-scroll": "^2.0.2",
"web-buried-point": "^2.1.0"
},
"devDependencies": {
"@nuxtjs/axios": "^5.5.4",
"@vue/test-utils": "^1.0.0-beta.27",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^24.1.0",
"jest": "^24.1.0",
"less": "^3.9.0",
"less-loader": "^5.0.0",
"nodemon": "^1.18.9",
"postcss-pxtorem": "^4.0.1",
"qs": "^6.7.0",
"vue-jest": "^3.0.3"
}
}
# PAGES
This directory contains your Application Views and Routes.
The framework reads all the `*.vue` files inside this directory and creates the router of your application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
<template>
<section class="agreements-wrap">
<div class="content" v-html="agreementData.agreementContent">
</div>
</section>
</template>
<script>
import { getAgreements } from "../service";
export default {
name: "agreement-pages",
async asyncData({ query }) {
const { data } = await getAgreements({
agreementType: query.type
})
return {
agreementData: data
}
}
}
</script>
<style>
.content p {
width: 100%;
font-size: 14px;
overflow: hidden;
word-wrap:break-word;
}
</style>
<style scoped lang="less">
.agreements-wrap {
padding: 20px 18px;
}
</style>
\ No newline at end of file
<template>
<section class="index-container" id="index-container">
<img class="pica-icon" src="~/assets/img/icon-pica.png" alt="" />
<p class="description">欢迎登录云鹊医体验更多内容!</p>
<input-phone
:defaultMobile="storeMobile"
:placeholder-text="placeholderText"
@getPhone="getPhone"
>
</input-phone>
<my-button
:button-info="buttonInfo"
@handlerClick="handlerClick"
>
</my-button>
<p class="tips">未注册手机号验证成功后自动注册</p>
<div class="bottom-wrap">
<login-types
:arrayData="loginTypes"
@goToTarget="goToTarget"
:is_Wx="is_Wx"
>
</login-types>
<div class="protocol">
登录即代表您已同意<span @click="goToAgreements(1)" v-bp="{ component_tag: '903#903005'}">《云鹊医用户协议》</span><span @click="goToAgreements(5)" v-bp="{ component_tag: '903#903006'}">《云鹊隐私声明》</span>
</div>
</div>
<no-ssr>
<Loading v-if="showLoading"/>
</no-ssr>
</section>
</template>
<script>
import MyButton from '@/components/button';
import InputPhone from '@/components/input-phone';
import LoginTypes from '@/components/login-types';
import Loading from '@/components/loading';
import accountIcon from '../assets/img/icon-account.png';
import wxIcon from '../assets/img/icon-wx.png';
import { isIOS } from '@/utils';
import { is_weixin } from '@/utils/wxLogin';
import { verifyPhone } from '@/utils/verify';
import { sendEncryptRequest } from '@/utils/encrypt';
import { wxGetCode } from '@/utils/wxLogin'
import { mapActions } from 'vuex';
import { setCookie, getCookie, delCookie } from '@/utils/cookieFun';
import {
checkNeedImgCode,
getMessageCode
} from "@/service";
export default {
name: 'index-container',
components: {
MyButton,
InputPhone,
LoginTypes,
Loading
},
data() {
return {
buttonInfo: {
buttonText: '获取验证码',
isDisabled: true
},
placeholderText: '请输入手机号',
loginTypes: [
{
img: accountIcon,
content: '帐号密码登录',
url: `/phone-page?fromType=1`,
buriedData: '903#903002'
},
{
img: wxIcon,
content: '微信登录',
url: '/wxLogin',
buriedData: '903#903003'
}
],
mobile: '', //手机号
showLoading: false,
storeMobile: '',
is_Wx: false
};
},
created() {
if(process.client) {
// 获取当前可视区域的高度
const height = document.documentElement.clientHeight;
// 在页面整体加载完毕时
window.onresize = () => {
// 把获取到的高度赋值给根div
if(!isIOS()) {
document.getElementById('index-container').style.height = `${height}px`;
}
};
}
},
mounted() {
this.storeMobile = localStorage.getItem('mobile')? localStorage.getItem('mobile') : '';
if(this.$route.query.target_url) { //将等候跳转链接存储在本地
sessionStorage.setItem('target_url', this.$route.query.target_url)
}
/*兼容安卓手机软键盘弹起居底元素向上浮动---start*/
/*const _this = this
const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = () => {
const nowClientHeight = document.documentElement.clientHeight || document.body.clientHeight;
console.log(clientHeight, nowClientHeight)
if (clientHeight > nowClientHeight) {
//键盘弹出的事件处理
if(!isIOS()) {
_this.isHide = true
}
}
else {
//键盘收起的事件处理
_this.isHide = false
}
};*/
/*兼容安卓手机软键盘弹起居底元素向上浮动---end*/
/*非微信环境下去掉微信按钮*/
this.is_Wx = is_weixin();
},
methods: {
...mapActions(['setImgCodeData', 'setNeedTimer']),
handlerClick() {
if(!verifyPhone(this.mobile)) {
this.$toast('请输入正确的手机号');
return;
}
this.showLoading = true;
this.checkControlStatus();
//this.setMobile(this.mobile);
localStorage.setItem('mobile', this.mobile);
//埋点
this.$sendBuriedData({
component_tag: '903#903001'
})
},
goToTarget(item) {
//如果本页面输入已输入手机号,跳转到其他页面时需要把手机号带过去
if(verifyPhone(this.mobile)) {
//this.setMobile(this.mobile)
localStorage.setItem('mobile', this.mobile);
}
if(item.url == '/wxLogin') {
wxGetCode(`https://${location.host}/pica_login/wxLogin`)
//this.$router.replace('/wxLogin')
} else {
this.$router.push(item.url);
}
//埋点
if(item.buriedData) {
this.$sendBuriedData({
component_tag: item.buriedData
})
}
},
getPhone(val) {
this.mobile = val;
if(this.mobile.length != 11) {
this.buttonInfo.isDisabled = true;
} else {
this.buttonInfo.isDisabled = false;
}
},
goToAgreements(type) {
this.$router.push({
path: '/agreement-pages',
query: {
type: type
}
})
},
checkControlStatus() {
let data = {
mobile: this.mobile,
}
sendEncryptRequest(data, params => {
checkNeedImgCode(params).then( res => {
this.showLoading = false;
if(res.code == '000000') {
if(res.data.capCode) {//跳转至风控页面
this.setImgCodeData(res.data)
this.$router.push({
path: '/slide-check-page',
query: {
fromType: 0 //验证码登录
}
})
} else {//不需要风控直接获取验证码
this.getMessageCode();
}
} else {
this.$toast(res.message);
}
})
});
},
getMessageCode() {
let data = {
flag: 0,
mobile: this.mobile
}
sendEncryptRequest(data, params => {
getMessageCode(params).then(res => {
if(res.code == '000000') {
this.setNeedTimer();
this.$router.push({
path: '/msg-code-page',
query: {
fromType: 0 //验证码登录
}
})
} else {
this.$toast(res.message);
return;
}
})
});
}
}
};
</script>
<style>
html,body,#__nuxt,#__layout, #__layout>div {
height: 100%;
}
</style>
<style scoped lang="less">
.index-container {
overflow: hidden;
height: 100%;
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
.pica-icon {
display: block;
width: 59.51px;
height: 59.51px;
margin: 40px auto 16px auto;
}
.description {
color: #373839;
font-size: 20px;
line-height: 20px;
text-align: center;
margin-bottom: 50px;
}
.button-container {
margin-top: 16px;
margin-bottom: 12px;
}
.tips {
color: #979899;
font-size: 12px;
line-height: 12px;
text-align: center;
}
.bottom-wrap {
margin-top: auto;
margin-bottom: 30px;
}
.login-types-container {
width: 100%;
margin-bottom: 40px;
}
.protocol {
width: 340px;
font-size: 12px;
line-height: 12px;
color: #979899;
text-align: justify;
margin: 0 auto;
span {
color: #373839;
}
}
}
</style>
<template>
<div class="msg-code-page-wrap">
<p class="title">输入验证码</p>
<p class="target-phone">验证码已发送到<i>{{getPhoneNum}}</i></p>
<MsgCode :codeInfo="codeInfo"/>
<p :class="getSMSClass" @click="getSMSCode(1)">{{SMSTips}}</p>
</div>
</template>
<script>
import MsgCode from '@/components/msg-code';
import {checkNeedImgCode, getMessageCode} from "@/service";
import { sendEncryptRequest } from '@/utils/encrypt';
import { mapActions, mapState } from 'vuex';
export default {
name: "msg-code-page",
components: {
MsgCode,
},
asyncData({query}) {
return {
fromType: query.fromType,
getMsgCode: query.getMsgCode
}
},
data() {
return {
mobile: '',
SMSTips: '重新获取验证码',
countDownNum: 60, // 倒计时
timer: null, // 倒计时定时器
codeInfo: {
fromType: '', // 页面来源 url传参
},
};
},
computed: {
...mapState({
needTimer: state => state.needTimer
}),
getPhoneNum() {
// let phoneNum = this.$store.state.mobile;
if( this.mobile ) {
return this.mobile.replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3');
}
},
getSMSClass() {
if( this.countDownNum == 60 ){
return 'code-under-tips';
}else{
return 'code-under-tips gray';
}
}
},
mounted() {
this.getSMSCode();
this.mobile = localStorage.getItem('mobile')? localStorage.getItem('mobile') : '';
this.codeInfo.fromType = this.fromType; //由登录页面传过来的页面来源: 0验证码登录,2微信登录手机号绑定
},
methods: {
...mapActions(['setImgCodeData']),
getSMSCode(needGetMsg) {
// 倒计时过程中不可点
if(this.needTimer) {
this.timeCount()
} else if(!needGetMsg) {
return;
}
if (this.fromType == 0) {
this.$sendBuriedData({
component_tag: '906#906001'
})
} else if (this.fromType == 2) {
this.$sendBuriedData({
component_tag: '910#910001'
})
}
let data = {
mobile: this.mobile,
}
console.log('data',data)
if(needGetMsg) {
sendEncryptRequest(data, params => {
checkNeedImgCode(params).then( res => {
this.showLoading = false;
if(res.code == '000000') {
if(res.data.capCode) {//跳转至风控页面
this.setImgCodeData(res.data)
this.$router.replace({
path: '/slide-check-page',
query: {
fromType: this.fromType
}
})
} else {//不需要风控直接获取验证码
this.getMessageCode();
}
} else {
this.$toast(res.message);
}
})
});
} else {
// 前面不触发风控时 开始倒计时
this.timeCount();
}
},
timeCount() {
clearInterval(this.timer);
this.countDownNum -= 1;
this.SMSTips = `${this.countDownNum}秒后重新获取验证码`;
this.timer = setInterval( () => {
this.countDownNum -= 1;
this.SMSTips = `${this.countDownNum}秒后重新获取验证码`;
if(this.countDownNum == 0){
this.SMSTips = '重新获取验证码';
clearInterval(this.timer);
this.countDownNum = 60;
}
}, 1000);
},
getMessageCode() {
let data = {
flag: this.fromType,
mobile: this.mobile
}
sendEncryptRequest(data, params => {
getMessageCode(params).then(res => {
if(res.code == '000000') {
this.$toast(res.message);
this.timeCount()
} else {
this.$toast(res.message);
return;
}
})
});
}
},
}
</script>
<style lang="less">
.msg-code-page-wrap {
width: 100%;
height: auto;
box-sizing: border-box;
padding: 0 25px;
position: relative;
.title {
height: 36px;
line-height: 36px;
padding-top: 22px;
font-size: 20px;
font-weight: 700;
color: #373839;
}
.target-phone {
height: 32px;
line-height: 32px;
font-size: 16px;
color: #979899;
padding-bottom: 33px;
i {
font-style: normal;
color: #333333;
margin-left: 6px;
line-height: 32px;
display: inline-block;
}
}
.code-under-tips{
width: 100%; height: 34px;
line-height: 34px;
margin: 10px 0;
font-size: 14px;
color: #5890DD;
&.gray{
color: #979899;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="password-page-wrap">
<div class="inner-title">账号密码</div>
<PasswordInput :pwdInfo="pwdInfo" @updatePassword="updatePassword"/>
<MyButton class="login-button" :button-info="buttonInfo" @handlerClick="handlerClick"/>
<div class="tips-content">
<p class="find-password">找回密码前往云鹊医APP</p>
</div>
<DialogModal v-if="showLockModal" :dialogInfos="dialogInfos" @cancelBtn="cancelBtn" @submitBtn="submitBtn"/>
<no-ssr>
<Loading v-if="showLoading"/>
</no-ssr>
</div>
</template>
<script>
import MyButton from '@/components/button';
import PasswordInput from '@/components/password-input';
import Loading from '@/components/loading';
import DialogModal from '@/components/dialog'
import { sendEncryptRequest } from '@/utils/encrypt';
import '@/utils/prototype';
import { passwordLoginReq, signAgreements } from "@/service";
import { setCookie, getCookie, delCookie } from '@/utils/cookieFun';
export default {
name: "password-page",
components: {
MyButton,
PasswordInput,
Loading,
DialogModal,
},
data() {
return {
showLockModal: false, // 是否显示错误上限提醒弹窗
showLoading: false,
pwdInfo: {
inputType: 'password', // 默认输入框类型(password / text)
password: '',
},
buttonInfo: {
buttonText: '登录',
isDisabled: true
},
dialogInfos: {
title: '提醒',
content: '',
cancelText: '我知道了',
affirmText: '其它方式登录'
},
};
},
computed: {
},
created() {
},
methods: {
updatePassword() {
let status = this.pwdInfo.password != '' ? false : true;
this.buttonInfo.isDisabled = status;
},
handlerClick() {
this.showLoading = true;
let data = {
mobile: localStorage.getItem('mobile'),
password: `${this.pwdInfo.password}`.MD5(32).toUpperCase(), // 密码要MD5处理
bizType: 1, // 新老版本业务区分标识(1:新版本,未传值:老版本)
};
this.$sendBuriedData({
component_tag: '908#908001'
})
sendEncryptRequest(data, params => {
passwordLoginReq(params).then( res => {
this.showLoading = false;
if(res.code == '000000') {
// 登录成功并成功返回
this.loginCallback(res.data);
} else if(res.code == '216547' || res.code == '216548' || res.code == '216549') {
this.dialogInfos.content = res.message;
this.showLockModal = true;
} else {
this.$toast(res.message);
}
})
});
},
loginCallback(data) {
// 登录回调
delCookie('token');
setCookie('token', data.token);
this.signAnAgreements();
if(sessionStorage.getItem('target_url')) {
const target_url = decodeURIComponent(sessionStorage.getItem('target_url'));
window.location.replace(target_url);
} else {
console.log('登录成功,后面跳转页面>>>>>>'); // 此行代码测试用,后续上线前删掉 -----------------------------------------------
}
},
signAnAgreements() {
signAgreements({}).then(res => {
if(res.code != '000000') {
this.$toast(res.message)
}
})
},
cancelBtn() {
this.showLockModal = false;
},
submitBtn() {
// console.log('回到登录首页')
this.$router.push({
path: '/',
})
},
},
}
</script>
<style lang="less">
.password-page-wrap{
width: 100%;
height: auto;
box-sizing: border-box;
padding: 0 25px;
.inner-title{
width: 100%; height: 68px;
padding-top: 6px;
line-height: 68px;
color: #373839; font-size: 20px; font-weight: 700;
}
.login-button{
margin-top: 16px;
}
.tips-content {
.find-password {
color: #979899;
font-size: 14px;
line-height: 14px;
margin: 16px auto 0 auto;
text-align: center;
}
}
}
</style>
\ No newline at end of file
<template>
<section class="phone-page-wrap">
<p class="title">{{baseInfo[fromType].titleText}}</p>
<input-phone
:defaultMobile="defaultMobile"
:placeholderText="baseInfo[fromType].placeholderText"
@getPhone="getPhone"
>
</input-phone>
<my-button
:button-info="buttonInfo"
@handlerClick="handlerClick"
>
</my-button>
<div class="tips-content">
<p v-show="fromType == 2" class="find-password">找回密码前往云鹊医APP</p>
</div>
<no-ssr>
<Loading v-if="showLoading"/>
</no-ssr>
<my-dialog
:dialogInfos="dialogInfos"
@cancelBtn="cancelBtn"
@submitBtn="submitBtn"
v-show="showDialog"
>
</my-dialog>
</section>
</template>
<script>
import InputPhone from '@/components/input-phone';
import MyButton from '@/components/button';
import Loading from '@/components/loading';
import MyDialog from '@/components/dialog';
import { verifyPhone } from '@/utils/verify';
import { sendEncryptRequest } from '@/utils/encrypt';
import { mapState, mapActions } from 'vuex';
import {
verityStatus,
checkNeedImgCode,
getMessageCode
} from "@/service";
export default {
name: "phone-page",
components: {
InputPhone,
MyButton,
Loading,
MyDialog
},
data() {
return {
defaultMobile: '',
baseInfo: {
/*'1': {
titleText: '账号密码登录',
placeholderText: '账号为11位手机号',
},*/
'1': {
titleText: '账号密码登录',
placeholderText: '账号为11位手机号',
buriedPoint: '907#907001'
},
'2': {
titleText: '微信已关联,请绑定手机号',
placeholderText: '请输入手机号',
buriedPoint: '909#909001'
}
},
buttonInfo: {
buttonText: '下一步',
isDisabled: true
},
showLoading: false,
dialogInfos: {},
showDialog: false,
mobile: ''
}
},
asyncData( {query} ) {
return {
fromType: query.fromType || 1 , // 0验证码登录,1账号密码登录,2微信登录手机号绑定
}
},
computed: {
...mapState({
code: state => state.code,
}),
},
mounted() {
this.defaultMobile = localStorage.getItem('mobile')? localStorage.getItem('mobile') : '';
},
methods: {
...mapActions(['setImgCodeData', 'setNeedTimer']),
handlerClick() {
if(!verifyPhone(this.mobile)) {
this.$toast('请输入正确的手机号');
return;
}
localStorage.setItem('mobile', this.mobile)
this.showLoading = true;
if(this.fromType == 1) { //账号密码登录
this.verifyMobileStatus();
} else if(this.fromType == 2) { //微信登录绑定手机号
this.wxBindMobile();
}
if(this.baseInfo[this.fromType].buriedPoint) {
this.$sendBuriedData({
component_tag: this.baseInfo[this.fromType].buriedPoint
})
}
},
getPhone(val) {
this.mobile = val;
if(this.mobile.length != 11) {
this.buttonInfo.isDisabled = true;
} else {
this.buttonInfo.isDisabled = false;
}
},
wxBindMobile() {
let data = {
mobile: this.mobile,
}
sendEncryptRequest(data, params => {
checkNeedImgCode(params).then( res => {
this.showLoading = false;
if(res.code == '000000') {
if(res.data.capCode) {//跳转至风控页面
this.setImgCodeData(res.data)
this.$router.replace({
path: '/slide-check-page',
query: {
fromType: 2 //微信绑定手机号流程进入触发风控页面
}
})
} else {//不需要风控直接获取验证码
this.getMessageCode();
}
} else {
this.$toast(res.message);
}
})
});
},
verifyMobileStatus() {
let data = {
mobile: this.mobile,
bizType: 3, //业务类型, 2-手机号格式校验业务,3-密码登录校验业务
}
sendEncryptRequest(data, params => {
verityStatus(params).then( res => {
this.showLoading = false;
if(res.code == '000000') { //手机号可以正常登录
this.$router.push({
path: '/password-page',
query: {
fromType: 1
}
})
} else if(res.code == '216547' || res.code == '216548') { //尚未设置密码
this.dialogInfos = {
title: '提醒',
//content: `该手机号<span style="color: #373839">${this.mobile}</span>尚未设置密码,请先设置密码。`,
content: res.message,
cancelText: '取消',
affirmText: '其他登录方式'
}
this.showDialog = true;
} else {
this.$toast(res.message);
return;
}
})
});
},
cancelBtn() {
this.showDialog = false;
return;
},
submitBtn() { //选择其他登录方式
this.$router.push('/')
},
getMessageCode() {
let data = {
flag: 2,
mobile: this.mobile
}
sendEncryptRequest(data, params => {
getMessageCode(params).then(res => {
if(res.code == '000000') {
this.setNeedTimer();
this.$router.replace({
path: '/msg-code-page',
query: {
fromType: 2 //微信绑定手机号
}
})
} else {
this.$toast(res.message);
return;
}
})
});
}
}
}
</script>
<style scoped lang="less">
.phone-page-wrap {
padding: 0 25px;
overflow: hidden;
.title {
color: #373839;
font-size: 20px;
line-height: 20px;
margin: 30px 0 40px 0;
}
.button-container {
margin-top: 16px;
}
.tips-content {
.find-password {
color: #979899;
font-size: 14px;
line-height: 14px;
margin: 16px auto 0 auto;
text-align: center;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="slide-check-wrap">
<!-- <p class="slide-text">向右滑动完成验证</p>
<SlideToCheck @slideCallback="slideCallback"/>-->
<div id="imgScode"></div>
</div>
</template>
<script>
import SlideToCheck from '@/components/slide-to-check';
import {
/*getImgCode,
checkAndGetCode*/
checkNeedImgCode,
getMessageCode
} from '@/service'
import { mapState, mapActions } from 'vuex';
import { sendEncryptRequest } from '@/utils/encrypt';
export default {
name: "slide-check",
components: {
SlideToCheck,
},
computed: {
...mapState({
imgCodeData: state => state.imgCodeData,
}),
},
asyncData({query}) {
return {
fromType: query.fromType //0验证码登录 2微信登录绑定手机号
}
},
data() {
return {
mobile: ''
}
},
mounted() {
this.mobile = localStorage.getItem('mobile')? localStorage.getItem('mobile') : '';
const _this = this;
if (JSON.stringify(_this.imgCodeData) === '{}') {
if(this.fromType == 2) {
this.$router.replace({
path: '/phone-page',
query: {
fromType: 2 //微信登录绑定手机号
}
})
} else {
this.$router.replace('/')
}
return;
}
$('#imgScode').imgcode({
frontimg: 'data:image/png;base64,' + _this.imgCodeData.slidingImage,
backimg: 'data:image/png;base64,' + _this.imgCodeData.backImage,
yHeight : _this.imgCodeData.yHeight,
refreshcallback : function() {
//刷新验证码
_this.refreshImg(undefined);
},
callback: function(msg) {
const $this = this;
_this.getMsgCode($this, msg, _this.imgCodeData, undefined);
}
})
},
methods: {
...mapActions(['setNeedTimer']),
getImg(type) { //
const _this = this;
let data = {
mobile: this.mobile,
}
sendEncryptRequest(data, params => {
checkNeedImgCode(params).then(res => {
$('#imgScode').imgcode({
frontimg: 'data:image/png;base64,' + res.data.slidingImage,
backimg: 'data:image/png;base64,' + res.data.backImage,
yHeight : res.data.yHeight,
refreshcallback : function() {
//刷新验证码
_this.refreshImg(type);
},
callback: function(msg) {
const $this = this;
_this.getMsgCode($this, msg, res.data, type);
}
})
})
});
},
refreshImg(type) {
const _this = this;
let data = {
mobile: this.mobile,
}
sendEncryptRequest(data, params => {
checkNeedImgCode(params).then(res => {
$('#imgScode').imgcode({
frontimg: 'data:image/png;base64,' + res.data.slidingImage,
backimg: 'data:image/png;base64,' + res.data.backImage,
yHeight : res.data.yHeight,
refreshcallback : function() {
//刷新验证码
_this.getImg(type);
},
callback: function(msg) {
const $this = this;
_this.getMsgCode($this, msg, res.data, type);
}
})
})
});
},
getMsgCode($this, msg, data, type) {
let data1 = {
mobile: this.mobile,
flag: this.fromType, //0登录(默认)1注册 2微信登录绑定手机 3修改手机 4重置密码
capCode: data.capCode,
xpos: msg.xpos,
imageW: msg.imageW
}
console.log('data1',data1)
sendEncryptRequest(data1, params => {
getMessageCode(params).then(res => {
if(res.code == '000000') {
this.setNeedTimer();
this.$router.replace({
path: '/msg-code-page',
query: {
fromType: this.fromType,
}
})
} else {
$this.getfail(res.message);
}
})
});
this.$sendBuriedData({
component_tag: '905#905001'
})
},
},
}
</script>
<style lang="less">
.slide-check-wrap{
width: auto;
height: auto;
margin: 0 auto;
.slide-text{
width: 100%;
color: #373839; font-size: 20px; font-weight: 700;
padding: 30px 0 20px;
}
}
.code-k-div {
position: fixed;
top:0;
left: 0;
right:0;
bottom:0;
background-color: rgba(0,0,0,.2);
z-index: 999;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
}
.icon-login-bg{
background-image: url(../assets/loginicon.png);
background-repeat: no-repeat;
}
.code-con{
width: 330px;
background-color: #fff;
z-index: 1000;
-moz-user-select: none;
-webkit-user-select: none;
align-self: flex-start;
-webkit-align-self: flex-start;
margin-top: 30px;
}
.code-img{
margin: 5px auto;
padding: 5px 0;
width: 300px;
background-color: #f5f6f7;
}
.code-back-img {
width: 100%;
}
.code-img img{
display: block;
}
.icon-w-25{
display: inline-block;
width: 25px;
height: 25px;
text-indent: -9999px;
}
.icon-push{
background-position: 81% 75%;
}
.code-push{
height: 25px;
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
}
.code-btn{
position: relative;
height: 30px;
text-align: center;
color: #999;
margin: 10px 10px;
box-sizing: border-box;
background-color: #f5f6f7;
border-radius: 15px;
border: 1px solid #e1e1e1;
}
.code-btn-m{
position: absolute;
width: 35px;
height: 35px;
border-radius: 50%;
background-color: #f5f6f7;
border: 1px solid #e1e1e1;
z-index: 5;
top:-4px;
left: 5px;
box-shadow: 0 0 3px #ccc;
cursor: pointer;
background-position: 39.5% 50%;
}
.code-btn-img{
background-image:url(../assets/arrow.png);
background-repeat: no-repeat;
}
.code-btn-img.active{
background-position: 82% 50%;
}
.code-span{
display: block;
height: 100%;
font-size: 14px;
line-height: 30px;
}
.code-btn-img.error{
background-position: 6px 50%;
}
.code-img-con{
position: relative;
}
.code-mask{
width: 60px;
position: absolute;
top:0;
left: 0;
z-index: 10;
}
.code-front-img {
width: 100%;
}
.code-tip{
padding-left: 10px;
font-size: 12px;
color: #999;
margin-top: 4px;
}
.code-tip-red{
color: red;
}
.code-tip-green{
color: green;
}
</style>
\ No newline at end of file
<template>
<section class="wx-login-wrap"></section>
</template>
<script>
import { wxLogin, signAgreements } from '@/service'
import { sendEncryptRequest } from '@/utils/encrypt';
import { setCookie, getCookie, delCookie } from '@/utils/cookieFun';
import { mapActions } from 'vuex';
import { wxGetCode } from '@/utils/wxLogin'
export default {
name: "wxLogin",
data() {
return {
}
},
asyncData({query}) {
return {
code: query.code
}
},
mounted() {
if(!this.code) {
this.$router.replace('/')
//wxGetCode(`https://${location.host}/pica_login/wxLogin`)
} else {
this.doWxLogin();
}
},
methods: {
...mapActions(['setCode', 'setUnionId']),
doWxLogin() {
let data = {
weChatCode: this.code,
weChatLoginType: '1',//1云鹊医2云鹊健康3云鹊医联4nccd大众版5nccd医生版6,云鹊医app微信登陆,7云鹊健康app微信登陆
bizType: 1, //1:h5微信登录,其它:原生微信登录
}
sendEncryptRequest(data, params => {
wxLogin(params).then( res => {
if (res.code == '000000') {
if(res.data.bindFlag == 1) { //不需要绑定手机号
delCookie('token');
setCookie('token', res.data.token);
this.signAnAgreements();
if(sessionStorage.getItem('target_url')) {
const target_url = decodeURIComponent(sessionStorage.getItem('target_url'));
window.location.replace(target_url);
} else {
console.log('登录成功,后面跳转页面>>>>>>'); // 此行代码测试用,后续上线前删掉 -----------------------------------------------
}
} else { //需要绑定手机号
this.setCode(this.code);
this.setUnionId(res.data.unionId);
this.$router.replace({
path: '/phone-page',
query: {
fromType: 2 //微信登录绑定手机号
}
})
}
} else {
this.$toast(res.message)
}
})
});
},
signAnAgreements() {
signAgreements({}).then(res => {
if(res.code != '000000') {
this.$toast(res.message)
}
})
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
# PLUGINS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains Javascript plugins that you want to run before mounting the root Vue.js application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).
/**
* 图片验证码
*/
(function ($) {
$.fn.imgcode = function (options) {
// 初始化参数
var defaults = {
frontimg: "",
backimg: "",
refreshImg: "",
getsuccess: "",
getfail: "",
maskclose: true,
callback: "",
// 回调函数
refreshcallback: "",
yHeight: 1
};
var opts = $.extend(defaults, options);
return this.each(function () {
var $this = $(this); // 获取当前对象
var html = '<div class="code-k-div">' + '<div class="code-con">' + '<div class="code-img">' + '<div class="code-img-con">' + '<div class="code-mask"><img class="code-front-img" src="' + opts.frontimg + '"></div>' + '<img id="BigImg" class="code-back-img" src="' + opts.backimg + '"></div>' + '<div class="code-push"><i class="icon-login-bg icon-w-25 icon-push">刷新</i><span class="code-tip"></span></div>' + '</div>' + '<div class="code-btn">' + '<div class="code-btn-img code-btn-m"></div>' + '<span class="code-span">按住滑块,拖动完成上方拼图</span>' + '</div></div></div>';
$this.html(html);
$(".code-mask").css("margin-top", `${(opts.yHeight * 2) / 75}rem`)
// 定义拖动参数
var $divMove = $(this).find(".code-btn-img"); // 拖动按钮
var $divWrap = $(this).find(".code-btn"); // 鼠标可拖拽区域
var mX = 0,
mY = 0; // 定义鼠标X轴Y轴
var dX = 0,
dY = 0; // 定义滑动区域左、上位置
var isDown = false; // touchmove标记
if (document.attachEvent) { // ie的事件监听,拖拽div时禁止选中内容,firefox与chrome已在css中设置过-moz-user-select:
// none; -webkit-user-select:
// none;
$divMove[0].attachEvent('onselectstart',
function () {
return false;
});
}
// 按钮拖动事件
$divMove.on('touchstart', function (e) {
console.log('touchstart');
// 清除提示信息
$this.find(".code-tip").html("");
var event = e || window.event;
// mX = event.originalEvent.touches[0].pageX;
mX = event.originalEvent.pageX;
dX = $divWrap.offset().left;
dY = $divWrap.offset().top;
console.log('event', mX, dX, dY)
isDown = true; // 鼠标拖拽启
$(this).addClass("active");
// 修改按钮阴影
$divMove.css({
"box-shadow": "0 0 8px #666"
});
}); // 按钮拖动事件
$divMove.on('mousedown', function (e) {
console.log('mousedown');
// 清除提示信息
$this.find(".code-tip").html("");
var event = e || window.event;
// mX = event.originalEvent.touches[0].pageX;
mX = event.originalEvent.pageX;
dX = $divWrap.offset().left;
dY = $divWrap.offset().top;
console.log('event', mX, dX, dY)
isDown = true; // 鼠标拖拽启
$(this).addClass("active");
// 修改按钮阴影
$divMove.css({
"box-shadow": "0 0 8px #666"
});
});
/*// 点击背景关闭
if (opts.maskclose) {
$this.find(".code-k-div").unbind('click').click(function() {
$this.html("");
})
}*/
// 刷新code码
$this.find(".icon-push").unbind('click').click(function () {
opts.refreshcallback();
});
// 鼠标点击松手事件
$divMove.on('touchend', function (e) {
var lastX = $this.find(".code-mask").offset().left - dX - 1;
isDown = false; // 鼠标拖拽启
$divMove.removeClass("active");
// 还原按钮阴影
$divMove.css({
"box-shadow": "0 0 3px #ccc"
});
var imgW = $("#BigImg").width()
returncode(lastX, imgW);
}); // 鼠标点击松手事件
$divMove.on('mouseup', function (e) {
console.log('mouseup');
var lastX = $this.find(".code-mask").offset().left - dX - 1;
isDown = false; // 鼠标拖拽启
$divMove.removeClass("active");
// 还原按钮阴影
$divMove.css({
"box-shadow": "0 0 3px #ccc"
});
var imgW = $("#BigImg").width()
returncode(lastX, imgW);
});
// 滑动事件
$divWrap.on('touchmove', function (event) {
console.log('touchmove', event);
var event = event || window.event;
// var x = event.originalEvent.touches[0].pageX; // 鼠标滑动时的X轴
var x = event.originalEvent.pageX; // 鼠标滑动时的X轴
if (isDown) {
if (x > (dX + 30) && x < dX + $(this).width() - 20) {
$divMove.css({
"left": (x - dX - 20) + "px"
}); // div动态位置赋值
$this.find(".code-mask").css({
"left": (x - dX - 30) + "px"
});
}
}
event.preventDefault();
});
// 滑动事件
$divWrap.on('mousemove', function (event) {
console.log('mousemove', event);
// debugger
var event = event || window.event;
// var x = event.originalEvent.touches[0].pageX; // 鼠标滑动时的X轴
var x = event.originalEvent.pageX; // 鼠标滑动时的X轴
if (isDown) {
if (x > (dX + 30) && x < dX + $(this).width() - 20) {
$divMove.css({
"left": (x - dX - 20) + "px"
}); // div动态位置赋值
$this.find(".code-mask").css({
"left": (x - dX - 30) + "px"
});
}
}
event.preventDefault();
});
// 返回坐标系
function returncode(xpos, imageW) {
opts.callback({
xpos: xpos,
imageW: imageW
});
}
// 验证数据
function checkcode(code) {
var iscur = true;
// 模拟ajax
setTimeout(function () {
if (iscur) {
checkcoderesult(1, "验证通过");
$this.find(".code-k-div").remove();
opts.callback({
code: 1000,
msg: "验证通过",
msgcode: "23dfdf123"
});
} else {
$divMove.addClass("error");
checkcoderesult(0, "验证不通过");
opts.callback({
code: 1001,
msg: "验证不通过"
});
setTimeout(function () {
$divMove.removeClass("error");
$this.find(".code-mask").animate({
"left": "0px"
},
200);
$divMove.animate({
"left": "10px"
},
200);
},
300);
}
},
500)
}
// 刷新图标
opts.refreshImg = function (data) {
console.log(data)
// $this.find(".code-img-con .code-front-img").attr("src", data.frontImg);
// $this.find(".code-img-con .code-back-img").attr("src", data.backGoundImg);
}
// 验证成功
opts.getsuccess = function () {
checkcoderesult(1, "验证通过");
setTimeout(function () {
$this.find(".code-k-div").remove();
},
800);
}
// 验证失败
opts.getfail = function (txt) {
$divMove.addClass("error");
checkcoderesult(0, txt);
setTimeout(function () {
$divMove.removeClass("error");
$this.find(".code-mask").animate({
"left": "0px"
},
200);
$divMove.animate({
"left": "10px"
},
200);
},
400);
}
// 验证结果
function checkcoderesult(i, txt) {
if (i == 0) {
$this.find(".code-tip").addClass("code-tip-red");
} else {
$this.find(".code-tip").addClass("code-tip-green");
}
$this.find(".code-tip").html(txt);
}
})
}
})(jQuery);
\ No newline at end of file
import Vue from 'vue';
import { BASE_URL } from '@/utils/enumerate';
import rocNative from '@/utils/jsbridge';
import WebBuriedPoint, { sendBuriedData } from 'web-buried-point';
const { name } = require('../package.json');
const { NUXT_ENV_APP } = process.env;
Vue.prototype.$rocNative = new rocNative();
Vue.prototype.$sendBuriedData = sendBuriedData;
if (name === 'nuxt_ssr') throw Error('需要给当前项目起一个有意义的名称,多英文单词用 _ 拼接,不能有空格。修改文件:package.json (name)');
Vue.use(WebBuriedPoint, {
class_name: name || 'pica-login',
url: `${BASE_URL[NUXT_ENV_APP]}/file/log/trace1`
});
\ No newline at end of file
import Vue from 'vue'
import {
CountDown,
Row,
Col,
Collapse,
CollapseItem,
Sticky,
Icon,
Field,
Cell,
CellGroup,
Button,
Dialog,
Toast,
Checkbox,
Popup,
CheckboxGroup,
RadioGroup,
Radio,
Progress,
ImagePreview,
Uploader,
Overlay,
Loading,
Search,
List
} from 'vant';
Vue.use(CountDown)
.use(Row)
.use(Col)
.use(Collapse)
.use(CollapseItem)
.use(Sticky)
.use(Icon)
.use(Field)
.use(Cell)
.use(CellGroup)
.use(Button)
.use(Dialog)
.use(Toast)
.use(Checkbox)
.use(Popup)
.use(CheckboxGroup)
.use(RadioGroup)
.use(Radio)
.use(Progress)
.use(ImagePreview)
.use(Uploader)
.use(Overlay)
.use(Loading)
.use(Search)
.use(List);
const Koa = require('koa')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = new Koa()
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = !(app.env === 'production')
async function start() {
// Instantiate nuxt.js
const nuxt = new Nuxt(config)
const {
host = process.env.HOST || '127.0.0.1',
port = process.env.PORT || 3008
} = nuxt.options.server
// Build in development
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
} else {
await nuxt.ready()
}
app.use((ctx) => {
ctx.status = 200
ctx.respond = false // Bypass Koa's built-in response handling
ctx.req.ctx = ctx // This might be useful later on, e.g. in nuxtServerInit or with nuxt-stash
nuxt.render(ctx.req, ctx.res)
})
app.listen(port, host)
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
})
}
start()
import Axios from 'axios';
import { Toast } from 'vant';
import { API_CONFIG, REPONSE_CODE } from '@/utils/enumerate';
import { isIOS, isAndroid } from '@/utils';
const { VUE_ENV } = process.env; // server or client
import { getCookie } from '@/utils/cookieFun';
Axios.interceptors.request.use(
config => {
// 0. Do something before request is sent
// 1. can be add loading
// 2. make sure if need token
// console.log('config>>>>>> ', config)
const method = config.method.toLocaleLowerCase();
if (method === 'post' || method === 'put' || method === 'delete') {}
if (config.withCredentials) {
config.headers.token = getCookie('token');
// config.headers.token = 'FE9A61476DA84BAD9B966FAF4C497871'
}
return config;
},
error => {
// when set loading close it
if (
error.code === 'ECONNABORTED' &&
error.message.indexOf('timeout') !== -1
) {
VUE_ENV === 'client' && Toast({ message: '请求超时', duration: 1000 });
}
return Promise.reject(error);
}
)
export default function(options) {
if (typeof options !== 'object') {
throw new Error('make sure the params options is an Object...');
}
console.log('isIOS, isAndroid', isIOS(), isAndroid());
if(!isIOS() && !isAndroid()) {
API_CONFIG.headers.sourceType = 5;
}
const cf = JSON.parse(JSON.stringify(API_CONFIG));
options = Object.assign(cf, options); // 合并 config
return new Promise((resolve, reject) => {
Axios(options)
.then(res => {
const { status, data } = res;
if (status !== 200) {
let cmsg = REPONSE_CODE[status];
let message = cmsg !== undefined ? cmsg : '系统异常。';
throw Error(message);
}
if (!data) throw Error('axios reponse data in not defined.');
if (data.code != '000000') {
// 如果要是有其他特殊需求在此处添加
console.log(`调用后台接口报错,CODE: ${data.code},MESSAGE: ${data.message}。`);
}
resolve(res.data);
})
.catch(error => {
console.log('axios catch error: ', error.message);
VUE_ENV === 'client' && Toast({ message: error.message, duration: 1000 });
// reject(error);
})
})
}
\ No newline at end of file
import request from './api';
// 获取隐私协议
export const getAgreements = ( param ) => {
return request({
url: `/api-ws/agreements/`,
method: 'get',
params: param
})
}
// 协议签订接口
export const signAgreements = ( data ) => {
return request({
url: `/api-ws/agreements/consent`,
method: 'post',
data: data,
withCredentials: true
})
}
// 统一验证接口,判断手机号是否注册是否设置密码,等等
export const verityStatus = ( data ) => {
return request({
url: `/account/unifiedVerification`,
method: 'post',
data: data
})
}
// 获取RSA public key
export const getPubKey = ( param ) => {
return request({
url: `/account/cipher/key`,
method: 'get',
params: param
})
}
//微信登录
export const wxLogin = ( data ) => {
return request({
url: `/account/login/wechat`,
method: 'post',
data: data
})
}
//微信绑定手机号 并登录
export const wxBindMobile = ( data ) => {
return request({
url: `/account/login/wechat/step2`,
method: 'post',
data: data
})
}
// 验证码登录
export const msgCodeLogin = data => {
return request({
url: `/account/account/login-register/v1`,
method: 'post',
data: data
})
}
// 密码登录
export const passwordLoginReq = data => {
return request({
url: `/account/login`,
method: 'post',
data: data
})
}
// 判断是否需要触发拼图风控
export const checkNeedImgCode = data => {
return request({
url: `/account/jigsawCode`,
method: 'post',
data: data
})
}
// 获取短信验证码
export const getMessageCode = data => {
return request({
url: `/account/H5/authCode`,
method: 'post',
data: data
})
}
# STATIC
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your static files.
Each file inside this directory is mapped to `/`.
Thus you'd want to delete this README.md before deploying to production.
Example: `/static/robots.txt` is mapped as `/robots.txt`.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).
@charset "utf-8";
html {
color: #000;
background: #fff;
overflow-y: scroll;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%
}
html * {
outline: 0;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}
html,body {
font-family: PingFangSC-Regular, -apple-system-font, Source Han Sans, Helvetica Neue, sans-serif;
}
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
margin: 0;
padding: 0;
}
/*
input, select, textarea {
font-size: 100%;
}
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset, img {
border: 0;
}
abbr, acronym {
border: 0;
font-variant: normal;
}
del {
text-decoration: line-through;
}
address, caption, cite, code, dfn, em, th, var {
font-style: normal;
font-weight: 500;
}
ol, ul {
list-style: none;
}
caption, th {
text-align: left;
}
/*
h1, h2, h3, h4, h5, h6 {
font-size: 100%;
font-weight: 500;
}
*/
q:before, q:after {
content: '';
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -.5em;
}
sub {
bottom: -.25em;
}
a:hover {
text-decoration: underline;
}
ins, a {
text-decoration: none;
}
;(function(win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute('data-dpr', dpr);
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
}
return val;
}
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
}
return val;
}
})(window, window['lib'] || (window['lib'] = {}));
\ No newline at end of file
# STORE
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your Vuex Store files.
Vuex Store option is implemented in the Nuxt.js framework.
Creating a file in this directory automatically activates the option in the framework.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).
// import { getHospital } from '@/service';
export const state = () => ({
userToken:null,
code: null, //微信登录返回的code
unionId: null, //微信登录返回的unionId
imgCodeData: {}, //拼图片验证码数据
needTimer: false, //是否倒计时
});
export const mutations = {
SET_TOKEN: (state, userToken) => {
state.userToken = userToken
},
SET_CODE: (state, code) => {
state.code = code
},
SET_UNIONID: (state, unionId) => {
state.unionId = unionId
},
SET_IMGDATA: (state, imgCodeData) => {
state.imgCodeData = imgCodeData
},
SET_NEEDTIMER: (state, needTimer) => {
state.needTimer = needTimer
},
};
export const actions = {
setToken({ commit }, userToken) {
commit('SET_TOKEN', userToken)
},
setCode({ commit }, code) {
commit('SET_CODE', code)
},
setUnionId({ commit }, unionId) {
commit('SET_UNIONID', unionId)
},
setImgCodeData({ commit }, imgCodeData) {
commit('SET_IMGDATA', imgCodeData)
},
setNeedTimer({ commit }) {
commit('SET_NEEDTIMER', true)
},
};
import { mount } from '@vue/test-utils'
import Logo from '@/components/Logo.vue'
describe('Logo', () => {
test('is a Vue instance', () => {
const wrapper = mount(Logo)
expect(wrapper.isVueInstance()).toBeTruthy()
})
})
const { NUXT_ENV_APP } = process.env;
export const setCookie = (cname,cvalue, exdays = 7, domain = '.yunqueyi.com', validMsec) => { //yunqueyi.com
let d = new Date(), expires = '';
 
if (NUXT_ENV_APP === 'dev') {
domain = window.location.hostname;
}
if(validMsec){
d.setTime(d.getTime() + validMsec);
}else{
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
}
expires = `expires=${d.toUTCString()}`;
 
document.cookie = `${cname}=${cvalue};path=/;${expires};domain=${domain}`;
}
export const getCookie = (cname) => {
const reg = new RegExp('(^| )' + cname + '=([^;]*)(;|$)');
const arr = document.cookie.match(reg);
return arr ? unescape(arr[2]) : null;
}
export const delCookie = (cname) => {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(cname);
if(cval!=null){
document.cookie = 'token=; path=/; expires=' + new Date(0).toUTCString();
document.cookie = 'token=; path=/; domain=.yunqueyi.com; expires=' + new Date(0).toUTCString();
//document.cookie= name + "="+cval+";path=/;expires="+exp.toGMTString() + ";domain=" + domain;
}
}
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,
2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},
q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this._doProcessBlock(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},_createHmacHelper:function(a){return function(b,e){return(new n.HMAC.init(a,
e)).finalize(b)}}});var n=d.algo={};return d}(Math);
(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this._map;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,
l)}})();
CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this._ENC_XFORM_MODE,e,a)},createDecryptor:function(e,a){return this.create(this._DEC_XFORM_MODE,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this._xformMode=e;this._key=a;this.reset()},reset:function(){t.reset.call(this);this._doReset()},process:function(e){this._append(e);return this._process()},
finalize:function(e){e&&this._append(e);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this._iv;c?this._iv=u:c=this._prevBlock;for(var d=0;d<b;d++)e[a+d]^=
c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this._cipher=e;this._iv=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this._prevBlock=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,
e,a,c);this._prevBlock=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
CryptoJS.mode.ECB=function(){var a=CryptoJS.lib.BlockCipherMode.extend();a.Encryptor=a.extend({processBlock:function(a,b){this._cipher.encryptBlock(a,b)}});a.Decryptor=a.extend({processBlock:function(a,b){this._cipher.decryptBlock(a,b)}});return a}();
export {
CryptoJS
};
import { Toast } from 'vant';
import { CryptoJS } from './aes'
if (process.client) {
require('jsencrypt')
}
import { getPubKey } from "@/service";
let pubKey = "";
// generate key
function getAesKey(len) {
len = len || 16;
var aesKey = "";
var strList = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var strLen = strList.length;
for(var i=0; i<len; i++){
aesKey += strList.charAt( Math.floor( Math.random()*strLen ) );
};
return aesKey;
}
// 加密传参,发送请求
async function sendEncryptRequest(content, cb){
console.log('content',content)
content = JSON.stringify(content); // 后端要求转 string
// debugger;
let params = null
if(pubKey){ // pubKey获取过就不用再获取了
let params = formatContent(content, pubKey);
cb && cb(params);
}else{
handleGetPubKey(content, cb);
}
return params
}
// get public key
function handleGetPubKey(content, cb){
// debugger;
getPubKey().then(res => {
// console.log('>>>>>>>>>>>>>>>>>>>> publicKey: ', res);
/* if(res.status && res.status === 200) {
res = res.data;
}*/
console.log('res',res)
// debugger;
if(res.code == '000000'){
pubKey = res.data;
if(cb){
let params = formatContent(content, pubKey);
cb && cb(params);
}
}else{
Toast({
message: (res && res.message) || '接口出错',
duration: 1500
});
}
})
}
// format account params
function formatContent(content, pubKey) { // obj为具体的json传参
let aesKey = getAesKey(16);
let params = {
key: '',
content: ''
};
params.content = AesEncrypt(content, aesKey);
params.key = RsaEncrypt(aesKey, pubKey);
return params;
}
// AES encrypt
function AesEncrypt(content, aesKey) {
let sKey = CryptoJS.enc.Utf8.parse(aesKey);
let sContent = CryptoJS.enc.Utf8.parse(content);
let encrypted = CryptoJS.AES.encrypt(sContent, sKey, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}
// RSA encrypt
function RsaEncrypt(aesKey, pubKey){
let _encrypt = new JSEncrypt();
let boss_public_key = pubKey;
_encrypt.setPublicKey(boss_public_key);
let encrypted = _encrypt.encrypt(aesKey);
return encrypted;
}
export {
getAesKey,
sendEncryptRequest,
handleGetPubKey,
formatContent,
AesEncrypt,
RsaEncrypt,
}
\ No newline at end of file
import { getTerminalType, detectOS, getDeviceInfo } from '@/utils/getDeviceInfo';
const { NUXT_ENV_APP } = process.env;
export const BASE_URL = {
dev:'https://dev-sc.yunqueyi.com',
test: 'https://test1-sc.yunqueyi.com',
uat: 'https://uat-sc.yunqueyi.com',
prod: 'https://sc.yunqueyi.com'
};
export const APPID = {
dev: 'wx08b383d002c73f26',
test: 'wxcaad75b7fff5659c',
uat: 'wx342ef0e5afee54a7',
prod: 'wx2c577552a2d28550'
};
let deviceInfo = null
if(process.client) {
deviceInfo = getDeviceInfo()
}
export const API_CONFIG = {
baseURL: BASE_URL[NUXT_ENV_APP],
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json;charset=UTF-8',
'deviceInfo': deviceInfo, //设备信息
'productType': 1, // 1表示云鹊医产品系
'sourceType': 4, // 4表示H5登录
},
timeout: 10000,
withCredentials: false,
responseType: 'json',
method: 'get'
}
export const REPONSE_CODE = {
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(登录过期、token错误)',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。'
};
export const ENV_CONFIG = {
development: {
baseUrl: 'http://10.177.10.217:10201/',
apiUrl: 'https://dev-api.yunqueyi.com/',
shareUrl: 'https://dev-phome.yunqueyi.com/',
topicUrl: 'http://10.177.11.245:8081',
wxLoginUrl : 'https://sc.yunqueyi.com/wechats/users',
},
dev: {
baseUrl: 'https://dev-sc.yunqueyi.com/',
apiUrl: 'https://dev-api.yunqueyi.com/',
shareUrl:'https://dev-phome.yunqueyi.com/',
topicUrl:'https://dev-discuss.yunqueyi.com',
wxLoginUrl: 'https://sc.yunqueyi.com/wechats/users',
domain:'https://dev-sc.yunqueyi.com/account',
APPID:'wx2c577552a2d28550',
},
test: {
baseUrl: 'https://test1-sc.yunqueyi.com/',
apiUrl: 'https://test1-api.yunqueyi.com/',
shareUrl: 'https://test1-phome.yunqueyi.com/',
topicUrl: 'https://test1-discuss.yunqueyi.com',
wxLoginUrl : 'https://test1-sc.yunqueyi.com/wechats/users',
domain : 'https://test1-sc.yunqueyi.com/account',
APPID: 'wxcaad75b7fff5659c' ,
},
uat: {
baseUrl: 'https://uat-sc.yunqueyi.com/',
apiUrl: 'https://uat-api.yunqueyi.com/',
shareUrl: 'https://uat-phome.yunqueyi.com/',
topicUrl: 'https://uat-discuss.yunqueyi.com',
wxLoginUrl : 'https://uat-sc.yunqueyi.com/wechats/users',
domain : 'https://uat-sc.yunqueyi.com/account',
APPID:'wx342ef0e5afee54a7',
},
prod: {
baseUrl: 'https://sc.yunqueyi.com/',
apiUrl: 'https://api.yunqueyi.com/',
shareUrl: 'https://phome.yunqueyi.com/',
topicUrl: 'https://discuss.yunqueyi.com',
wxLoginUrl : 'https://sc.yunqueyi.com/wechats/users',
domain : 'https://sc.yunqueyi.com/account',
APPID:'wx2c577552a2d28550',
}
};
// 获取用户终端信息
export const getTerminalType = () => {
let brow = "unknown";
// alert(navigator.userAgent);
if (navigator.userAgent.indexOf('iPad') > -1) {
// alert("iPad");
return brow = "iPad";
}
if (navigator.userAgent.indexOf('Android') > -1
|| navigator.userAgent.indexOf('Linux') > -1) {
// alert("Android");
return brow = "android";
}
if (navigator.userAgent.indexOf('iPhone') > -1
// || navigator.userAgent.indexOf('Mac') > -1
) {
// alert("iPhone");
return brow = "iPhone";
}
if (navigator.userAgent.indexOf('Trident') > -1) {
// alert("Trident");
return brow = "PC";
}
if (navigator.userAgent.indexOf('Presto') > -1) {
// alert("Presto");
return brow = "PC";
}
if (navigator.userAgent.indexOf('Chrome') > -1) {
// alert("Chrome");
return brow = "PC";
}
if (navigator.userAgent.indexOf('AppleWebKit') > -1) {
// alert("AppleWebKit");
return brow = "iPad";
}
if (navigator.userAgent.indexOf('Gecko') > -1
&& navigator.userAgent.indexOf('KHTML') == -1) {
// alert("Gecko");
return brow = "PC";
}
if (navigator.userAgent.indexOf("Mac OS X") > -1) {
// alert("ios");
return brow = "ios";
}
if (navigator.userAgent.indexOf('Safari') == -1) {
// alert("Safari");
return brow = "PC";
}
return brow;
};
// 获取用户系统信息start
export const detectOS = () => {
let sUserAgent = navigator.userAgent;
let isWin = (navigator.platform == "Win32")
|| (navigator.platform == "Windows");
let isMac = (navigator.platform == "Mac68K")
|| (navigator.platform == "MacPPC")
|| (navigator.platform == "Macintosh")
|| (navigator.platform == "MacIntel");
if (isMac)
return "Mac";
let isUnix = (navigator.platform == "X11") && !isWin && !isMac;
if (isUnix)
return "Unix";
let isLinux = (String(navigator.platform).indexOf("Linux") > -1);
if (isLinux)
return "Linux";
let isIos = (sUserAgent.indexOf("Mac OS X") > -1);
if (isIos)
return "Mac";
if (isWin) {
let isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1
|| sUserAgent.indexOf("Windows XP") > -1;
if (isWinXP)
return "WinXP";
let isWinVista = sUserAgent.indexOf("Windows NT 6.0") > -1
|| sUserAgent.indexOf("Windows Vista") > -1;
if (isWinVista)
return "WinVista";
let isWin7 = sUserAgent.indexOf("Windows NT 6.1") > -1
|| sUserAgent.indexOf("Windows 7") > -1;
if (isWin7)
return "Win7";
let isWin8_1 = sUserAgent.indexOf("Windows NT 6.2") > -1
|| sUserAgent.indexOf("Windows 8") > -1;
let isWin8_2 = sUserAgent.indexOf("Windows NT 6.3") > -1
|| sUserAgent.indexOf("Windows 8.1") > -1;
if (isWin8_1 || isWin8_2)
return "Win8";
let isWin10_1 = sUserAgent.indexOf("Windows NT 6.4") > -1
|| sUserAgent.indexOf("Windows 10") > -1;
let isWin10_2 = sUserAgent.indexOf("Windows NT 10.0") > -1
|| sUserAgent.indexOf("Windows 10") > -1;
if (isWin10_1 || isWin10_2)
return "Win10";
}
return "other";
};
export const getDeviceInfo = () => {
let deviceInfo = { "app_channel": "", "app_mac": "", "app_uuid": "", "app_version": "", "device_brand": "", "device_ip": "", "device_model": "", "device_net": "", "device_ops": "", "resolution_wh": "", "system_level": "", "device_type": "" };
try{
let terminalType = getTerminalType();
let OS = detectOS();
deviceInfo.device_brand = terminalType;
deviceInfo.system_level = OS;
}catch(err){
console.log('deviceInfo err>>>> ', err)
}
deviceInfo = JSON.stringify(deviceInfo);
return deviceInfo;
}
import { ENV_CONFIG } from './enumerate.js'
function p_getElm(elmId) {
return document.getElementById(elmId)
}
/**
* 配置编译环境和线上环境之间的切换
*/
function getTestEnv (ipAddress) {
let environments = ["localhost","dev", "uat","test1","10.177.10.231"];
for (let i = 0; i < environments.length; i++) {
if (ipAddress.indexOf(environments[i]) > -1) {
return environments[i];
}
}
return null;
};
// 根据不同环境,生成URL
function getConfigByEnvType(urlType) {
if (process.client){
console.log(window)
let ipAddress = "https://" + window.location.host;
let parm = null;
let env = getTestEnv(ipAddress);
if(env == 'localhost' || env == 'dev' || env == 'test1' || env == "10.177.10.231"){
parm = 'test'
}else{
parm = 'prod'
}
// console.log(parm)
console.log(ENV_CONFIG[parm][urlType])
return ENV_CONFIG[parm][urlType]
}
}
import { ENV_CONFIG } from './enumerate';
const { NUXT_ENV_APP } = process.env;
export const getSearchByName = name => {
const match = RegExp(`[?&]${name}=([^&]*)`).exec(window.location.href);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
};
export const getItem = name => {
if (!name) return;
const v = sessionStorage.getItem(name);
let val = null;
try {
val = JSON.parse(v);
} catch (e) {
// JSON.parse 失败 后 直接赋v给val;
val = v;
}
return val;
};
export const setItem = (name, value) => {
if (!name) return;
if (typeof value !== 'string') {
value = JSON.stringify(value);
}
sessionStorage.setItem(name, value);
};
export const removeItem = name => {
if (!name) return;
sessionStorage.removeItem(name);
};
export const getConfigByEvtType = key => {
return ENV_CONFIG[NUXT_ENV_APP][key];
}
export const getNoticeUrl = url => {
return `${getConfigByEvtType('noticeUrl')}${url}`;
}
export const getWxLoginUrl = url => {
return `${getConfigByEvtType('wxLoginUrl')}`;
}
export const getWxAPPID = url => {
return `${getConfigByEvtType('APPID')}`;
}
// 获取SC服务器域名地址
export const getBaseUrl = url => {
return `${getConfigByEvtType('baseUrl')}${url}`;
}
// 获取API服务器域名地址
export const getApiUrl = url => {
return `${getConfigByEvtType('apiUrl')}${url}`;
}
export const getWxDomainUrl = url => {
return `${getConfigByEvtType('domain')}`;
}
export const getShareUrl = url => {
return `${getConfigByEvtType('shareUrl')}`;
}
export const getBaseMainUrl = url => {
return `${getConfigByEvtType('baseUrl')}`;
}
export const getCookie = cname => {
        var name = cname + "=";
        var ca = document.cookie.split(';');
        //console.log("获取cookie,现在循环")
        for (var i = 0; i < ca.length; i++) {
          var c = ca[i];
         // console.log(c)
          while (c.charAt(0) == ' ') c = c.substring(1);
          if (c.indexOf(name) != -1){
            return c.substring(name.length, c.length);
          }
        }
        return "";
    };
export const delCookie = (name,domain) =>{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if(cval!=null){
//document.cookie = name + "="+cval+";expires="+exp.toGMTString();
document.cookie = name + '=; path=/; expires=' + new Date(0).toUTCString();
document.cookie = name + '=; path=/; domain=.yunqueyi.com; expires=' + new Date(0).toUTCString();
}
};
export const setCookie = (cname, cvalue, exdays) => {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
//d.setTime(d.getTime() + (2* 60 * 1000));
        var expires = "expires=" + d.toUTCString();
       // console.info(cname + "=" + cvalue + "; " + expires);
        document.cookie = cname + "=" + cvalue + ";path=/;" + expires;
        //console.info(document.cookie);
    };
export const setEventByModuleCode = (itemData, token) => {
let modeCode = itemData.code || '';
let paramList = itemData.paramList ? itemData.paramList : '';
if (modeCode === 'M001' || modeCode === 'M002' || modeCode === 'M003') {
paramList = '';
} else if (
modeCode === 'M100' ||
modeCode === 'M300' ||
modeCode === 'M500' || modeCode === 'M301'
) {
let urlPara = getUrlParmByCode(paramList, token);
paramList[0] && (paramList[0].value += urlPara);
// 前端拼接了数据,原生不用再拼接
paramList = paramList.slice(0, 1)
}
if (typeof paramList === 'string' && !paramList) {
paramList = [];
}
return paramList;
}
export const refreFun = () => {
let str = location.href,
a = '',
b = '',
url = ''
if (str.indexOf('?code') > -1) {
a = str.split('#')[0].split('?')[0];
b = str.split('#')[1];
url = a + '#' + b;
console.log(url)
setTimeout(() => {
location.href = url;
}, 1000)
}
}
export const pageBurialPoin = (options) => {
let opt = {
menuLevel: options.menuLevel || '',
functionCode: options.functionCode || '',
actionCode: options.actionCode || '',
// label:options.label || '',
labelId: options.labelId || '',
labelValue: options.labelValue || '',
createdTime: options.createdTime || new Date().getTime(),
//type: options.type || '0',
menuCode: options.menuCode || '',
// menuToCode:options.menuToCode || '',
duration: options.duration || 0,
menuFromCode: options.menuFromCode || '',
params: options.params || '',
session: options.session || ''
};
rocNative.appBuryingPointEntrust(opt);
}
function getUrlParmByCode(paramList, token) {
if (paramList.length <= 1) return `?token=${token}`;
let dataStr = '', list = [];
let str = paramList.length > 0 && paramList[0].value.indexOf('?') > -1 ? '&' : '?';
for (let i = 1; i < paramList.length; i++) {
list.push(paramList[i].key + '=' + encodeURI(paramList[i].value));
}
dataStr = list.join('&');
if (dataStr !== '') return `${str}${dataStr}&token=${token}`;
return `${str}token=${token}`;
}
export const getFirstAwards = (awardsDate) => {
const awardsTime = Date.parse(new Date(awardsDate.replace(/-/g, "/")))
if (Date.parse(new Date(('2019-12-16 00:00:00').replace(/-/g, "/")))<=awardsTime&&Date.parse(new Date(('2019-12-19 23:59:59').replace(/-/g, "/")))>=awardsTime) {
return '小米电视';
} else if (Date.parse(new Date(('2019-12-20 00:00:00').replace(/-/g, "/")))<=awardsTime&&Date.parse(new Date(('2019-12-23 23:59:59').replace(/-/g, "/")))>=awardsTime) {
return '米家洗衣机';
} else if (Date.parse(new Date(('2019-12-24 00:00:00').replace(/-/g, "/")))<=awardsTime&&Date.parse(new Date(('2019-12-26 23:59:59').replace(/-/g, "/")))>=awardsTime) {
return '米家两门冰箱';
} else if (Date.parse(new Date(('2019-12-27 00:00:00').replace(/-/g, "/")))<=awardsTime/*&&Date.parse(new Date('2019-12-29 23:59:59'))>=awardsTime*/) {
return '荣耀手机';
};
}
// 根据不同环境获取topic的URL
// export function getTopicUrl() {
// return getConfigByEvtType('topicUrl')
// }
// // 获取WEB部署服务器域名地址
// export function getBaseMainUrl() {
// return getConfigByEvtType('baseUrl');
// }
// 判断手机环境
export const isIOS = () => {
const u = navigator.userAgent;
const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
return isiOS;
}
// 判断手机环境
export const isAndroid = () => {
const u = navigator.userAgent;
return u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
}
/*
* @Author: souse
* @Date: 2019-08-12 18:08:07
* @Last Modified by: souse
* @Last Modified time: 2019-09-05 15:45:26
* @Descript 和app交互的接口调用 单例模式
*/
const ARRAY_CLASS = '[object Array]';
const _toString = Object.prototype.toString;
/**
* set default options
*/
export const JsBridgeOptions = {
GLOBAL_NAME: 'rocNative',
NATIVE_IOS_NAME: 'rociOS',
NATIVE_ANDROID_NAME: '__rocAndroid',
initMethodsWithCallBack: ['getToken', 'getUserInfo','addEnclosure', 'getStatusBarHeight','getAppVersionCode','getLocalData'], // value is string
initMethodsWithoutCallBack: [
'appInit',
'goBack',
'gotoLogin',
'shareWechat',
'showNativeToast',
'appBuryingPointEntrust',
'webLoadSuccess',
'WfileImageCallBack',
'selectPhoto',
'gotoInstitutionalReview',
'gotoActivityHospital',
'setNeedClearUrl',
'dispatchEventByModuleCode',
'sendBuriedPoint',
'openErrorDebug'
] // value is string
}
/**
* @description
* @author souse
* @date 2019-08-12
* @export
* @class PicaJsBridge
*/
export default class PicaJsBridge {
constructor(options = JsBridgeOptions) {
const initMethodsWithCallBack = options.initMethodsWithCallBack;
const initMethodsWithoutCallBack = options.initMethodsWithoutCallBack;
this._callbakFns = {};
this._callbackId = 0;
this._GLOBAL_NAME = options.GLOBAL_NAME;
this._NATIVE_IOS_NAME = options.NATIVE_IOS_NAME;
this._NATIVE_ANDROID_NAME = options.NATIVE_ANDROID_NAME;
this.isIOS = this._isIos();
this.isAndroid = this._isAndroid();
this.isWeb = this._isWeb();
if (_toString.call(initMethodsWithCallBack) === ARRAY_CLASS && initMethodsWithCallBack.length !== 0) {
this.registerMethods(initMethodsWithCallBack, true);
}
if (_toString.call(initMethodsWithoutCallBack) === ARRAY_CLASS && initMethodsWithoutCallBack.length !== 0) {
this.registerMethods(initMethodsWithoutCallBack, false);
}
this.mountToWindow();
}
// is ios flag
_isIos() {
return !!(window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers[this._NATIVE_IOS_NAME]);
}
// is android flag
_isAndroid() {
return !!window[this._NATIVE_ANDROID_NAME];
}
// is web flag
_isWeb() {
return !this.isIOS && !this.isAndroid;
}
// register method width callback in window
_registerMethod(method) {
const _this = this;
_this[method] = (param) => {
return new Promise((response, reject) => {
_this._callNative(method, param, function(result) {
response(result);
}) ? void 0 : reject(`${method} not handled.`);
});
}
}
// register method widthout callback in window
_registerMethodWithoutMethod(method) {
const _this = this;
_this[method] = (param) => {
return new Promise((response, reject) => {
_this._callNative(method, param, null) ? response('success') : reject(`${method} not handled.`);
});
}
}
// window call app method
_callNative(name, param, callbackFn) {
let callbackId = 0, pm;
//alert(name)
if (typeof callbackFn === 'function') {
this._callbackId++;
callbackId = this._callbackId;
this._callbakFns[callbackId] = callbackFn;
}
pm = JSON.stringify({
name,
callbackId: callbackId ? callbackId.toString() : '',
param: param || {}
});
if (this.isAndroid) {
window[this._NATIVE_ANDROID_NAME].postMessage(pm);
return true;
}
if (this.isIOS) {
window.webkit.messageHandlers[this._NATIVE_IOS_NAME].postMessage(pm);
return true;
}
return false;
}
// app call window method
// __nativeCall(name, callbackId, result) {
// const fun = callbackId && this._callbakFns[callbackId];
//
// delete this._callbakFns[callbackId];
//
// if (fun && typeof fun === 'function') fun(result);
// }
__nativeCall(name, callbackId, result) {
// alert(`${name}__${callbackId}__${JSON.stringify(result)}`);
const wFun = callbackId === '__refresh' ? window[callbackId] : window[name];
const fun = callbackId && this._callbakFns[callbackId];
//add by zhangping
if (wFun && typeof wFun === 'function') {
wFun(result);
return;
}
delete this._callbakFns[callbackId];
if (fun && typeof fun === 'function') fun(result);
}
// batch register methods
registerMethods(methods = [], widthCallback) {
if (undefined === widthCallback)
throw Error('widthCallback flag not defined, registerMethods should take second param value(true/false) for is not has callback.');
methods.forEach(m => {
widthCallback === true ? this._registerMethod(m) : this._registerMethodWithoutMethod(m)
});
}
// async call app method do not need register
asyncCallNative(method, param) {
const _this = this;
return new Promise(resolve => {
_this._callNative(method, param, function(result) {
resolve(result);
});
});
}
// call app method direct without register and callback
callNative(method, param) {
return this._callNative(method, param, null);
}
// register jsbridge to window
mountToWindow() {
window[this._GLOBAL_NAME] = this;
}
}
\ No newline at end of file
String.prototype.MD5 = function(bit) {
var sMessage = this;
function RotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function AddUnsigned(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else return (lResult ^ lX8 ^ lY8);
}
function F(x, y, z) {
return (x & y) | ((~x) & z);
}
function G(x, y, z) {
return (x & z) | (y & (~z));
}
function H(x, y, z) {
return (x ^ y ^ z);
}
function I(x, y, z) {
return (y ^ (x | (~z)));
}
function FF(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function GG(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function HH(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function II(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function ConvertToWordArray(sMessage) {
var lWordCount;
var lMessageLength = sMessage.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
}
function WordToHex(lValue) {
var WordToHexValue = "",
WordToHexValue_temp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return WordToHexValue;
}
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d
var S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22;
var S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20;
var S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23;
var S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
// Steps 1 and 2. Append padding bits and length and convert to words
x = ConvertToWordArray(sMessage);
// Step 3. Initialise
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
// Step 4. Process the message in 16-word blocks
for (k = 0; k < x.length; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = AddUnsigned(a, AA);
b = AddUnsigned(b, BB);
c = AddUnsigned(c, CC);
d = AddUnsigned(d, DD);
}
if (bit == 32) {
return WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
} else {
return WordToHex(b) + WordToHex(c);
}
}
\ No newline at end of file
export const verifyPhone = (num) => {
if(!/^1[3456789]\d{9}$/.test(num)) {
return false;
} else {
return true;
}
}
\ No newline at end of file
import {BASE_URL} from "./enumerate";
const { NUXT_ENV_APP } = process.env;
import {APPID} from '@/utils/enumerate'
//弹出微信授权
export const wxGetCode = (url) => {
const redirectUrl = encodeURIComponent(url);
location.replace(`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APPID[NUXT_ENV_APP]}&redirect_uri=${redirectUrl}&response_type=code&scope=snsapi_userinfo&#wechat_redirect`)
}
// export const wxGetToken
//判断当前是不是微信内部
export const is_weixin = () => {
let ua = navigator.userAgent.toLowerCase();
 let isWeixin = ua.indexOf('micromessenger') != -1;
 if (isWeixin) {
  return true;
 }else{
   return false;
 }
}
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册