verification.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. <template>
  2. <view>
  3. <view
  4. v-if="!hid"
  5. class="flex-row-center"
  6. :style="{ top: scHight }"
  7. style="width: 750rpx; position: fixed; z-index: 100; left: 0"
  8. >
  9. <view
  10. class="flex-column-center"
  11. style="background-color: #fcfcfc; padding: 30rpx; border-radius: 10rpx"
  12. >
  13. <movable-area
  14. class="flex"
  15. style="width: 100%"
  16. animation="false"
  17. :style="{ height: originalHeight }"
  18. >
  19. <movable-view
  20. scale-value="1"
  21. animation="false"
  22. damping="5000"
  23. :x="moveX"
  24. :style="{
  25. height: sliderHeight,
  26. width: sliderWidth,
  27. 'z-index': 101,
  28. }"
  29. direction="horizontal"
  30. >
  31. <image
  32. :src="imgbk"
  33. class="image"
  34. mode="aspectFit"
  35. :style="{
  36. height: sliderHeight,
  37. width: sliderWidth,
  38. 'margin-top': imgbKH,
  39. }"
  40. ></image>
  41. </movable-view>
  42. <image
  43. :src="img"
  44. mode="aspectFit"
  45. :style="{ height: originalHeight, width: originalWidth }"
  46. style="border-radius: 10rpx"
  47. ></image>
  48. </movable-area>
  49. <movable-area
  50. class="flex-row-start"
  51. style="
  52. width: 100%;
  53. background-color: #efefef;
  54. height: 80rpx;
  55. border-radius: 40rpx;
  56. margin-top: 30rpx;
  57. "
  58. >
  59. <movable-view
  60. scale-value="1"
  61. animation="false"
  62. damping="50"
  63. :x="movePv"
  64. class="flex-row-center"
  65. style="
  66. border-radius: 50%;
  67. height: 100rpx;
  68. width: 100rpx;
  69. background-color: #ffffff;
  70. border: 2rpx solid #e3e3e3;
  71. margin-top: -13rpx;
  72. "
  73. direction="horizontal"
  74. @change="moveChange"
  75. @touchend="end"
  76. >
  77. <u-icon
  78. :color="mainColor"
  79. size="40"
  80. v-if="endLoad"
  81. name="arrow-right"
  82. ></u-icon>
  83. <u-icon :color="mainColor" size="40" v-else name="reload"></u-icon>
  84. </movable-view>
  85. <text style="padding-left: 140rpx" :style="{ color: col }">{{
  86. hasImg
  87. }}</text>
  88. </movable-area>
  89. <view class="flex-row-around padding-top" style="width: 100%">
  90. <u-icon
  91. @click="hide"
  92. :color="mainColor"
  93. size="40"
  94. name="close"
  95. ></u-icon>
  96. <text class="cu-tag bg-cyan round" @click="getCode">刷新拼图</text>
  97. <text class="my-neirong-sm cuIcon-safe" style="color: #c1c1c1"
  98. >Lili-FRAMEWORK</text
  99. >
  100. </view>
  101. </view>
  102. </view>
  103. </view>
  104. </template>
  105. <script>
  106. import api from "@/config/api.js";
  107. import storage from "@/utils/storage.js";
  108. import uuid from "@/utils/uuid.modified.js";
  109. const phone = uni.getSystemInfoSync();
  110. const l = phone.screenWidth / 750;
  111. export default {
  112. name: "verification",
  113. created() {
  114. // 可自行调整
  115. this.scHight = phone.screenHeight / 2 - 200 + "px";
  116. this.getCode();
  117. },
  118. props: {
  119. height: {
  120. type: String,
  121. default: "80rpx",
  122. },
  123. width: {
  124. type: String,
  125. default: "350rpx",
  126. },
  127. left: {
  128. type: String,
  129. default: "180rpx",
  130. },
  131. top: {
  132. type: String,
  133. default: "30rpx",
  134. },
  135. business: {
  136. type: String,
  137. default: "LOGIN",
  138. },
  139. },
  140. data() {
  141. return {
  142. mainColor: this.$mainColor,
  143. flage: false,
  144. key: "", //key
  145. vsrtx: "点击进行验证", //按钮提示语
  146. vsr: false, //
  147. hid: true,
  148. col: "#838383",
  149. movePv: 0,
  150. hasImg: "拖动滑块已完成拼图",
  151. spcode: "",
  152. tl: 0,
  153. moveCode: 0,
  154. //X轴移动距离
  155. moveX: 0,
  156. //模版高度
  157. originalHeight: "",
  158. //模版宽度
  159. originalWidth: "",
  160. //拼图高度
  161. sliderHeight: "",
  162. //平涂宽度
  163. sliderWidth: "",
  164. scHight: 0,
  165. //原图
  166. img: "",
  167. //拼图
  168. imgbk: "",
  169. endLoad: true,
  170. imgbKH: "",
  171. };
  172. },
  173. methods: {
  174. show() {
  175. this.hid = false;
  176. },
  177. hide() {
  178. if (!this.vsr) {
  179. // vsr判断是否验证成功,成功隐藏验证框
  180. this.hid = !this.hid;
  181. }
  182. },
  183. error() {
  184. this.vsr = false;
  185. this.hid = false;
  186. this.moveX = 0;
  187. this.moveCode = 0;
  188. },
  189. // 获取验证图片
  190. getCode() {
  191. this.col = "#b3afae";
  192. this.hasImg = "图片加载中...";
  193. if (!storage.getUuid()) {
  194. storage.setUuid(uuid.v1());
  195. }
  196. uni.request({
  197. url: api.common + "/common/slider/" + this.business,
  198. header: {
  199. uuid: storage.getUuid(),
  200. },
  201. success: (res) => {
  202. this.col = "#838383";
  203. this.hasImg = "拖动滑块以完成拼图";
  204. var data = res.data.result;
  205. // base64的图片
  206. this.img = data.backImage;
  207. this.imgbk = data.slidingImage;
  208. // 根据参数动态适应验证图片的高宽
  209. this.imgbKH = data.randomY * 1.8 + "rpx";
  210. this.originalHeight = data.originalHeight * 1.8 + "rpx";
  211. this.originalWidth = data.originalWidth * 1.8 + "rpx";
  212. this.sliderHeight = data.sliderHeight * 1.8 + "rpx";
  213. this.sliderWidth = data.sliderWidth * 1.8 + "rpx";
  214. // 适应比率,用来适应滑动距离
  215. this.tl = 1 / (1.8 * l);
  216. // 无用信息
  217. this.spcode = data.capcode;
  218. // 验证令牌
  219. this.key = data.key;
  220. this.$store.state.verificationKey = data.key;
  221. },
  222. });
  223. },
  224. end(e) {
  225. this.endLoad = false;
  226. // 验证拼图位置是否正确
  227. uni.request({
  228. method: "POST",
  229. url:
  230. api.common +
  231. "/common/slider/" +
  232. this.business +
  233. "?xPos=" +
  234. parseInt(this.moveCode * this.tl),
  235. header: {
  236. uuid: storage.getUuid(),
  237. },
  238. success: (res) => {
  239. this.endLoad = true;
  240. res.data.result == false
  241. ? (res.data.result = false)
  242. : (res.data.result = true);
  243. if (res.data && res.data.result) {
  244. //验证成功后把key发送出去,后端会把验证信息存在缓存里
  245. this.$emit("send", this.key);
  246. this.hide();
  247. this.vsr = true;
  248. this.vsrtx = "已通过验证";
  249. } else {
  250. this.getCode(); // 让滑块回到起始位置
  251. if (this.movePv == 1) {
  252. this.movePv = 0;
  253. } else {
  254. this.movePv = 1;
  255. }
  256. }
  257. },
  258. fail: (res) => {
  259. this.$msg("连接服务器失败");
  260. },
  261. });
  262. },
  263. // 绑定拼图位置
  264. moveChange(e) {
  265. this.moveX = e.detail.x;
  266. this.moveCode = e.detail.x;
  267. },
  268. },
  269. };
  270. </script>
  271. <style lang="scss" scoped>
  272. @import "./animation.css";
  273. @import "./icon.css";
  274. // @import './main.css';
  275. .dh-wt {
  276. animation: at 1.1s ease;
  277. animation-iteration-count: infinite;
  278. animation-direction: alternate;
  279. background-color: $main-color;
  280. border-radius: 50%;
  281. }
  282. @keyframes at {
  283. from {
  284. width: 27rpx;
  285. height: 27rpx;
  286. }
  287. to {
  288. width: 45rpx;
  289. height: 45rpx;
  290. }
  291. }
  292. .ttcl {
  293. color: $main-color;
  294. }
  295. .border-index {
  296. border: 1rpx solid $main-color;
  297. }
  298. .status_bar {
  299. height: var(--status-bar-height);
  300. background-color: #f1f1f1;
  301. width: 100%;
  302. }
  303. .status_bar-nobg {
  304. height: var(--status-bar-height);
  305. width: 100%;
  306. }
  307. /* 转圈动画 */
  308. .turn-load {
  309. animation: turnmy 1s linear infinite;
  310. }
  311. @keyframes turnmy {
  312. 0% {
  313. -webkit-transform: rotate(0deg);
  314. }
  315. 25% {
  316. -webkit-transform: rotate(90deg);
  317. }
  318. 50% {
  319. -webkit-transform: rotate(180deg);
  320. }
  321. 75% {
  322. -webkit-transform: rotate(270deg);
  323. }
  324. 100% {
  325. -webkit-transform: rotate(360deg);
  326. }
  327. }
  328. .status_bar-fixed {
  329. height: var(--status-bar-height);
  330. width: 100%;
  331. position: fixed;
  332. background-color: #f1f1f1;
  333. z-index: 20;
  334. }
  335. .head-dh-my {
  336. display: flex;
  337. position: fixed;
  338. justify-content: space-around;
  339. align-items: flex-end;
  340. padding-bottom: 10rpx;
  341. z-index: 15;
  342. background-color: #e3e3e3;
  343. width: 750rpx;
  344. }
  345. .padding-left {
  346. padding-left: 20rpx;
  347. }
  348. .padding-left-top {
  349. padding-left: 20rpx;
  350. padding-top: 20rpx;
  351. }
  352. .padding-right {
  353. padding-right: 20rpx;
  354. }
  355. .input-my {
  356. padding-left: 20rpx;
  357. border-radius: 40rpx;
  358. height: 50rpx;
  359. margin: 10rpx;
  360. }
  361. .tb-tag-absolute {
  362. position: absolute;
  363. z-index: 5;
  364. border-radius: 25rpx;
  365. font-size: 16rpx;
  366. margin-left: 25rpx;
  367. margin-top: -35rpx;
  368. }
  369. .flex-column-center {
  370. display: flex;
  371. flex-direction: column;
  372. justify-content: center;
  373. align-items: center;
  374. }
  375. .flex-column-between {
  376. display: flex;
  377. flex-direction: column;
  378. justify-content: space-between;
  379. align-items: center;
  380. }
  381. .flex-column-start {
  382. display: flex;
  383. flex-direction: column;
  384. justify-content: center;
  385. }
  386. .flex-column-around {
  387. display: flex;
  388. flex-direction: column;
  389. justify-content: space-around;
  390. align-items: center;
  391. }
  392. .flex-row-start {
  393. display: flex;
  394. flex-direction: row;
  395. align-items: center;
  396. }
  397. .flex-row-around {
  398. display: flex;
  399. flex-direction: row;
  400. justify-content: space-around;
  401. align-items: center;
  402. }
  403. .flex-row-center {
  404. display: flex;
  405. flex-direction: row;
  406. justify-content: center;
  407. align-items: center;
  408. }
  409. .flex-row-between {
  410. display: flex;
  411. flex-direction: row;
  412. justify-content: space-between;
  413. align-items: center;
  414. }
  415. .my-title {
  416. font-size: 35rpx;
  417. font-weight: bold;
  418. }
  419. .my-neirong {
  420. font-size: 26rpx;
  421. color: #6d6d6d;
  422. }
  423. .my-neirong-sm {
  424. font-size: 23rpx;
  425. color: #616161;
  426. }
  427. .my-tag-text {
  428. font-size: 22rpx;
  429. padding-top: 20rpx;
  430. color: #bababa;
  431. }
  432. .padding-top {
  433. padding-top: 35rpx;
  434. }
  435. .padding-top-sm {
  436. padding-top: 20rpx;
  437. }
  438. .bottom-dh {
  439. background-color: #f1f1f1;
  440. position: fixed;
  441. z-index: 10;
  442. bottom: 0;
  443. width: 750rpx;
  444. height: 110rpx;
  445. }
  446. .tb-text {
  447. display: flex;
  448. flex-direction: column;
  449. justify-content: center;
  450. align-items: center;
  451. }
  452. .bottom-text {
  453. width: 750rpx;
  454. position: fixed;
  455. text-align: center;
  456. font-size: 26rpx;
  457. color: #9d9d9d;
  458. bottom: 70rpx;
  459. }
  460. .moneycolor {
  461. color: #ea5002;
  462. }
  463. .margin-top {
  464. margin-top: 20rpx;
  465. }
  466. .margin-top-sm {
  467. margin-top: 12rpx;
  468. }
  469. .margin {
  470. margin: 20rpx;
  471. }
  472. .margin-left {
  473. margin-left: 20rpx;
  474. }
  475. .margin-right {
  476. margin-right: 20rpx;
  477. }
  478. .main-color {
  479. color: #07d188;
  480. }
  481. </style>