| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- <template>
- <view class="page_login" v-if="!state.isLoading">
- <view class="login_weclome">
- Hi~欢迎使用
- </view>
- <view class="login_title">
- 大数据精准教学诊断平台
- </view>
- <view class="login_content">
- <view class="user_name">
- <input class="input_name" v-model="state.username" placeholder="请输入账号" @blur="inputBlur"
- @focus="inputFocus" />
- <text class="clear_icon" v-if="state.showClearIcon" @click="clearUserName"></text>
- </view>
- <view class="user_pass">
- <input class="input_name" v-model="state.password" :password="!state.isShowPassWord"
- placeholder="请输入密码" />
- <text v-if="!state.isShowPassWord" class="eyes_icon" @click="showUserPass"></text>
- <text v-else class="eye_icon" @click="hideUserPass"></text>
- </view>
- <view class="login_button" @click="handleLogin">
- 登录
- </view>
- <view class="agreement">
- <radio :checked="isCheck" @click="isCheck = !isCheck" value="radio" activeBackgroundColor="#2E64FA"
- activeBorderColor="#2E64FA" />
- <view class="text">
- <text class="color_999">我已阅读并同意</text>
- <text class="color_blue" @click="AgreementDetails">用户协议</text>
- <text class="color_blue" @click="AgreementDetails">和</text>
- <text class="color_blue" @click="AgreementDetails">隐私改策</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 提示框 -->
- <popupDialog ref="popupDialogRef" popType="custom" title="选择学校" @DialogConfirm="DialogConfirm">
- <view class="school_list">
- <view :class="['list_item', { active: state.schoolId == item.schoolId }]" @click="SelectSchool(item.schoolId)"
- v-for="item in state.schoolsList" :key="item.schoolId">
- <view class="school_logo">
- <image class="logo" v-if="item.schoolLogoUrl" :src="item.schoolLogoUrl"></image>
- <image class="logo" v-else src="@/static/image/bg/default_user.png"></image>
- </view>
- <text class="school_name">{{ item.schoolName }}</text>
- <uni-icons class="item_right" type="right"></uni-icons>
- </view>
- </view>
- </popupDialog>
- <custom-dialog ref="popupSlideCode" title="滑动验证">
- <view class="slide_code_content">
- <slide-code ref="slideRef" :sliderBgUrl="state.sliderBgUrl" :sliderUUID="state.sliderUUID"
- :blockBgUrl="state.blockBgUrl" :sliderVerified="state.sliderVerified"
- :sliderPositionY="state.sliderPositionY" @Refresh="GetObtainSliderImg" @CheckResult="CheckResult" />
- </view>
- <view class="login_code_message" v-if="state.sliderPhone">
- 验证码已发送至手机:{{ state.sliderPhone }}
- </view>
- <view class="login_code_input">
- <input class="input_name" v-model="state.loginCode" placeholder="请输入验证码" maxlength="6" @blur="inputBlur"
- @focus="inputFocus" />
- </view>
- <view class="login_code_button" @click="ConfirmEnter">
- 确定
- </view>
- </custom-dialog>
- </template>
- <script setup>
- import user from '@/reqApi/user.js';
- import { encrypt } from '@/common/crypto.js';
- import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
- import popupDialog from '@/components/popupDialog.vue';
- import customDialog from '@/components/customDialog.vue';
- import slideCode from '@/components/slideCode.vue';
- import {
- reactive,
- ref,
- onMounted,
- onUnmounted
- } from 'vue';
- import { useStore } from 'vuex';
- import { useRoute, useRouter } from 'vue-router'
- const store = useStore();
- const route = useRoute() // 获取当前路由信息
- const popupDialogRef = ref(null);
- const popupSlideCode = ref(null);
- const isCheck = ref(false);
- const state = reactive({
- username: '',
- password: '',
- schoolId: '',
- schoolsList: [],
- showClearIcon: false,
- isShowPassWord: false,
- isLoading: false,
- sliderBgUrl: '',//滑动验证码背景图
- blockBgUrl: '',//滑动验证码块切块图
- sliderUUID: '',//滑动验证码唯一标识
- sliderPositionY: 0,//滑动验证码块切块图位置y坐标
- sliderPositionX: 0,//滑动验证码块切块图位置x坐标
- loginCode: '',//登录验证码
- sliderVerified: 0,//滑动验证码是否验证成功 0 未验证 1 验证成功 -1 验证失败
- sliderPhone: '',//滑动验证码显示的手机号
- deviceFinger: '',//设备指纹
- });
- onMounted(() => {
- // #ifdef H5
- const options = route.query;
- if (options.schoolId && options.ticket) {
- state.isLoading = true;
- uni.showLoading({
- title: '登录中,请稍等!'
- });
- user.adminLoginTeach({
- id: options.schoolId,
- ticket: options.ticket
- }).then(res => {
- if (res.code == 200) {
- //先清除所有缓存
- store.dispatch('logout', false);
- const token = res.data.tokenValue;
- store.dispatch('setToken', token);
- uni.setStorageSync('token', token); // 存储 token 到本地
- store.dispatch('setUserInfo');
- uni.redirectTo({
- url: '/pages/workspace/index'
- });
- } else {
- uni.showToast({
- title: res.msg || '账号不存在或者密码错误!',
- icon: 'none'
- });
- }
- }).finally(() => {
- state.isLoading = false;
- uni.hideLoading();
- })
- }
- const systemInfo = uni.getSystemInfoSync();
- state.deviceFinger = systemInfo.deviceId;//设备指纹
- console.log('设备标识id', systemInfo);
- // #endif
- });
- const hideUserPass = () => {
- state.isShowPassWord = false;
- }
- const showUserPass = () => {
- state.isShowPassWord = true;
- }
- //清除用户名
- const clearUserName = () => {
- state.username = "";
- state.showClearIcon = false;
- }
- //滑动验证码验证结果返回
- const CheckResult = (result) => {
- console.log("滑动验证码结果", result);
- state.sliderPhone = result;
- state.sliderVerified = 1;
- // VerifySlideCaptcha();
- }
- //保存用户设备指纹信息
- const SaveUserDeviceFinge = () => {
- if (state.deviceFinger) {
- let param = {
- username: state.username.trim(),
- deviceFinger: state.deviceFinger,//设备指纹
- };
- user.saveUserDeviceFinge(param).then(res => {
- console.log("保存用户设备指纹信息结果", res);
- })
- }
- else {
- console.log("设备指纹为空");
- }
- }
- //验证滑动验证码位置是否正确
- const VerifySlideCaptcha = () => {
- let params = {
- sliderUUID: state.sliderUUID,
- x: Math.round(state.sliderPositionX),//滑动验证码块切块图位置x坐标
- };
- user.checkSlideCaptcha(params).then(res => {
- console.log("333验证滑动验证码结果", res);
- if (res.code == 200) {
- //验证成功
- state.sliderVerified = 1;
- state.sliderPhone = res.data;//手机号
- }
- else if (res.code == 601) {
- //验证成功
- state.sliderVerified = 1;
- uni.showToast({
- title: res.msg || '滑块验证通过,您上次的验证码还在有效期,请输入上次发送的验证码进行登录!',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- }
- else if (res.code == 602) {
- //滑动验证码过期 重新获取验证码
- uni.showToast({
- title: '验证码已过期,已重新获取,请重新拖动滑块验证',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- GetObtainSliderImg();//重新获取验证码
- }
- else {
- state.sliderVerified = 0;//验证失败
- state.sliderPositionX = 0;//重置滑块位置
- }
- });
- }
- //重新获取验证码
- const GetObtainSliderImg = () => {
- let params = {
- sliderUUID: state.sliderUUID,
- };
- user.obtainSliderImg(params).then(res => {
- console.log("重新获取滑动验证码结果", res);
- if (res.code == 200) {
- state.sliderVerified = 0;//未验证
- state.sliderUUID = res.data.sliderUUID;//滑动验证码唯一标识
- state.sliderBgUrl = res.data.backgroundBase64;//滑动验证码背景图
- state.blockBgUrl = res.data.blockBase64;//滑动验证码块
- state.sliderPositionY = Math.round(res.data.y);
- }
- })
- }
- // 失去焦点
- const inputBlur = () => {
- if (state.username != '') {
- state.showClearIcon = true;
- } else {
- state.showClearIcon = false;
- }
- }
- //获取焦点
- const inputFocus = (event) => {
- if (state.username != '') {
- state.showClearIcon = true;
- } else {
- state.showClearIcon = false;
- }
- }
- //选择学校
- const SelectSchool = (schoolId) => {
- state.schoolId = schoolId;
- }
- //点击确定按钮
- const DialogConfirm = () => {
- user.chooseBelongSchool({
- schoolId: state.schoolId,
- deviceType: 'APP'
- }).then(res => {
- if (res.code == 200) {
- const modules = res?.data?.modules || [];
- store.dispatch('setModulesList', modules);
- uni.setStorageSync('modulesList', modules);
- LoginSuccess();
- }
- })
- }
- //登录验证点击确定
- const ConfirmEnter = () => {
- if (state.sliderVerified != 1) {
- uni.showToast({
- title: '请拖动滑块进行验证!',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- return;
- }
- if (state.loginCode == '') {
- uni.showToast({
- title: '请输入验证码',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- return;
- }
- let param = {
- username: state.username.trim(),
- password: encrypt(state.password.trim()),
- phoneCode: state.loginCode.trim(),//手机验证码
- sliderUUID: state.sliderUUID,//验证码唯一id
- deviceType: 'APP'
- };
- user.teacherLoginByCode(param).then(res => {
- console.log("教师端手机验证码登录返回结果", res);
- if (res.code == 200) {
- //登录成功
- console.log("打印登录结果", res);
- popupSlideCode.value.close();//关闭滑动验证码弹窗
- const token = res.data.tokenValue;
- store.dispatch('setToken', token);
- uni.setStorageSync('token', token); // 存储 token 到本地
- uni.showModal({
- title: '信任此设备',
- content: '是否将此设备设为信任设备?未来30天内登录可免滑动验证',
- confirmText: '信任',
- cancelText: '不信任',
- success: function (modalResult) {
- if (modalResult.confirm) {
- //用户信任此设备
- SaveUserDeviceFinge();
- }
- else if (modalResult.cancel) {
- //用户选择不信任
- }
- HandleSuccessfulLogin(res);//登录成功
- }
- })
- } else {
- //登录失败
- uni.showToast({
- title: res.msg,
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- }
- })
- }
- const handleLogin = () => {
- state.schoolsList = [];
- // 登录逻辑
- // console.log('用户名:', state.username)
- // console.log('密码:', state.password)
- let params = {
- username: state.username.trim(),
- password: encrypt(state.password.trim()),
- deviceFinger: state.deviceFinger,//设备唯一指纹id
- deviceType: 'APP'
- }
- if (!params.username) {
- console.log("没有输入用户名");
- uni.showToast({
- title: '请输入用户名',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- return;
- }
- if (!params.password) {
- uni.showToast({
- title: '请输入密码',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- return;
- }
- if (!isCheck.value) {
- uni.showToast({
- title: '请先阅读并同意相关协议',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- return;
- }
- user.login(params).then(res => {
- console.log("打印登录结果", res);
- if (res.code == 200) {
- //先判断是否有token 有token 直接登录成功
- if (res.data.tokenValue != null) {
- HandleSuccessfulLogin(res);//登录成功
- }
- else {
- //没有token 判断是否绑定了手机号
- if (res.data.bindPhone == 1) {
- //有手机号 弹出滑动验证码
- state.sliderVerified = 0;//未验证
- popupSlideCode.value.open();//打开滑动验证码弹窗
- state.sliderBgUrl = res.data.backgroundBase64;
- state.blockBgUrl = res.data.blockBase64;
- state.sliderUUID = res.data.sliderUUID;
- state.sliderPositionY = Math.round(res.data.y);
- }
- else {
- //没有手机号 弹出登录验证码弹窗
- uni.showToast({
- title: '您的账号未绑定手机号,请先去pc端绑定手机号!',
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- }
- }
- }
- else {
- uni.showToast({
- title: res.msg,
- icon: 'none', // 可选值:'success', 'loading', 'none'
- duration: 2000 // 提示持续时间,单位毫秒
- });
- }
- })
- }
- //统一登录处理
- const HandleSuccessfulLogin = (res) => {
- const token = res.data.tokenValue;
- store.dispatch('setToken', token);
- uni.setStorageSync('token', token); // 存储 token 到本地
- const schoolsList = res?.data?.schools || [];
- state.schoolsList = schoolsList;
- store.dispatch('setSchoolsList', schoolsList);
- uni.setStorageSync('schoolsList', schoolsList); // 存储 学校 到本地
- if (schoolsList.length > 1) {
- popupDialogRef.value.OpenDialog();
- } else {
- // state.schoolInfo = schoolsList?.[0];
- LoginSuccess();
- }
- }
- const LoginSuccess = () => {
- uni.showToast({
- title: '登录成功',
- icon: 'success',
- mask: true,
- duration: 2000
- });
- store.dispatch('setUserInfo');
- uni.redirectTo({
- url: '/pages/workspace/index'
- });
- }
- const AgreementDetails = () => {
- uni.navigateTo({
- url: '/pages/login/agreement'
- })
- }
- </script>
- <style lang="scss">
- :deep(.school_list) {
- padding: 0 30rpx;
- width: 100%;
- box-sizing: border-box;
- .list_item {
- margin-top: 20rpx;
- display: flex;
- align-items: center;
- width: 100%;
- height: 108rpx;
- background-color: #FFFFFF;
- border-radius: 12rpx;
- border: 1px solid #E4E7ED;
- padding: 20rpx 38rpx 20rpx 24rpx;
- box-sizing: border-box;
- &.active {
- border: 1px solid #2E64FA;
- background-color: rgba(46, 100, 250, 0.1);
- }
- .school_logo {
- width: 68rpx;
- height: 68rpx;
- background: #C2D2FF;
- border-radius: 50%;
- overflow: hidden;
- margin-right: 28rpx;
- .logo {
- width: 100%;
- height: 100%;
- border-radius: 50%;
- }
- }
- .school_name {
- flex: 1;
- height: 68rpx;
- display: inline-flex;
- align-items: center;
- justify-content: flex-start;
- font-weight: 500;
- font-size: 24rpx;
- color: #000000;
- span {
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- overflow: hidden;
- word-break: break-all;
- }
- }
- .item_right {
- margin-left: 28rpx;
- font-size: 36rpx !important;
- color: #999999 !important;
- }
- }
- }
- :deep(.login_code_input) {
- width: 100%;
- height: 40px;
- border-radius: 10px 10px 10px 10px;
- border: 1px solid #EBEEF5;
- line-height: 40px;
- margin-top: 20rpx;
- display: flex;
- align-items: center;
- justify-content: left;
- text-indent: 20rpx;
- }
- .login_code_message {
- width: 100%;
- font-size: 24rpx;
- margin-top: 20rpx;
- }
- .login_code_button {
- width: 100%;
- height: 40px;
- border-radius: 8px;
- background-color: #2E64FA;
- color: #FFFFFF;
- text-align: center;
- line-height: 40px;
- margin-top: 20rpx;
- }
- </style>
|