verification.vue 11 KB

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