|
@@ -3,136 +3,376 @@
|
|
</style>
|
|
</style>
|
|
|
|
|
|
<style lang="less">
|
|
<style lang="less">
|
|
- .demo-spin-icon-load{
|
|
|
|
- animation: ani-demo-spin 1s linear infinite;
|
|
|
|
- }
|
|
|
|
- @keyframes ani-demo-spin {
|
|
|
|
- from { transform: rotate(0deg);}
|
|
|
|
- 50% { transform: rotate(180deg);}
|
|
|
|
- to { transform: rotate(360deg);}
|
|
|
|
|
|
+.loginBox{
|
|
|
|
+ .loginForm{
|
|
|
|
+ .formItem{
|
|
|
|
+ input, select{
|
|
|
|
+ border-radius: 0;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ }
|
|
|
|
+ .ivu-select-selection{
|
|
|
|
+ border-radius: 0;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-.login{
|
|
|
|
- &-server{
|
|
|
|
- .ivu-select-selection, .ivu-btn{
|
|
|
|
- border-radius: 0;
|
|
|
|
- background-color: #0d253f;
|
|
|
|
- color: #e3e5e8;
|
|
|
|
- border: 0;
|
|
|
|
- span{
|
|
|
|
- display: flex;
|
|
|
|
- justify-content: space-between;
|
|
|
|
- align-items: center;
|
|
|
|
|
|
+ .schoolAutoComplete{
|
|
|
|
+ height: 170px;
|
|
|
|
+ .schoolsBox{
|
|
|
|
+ border-bottom: 1px solid #e9e9e9;
|
|
|
|
+ padding: 5px 5px 5px 15px;
|
|
|
|
+ .area{
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ padding: 5px;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- .ivu-select-arrow{
|
|
|
|
- font-size: 18px;
|
|
|
|
- }
|
|
|
|
.ivu-select-dropdown{
|
|
.ivu-select-dropdown{
|
|
- background-color: #091529;
|
|
|
|
border-radius: 0;
|
|
border-radius: 0;
|
|
}
|
|
}
|
|
- .ivu-select-item, .ivu-dropdown-item{
|
|
|
|
- color: #ffffff;
|
|
|
|
- &:hover{
|
|
|
|
- background-color:transparent;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- .ivu-select-item-focus{
|
|
|
|
- background-color:transparent;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- &-body{
|
|
|
|
- .loginBox{
|
|
|
|
- .loginForm{
|
|
|
|
- .formItem{
|
|
|
|
- input, select{
|
|
|
|
- border-radius: 0;
|
|
|
|
- font-size: 12px;
|
|
|
|
- }
|
|
|
|
- .ivu-select-selection{
|
|
|
|
- border-radius: 0;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- .schoolAutoComplete{
|
|
|
|
- height: 170px;
|
|
|
|
- .schoolsBox{
|
|
|
|
- border-bottom: 1px solid #e9e9e9;
|
|
|
|
- padding: 5px 5px 5px 15px;
|
|
|
|
- .area{
|
|
|
|
- font-size: 12px;
|
|
|
|
- padding: 5px;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- .ivu-select-dropdown{
|
|
|
|
- border-radius: 0;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|
|
|
|
|
|
<template>
|
|
<template>
|
|
- <div id="login" class="login">
|
|
|
|
- <div class="login-mark">
|
|
|
|
- <img width="125" src="@/assets/ies5_logo.svg">
|
|
|
|
- </div>
|
|
|
|
- <div class="login-server">
|
|
|
|
- <h5>{{ $t('login.title.ser') }}</h5>
|
|
|
|
- <Dropdown trigger="click" @on-click="chgSerType">
|
|
|
|
- <a href="javascript:void(0)">
|
|
|
|
- <Button style="width:120px;">
|
|
|
|
-
|
|
|
|
- <span>
|
|
|
|
- {{ $t('login.serAdress.' + config.srvAdr) }}
|
|
|
|
- </span>
|
|
|
|
-
|
|
|
|
- <Icon type="ios-arrow-down"></Icon>
|
|
|
|
- </Button>
|
|
|
|
- </a>
|
|
|
|
- <DropdownMenu slot="list" style="width:120px">
|
|
|
|
- <DropdownItem name="China" >{{ $t('login.serAdress.China') }}</DropdownItem>
|
|
|
|
- <DropdownItem name="Global">{{ $t('login.serAdress.Global') }}</DropdownItem>
|
|
|
|
- </DropdownMenu>
|
|
|
|
- </Dropdown>
|
|
|
|
- </div>
|
|
|
|
- <div class="login-body">
|
|
|
|
- <SignIn/> <!-- 登入模組 -->
|
|
|
|
- </div>
|
|
|
|
- <div class="login-footer">
|
|
|
|
- <h5 style="position: absolute;bottom:0;width: 100%;padding: 7px;color: #515a6e;">© HABOOL Group 2019</h5>
|
|
|
|
|
|
+ <div class="loginDiv">
|
|
|
|
+ <div class="loginBox">
|
|
|
|
+ <div class="title">
|
|
|
|
+ <div class="logo">
|
|
|
|
+ <img width="15" height="15" src="@/assets/icon/tmd_account.svg">
|
|
|
|
+ </div>
|
|
|
|
+ <h4 class="text">
|
|
|
|
+ {{ qrloginFlag ? $t('login.title.QRLogin'): $t('login.title.IDLogin') }}
|
|
|
|
+ </h4>
|
|
|
|
+ <Tooltip class="tooltip" placement="right-end" :transfer="true" max-width="200">
|
|
|
|
+ <img src="@/assets/icon/icon_info.svg" width="15" height="15">
|
|
|
|
+ <div slot="content">
|
|
|
|
+ <p style="font-size: 12px;">{{ $t('login.tooltip.text1') }}</p>
|
|
|
|
+ </div>
|
|
|
|
+ </Tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ <h4 class="subTitle">
|
|
|
|
+ {{ qrloginFlag ? $t('login.subTitle.QRLogin') : $t('login.subTitle.IDLogin')}}
|
|
|
|
+ </h4>
|
|
|
|
+
|
|
|
|
+ <template v-if="!qrloginFlag">
|
|
|
|
+ <Form class="loginForm" ref="loginForm" :model="loginForm" :rules="loginRule" @keydown.enter.native="loginSubmit('loginForm')" :show-message="false">
|
|
|
|
+ <FormItem class="formItem" prop="id" >
|
|
|
|
+ <Input v-model="loginForm.id" :placeholder="$t('login.placeholder.id')"/>
|
|
|
|
+ </FormItem>
|
|
|
|
+ <FormItem class="formItem" prop="pass">
|
|
|
|
+ <Input type="password" v-model="loginForm.pass" :placeholder="$t('login.placeholder.psw')" >
|
|
|
|
+ <Icon size="24" v-show="!loading && loginFormEnter" @click="loginSubmit('loginForm')" type="md-arrow-forward" slot="suffix" />
|
|
|
|
+ <div v-show="loading" class="demo-spin-col" slot="suffix">
|
|
|
|
+ <Spin>
|
|
|
|
+ <Icon type="ios-loading" size=18 class="demo-spin-icon-load"></Icon>
|
|
|
|
+ </Spin>
|
|
|
|
+ </div>
|
|
|
|
+ </Input>
|
|
|
|
+ </FormItem>
|
|
|
|
+ <div class="errlable">{{ loginErrText }}</div>
|
|
|
|
+ </Form>
|
|
|
|
+
|
|
|
|
+ <div class="extra">
|
|
|
|
+ <div class="qrlogin">
|
|
|
|
+ <div class="logo">
|
|
|
|
+ <img width="15" height="15" src="@/assets/icon/icon_qrcode.svg">
|
|
|
|
+ </div>
|
|
|
|
+ <a @click="chgLoginType()">{{ $t('login.link.QRLogin') }}</a>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="link">
|
|
|
|
+ <router-link to="/regist">{{ $t('login.link.regist') }}</router-link> | <a>{{ $t('login.link.forgetPsw') }}</a>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="communyLoging">
|
|
|
|
+ <div class="description">{{ $t('login.communy.title')}}</div>
|
|
|
|
+ <div class="links">
|
|
|
|
+ <div class="icon">
|
|
|
|
+ <img src="@/assets/icon/icon_fb.svg">
|
|
|
|
+ <span>{{ $t('login.communy.fb')}}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="icon">
|
|
|
|
+ <img src="@/assets/icon/icon_google.svg">
|
|
|
|
+ <span>{{ $t('login.communy.google')}}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="icon">
|
|
|
|
+ <img src="@/assets/icon/icon_wechat.svg">
|
|
|
|
+ <span>{{ $t('login.communy.wechat')}}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <div class="qrloginMode">
|
|
|
|
+ <img class="qrcode" src="@/assets/image/demoQRCode.jpg">
|
|
|
|
+ <div class="links">
|
|
|
|
+ <div class="icon-a">
|
|
|
|
+ <img src="@/assets/icon/icon_account.svg">
|
|
|
|
+ <a @click="chgLoginType()">{{ $t('login.link.IDLogin') }}</a>
|
|
|
|
+ </div>
|
|
|
|
+ <a > {{ $t('login.link.regist') }}</a>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="loginBox">
|
|
|
|
+ <div class="title">
|
|
|
|
+ <div class="logo">
|
|
|
|
+ <img width="15" height="15" src="@/assets/icon/tmd_account.svg">
|
|
|
|
+ </div>
|
|
|
|
+ <h4 class="text">{{ $t('login.title.schoolLogin') }}</h4>
|
|
|
|
+ <Tooltip class="tooltip" placement="right-end" :transfer="true" max-width="200">
|
|
|
|
+ <img src="@/assets/icon/icon_info.svg" width="15" height="15">
|
|
|
|
+ <div slot="content">
|
|
|
|
+ <p style="font-size: 12px;">{{ $t('login.tooltip.text2') }}</p>
|
|
|
|
+ </div>
|
|
|
|
+ </Tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ <h4 class="subTitle">{{ $t('login.subTitle.schoolLogin') }}</h4>
|
|
|
|
+ <Form class="loginForm">
|
|
|
|
+ <FormItem class="formItem" style="margin-bottom: 15px;" >
|
|
|
|
+ <Select v-model="schoolForm.schoolCode" :placeholder="$t('login.placeholder.schoolMenu')" filterable clearable >
|
|
|
|
+ <template v-for="(item, index) in data3" >
|
|
|
|
+ <OptionGroup :label="item.area" :key="index">
|
|
|
|
+ <Option v-for="school in item.schools" :key="school.id" :value="school.id">{{ school.name }}</Option>
|
|
|
|
+ </OptionGroup>
|
|
|
|
+ </template>
|
|
|
|
+ </Select>
|
|
|
|
+ </FormItem>
|
|
|
|
+ <FormItem class="formItem" prop="id" >
|
|
|
|
+ <Input v-model="schoolForm.id" :placeholder="$t('login.placeholder.schoolID')"/>
|
|
|
|
+ </FormItem>
|
|
|
|
+ <FormItem class="formItem" prop="pass">
|
|
|
|
+ <Input type="password" v-model="schoolForm.pass" :placeholder="$t('login.placeholder.schoolPsw')" >
|
|
|
|
+ <Icon v-show="schoolFormEnter" @click="login()" type="md-arrow-forward" slot="suffix" />
|
|
|
|
+ </Input>
|
|
|
|
+ </FormItem>
|
|
|
|
+ <div class="errlable">{{ schoolErrText }}</div>
|
|
|
|
+ </Form>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
- </div>
|
|
|
|
</template>
|
|
</template>
|
|
-
|
|
|
|
<script>
|
|
<script>
|
|
|
|
+import { User } from '@/service/User'
|
|
import { mapState, mapGetters } from 'vuex'
|
|
import { mapState, mapGetters } from 'vuex'
|
|
-import SignIn from '@/view/login/components/SignIn.vue'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
- components:{
|
|
|
|
- SignIn
|
|
|
|
|
|
+ data() {
|
|
|
|
+ const validatePass = (rule, value, callback) => {
|
|
|
|
+ if (value === '') {
|
|
|
|
+ callback(new Error());
|
|
|
|
+ this.loginErrText = this.$t('error.required')
|
|
|
|
+ } else if (value.search(/^\+/) == 0) {
|
|
|
|
+ callback(new Error());
|
|
|
|
+ this.loginErrText = this.$t('error.format.default')
|
|
|
|
+ } else {
|
|
|
|
+ if(value.indexOf('@') >=0){ //是否為Email
|
|
|
|
+ var emailRule = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/;
|
|
|
|
+ if(value.search(emailRule)!= -1){
|
|
|
|
+ callback();
|
|
|
|
+ this.loginErrText = ''
|
|
|
|
+ } else {
|
|
|
|
+ callback(new Error());
|
|
|
|
+ this.loginErrText = this.$t('error.format.email')
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ callback();
|
|
|
|
+ this.loginErrText = ''
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ const validatePasswordCheck = (rule, value, callback) => {
|
|
|
|
+ let error = ''
|
|
|
|
+ if (value === '') {
|
|
|
|
+ callback(new Error());
|
|
|
|
+ this.loginErrText = this.$t('error.required')
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ callback();
|
|
|
|
+ this.loginErrText = ''
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ return {
|
|
|
|
+ qrloginFlag: false,
|
|
|
|
+ loginForm: {
|
|
|
|
+ id: '',
|
|
|
|
+ pass: '',
|
|
|
|
+ },
|
|
|
|
+ loginRule: {
|
|
|
|
+ id: [
|
|
|
|
+ { validator: validatePass, trigger: 'blur' },
|
|
|
|
+ ],
|
|
|
|
+ pass: [
|
|
|
|
+ { validator: validatePasswordCheck, trigger: 'blur' },
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ schoolForm: {
|
|
|
|
+ schoolCode: '',
|
|
|
|
+ id: '',
|
|
|
|
+ pass: ''
|
|
|
|
+ },
|
|
|
|
+ loginErrText: '',
|
|
|
|
+ schoolErrText: '',
|
|
|
|
+ data3: [
|
|
|
|
+ {
|
|
|
|
+ area: '四川省',
|
|
|
|
+ schools: [
|
|
|
|
+ {
|
|
|
|
+ id: 'DFGDFG',
|
|
|
|
+ name: '成都市鹽道街小學',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'QWERRR',
|
|
|
|
+ name: '四川師範大學附屬實驗學校',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE',
|
|
|
|
+ name: '成都市和平街小學',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE1',
|
|
|
|
+ name: '成都師範銀都紫藤小學',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE2',
|
|
|
|
+ name: '成都市錦江區駙馬小學校',
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ area: '湖北省',
|
|
|
|
+ schools: [
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE3',
|
|
|
|
+ name: '武漢市第三十中學',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE4',
|
|
|
|
+ name: '武漢市漢鐵寄宿初級中學',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'ERTRE5',
|
|
|
|
+ name: '武漢市江岸區新建小學',
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ loading: false
|
|
|
|
+ }
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
...mapState({
|
|
...mapState({
|
|
config: state => state.config
|
|
config: state => state.config
|
|
}),
|
|
}),
|
|
|
|
+ ...mapGetters({
|
|
|
|
+ loginSchooCode: 'user/getLoginSchooCode',
|
|
|
|
+ }),
|
|
|
|
+ userAccess() { return this.$access.getExtendInfo('userAccess');},
|
|
|
|
+ userInfo() { return this.$access.getExtendInfo('userInfo');},
|
|
|
|
+ loginFormEnter: function(){
|
|
|
|
+ let flag = false
|
|
|
|
+ if(this.loginForm.id && this.loginForm.pass) flag = true
|
|
|
|
+ return flag
|
|
|
|
+ },
|
|
|
|
+ schoolFormEnter: function(){
|
|
|
|
+ let flag = false
|
|
|
|
+ if(this.schoolForm.schoolCode && this.schoolForm.id && this.schoolForm.pass) flag = true
|
|
|
|
+ return flag
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ created() {
|
|
|
|
+
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
chgLoginType: function(){
|
|
chgLoginType: function(){
|
|
this.qrloginFlag = !this.qrloginFlag
|
|
this.qrloginFlag = !this.qrloginFlag
|
|
},
|
|
},
|
|
- chgSerType: function(val){
|
|
|
|
- if(this.config.srvAdr != val){
|
|
|
|
- let isProduction = process.env.NODE_ENV == 'development' ? false : true
|
|
|
|
- if(isProduction){
|
|
|
|
- window.open(this.config[val].domainUrl);
|
|
|
|
- } else {
|
|
|
|
- this.$store.dispatch('config/setSrvAdr', val)
|
|
|
|
|
|
+ loginSubmit: function(name){
|
|
|
|
+ this.$refs[name].validate( async(valid) => {
|
|
|
|
+ if (valid) {
|
|
|
|
+ this.loading = true
|
|
|
|
+ let result;
|
|
|
|
+ let id = this.loginForm.id
|
|
|
|
+
|
|
|
|
+ if(id.indexOf(0) == 0) id = id.substr(1)
|
|
|
|
+
|
|
|
|
+ // 呼叫Azure是否帳號正確
|
|
|
|
+ await this.$api.login.Verification({id: id, pass: this.loginForm.pass}).then(res => {
|
|
|
|
+ this.loading = false
|
|
|
|
+ result = res
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ if(result.error){
|
|
|
|
+ this.loginErrText = this.$t('login.apiError.text1')
|
|
|
|
+ } else {
|
|
|
|
+ let t_Data = this.$jwtDecode(result.id_token)
|
|
|
|
+ let id_token = result.id_token
|
|
|
|
+
|
|
|
|
+ // 設定Token 和 保存時間
|
|
|
|
+ localStorage.setItem("id_token", result.id_token)
|
|
|
|
+ localStorage.setItem("access_token", result.access_token)
|
|
|
|
+ localStorage.setItem("expires_in", result.expires_in)
|
|
|
|
+
|
|
|
|
+ // 取得大雲裡面使用者的資訊
|
|
|
|
+ await this.$api.login.getSingleSchoolUser({ id: t_Data.sub }).then( res => {
|
|
|
|
+ result = []
|
|
|
|
+ if(res.result.data.length != 0){
|
|
|
|
+ result = res.result.data
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ // 整理符合登入的內容
|
|
|
|
+ let userDetails = result.filter(function(item){
|
|
|
|
+ return parseInt(item.joinStatus) == 1
|
|
|
|
+ })
|
|
|
|
+ // 沒有符合的學校
|
|
|
|
+ if(userDetails.length === 0){
|
|
|
|
+ let userAccess = {
|
|
|
|
+ id: t_Data.sub,
|
|
|
|
+ role: [],
|
|
|
|
+ authority: [],
|
|
|
|
+ picture: t_Data.picture ? t_Data.picture : ''
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ User.login(userAccess).then(res => {
|
|
|
|
+ if(res) {
|
|
|
|
+ // 沒有加入過任何一間大雲學校,直接到選擇學校頁面
|
|
|
|
+ this.$router.push({ name: 'schoolList' })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ // 設定user詳細資訊
|
|
|
|
+ this.$store.dispatch('user/setUserDetails', userDetails)
|
|
|
|
+
|
|
|
|
+ let _this = this
|
|
|
|
+ let loginSchoolData = userDetails.filter(function(item){
|
|
|
|
+ return item.schoolCode == _this.loginSchooCode
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 檢查登入過的痕跡
|
|
|
|
+ if(loginSchoolData.length === 0){
|
|
|
|
+ // 以第一筆登入
|
|
|
|
+ let firstSchoolInfo = userDetails[0]
|
|
|
|
+ // 設定此瀏覽器的學校簡碼
|
|
|
|
+ this.$store.dispatch('user/setSchoolCode', firstSchoolInfo.schoolCode)
|
|
|
|
+
|
|
|
|
+ // 設定權限並登入
|
|
|
|
+ User.login(firstSchoolInfo).then(res => {
|
|
|
|
+ if(res) {
|
|
|
|
+ this.$router.push({ path: '/home' })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ User.login(loginSchoolData[0]).then(res => {
|
|
|
|
+ if(res) {
|
|
|
|
+ this.$router.push({ path: '/home' })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- },
|
|
|
|
|
|
+ })
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-</script>
|
|
|
|
|
|
+</script>
|