loginPage.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. <template>
  2. <div class="loginPage">
  3. <div class="lp_left">
  4. <img :src="showLoginMessage.banner" />
  5. </div>
  6. <div class="lp_right">
  7. <div v-if="allowOrgList.findIndex((i) => i.area) == -1" @click="backVersion" class="Version">
  8. {{ lang.Returnoldversion }}
  9. </div>
  10. <div class="lp_r_box">
  11. <div class="lp_r_b_logo">
  12. <div>
  13. <el-image
  14. v-if="showLoginMessage.logo"
  15. style="width: 35px; height: 35px; border-radius: 50%"
  16. :src="showLoginMessage.logo"
  17. ></el-image>
  18. </div>
  19. <div
  20. style="width: 100%; display: flex; justify-content: space-between"
  21. >
  22. <div>
  23. <div v-if="steps == 1">
  24. <span v-if="showLoginMessage.name">{{
  25. showLoginMessage.name
  26. }}</span>
  27. <span style="margin: 0" v-else>{{ lang.KekeleboPlatform }}</span>
  28. </div>
  29. </div>
  30. <div v-if="steps == 2" style="cursor: pointer" @click="steps = 1,stuInfoCode = {}">
  31. <i style="font-size: 30px" class="el-icon-back"></i>
  32. </div>
  33. </div>
  34. </div>
  35. <template v-if="steps == 1">
  36. <span v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)"
  37. >{{ lang.login }}</span
  38. >
  39. <span v-if="['bind'].includes(loginType)">{{ lang.Bindaccount }}</span>
  40. <div class="lp_r_b_formArea">
  41. <!-- 微信绑定,账号登录,组织号登录 -->
  42. <div
  43. class="fa_input"
  44. v-if="['default', 'bind', 'orgL'].includes(loginType)"
  45. >
  46. <div
  47. class="fa_i_item"
  48. style="position: relative"
  49. v-if="loginType == 'orgL'"
  50. >
  51. <span>{{ lang.OrganizationNumber }}</span>
  52. <div>
  53. <input
  54. type="text"
  55. :placeholder="lang.enterorgnumber"
  56. v-model.trim="SuffixData"
  57. @input="getSuffix"
  58. />
  59. </div>
  60. <div
  61. style="
  62. border: none;
  63. font-size: 12px;
  64. position: absolute;
  65. left: 0;
  66. bottom: -70%;
  67. "
  68. v-if="SuffixData.trim()"
  69. >
  70. {{ orginfo.length ? orginfo[0].name : lang.schoolnotexist }}
  71. </div>
  72. </div>
  73. <div class="fa_i_item">
  74. <span>{{ lang.account }}</span>
  75. <div>
  76. <!-- @change="getOrgData" -->
  77. <input
  78. type="text"
  79. :placeholder="lang.enteraccount"
  80. v-model.trim="account"
  81. @keyup.enter="loginFn"
  82. />
  83. </div>
  84. </div>
  85. <div class="fa_i_item">
  86. <span>{{ lang.password }}</span>
  87. <div>
  88. <input
  89. type="password"
  90. :placeholder="lang.enterpassword"
  91. v-model="password"
  92. @keyup.enter="loginFn"
  93. />
  94. </div>
  95. </div>
  96. </div>
  97. <!-- 微信登录 -->
  98. <div class="fa_weChat" v-if="['weChat'].includes(loginType)">
  99. <div id="QRcode" class="QRcode" ref="QRcode"></div>
  100. <!-- @click="loginType = 'bind'" -->
  101. </div>
  102. <!-- 随机码登录 -->
  103. <div class="fa_input" v-if="['code'].includes(loginType)">
  104. <div class="fa_i_item" style="position: relative">
  105. <span v-if="prefixL == 'liyuan_'">{{ lang.SelectCampus }}</span>
  106. <span v-else>{{ lang.OrganizationNumber }}</span>
  107. <!-- v-if="prefixL == 'liyuan_'" -->
  108. <div v-if="prefixL == 'liyuan_'">
  109. <el-select
  110. v-loading="Codeloading"
  111. @change="getSuffix"
  112. v-model.trim="SuffixData"
  113. :placeholder="lang.Pleaseselect"
  114. >
  115. <el-option
  116. v-for="item in CodeOptions"
  117. :key="item.code"
  118. :label="item.name"
  119. :value="item.code"
  120. >
  121. </el-option>
  122. </el-select>
  123. </div>
  124. <div v-else>
  125. <input
  126. type="text"
  127. :placeholder="lang.enterorgnumber"
  128. v-model.trim="SuffixData"
  129. @input="getrandomcodeSuffix"
  130. />
  131. </div>
  132. <div
  133. style="
  134. border: none;
  135. font-size: 12px;
  136. position: absolute;
  137. left: 0;
  138. bottom: -70%;
  139. "
  140. v-if="SuffixData.trim() && prefixL != 'liyuan_'"
  141. >
  142. {{ orginfo.length ? orginfo[0].name : lang.schoolnotexist }}
  143. </div>
  144. </div>
  145. <div class="fa_i_item">
  146. <span>{{ lang.randomcode }}</span>
  147. <div>
  148. <input
  149. type="text"
  150. :placeholder="lang.Pleaseenter"
  151. v-model.trim="icode"
  152. @keyup.enter="nextSteps"
  153. />
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. <div
  159. class="lp_r_b_btn"
  160. v-if="['code'].includes(loginType)"
  161. @click="nextSteps"
  162. v-loading="loading"
  163. >
  164. {{ lang.confirm }}
  165. </div>
  166. <div
  167. class="lp_r_b_btn"
  168. v-if="['default', 'orgL'].includes(loginType)"
  169. @click="loginFn"
  170. v-loading="loading"
  171. >
  172. {{ lang.login }}
  173. </div>
  174. <div
  175. class="lp_r_b_btn"
  176. v-if="loginType == 'weChat'"
  177. style="opacity: 0; cursor: default"
  178. >
  179. {{ lang.Accpaslogin }}
  180. </div>
  181. <div class="btn_box" v-if="loginType == 'bind'">
  182. <div class="lp_r_b_btn" @click="loginFn" v-loading="loading">
  183. {{ lang.Confirmbinding }}
  184. </div>
  185. <div class="lp_r_b_btn" @click="loginType = 'default'">
  186. {{ lang.Returnlogin }}
  187. </div>
  188. </div>
  189. <div class="lp_r_b_line">
  190. <template
  191. v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)"
  192. >
  193. <div></div>
  194. <span>{{ lang.Otherlogin }}</span>
  195. <div></div>
  196. </template>
  197. </div>
  198. <div class="lp_r_b_iconBtn">
  199. <div v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)" @click="getData">
  200. <!-- v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)" -->
  201. <el-tooltip effect="dark" :content="lang.Rancodelogin" placement="bottom">
  202. <img
  203. :src="
  204. loginType == 'code'
  205. ? require('../../assets/login/codel.png')
  206. : require('../../assets/login/code.png')
  207. "
  208. :class="[loginType == 'code' ? 'backWin' : '']"
  209. />
  210. </el-tooltip>
  211. </div>
  212. <div
  213. @click="(loginType = 'orgL'), (org = '')"
  214. v-if="
  215. ['default', 'weChat', 'orgL', 'code'].includes(loginType) &&
  216. allowOrgList.findIndex((i) => i.area) == -1
  217. "
  218. >
  219. <el-tooltip effect="dark" :content="lang.OrgIDLogin" placement="bottom">
  220. <img
  221. style="width: 32px; object-fit: cover"
  222. :src="
  223. loginType == 'orgL'
  224. ? require('../../assets/login/zzl.svg')
  225. : require('../../assets/login/orgh.svg')
  226. "
  227. :class="[loginType == 'orgL' ? 'backWin' : '']"
  228. />
  229. </el-tooltip>
  230. </div>
  231. <div
  232. @click="wechatLogin"
  233. v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)"
  234. >
  235. <el-tooltip effect="dark" :content="lang.WeChatLogin" placement="bottom">
  236. <img
  237. :src="
  238. loginType == 'weChat'
  239. ? require('../../assets/login/wxl.svg')
  240. : require('../../assets/login/wxh.svg')
  241. "
  242. :class="[loginType == 'weChat' ? 'backWin' : '']"
  243. />
  244. </el-tooltip>
  245. </div>
  246. <div
  247. @click="(loginType = 'default'), (SuffixData = '')"
  248. v-if="['default', 'weChat', 'orgL', 'code'].includes(loginType)"
  249. >
  250. <el-tooltip
  251. effect="dark"
  252. :content="lang.Accpaslogin"
  253. placement="bottom"
  254. >
  255. <img
  256. :src="
  257. loginType == 'default'
  258. ? require('../../assets/login/zhl.svg')
  259. : require('../../assets/login/zhh.svg')
  260. "
  261. :class="[loginType == 'default' ? 'backWin' : '']"
  262. />
  263. </el-tooltip>
  264. </div>
  265. </div>
  266. </template>
  267. <div class="stuPage" v-if="steps == 2">
  268. <div>{{ lang.choosename }}</div>
  269. <div class="stuList">
  270. <!-- <span v-for="i in classJuri" :key="i.userid">{{ i.name }}</span> -->
  271. <!-- <div v-for="i in 10" :key="i" @click="selAcc(i)">yym</div> -->
  272. <div
  273. v-for="i in classJuri"
  274. :key="i.userid"
  275. :class="[stuInfoCode.userid == i.userid ? 'stuback' : '']"
  276. @click="selAcc(i)"
  277. >
  278. <el-tooltip effect="dark" :content="i.name" placement="top">
  279. <span>
  280. {{ i.name }}
  281. </span>
  282. </el-tooltip>
  283. </div>
  284. </div>
  285. <div v-if="!classJuri.length" class="none">{{ lang.nostudents }}</div>
  286. <div class="lp_r_b_btn" @click="loginCode" v-loading="loading">
  287. {{ lang.Confirmlogin }}
  288. </div>
  289. </div>
  290. </div>
  291. </div>
  292. </div>
  293. </template>
  294. <script>
  295. import { mapActions } from "vuex";
  296. import axios from "axios";
  297. import qs from "qs";
  298. import { API_CONFIG } from "@/common/apiConfig";
  299. import "@/common/wxLogin";
  300. import { getUser, loginOut,GetSuffix } from "@/api/user";
  301. import { myMixin } from "@/mixins/mixin.js";
  302. export default {
  303. mixins: [myMixin],
  304. name: "loginPage",
  305. data() {
  306. return {
  307. // 判断显示组织号区域
  308. SuffixShow: false,
  309. // 组织号查询区域结果
  310. SuffixData: "",
  311. orginfo: [],
  312. CodeOptions: [],
  313. // 随机码
  314. icode: "",
  315. // 根据随机码获取到的课程id
  316. courseId: "",
  317. // 随机码登录获取到的课程学生列表
  318. classJuri: [],
  319. // 随机码荔园登录获code数据加载框
  320. Codeloading: false,
  321. // 随机码登录页面切换
  322. steps: 1,
  323. // 随机码选择学生账户信息登录
  324. stuInfoCode: {},
  325. // 后缀
  326. org: "",
  327. account: "",
  328. password: "",
  329. loading: false,
  330. loginType: "default",
  331. redirect: this.$route.query["redirect"],
  332. org2:
  333. this.$route.query["org"] ||
  334. (window.location.href.includes("/liyuan")
  335. ? window.sessionStorage.getItem("org2")
  336. : ""),
  337. oid: this.$route.query["oid"],
  338. // 组织列表
  339. OrgOptions: [],
  340. form: {},
  341. showName: "",
  342. oloading: false,
  343. openid: "",
  344. allowOrgList: [
  345. {
  346. area:
  347. parent.location.href.includes("lyxx") ||
  348. parent.location.href.includes("liyuan"),
  349. banner:
  350. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/20250421-1139511745206807965.jpg",
  351. logo: "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/image%2051744962188550.svg",
  352. name: "荔园小学教育集团",
  353. list: [
  354. "3823a6a5-1b6e-11f0-a66a-005056924926",
  355. "292e34dc-1b6e-11f0-a66a-005056924926",
  356. "21d6b367-1b6e-11f0-a66a-005056924926",
  357. "1a1a172d-1b6e-11f0-a66a-005056924926",
  358. "1197f86b-1b6e-11f0-a66a-005056924926",
  359. "f235659b-1b6d-11f0-a66a-005056924926",
  360. "d87b62d3-1b6d-11f0-a66a-005056924926",
  361. "c25ea59b-1b6d-11f0-a66a-005056924926",
  362. ],
  363. },
  364. ],
  365. };
  366. },
  367. watch: {
  368. loginType(newValue) {
  369. if (newValue != "weChat") {
  370. if (this.$refs.QRcode && this.$refs.QRcode.innerHTML) {
  371. this.$refs.QRcode.innerHTML = "";
  372. }
  373. }
  374. },
  375. },
  376. computed: {
  377. showLoginMessage() {
  378. let _result = {
  379. banner: require("@/assets/login2.jpg"),
  380. logo: "",
  381. name: "",
  382. };
  383. if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  384. let _index = this.allowOrgList.findIndex((i) => i.area);
  385. let _obj = this.allowOrgList[_index];
  386. _result.banner = _obj.banner;
  387. _result.name = _obj.name;
  388. _result.logo = _obj.logo;
  389. }
  390. return _result;
  391. },
  392. userRequest() {
  393. console.log('this.$region',this.$region);
  394. let _result = this.$region == 'hk' ? 'https://cloud.api.cocorobo.hk/api/user' : 'https://beta.api.cocorobo.cn/api/user'
  395. return _result;
  396. },
  397. },
  398. methods: {
  399. ...mapActions({
  400. login: "user/login",
  401. logout: "user/logout",
  402. }),
  403. // 返回旧版本
  404. backVersion(){
  405. this.$confirm(this.lang.backoldversion, this.lang.tip, {
  406. confirmButtonText: this.lang.confirm,
  407. cancelButtonText: this.lang.Cancel,
  408. type: "warning",
  409. })
  410. .then(() => {
  411. console.log(this.$region);
  412. if (this.$region == 'beta') {
  413. window.topU.location.href = 'https://beta.cloud.cocorobo.cn/index.html'
  414. }else if(this.$region == 'hk'){
  415. window.topU.location.href = 'https://cloud.cocorobo.hk/'
  416. }else{
  417. window.topU.location.href = 'https://cloud.cocorobo.cn/index.html'
  418. }
  419. })
  420. .catch(() => {});
  421. },
  422. // 随机码获取组织后缀
  423. async getrandomcodeSuffix() {
  424. let params = [
  425. {
  426. functionName: API_CONFIG.ajax_getliyuanCode.functionName,
  427. mode: this.SuffixData
  428. },
  429. ];
  430. const res = await this.$ajax.post(API_CONFIG.baseUrl, params);
  431. let data = [...res.data[0], ...res.data[1]];
  432. console.log('data', data);
  433. if (data.length) {
  434. this.orginfo = data;
  435. this.org = this.orginfo[0].mail;
  436. } else {
  437. this.orginfo = [];
  438. this.org = "";
  439. }
  440. },
  441. // 获取组织后缀
  442. async getSuffix() {
  443. if (!this.SuffixData){
  444. this.orginfo = [];
  445. this.org = "";
  446. return
  447. }
  448. let res = await GetSuffix({ mode: this.SuffixData });
  449. console.log("res.data[0]", res.data[0]);
  450. if (res.data[0].length && this.SuffixData) {
  451. this.orginfo = res.data[0];
  452. this.org = this.orginfo[0].mail;
  453. } else {
  454. this.orginfo = [];
  455. this.org = "";
  456. }
  457. // let res = await getliyuanCode({ mode: this.SuffixData });
  458. // console.log("res.data", res.data);
  459. // if (res.data[0].length && this.SuffixData) {
  460. // this.orginfo = res.data[0];
  461. // this.org = this.orginfo[0].mail;
  462. // } else {
  463. // this.orginfo = [];
  464. // this.org = "";
  465. // }
  466. },
  467. async loginFn() {
  468. if (this.loading) return;
  469. this.loading = true;
  470. // loginType == orgL为组织号登录
  471. if (this.loginType == "orgL" && !this.org){
  472. this.loading = false;
  473. return this.$message.error(this.lang.enterorgnumber);
  474. }
  475. // if (this.loginType != 'orgL') {
  476. if ((await this.getOrgData()) == 2){
  477. this.loading = false;
  478. return (this.loginType = "orgL");
  479. }
  480. // }
  481. const regEmail = new RegExp(
  482. "^[A-Za-z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"
  483. );
  484. if (this.account.length <= 0) {
  485. this.$message.error(this.lang.enteraccount);
  486. this.loading = false;
  487. return;
  488. }
  489. if (this.password.length < 6 || /[\u4e00-\u9fa5]/.test(this.password)) {
  490. this.$message.error(this.lang.passwordlength);
  491. this.loading = false;
  492. return;
  493. }
  494. // 荔园平台登录账号进行判断
  495. if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  496. let _index = this.allowOrgList.findIndex((i) => i.area);
  497. let _list = this.allowOrgList[_index].list;
  498. if (
  499. this.OrgOptions.find((i) => i.Uorg == this.org) &&
  500. !_list.includes(this.OrgOptions.find((i) => i.Uorg == this.org).id)
  501. ) {
  502. this.loading = false;
  503. return this.$message.error(this.lang.Accountcannot);
  504. }
  505. } else {
  506. let mergedList = this.allowOrgList.reduce((acc, curr) => {
  507. return [...acc, ...curr.list];
  508. }, []);
  509. let str = this.account.replace(/(^\s*)|(\s*$)/g, "");
  510. console.log('regEmail.test(str)',!regEmail.test(str),this.org);
  511. if (this.OrgOptions.find((i) => i.Uorg == this.org)) {
  512. if (
  513. mergedList.includes(
  514. this.OrgOptions.find((i) => i.Uorg == this.org).id
  515. )
  516. ) {
  517. this.loading = false;
  518. return this.$message.error(this.lang.Accountcannot);
  519. }
  520. } else {
  521. if (regEmail.test(str)) {
  522. if (this.OrgOptions.find((i) => i.Uorg == str)) {
  523. if (
  524. mergedList.includes(
  525. this.OrgOptions.find((i) => i.Uorg == str).id
  526. )
  527. ) {
  528. this.loading = false;
  529. return this.$message.error(this.lang.Accountcannot);
  530. }
  531. }
  532. }else{
  533. this.loading = false;
  534. return this.$message.error(this.lang.accountnotcreated);
  535. }
  536. }
  537. }
  538. let str = this.account.replace(/(^\s*)|(\s*$)/g, "");
  539. if (!this.org && !regEmail.test(str)) {
  540. // this.$message.error(
  541. // "请在账号后添加组织后缀(账号@组织号.com 如:123456@cocorobo.com)"
  542. // );
  543. if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  544. this.$message.error(
  545. this.lang.addsuffix
  546. );
  547. } else {
  548. this.$message.error(this.lang.accountmustOrg);
  549. this.loginType = "orgL";
  550. }
  551. this.loading = false;
  552. return;
  553. }
  554. let orgValue = this.org ? "@" + this.org : "@cocorobo.cc";
  555. let email = "";
  556. // 判断用户输入账户带不带后缀
  557. if (!regEmail.test(str)) {
  558. email = str + orgValue;
  559. } else {
  560. email = str;
  561. }
  562. if (["default", "orgL"].includes(this.loginType)) {
  563. let params = {
  564. geetest_challenge: "",
  565. geetest_validate: "",
  566. geetest_seccode: "",
  567. loginUsername: email.trim(),
  568. loginPassword: window.btoa(this.password.trim()),
  569. };
  570. axios.defaults.withCredentials = true;
  571. console.log("👇", this.prefixL);
  572. // this.addOp3('1', "", { type:this.prefixL + "login" }, "success",'0c3735c9-a2ef-11ef-9b30-005056b86db5')
  573. axios
  574. .post(this.userRequest, qs.stringify(params))
  575. .then(async (res) => {
  576. console.log("this.userRequestres", res);
  577. let _data = res.data[0][0];
  578. let userjson = await getUser({ userid: _data.userid });
  579. if (userjson.data[0][0].type == 2) {
  580. this.loading = false;
  581. this.$message.error(this.lang.Nologinpermission);
  582. return;
  583. }
  584. console.log("userjson", userjson);
  585. if (_data.active === 1) {
  586. window.localStorage["identity"] = JSON.stringify(_data.identity);
  587. window.topU.U.UF.Cookie.set("cocoroboLoginType=2");
  588. window.topU
  589. ? (window.topU.US.userInfo = _data)
  590. : (window.parent.US.userInfo = _data);
  591. await this.login();
  592. this.$message.success(this.lang.Loginsuccessful);
  593. if (
  594. userjson.data[0][0].type == 1 &&
  595. userjson.data[0][0].role == 1 &&
  596. userjson.data[0][0].rrole == 1 &&
  597. this.allowOrgList.findIndex((i) => i.area) != -1
  598. ) {
  599. this.$router.push({ path: "/kanban" });
  600. } else {
  601. this.$router.push({ path: this.redirect || "/" });
  602. }
  603. this.addOp3(
  604. "1",
  605. "",
  606. { type: this.prefixL + "login" },
  607. "success",
  608. _data.userid
  609. );
  610. } else {
  611. this.$message.error(this.lang.Loginfailed);
  612. }
  613. this.loading = false;
  614. })
  615. .catch((e) => {
  616. if (e.response && e.response.data == "Wrong email or password") {
  617. this.$message.error(this.lang.Accerror);
  618. } else {
  619. this.$message.error(this.lang.Loginfailed);
  620. }
  621. this.loading = false;
  622. });
  623. } else if (this.loginType == "bind") {
  624. // this.$message.info("绑定账号");
  625. let data = await this.$ajax.post(API_CONFIG.baseUrl2 + "checkOpenId", [
  626. { email: email },
  627. ]);
  628. if (!data.data[0].length) {
  629. this.$message.error(this.lang.Nocoracc);
  630. this.loading = false;
  631. return;
  632. }
  633. if (data.data[0][0].thirdpartyid) {
  634. this.$message.error(this.lang.hasbeenlinked);
  635. this.loading = false;
  636. return;
  637. }
  638. let params = {
  639. geetest_challenge: "",
  640. geetest_validate: "",
  641. geetest_seccode: "",
  642. loginUsername: email.trim(),
  643. loginPassword: window.btoa(this.password.trim()),
  644. };
  645. this.loading = true;
  646. axios.defaults.withCredentials = true;
  647. console.log("👇进入进行微信绑定环节");
  648. axios
  649. .post(this.userRequest, qs.stringify(params))
  650. .then(async (res) => {
  651. console.log("res", res);
  652. let _data = res.data[0][0];
  653. let userjson = await getUser({ userid: _data.userid });
  654. if (userjson.data[0][0].type == 2) {
  655. this.loading = false;
  656. this.$message.error(this.lang.Nologinpermission);
  657. return;
  658. }
  659. console.log("userjson", userjson);
  660. if (_data.active === 1) {
  661. await this.$ajax.post(API_CONFIG.baseUrl2 + "UpdateOpenId", [
  662. { userid: _data.userid, openid: this.openid },
  663. ]);
  664. window.localStorage["identity"] = JSON.stringify(_data.identity);
  665. this.$message.success(this.lang.Bindingsuc);
  666. window.topU.U.UF.Cookie.set("cocoroboLoginType=2");
  667. window.topU
  668. ? (window.topU.US.userInfo = _data)
  669. : (window.parent.US.userInfo = _data);
  670. await this.login();
  671. if (
  672. userjson.data[0][0].type == 1 &&
  673. userjson.data[0][0].role == 1 &&
  674. userjson.data[0][0].rrole == 1 &&
  675. this.allowOrgList.findIndex((i) => i.area) != -1
  676. ) {
  677. this.$router.push({ path: "/kanban" });
  678. } else {
  679. this.$router.push({ path: this.redirect || "/" });
  680. }
  681. } else {
  682. this.$message.error(this.lang.Bindingfailed);
  683. }
  684. this.loading = false;
  685. })
  686. .catch((e) => {
  687. console.log(e);
  688. if (e.response && e.response.data == "Wrong email or password") {
  689. this.$message.error(this.lang.Accerror);
  690. } else {
  691. this.$message.error(this.lang.Bindingfailed);
  692. }
  693. this.loading = false;
  694. });
  695. }
  696. },
  697. async getLoading() {
  698. // 检查用户是否已登录
  699. const hasToken = this.$store.getters.token;
  700. if (hasToken) {
  701. // 如果已登录,直接重定向
  702. this.$router.push({ path: this.redirect || "/" });
  703. return;
  704. }
  705. const userid = await this.login();
  706. if (userid) {
  707. this.$router.push({ path: this.redirect || "/" });
  708. }
  709. },
  710. // 输入账号获取组织
  711. getOrgData() {
  712. return new Promise((resolve) => {
  713. let params = [
  714. {
  715. functionName: API_CONFIG.ajax_liYuanOrg.functionName,
  716. uname: this.account,
  717. },
  718. ];
  719. this.$ajax
  720. .post(API_CONFIG.baseUrl, params)
  721. .then((res) => {
  722. console.log("res", res);
  723. // 组织号登陆时不清空
  724. if (this.loginType != "orgL") {
  725. this.org = "";
  726. }
  727. this.OrgOptions = [];
  728. let getList = res.data[0];
  729. // if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  730. // let _index = this.allowOrgList.findIndex((i) => i.area);
  731. // let _list = this.allowOrgList[_index].list;
  732. // getList = getList.filter((i) => _list.includes(i.id));
  733. // } else {
  734. // let mergedList = this.allowOrgList.reduce((acc, curr) => {
  735. // return [...acc, ...curr.list];
  736. // }, []);
  737. // getList = getList.filter((i) => !mergedList.includes(i.id));
  738. // }
  739. this.OrgOptions = getList;
  740. if (this.OrgOptions.length == 0)
  741. return this.$message.error(
  742. this.lang.Accnotfound
  743. );
  744. if (this.loginType == "orgL") return resolve(1);
  745. if (this.OrgOptions.length == 1) {
  746. this.org = this.OrgOptions[0].Uorg;
  747. } else if (this.OrgOptions.length > 0) {
  748. // liyuan走这里
  749. if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  750. // console.log('1111');
  751. try {
  752. let _index = this.allowOrgList.findIndex((i) => i.area);
  753. let _list = this.allowOrgList[_index].list;
  754. this.org = this.OrgOptions.filter((i) =>
  755. _list.includes(i.id)
  756. )[0].Uorg;
  757. } catch (error) {
  758. console.log(error);
  759. return this.$message.error(
  760. this.lang.Accountcannot
  761. );
  762. }
  763. } else {
  764. // admin走这里
  765. let mergedList = this.allowOrgList.reduce((acc, curr) => {
  766. return [...acc, ...curr.list];
  767. }, []);
  768. if (
  769. this.OrgOptions.filter((i) => !mergedList.includes(i.id))
  770. .length == 1
  771. )
  772. return this.$message.error(
  773. this.lang.Accountcannot
  774. );
  775. this.$message.error(this.lang.accountmustOrg);
  776. this.loginType = "orgL";
  777. return resolve(2);
  778. }
  779. }
  780. return resolve(1);
  781. })
  782. .catch((err) => {
  783. console.log(err);
  784. });
  785. });
  786. },
  787. //获取组织或学校的数据
  788. getOrdOidData() {
  789. let params = [
  790. {
  791. functionName: API_CONFIG.ajax_schoolPermission.functionName, // 调用存储过程的名称
  792. org: this.org2, //组织id
  793. oid: this.oid, //学校id
  794. },
  795. ];
  796. // 发起请求
  797. this.$ajax
  798. .post(API_CONFIG.baseUrl, params)
  799. .then((res) => {
  800. let data = res.data[0];
  801. console.log("data", data);
  802. this.form = JSON.parse(data[0].json);
  803. this.showName = this.form.basics.title || data[0].name;
  804. })
  805. .catch((err) => {
  806. console.error("请求失败,错误信息:", err);
  807. });
  808. },
  809. wechatLogin() {
  810. this.loginType = "weChat";
  811. setTimeout(() => {
  812. const randomState = Math.random().toString(36).substring(2); // 生成随机状态
  813. // eslint-disable-next-line no-undef
  814. new WxLogin({
  815. self_redirect: true,
  816. id: "QRcode",
  817. appid: "wxe9d7fff3c659445f",
  818. scope: "snsapi_login",
  819. redirect_uri: encodeURIComponent("https://cocorobo.cn/weixin.html"), //https://liyuan.cocorobo.cn/#/wxTest
  820. state: randomState,
  821. style: "black",
  822. href: "data:text/css;base64,LmltcG93ZXJCb3gge2Rpc3BsYXk6IGZsZXg7fQouaW1wb3dlckJveCAucXJjb2RlIHt3aWR0aDogMjMycHg7IGhlaWdodDogMjMycHh9Ci5pbXBvd2VyQm94IC50aXRsZSB7ZGlzcGxheTogbm9uZTt9Ci5pbXBvd2VyQm94IC5pbmZvIHtkaXNwbGF5OiBub25lO30KLmxvZ2luUGFuZWx7d2lkdGg6MTAwJTtoZWlnaHQ6MTAwJTtkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2FsaWduLWl0ZW1zOmNlbnRlcjtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyO30KLnN0YXR1c19pY29uIHtkaXNwbGF5OiBub25lfQoud2ViX3FyY29kZV9wYW5lbF9hcmVhe2hlaWdodDoxMDAlO3dpZHRoOjEwMCU7ZGlzcGxheTpmbGV4O2FsaWduLWl0ZW1zOmNlbnRlcjtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyO30K",
  823. onReady: function (isReady) {
  824. console.log(isReady);
  825. },
  826. });
  827. setTimeout(() => {
  828. let iframe = this.$refs.QRcode.querySelector("iframe");
  829. iframe.style.width = "100%";
  830. iframe.style.height = "100%";
  831. }, 0);
  832. }, 0);
  833. },
  834. // 微信登录
  835. async getOpenId(openid) {
  836. // oiztX1dwR-W2mBJ5HcvaSEB8yKGY
  837. axios.defaults.withCredentials = false;
  838. let params = {
  839. openid: openid,
  840. };
  841. this.openid = openid;
  842. axios.defaults.withCredentials = true;
  843. axios
  844. .post(this.userRequest, qs.stringify(params))
  845. .then(async (res) => {
  846. console.log("res", res);
  847. let _data = res.data[0][0];
  848. // let userData = await this.ajax.get("https://pbl.cocorobo.cn/api/pbl/selectUser/selectUser", { userid: _data.userid });
  849. // let _uorg = userData.data[0][0].org;
  850. this.account = _data.username;
  851. await this.getOrgData();
  852. // if (
  853. // (this.allowOrgList.find((i) => i.id == this.org2) &&
  854. // parent.location.href.includes("lyxx")) ||
  855. // parent.location.href.includes("liyuan")
  856. // ) {
  857. // let _list = this.allowOrgList.find((i) => i.id == this.org2).list;
  858. // let _nowOrgId = this.OrgOptions.find((i) => i.Uorg == this.org).id;
  859. // if (!_list.includes(_nowOrgId)) {
  860. // this.wechatLogin();
  861. // await loginOut();
  862. // await this.logout();
  863. // return this.$message.error("该组织/学校不允许登录");
  864. // }
  865. // window.sessionStorage.setItem("org2", this.org2);
  866. // }
  867. if (this.allowOrgList.findIndex((i) => i.area) != -1) {
  868. let _index = this.allowOrgList.findIndex((i) => i.area);
  869. let _list = this.allowOrgList[_index].list;
  870. if (
  871. this.OrgOptions.find((i) => i.Uorg == this.org) &&
  872. !_list.includes(
  873. this.OrgOptions.find((i) => i.Uorg == this.org).id
  874. )
  875. ) {
  876. this.$message.error(this.lang.Accountcannot);
  877. this.wechatLogin();
  878. await loginOut();
  879. await this.logout();
  880. return
  881. }
  882. } else {
  883. let mergedList = this.allowOrgList.reduce((acc, curr) => {
  884. return [...acc, ...curr.list];
  885. }, []);
  886. if (
  887. mergedList.includes(
  888. this.OrgOptions.find((i) => i.Uorg == this.org).id
  889. )
  890. ) {
  891. this.$message.error(this.lang.Accountcannot);
  892. this.wechatLogin();
  893. await loginOut();
  894. await this.logout();
  895. return
  896. }
  897. }
  898. let userjson = await getUser({ userid: _data.userid });
  899. if (userjson.data[0][0].type == 2) {
  900. this.$message.error(this.lang.Nologinpermission);
  901. return;
  902. }
  903. console.log("userjson", userjson);
  904. if (_data.active === 1) {
  905. window.localStorage["identity"] = JSON.stringify(_data.identity);
  906. window.topU.U.UF.Cookie.set("cocoroboLoginType=2");
  907. window.topU
  908. ? (window.topU.US.userInfo = _data)
  909. : (window.parent.US.userInfo = _data);
  910. await this.login();
  911. if (
  912. userjson.data[0][0].type == 1 &&
  913. userjson.data[0][0].role == 1 &&
  914. userjson.data[0][0].rrole == 1 &&
  915. this.allowOrgList.findIndex((i) => i.area) != -1
  916. ) {
  917. this.$router.push({ path: "/kanban" });
  918. } else {
  919. this.$router.push({ path: this.redirect || "/" });
  920. }
  921. this.$message.success(this.lang.Loginsuccessful);
  922. this.addOp3(
  923. "1",
  924. "",
  925. { type: this.prefixL + "login" },
  926. "success",
  927. _data.userid
  928. );
  929. } else {
  930. this.$message.error(this.lang.Loginfailed);
  931. }
  932. this.loading = false;
  933. })
  934. .catch((err) => {
  935. console.log('错误信息',err.response);
  936. if (err && err.response && err.response.status === 401) {
  937. this.loginType = "bind";
  938. }
  939. });
  940. //
  941. },
  942. backSteps() {
  943. this.steps = 1;
  944. this.account = "";
  945. this.password = "";
  946. this.stuInfoCode = {};
  947. },
  948. // 随机码登录
  949. nextSteps() {
  950. if (!this.SuffixData) {
  951. this.$message.error(this.prefixL == 'liyuan_' ? this.lang.choosecampus : this.lang.enterrandomcode);
  952. return;
  953. }
  954. let reg = /^\d+$/;
  955. if (!reg.test(this.icode)) {
  956. this.$message.error(this.lang.codecorrectly);
  957. return;
  958. }
  959. let params = [
  960. {
  961. functionName: API_CONFIG.ajax_selectCourseByIc2.functionName, // 调用存储过程的名称
  962. code: this.icode,
  963. oid: this.SuffixData,
  964. },
  965. ];
  966. this.$ajax
  967. .post(API_CONFIG.baseUrl, params)
  968. .then((res) => {
  969. if (res.data.length && res.data[0].length) {
  970. this.res = res.data[0][0];
  971. this.courseId = res.data[0][0].courseId;
  972. this.getClass(res.data[0][0].classid);
  973. } else {
  974. this.$message.error(this.lang.codenotexist);
  975. }
  976. })
  977. .catch((err) => {
  978. console.error(err);
  979. });
  980. },
  981. // 根据随机码获取学生
  982. getClass(classId) {
  983. let params = [
  984. {
  985. functionName: API_CONFIG.ajax_selectSnameByCid.functionName, // 调用存储过程的名称
  986. cid: classId,
  987. },
  988. ];
  989. this.$ajax
  990. .post(API_CONFIG.baseUrl, params)
  991. .then((res) => {
  992. this.classJuri = res.data[0];
  993. this.steps = 2;
  994. })
  995. .catch((err) => {
  996. console.error(err);
  997. });
  998. },
  999. // 选择学生账户
  1000. selAcc(val) {
  1001. console.log("val", val);
  1002. this.account = val.accountNumber;
  1003. this.password = val.userpassword;
  1004. this.stuInfoCode = val;
  1005. },
  1006. // 根据随机码获取的账号登录到课程里面
  1007. async loginCode() {
  1008. // let courseid = this.courseId;
  1009. try {
  1010. await this.$confirm(
  1011. this.lang.loginaccount.replace(/\*/g, this.stuInfoCode.username),
  1012. this.lang.tip,
  1013. {
  1014. confirmButtonText: this.lang.confirm,
  1015. cancelButtonText: this.lang.Cancel,
  1016. type: "warning",
  1017. }
  1018. );
  1019. this.loading = true;
  1020. console.log("this.stuInfoCode", this.stuInfoCode);
  1021. // let loginData=JSON.stringify({openid: this.stuInfoCode.userid,edu: true})
  1022. let params = {
  1023. geetest_challenge: "",
  1024. geetest_validate: "",
  1025. geetest_seccode: "",
  1026. openid: this.stuInfoCode.userid,
  1027. edu: true
  1028. };
  1029. axios.defaults.withCredentials = true;
  1030. axios
  1031. .post(this.userRequest, qs.stringify(params))
  1032. .then(async (res) => {
  1033. console.log("res", res);
  1034. this.loading = false;
  1035. let _data = res.data[0][0];
  1036. let userjson = await getUser({ userid: _data.userid });
  1037. console.log("userjson", userjson);
  1038. if (_data.active === 1) {
  1039. window.localStorage["identity"] = JSON.stringify(_data.identity);
  1040. window.topU.U.UF.Cookie.set("cocoroboLoginType=2");
  1041. window.topU
  1042. ? (window.topU.US.userInfo = _data)
  1043. : (window.parent.US.userInfo = _data);
  1044. await this.login();
  1045. this.$message.success(this.lang.Loginsuccessful);
  1046. this.$router.push({ path: this.redirect || "/", query: { courseId: this.courseId } });
  1047. this.addOp3(
  1048. "1",
  1049. "",
  1050. { type: this.prefixL + "stuCode_login" },
  1051. "success",
  1052. this.stuInfoCode.userid
  1053. );
  1054. } else {
  1055. this.$message.error(this.lang.Loginfailed);
  1056. }
  1057. })
  1058. .catch((err) => {
  1059. this.loading = false;
  1060. console.error(err);
  1061. });
  1062. } catch (error) {
  1063. this.loading = false;
  1064. console.error("登录过程中出错:", error);
  1065. }
  1066. },
  1067. // 获取荔园校区数据
  1068. getData() {
  1069. this.loginType = "code";
  1070. this.SuffixData = '';
  1071. this.Codeloading = true;
  1072. let params = [
  1073. {
  1074. functionName: API_CONFIG.select_liYuanCampus.functionName, // 调用存储过程的名称
  1075. org: "3823a6a5-1b6e-11f0-a66a-005056924926", //组织id
  1076. },
  1077. ];
  1078. // 发起请求
  1079. this.$ajax
  1080. .post(API_CONFIG.baseUrl, params)
  1081. .then((res) => {
  1082. let data = res.data[0];
  1083. console.log(data);
  1084. this.CodeOptions = data;
  1085. this.Codeloading = false;
  1086. })
  1087. .catch((err) => {
  1088. this.Codeloading = false;
  1089. console.error("请求失败,错误信息:", err);
  1090. });
  1091. },
  1092. },
  1093. mounted() {
  1094. let _this = this;
  1095. window.addEventListener("message", function (e) {
  1096. // 监听 message 事件
  1097. console.log('longin',e);
  1098. if (e.data && e.data.method == "getOpenId") {
  1099. console.log('e',e);
  1100. console.log('e.data.code',e.data.code);
  1101. console.log('_this.loginType',_this.loginType);
  1102. if (e.data.code == 200) {
  1103. _this.getOpenId(e.data.data.openid);
  1104. } else {
  1105. _this.$message.error("扫码登录失败请重新扫码");
  1106. _this.wechatLogin();
  1107. }
  1108. }
  1109. });
  1110. this.getLoading();
  1111. this.getOrdOidData();
  1112. }
  1113. };
  1114. </script>
  1115. <style scoped>
  1116. .loginPage {
  1117. width: 100vw;
  1118. height: 100vh;
  1119. background-color: white;
  1120. display: flex;
  1121. align-items: center;
  1122. justify-content: center;
  1123. }
  1124. .lp_left {
  1125. max-width: 50%;
  1126. width: 50%;
  1127. max-height: 100%;
  1128. height: 100%;
  1129. overflow: hidden;
  1130. box-sizing: border-box;
  1131. }
  1132. .lp_left > img {
  1133. width: 100%;
  1134. height: 100%;
  1135. object-fit: contain;
  1136. border-radius: 0 150px 0 0;
  1137. }
  1138. .lp_right {
  1139. width: 50%;
  1140. min-width: 520px;
  1141. height: 100%;
  1142. display: flex;
  1143. justify-content: center;
  1144. align-items: center;
  1145. position: relative;
  1146. }
  1147. .Version{
  1148. background: #f0f4fa;
  1149. /* border-radius: 50%; */
  1150. border-radius: 50px 50px 50px 50px;
  1151. /* border: .5px #cad1dc solid; */
  1152. position: absolute;
  1153. color: #060e17;
  1154. padding: 8px 15px;
  1155. box-sizing: border-box;
  1156. top: 30px;
  1157. right: 20px;
  1158. cursor: pointer;
  1159. }
  1160. .lp_r_box {
  1161. width: 500px;
  1162. height: auto;
  1163. box-sizing: border-box;
  1164. padding: 20px;
  1165. }
  1166. .lp_r_b_logo {
  1167. display: flex;
  1168. align-items: center;
  1169. }
  1170. .lp_r_b_logo > span {
  1171. margin-left: 15px;
  1172. font-weight: bold;
  1173. font-size: 18px;
  1174. }
  1175. .lp_r_box > span {
  1176. font-size: 46px;
  1177. font-weight: bold;
  1178. margin: 40px 0;
  1179. display: block;
  1180. }
  1181. .lp_r_b_formArea {
  1182. width: 100%;
  1183. height: 250px;
  1184. margin-bottom: 40px;
  1185. }
  1186. .fa_input {
  1187. width: 100%;
  1188. height: 100%;
  1189. display: flex;
  1190. flex-direction: column;
  1191. /* align-items: center; */
  1192. justify-content: center;
  1193. }
  1194. .fa_i_item {
  1195. width: 100%;
  1196. height: 70px;
  1197. margin-bottom: 30px;
  1198. }
  1199. .fa_i_item > span {
  1200. font-size: 16px;
  1201. color: rgba(0, 0, 0, 0.9);
  1202. font-weight: 600;
  1203. }
  1204. .fa_i_item > div {
  1205. width: 100%;
  1206. height: 40px;
  1207. border: solid 1px rgba(213, 213, 213, 1);
  1208. margin-top: 5px;
  1209. border-radius: 8px;
  1210. transition: 0.5s;
  1211. }
  1212. .fa_i_item > div > input {
  1213. width: 100%;
  1214. height: 100%;
  1215. border: none;
  1216. outline: none;
  1217. text-indent: 1em;
  1218. color: #000;
  1219. font-size: 14px;
  1220. background: none;
  1221. }
  1222. .fa_i_item > div >>> .el-select {
  1223. width: 100%;
  1224. height: 100%;
  1225. }
  1226. .fa_i_item > div >>> .el-select input {
  1227. border: none;
  1228. outline: none;
  1229. background: none;
  1230. text-indent: 1em;
  1231. font-size: 14px;
  1232. height: 40px;
  1233. padding-left: 0;
  1234. color: #000;
  1235. }
  1236. /* .fa_i_item > input {
  1237. width: 100%;
  1238. height: 45px;
  1239. border: solid 1px rgba(213, 213, 213, 1);
  1240. outline: none;
  1241. border-radius: 8px;
  1242. margin-top: 15px;
  1243. text-indent: 1em;
  1244. transition: 0.5s;
  1245. color: #000;
  1246. font-size: 16px;
  1247. } */
  1248. .fa_i_item > div >>> input::placeholder {
  1249. color: rgba(142, 142, 147, 1);
  1250. }
  1251. .fa_i_item > div:focus-within {
  1252. border-color: #006afe;
  1253. }
  1254. .fa_weChat {
  1255. width: 300px;
  1256. height: 300px;
  1257. margin: 0 auto;
  1258. display: flex;
  1259. align-items: center;
  1260. justify-content: center;
  1261. }
  1262. .fa_weChat > .QRcode {
  1263. width: 100%;
  1264. height: 100%;
  1265. display: flex;
  1266. align-items: center;
  1267. justify-content: center;
  1268. /* background-color: black; */
  1269. }
  1270. .lp_r_b_btn {
  1271. width: 100%;
  1272. height: 45px;
  1273. background-color: rgba(0, 106, 254, 1);
  1274. border-radius: 10px;
  1275. display: flex;
  1276. justify-content: center;
  1277. align-items: center;
  1278. color: #fff;
  1279. cursor: pointer;
  1280. transition: 0.3s;
  1281. }
  1282. .lp_r_b_btn:hover {
  1283. background-color: rgb(3, 87, 206);
  1284. }
  1285. .backBtn {
  1286. background-color: #d9d9d9;
  1287. color: #000;
  1288. }
  1289. .backBtn:hover {
  1290. background-color: #adadad;
  1291. }
  1292. .lp_r_b_line {
  1293. width: 100%;
  1294. height: 20px;
  1295. margin: 40px 0;
  1296. display: flex;
  1297. justify-content: center;
  1298. align-items: center;
  1299. }
  1300. .lp_r_b_line > div {
  1301. width: calc(100% / 2 - 70px);
  1302. height: 1px;
  1303. background-color: #e7e7e7;
  1304. }
  1305. .lp_r_b_line > span {
  1306. display: flex;
  1307. margin: 0 20px;
  1308. }
  1309. .lp_r_b_iconBtn {
  1310. width: 100%;
  1311. height: 40px;
  1312. display: flex;
  1313. justify-content: center;
  1314. }
  1315. .lp_r_b_iconBtn > div {
  1316. width: 32px;
  1317. height: 32px;
  1318. cursor: pointer;
  1319. margin: 0 20px;
  1320. }
  1321. .lp_r_b_iconBtn > div > img {
  1322. width: 100%;
  1323. height: 100%;
  1324. }
  1325. .btn_box {
  1326. display: flex;
  1327. gap: 10px;
  1328. }
  1329. .stuPage {
  1330. margin: 10px;
  1331. max-height: 500px;
  1332. display: flex;
  1333. flex-direction: column;
  1334. gap: 20px;
  1335. }
  1336. .stuList {
  1337. flex: 1;
  1338. display: grid;
  1339. max-height: 400px;
  1340. overflow: auto;
  1341. grid-template-columns: repeat(4, 1fr);
  1342. gap: 15px;
  1343. }
  1344. .stuList div {
  1345. padding: 3px 15px;
  1346. border-radius: 3px;
  1347. -webkit-line-clamp: 1;
  1348. line-height: 22px;
  1349. display: -webkit-box;
  1350. -webkit-box-orient: vertical;
  1351. overflow: hidden;
  1352. text-overflow: ellipsis;
  1353. border: 1px #e7e7e7 solid;
  1354. text-align: center;
  1355. cursor: pointer;
  1356. }
  1357. .stuback {
  1358. background: #006afe;
  1359. color: #fff;
  1360. }
  1361. /* .backWin{ */
  1362. /* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); */
  1363. /* } */
  1364. </style>