login.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <view
  3. style="height: calc(100vh - env(safe-area-inset-top));width: 100vw;background-color: #fff;padding-top: 120rpx;box-sizing: border-box;">
  4. <view class="head-image">
  5. <image src="/static/image/logo1.png" mode="heightFix" />
  6. </view>
  7. <view class="input-box">
  8. <view class="content">
  9. <picker class="picker" mode="selector" :range="countryCodes" range-key="name" :value="countryCode"
  10. @change="changeCountryCode">
  11. {{ countryCode }}
  12. </picker>
  13. <input type="number" :value="phonenumber" :focus="focused == 'phonenumber'"
  14. @input="onInput($event, 'phonenumber')" placeholder="请输入手机号" class="input" />
  15. </view>
  16. </view>
  17. <view class="input-box" style="margin-top:70rpx;">
  18. <view class="content">
  19. <input type="number" :value="password" :focus="focused == 'password'"
  20. @input="onInput($event, 'password')" placeholder="请输入验证码" class="input" />
  21. <view class="auth-code" @click="getAuthCode">
  22. {{ downTime == 0 ? '获取验证码' : downTime + "S" }}
  23. </view>
  24. </view>
  25. </view>
  26. <My-button :customStyle="customStyle" class="my-but" :loading="loading" :disabled="disabled" text="登录"
  27. @onClick="logIn" />
  28. <!-- <view class="agreement-box">
  29. <up-checkbox label="已阅读并同意" name="agree" usedAlone v-model:checked="isAgreement" />
  30. <view @click="checkTheAgreement" style="color: #3874F6;">
  31. 《隐私协议》
  32. </view>
  33. </view>
  34. -->
  35. <up-modal negativeTop="100" asyncClose :show="showModal" confirmColor="#052E5D" showCancelButton
  36. confirmText="阅读并获取" @confirm="onConfirm1" @cancel="showModal = false">
  37. <view class="modal-u">请阅读并同意<text style="color: #3874F6;" @click="checkTheAgreement">《隐私协议》</text></view>
  38. </up-modal>
  39. <!-- 正式无需使用 -->
  40. <up-picker title="选择站点" :show="account_list.length != 0" :columns="account_list" keyName="sitename"
  41. @cancel="onCancel" @confirm='onConfirm' />
  42. </view>
  43. </template>
  44. <script setup>
  45. import { ref, reactive, getCurrentInstance, computed } from 'vue'
  46. import { onLoad } from '@dcloudio/uni-app';
  47. const { $Http } = getCurrentInstance().proxy;
  48. onLoad(() => {
  49. const storedPhone = uni.getStorageSync('phonenumber');
  50. if (storedPhone) {
  51. phonenumber.value = storedPhone;
  52. isAgreement.value = true;
  53. }
  54. });
  55. // 登陆按钮相关
  56. const loading = ref(false);
  57. const disabled = computed(() => {
  58. return !(phonenumber.value.length > 0 && password.value.length >= 4);
  59. });
  60. const customStyle = ref({
  61. width: '380rpx',
  62. margin: '120rpx auto 0',
  63. });
  64. // 表单相关
  65. const focused = ref('');
  66. const countryCode = ref('+86');
  67. const phonenumber = ref('');
  68. const password = ref('');
  69. const countryCodes = reactive([
  70. { code: '+86', name: '中国 +86', regex: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/ }, // 中国手机号验证规则
  71. { code: '+1', name: '美国 +1', regex: /^[2-9]\d{2}[2-9](?!11)\d{6}$/ }, // 美国手机号验证规则
  72. { code: '+44', name: '英国 +44', regex: /^7\d{9}$/ }, // 英国手机号验证规则
  73. ]);
  74. function onInput(e, name) {
  75. if (name == 'phonenumber') {
  76. phonenumber.value = e.detail.value;
  77. } else if (name == 'password') {
  78. password.value = e.detail.value;
  79. }
  80. }
  81. function validatephonenumber() {
  82. const selectedCountry = countryCodes.find(country => country.code === countryCode.value);
  83. if (!selectedCountry || !selectedCountry.regex.test(phonenumber.value)) {
  84. uni.showToast({
  85. title: `请输入有效的${selectedCountry ? selectedCountry.name.split(" ")[0] + '号码' : '手机号'}`,
  86. icon: 'none',
  87. });
  88. focused.value = 'phonenumber'; // 聚焦输入框
  89. return false;
  90. }
  91. return true;
  92. }
  93. function changeCountryCode(e) {
  94. countryCode.value = countryCodes[e.detail.value].code;
  95. if (phonenumber.value) validatephonenumber();
  96. }
  97. // 验证码相关
  98. let countDown = null;
  99. const downTime = ref(0); // 倒计时初始值
  100. function getAuthCode() {
  101. if (downTime.value > 0) return;
  102. if (!validatephonenumber()) return;
  103. $Http.getpassword({ "phonenumber": phonenumber.value, "systemclient": "wechatsaletool" }).then(res => {
  104. console.log('获取验证码结果:', res);
  105. if (res.code == 1) {
  106. downTime.value = 60;
  107. countDown = setInterval(() => {
  108. downTime.value--;
  109. if (downTime.value <= 0) {
  110. clearInterval(countDown);
  111. downTime.value = 0;
  112. }
  113. }, 1000);
  114. const code = res.msg.split('手机验证码为:');
  115. if (code[1]) {
  116. password.value = code[1].trim(); // 自动填充验证码
  117. } else {
  118. focused.value = 'password'; // 聚焦输入框
  119. }
  120. } else {
  121. if (res.msg == '当前手机号未注册!') {
  122. $Http.base({
  123. "id": "2025082114174203",
  124. "content": {
  125. "name": "用户" + phonenumber.value.slice(-4),
  126. "phonenumber": phonenumber.value,
  127. accountprefix: 'MD',// 测试用的楚楚站点 正式要改为美大
  128. siteid: 'MD',
  129. }
  130. }).then(res => {
  131. console.log("注册结果:", res);
  132. if (res.code == 1) {
  133. getAuthCode();
  134. } else {
  135. uni.showToast({
  136. title: res.msg,
  137. icon: 'none',
  138. });
  139. }
  140. })
  141. } else {
  142. uni.showToast({
  143. title: res.msg,
  144. icon: 'none',
  145. });
  146. }
  147. }
  148. })
  149. }
  150. // 登录相关
  151. let account_list = reactive([]);
  152. function logIn() {
  153. if (!validatephonenumber()) return;
  154. // if (isAgreement.value == false) return showModal.value = true;
  155. loading.value = true;
  156. $Http.plogin({ "phonenumber": phonenumber.value, "password": hexMD5(password.value), "systemclient": "wechatsaletool" }).then(res => {
  157. if (res.code == 1) {
  158. if (res.account_list.length == 1) {
  159. handleLogin(res.account_list[0]);
  160. } else {
  161. account_list = reactive([res.account_list]);
  162. }
  163. } else {
  164. loading.value = false;
  165. uni.showToast({
  166. title: res.msg,
  167. icon: 'none',
  168. });
  169. }
  170. })
  171. }
  172. function onCancel() {
  173. account_list = reactive([]);
  174. }
  175. function onConfirm(e) {
  176. handleLogin(e.value[0]);
  177. account_list = reactive([]);
  178. }
  179. function handleLogin(data) {
  180. uni.removeStorageSync('userMsg');
  181. uni.setStorageSync('userMsg', data);
  182. uni.removeStorageSync('phonenumber');
  183. uni.setStorageSync('phonenumber', phonenumber.value);
  184. $Http.isLoad = true;
  185. if (getCurrentPages().length > 1) {
  186. uni.navigateBack();
  187. } else {
  188. uni.reLaunch({
  189. url: '/pages/index/index',
  190. });
  191. }
  192. $Http.basic({
  193. "classname": "webmanage.site.site",
  194. "method": "querySite_Parameter", //查询站点数据
  195. content: {
  196. nocache: true
  197. }
  198. }).then(res => {
  199. if (res.code == 1) {
  200. uni.removeStorageSync('siteP');
  201. uni.setStorageSync("siteP", res.data)
  202. }
  203. })
  204. $Http.basic({
  205. "id": "2025082114391803",
  206. "content": {
  207. "phonenumber": phonenumber.value
  208. }
  209. }).then(res => {
  210. console.log('用户档案', res)
  211. if (res.code == 1) {
  212. uni.removeStorageSync('userRecord');
  213. uni.setStorageSync("userRecord", res.data)
  214. }
  215. })
  216. }
  217. //隐私协议相关
  218. const isAgreement = ref(false);
  219. const showModal = ref(false);
  220. function checkTheAgreement() {
  221. uni.showLoading({
  222. title: "加载中...",
  223. });
  224. uni.downloadFile({
  225. url: "https://yossys22170.obs.cn-east-2.myhuaweicloud.com:443/202309261695715892017B6ef5bd76.docx",
  226. success: (res) => {
  227. uni.openDocument({
  228. filePath: res.tempFilePath,
  229. fileType: "docx",
  230. success: (s) => {
  231. uni.hideLoading();
  232. },
  233. fail: (err) => {
  234. console.log("openDocument", err);
  235. uni.hideLoading();
  236. uni.showToast({
  237. title: "读取失败,请稍后再试",
  238. icon: "none",
  239. });
  240. },
  241. });
  242. },
  243. fail: (err) => {
  244. console.log("downloadFile", err);
  245. uni.hideLoading();
  246. uni.showToast({
  247. title: "读取失败,请稍后再试",
  248. icon: "none",
  249. });
  250. },
  251. });
  252. }
  253. function onConfirm1() {
  254. showModal.value = false;
  255. isAgreement.value = true;
  256. logIn();
  257. }
  258. /* 以下为MD5加密 */
  259. function hexMD5(str) {
  260. return binl2hex(coreMD5(str2binl(str)))
  261. }
  262. function safe_add(x, y) {
  263. var lsw = (x & 0xFFFF) + (y & 0xFFFF)
  264. var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
  265. return (msw << 16) | (lsw & 0xFFFF)
  266. }
  267. function rol(num, cnt) {
  268. return (num << cnt) | (num >>> (32 - cnt))
  269. }
  270. function cmn(q, a, b, x, s, t) {
  271. return safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
  272. }
  273. function ff(a, b, c, d, x, s, t) {
  274. return cmn((b & c) | ((~b) & d), a, b, x, s, t)
  275. }
  276. function gg(a, b, c, d, x, s, t) {
  277. return cmn((b & d) | (c & (~d)), a, b, x, s, t)
  278. }
  279. function hh(a, b, c, d, x, s, t) {
  280. return cmn(b ^ c ^ d, a, b, x, s, t)
  281. }
  282. function ii(a, b, c, d, x, s, t) {
  283. return cmn(c ^ (b | (~d)), a, b, x, s, t)
  284. }
  285. function coreMD5(x) {
  286. var a = 1732584193
  287. var b = -271733879
  288. var c = -1732584194
  289. var d = 271733878
  290. for (var i = 0; i < x.length; i += 16) {
  291. var olda = a
  292. var oldb = b
  293. var oldc = c
  294. var oldd = d
  295. a = ff(a, b, c, d, x[i + 0], 7, -680876936)
  296. d = ff(d, a, b, c, x[i + 1], 12, -389564586)
  297. c = ff(c, d, a, b, x[i + 2], 17, 606105819)
  298. b = ff(b, c, d, a, x[i + 3], 22, -1044525330)
  299. a = ff(a, b, c, d, x[i + 4], 7, -176418897)
  300. d = ff(d, a, b, c, x[i + 5], 12, 1200080426)
  301. c = ff(c, d, a, b, x[i + 6], 17, -1473231341)
  302. b = ff(b, c, d, a, x[i + 7], 22, -45705983)
  303. a = ff(a, b, c, d, x[i + 8], 7, 1770035416)
  304. d = ff(d, a, b, c, x[i + 9], 12, -1958414417)
  305. c = ff(c, d, a, b, x[i + 10], 17, -42063)
  306. b = ff(b, c, d, a, x[i + 11], 22, -1990404162)
  307. a = ff(a, b, c, d, x[i + 12], 7, 1804603682)
  308. d = ff(d, a, b, c, x[i + 13], 12, -40341101)
  309. c = ff(c, d, a, b, x[i + 14], 17, -1502002290)
  310. b = ff(b, c, d, a, x[i + 15], 22, 1236535329)
  311. a = gg(a, b, c, d, x[i + 1], 5, -165796510)
  312. d = gg(d, a, b, c, x[i + 6], 9, -1069501632)
  313. c = gg(c, d, a, b, x[i + 11], 14, 643717713)
  314. b = gg(b, c, d, a, x[i + 0], 20, -373897302)
  315. a = gg(a, b, c, d, x[i + 5], 5, -701558691)
  316. d = gg(d, a, b, c, x[i + 10], 9, 38016083)
  317. c = gg(c, d, a, b, x[i + 15], 14, -660478335)
  318. b = gg(b, c, d, a, x[i + 4], 20, -405537848)
  319. a = gg(a, b, c, d, x[i + 9], 5, 568446438)
  320. d = gg(d, a, b, c, x[i + 14], 9, -1019803690)
  321. c = gg(c, d, a, b, x[i + 3], 14, -187363961)
  322. b = gg(b, c, d, a, x[i + 8], 20, 1163531501)
  323. a = gg(a, b, c, d, x[i + 13], 5, -1444681467)
  324. d = gg(d, a, b, c, x[i + 2], 9, -51403784)
  325. c = gg(c, d, a, b, x[i + 7], 14, 1735328473)
  326. b = gg(b, c, d, a, x[i + 12], 20, -1926607734)
  327. a = hh(a, b, c, d, x[i + 5], 4, -378558)
  328. d = hh(d, a, b, c, x[i + 8], 11, -2022574463)
  329. c = hh(c, d, a, b, x[i + 11], 16, 1839030562)
  330. b = hh(b, c, d, a, x[i + 14], 23, -35309556)
  331. a = hh(a, b, c, d, x[i + 1], 4, -1530992060)
  332. d = hh(d, a, b, c, x[i + 4], 11, 1272893353)
  333. c = hh(c, d, a, b, x[i + 7], 16, -155497632)
  334. b = hh(b, c, d, a, x[i + 10], 23, -1094730640)
  335. a = hh(a, b, c, d, x[i + 13], 4, 681279174)
  336. d = hh(d, a, b, c, x[i + 0], 11, -358537222)
  337. c = hh(c, d, a, b, x[i + 3], 16, -722521979)
  338. b = hh(b, c, d, a, x[i + 6], 23, 76029189)
  339. a = hh(a, b, c, d, x[i + 9], 4, -640364487)
  340. d = hh(d, a, b, c, x[i + 12], 11, -421815835)
  341. c = hh(c, d, a, b, x[i + 15], 16, 530742520)
  342. b = hh(b, c, d, a, x[i + 2], 23, -995338651)
  343. a = ii(a, b, c, d, x[i + 0], 6, -198630844)
  344. d = ii(d, a, b, c, x[i + 7], 10, 1126891415)
  345. c = ii(c, d, a, b, x[i + 14], 15, -1416354905)
  346. b = ii(b, c, d, a, x[i + 5], 21, -57434055)
  347. a = ii(a, b, c, d, x[i + 12], 6, 1700485571)
  348. d = ii(d, a, b, c, x[i + 3], 10, -1894986606)
  349. c = ii(c, d, a, b, x[i + 10], 15, -1051523)
  350. b = ii(b, c, d, a, x[i + 1], 21, -2054922799)
  351. a = ii(a, b, c, d, x[i + 8], 6, 1873313359)
  352. d = ii(d, a, b, c, x[i + 15], 10, -30611744)
  353. c = ii(c, d, a, b, x[i + 6], 15, -1560198380)
  354. b = ii(b, c, d, a, x[i + 13], 21, 1309151649)
  355. a = ii(a, b, c, d, x[i + 4], 6, -145523070)
  356. d = ii(d, a, b, c, x[i + 11], 10, -1120210379)
  357. c = ii(c, d, a, b, x[i + 2], 15, 718787259)
  358. b = ii(b, c, d, a, x[i + 9], 21, -343485551)
  359. a = safe_add(a, olda)
  360. b = safe_add(b, oldb)
  361. c = safe_add(c, oldc)
  362. d = safe_add(d, oldd)
  363. }
  364. return [a, b, c, d]
  365. }
  366. function binl2hex(binarray) {
  367. var hex_tab = "0123456789abcdef"
  368. var str = ""
  369. for (var i = 0; i < binarray.length * 4; i++) {
  370. str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
  371. hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF)
  372. }
  373. return str
  374. }
  375. function str2binl(str) {
  376. var nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks
  377. var blks = new Array(nblk * 16)
  378. for (var i = 0; i < nblk * 16; i++) blks[i] = 0
  379. for (var i = 0; i < str.length; i++)
  380. blks[i >> 2] |= (str.charCodeAt(i) & 0xFF) << ((i % 4) * 8)
  381. blks[i >> 2] |= 0x80 << ((i % 4) * 8)
  382. blks[nblk * 16 - 2] = str.length * 8
  383. return blks
  384. }
  385. </script>
  386. <style lang="scss" scoped>
  387. .head-image {
  388. display: flex;
  389. justify-content: center;
  390. height: 148rpx;
  391. margin-bottom: 120rpx;
  392. image {
  393. height: 100%;
  394. }
  395. }
  396. .input-box {
  397. width: 630rpx;
  398. padding-bottom: 20rpx;
  399. margin: 0 auto;
  400. border-bottom: 1px solid #dcdcdc;
  401. box-sizing: border-box;
  402. .content {
  403. display: flex;
  404. justify-content: space-between;
  405. align-items: center;
  406. height: 48rpx;
  407. width: 100%;
  408. .picker {
  409. font-family: Microsoft YaHei, Microsoft YaHei;
  410. font-weight: bold;
  411. font-size: 32rpx;
  412. color: #333333;
  413. margin-right: 20rpx;
  414. }
  415. .input {
  416. flex: 1;
  417. }
  418. .auth-code {
  419. margin-left: 20rpx;
  420. font-family: Microsoft YaHei, Microsoft YaHei;
  421. font-weight: bold;
  422. font-size: 28rpx;
  423. color: #3874F6;
  424. }
  425. }
  426. }
  427. .my-but {
  428. width: 380rpx;
  429. }
  430. .agreement-box {
  431. position: fixed;
  432. bottom: 80rpx;
  433. width: 100%;
  434. display: flex;
  435. justify-content: center;
  436. align-items: center;
  437. up-checkbox {
  438. font-family: Microsoft YaHei, Microsoft YaHei;
  439. font-weight: bold;
  440. font-size: 28rpx;
  441. color: #333333;
  442. }
  443. }
  444. </style>