优化验证码框 滑动正常,滑动定位异常
parent
c6e9644882
commit
80ec9b7e15
|
|
@ -50,7 +50,7 @@
|
|||
}
|
||||
},
|
||||
"__VTJ_BLOCK__": true,
|
||||
"__VERSION__": "1736401534792",
|
||||
"__VERSION__": "1742828337536",
|
||||
"id": "7pdk4mxyf",
|
||||
"nodes": [
|
||||
{
|
||||
|
|
@ -308,6 +308,17 @@
|
|||
},
|
||||
"directives": [],
|
||||
"events": {}
|
||||
},
|
||||
{
|
||||
"id": "13ajd7cw",
|
||||
"name": "div",
|
||||
"from": "",
|
||||
"invisible": false,
|
||||
"locked": false,
|
||||
"children": "容器文本内容示例",
|
||||
"props": {},
|
||||
"directives": [],
|
||||
"events": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"__VTJ_PROJECT__": true,
|
||||
"id": "vue-element-plus-admin",
|
||||
"platform": "web",
|
||||
"name": "ElementAdmin",
|
||||
"homepage": "",
|
||||
"description": "一套基于vue3、element-plus、typesScript、vite4的后台集成方案。",
|
||||
|
|
@ -9,17 +10,25 @@
|
|||
"package": "vue",
|
||||
"version": "latest",
|
||||
"library": "Vue",
|
||||
"urls": ["@vtj/materials/deps/vue/vue.global.prod.js"],
|
||||
"urls": [
|
||||
"@vtj/materials/deps/vue/vue.global.prod.js"
|
||||
],
|
||||
"assetsLibrary": "VueMaterial",
|
||||
"required": true,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"platform": [
|
||||
"web",
|
||||
"h5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "vue-router",
|
||||
"version": "latest",
|
||||
"library": "VueRouter",
|
||||
"urls": ["@vtj/materials/deps/vue-router/vue-router.global.prod.js"],
|
||||
"urls": [
|
||||
"@vtj/materials/deps/vue-router/vue-router.global.prod.js"
|
||||
],
|
||||
"assetsLibrary": "VueRouterMaterial",
|
||||
"required": true,
|
||||
"official": true,
|
||||
|
|
@ -29,7 +38,9 @@
|
|||
"package": "@vtj/utils",
|
||||
"version": "latest",
|
||||
"library": "VtjUtils",
|
||||
"urls": ["@vtj/materials/deps/@vtj/utils/index.umd.js"],
|
||||
"urls": [
|
||||
"@vtj/materials/deps/@vtj/utils/index.umd.js"
|
||||
],
|
||||
"required": true,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
|
|
@ -44,7 +55,11 @@
|
|||
],
|
||||
"required": true,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"platform": [
|
||||
"web",
|
||||
"h5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "@vueuse/core",
|
||||
|
|
@ -56,7 +71,11 @@
|
|||
],
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"platform": [
|
||||
"web",
|
||||
"h5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "element-plus",
|
||||
|
|
@ -73,7 +92,8 @@
|
|||
"assetsLibrary": "ElementPlusMaterial",
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"platform": "web"
|
||||
},
|
||||
{
|
||||
"package": "@vtj/ui",
|
||||
|
|
@ -90,21 +110,8 @@
|
|||
"assetsLibrary": "VtjUIMaterial",
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"package": "@vtj/charts",
|
||||
"version": "latest",
|
||||
"library": "VtjCharts",
|
||||
"urls": [
|
||||
"@vtj/materials/deps/echarts/echarts.min.js",
|
||||
"@vtj/materials/deps/@vtj/charts/index.umd.js"
|
||||
],
|
||||
"assetsUrl": "@vtj/materials/assets/charts/index.umd.js",
|
||||
"assetsLibrary": "VtjChartsMaterial",
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"platform": "web"
|
||||
},
|
||||
{
|
||||
"package": "ant-design-vue",
|
||||
|
|
@ -126,13 +133,48 @@
|
|||
"assetsLibrary": "AntdvMaterial",
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": false
|
||||
"enabled": false,
|
||||
"platform": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "@vtj/charts",
|
||||
"version": "latest",
|
||||
"library": "VtjCharts",
|
||||
"urls": [
|
||||
"@vtj/materials/deps/echarts/echarts.min.js",
|
||||
"@vtj/materials/deps/@vtj/charts/index.umd.js"
|
||||
],
|
||||
"assetsUrl": "@vtj/materials/assets/charts/index.umd.js",
|
||||
"assetsLibrary": "VtjChartsMaterial",
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true,
|
||||
"platform": [
|
||||
"web",
|
||||
"h5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "mockjs",
|
||||
"version": "latest",
|
||||
"library": "Mock",
|
||||
"urls": [
|
||||
"@vtj/materials/deps/mockjs/mock-min.js"
|
||||
],
|
||||
"required": false,
|
||||
"official": true,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"package": "vant",
|
||||
"version": "latest",
|
||||
"library": "vant",
|
||||
"urls": ["@vtj/materials/deps/vant/index.css", "@vtj/materials/deps/vant/vant.min.js"],
|
||||
"urls": [
|
||||
"@vtj/materials/deps/vant/index.css",
|
||||
"@vtj/materials/deps/vant/vant.min.js"
|
||||
],
|
||||
"assetsUrl": "@vtj/materials/assets/vant/index.umd.js",
|
||||
"assetsLibrary": "VantMaterial",
|
||||
"required": false,
|
||||
|
|
@ -174,6 +216,9 @@
|
|||
"blocks": [],
|
||||
"apis": [],
|
||||
"meta": [],
|
||||
"config": {},
|
||||
"config": {
|
||||
"title": ""
|
||||
},
|
||||
"uniConfig": {},
|
||||
"__BASE_PATH__": "/"
|
||||
}
|
||||
|
|
|
|||
26
README.md
26
README.md
|
|
@ -1,3 +1,29 @@
|
|||
|
||||
|
||||
[English](./README.md) | **中文**
|
||||
|
||||
## 介绍
|
||||
|
||||
vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台模版。使用了最新的`vue3`,`vite`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,可以用来作为项目的启动模版,也可用于学习参考。并且时刻关注着最新技术动向,尽可能的第一时间更新。
|
||||
|
||||
vue-element-plus-admin 的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。
|
||||
|
||||
|
||||
|
||||
## 特性
|
||||
|
||||
- **最新技术栈**:使用 Vue3/vite4 等前端前沿技术开发
|
||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||
- **主题**: 可配置的主题
|
||||
- **国际化**:内置完善的国际化方案
|
||||
- **自定义数据** 内置 Mock 数据方案
|
||||
- **权限** 内置完善的动态路由权限生成方案
|
||||
- **组件** 二次封装了多个常用的组件
|
||||
- **示例** 内置丰富的示例
|
||||
|
||||
|
||||
## 文档
|
||||
|
||||
获取代码
|
||||
git clone
|
||||
安装依赖
|
||||
|
|
|
|||
130
README.zh-CN.md
130
README.zh-CN.md
|
|
@ -1,9 +1,4 @@
|
|||
<div align="center"> <a href="https://github.com/kailong321200875/vue-element-plus-admin"> <img width="100" src="./public/logo.png"> </a> <br> <br>
|
||||
|
||||
[](LICENSE) [](repo-size) [](last-commit) [](stars) [](forks) [](release) [](watchers)
|
||||
|
||||
<h1>vue-element-plus-admin</h1>
|
||||
</div>
|
||||
|
||||
[English](./README.md) | **中文**
|
||||
|
||||
|
|
@ -13,7 +8,7 @@ vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台
|
|||
|
||||
vue-element-plus-admin 的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。
|
||||
|
||||
如需要基础模版,请切换到 `mini` 分支,`mini` 只简单集成了一些如:布局、动态菜单等常用布局功能,更适合开发者进行二次开发。
|
||||
|
||||
|
||||
## 特性
|
||||
|
||||
|
|
@ -26,123 +21,28 @@ vue-element-plus-admin 的定位是后台集成方案,不太适合当基础模
|
|||
- **组件** 二次封装了多个常用的组件
|
||||
- **示例** 内置丰富的示例
|
||||
|
||||
## 预览
|
||||
|
||||
- [vue-element-plus-admin](https://element-plus-admin.cn/) - 完整版 github 站点
|
||||
- [vue-element-plus-admin](https://kailong110120130.gitee.io/vue-element-plus-admin) - 完整版 gitee 站点
|
||||
|
||||
帐号:**admin/admin**
|
||||
|
||||
在线例子默认不适用菜单过滤,而是直接使用静态路由表
|
||||
|
||||
## 文档
|
||||
|
||||
[文档地址 Github](https://element-plus-admin-doc.cn/)
|
||||
|
||||
[文档地址 Gitee](https://kailong110120130.gitee.io/vue-element-plus-admin-doc)
|
||||
|
||||
## 前序准备
|
||||
|
||||
- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) - 项目开发环境
|
||||
- [Vite](https://vitejs.dev/) - 熟悉 vite 特性
|
||||
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
|
||||
- [TypeScript](https://www.typescriptlang.org/) - 熟悉 `TypeScript` 基本语法
|
||||
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
|
||||
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用
|
||||
- [Element-Plus](https://element-plus.org/) - element-plus 基本使用
|
||||
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
|
||||
|
||||
## 安装和使用
|
||||
|
||||
- 获取代码
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kailong321200875/vue-element-plus-admin.git
|
||||
```
|
||||
|
||||
- 安装依赖
|
||||
|
||||
```bash
|
||||
获取代码
|
||||
git clone
|
||||
安装依赖
|
||||
cd vue-element-plus-admin
|
||||
|
||||
pnpm config set registry https://registry.npmmirror.com/
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- 运行
|
||||
|
||||
```bash
|
||||
运行
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
- 打包
|
||||
|
||||
```bash
|
||||
打包
|
||||
pnpm run build:pro
|
||||
```
|
||||
|
||||
## 更新日志
|
||||
问题
|
||||
1.集成到本地项目 本地启动运行可以看到设计器入口
|
||||
设计器是在开发环境提供辅助开发服务的,不是在线的
|
||||
在线参考 https://gitee.com/newgateway/vtj/tree/master/lcdp
|
||||
|
||||
[更新日志](./CHANGELOG.md)
|
||||
npm install -g lerna@latest pnpm@latest --registry=https://registry.npmmirror.com
|
||||
|
||||
## 如何贡献
|
||||
|
||||
<a href="https://github.com/kailong321200875/vue-element-plus-admin/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=kailong321200875/vue-element-plus-admin" />
|
||||
</a>
|
||||
|
||||
你可以[提一个 issue](https://github.com/kailong321200875/vue-element-plus-admin/issues/new) 或者提交一个 Pull Request。
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. Fork 代码
|
||||
2. 创建自己的分支: `git checkout -b feat/xxxx`
|
||||
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. 推送您的分支: `git push origin feat/xxxx`
|
||||
5. 提交 `pull request`
|
||||
|
||||
## Git 贡献提交规范
|
||||
|
||||
- `feat` 新功能
|
||||
- `fix` 修补 bug
|
||||
- `docs` 文档
|
||||
- `style` 格式、样式(不影响代码运行的变动)
|
||||
- `refactor` 重构(即不是新增功能,也不是修改 BUG 的代码)
|
||||
- `perf` 优化相关,比如提升性能、体验
|
||||
- `test` 添加测试
|
||||
- `build` 编译相关的修改,对项目构建或者依赖的改动
|
||||
- `ci` 持续集成修改
|
||||
- `chore` 构建过程或辅助工具的变动
|
||||
- `revert` 回滚到上一个版本
|
||||
- `workflow` 工作流改进
|
||||
- `mod` 不确定分类的修改
|
||||
- `wip` 开发中
|
||||
- `types` 类型
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
本地开发推荐使用 `Chrome 80+` 浏览器
|
||||
|
||||
支持现代浏览器, 不支持 IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## Donate
|
||||
|
||||
如果你觉得这个项目有帮助,欢迎赞助以示支持~
|
||||
|
||||
[Paypal Me](https://www.paypal.com/paypalme/ckl94)
|
||||
|
||||
<img src="https://gitee.com/kailong110120130/my-image/raw/master/pay.jpg" />
|
||||
|
||||
### 我的二维码
|
||||
|
||||
如有项目合作或项目外包,扫码加我好友,请备注来意。
|
||||
|
||||
<img src="https://gitee.com/kailong110120130/my-image/raw/master/me.jpg" />
|
||||
|
||||
## 许可证
|
||||
|
||||
[MIT](./LICENSE)
|
||||
2.关于下载依赖报错:error (ERR_INVALID_THIS)
|
||||
pnpm升级到 8.3.1 :
|
||||
npm install -g pnpm@8.3.1
|
||||
|
|
@ -160,8 +160,10 @@ const show = () => {
|
|||
instance.value.init()
|
||||
} else {
|
||||
console.error('验证码组件实例不存在或没有init方法')
|
||||
// 尝试强制刷新
|
||||
refresh()
|
||||
}
|
||||
}, 500)
|
||||
}, 100) // 减少延时
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
<template>
|
||||
<div class="verify-slide">
|
||||
<!-- 验证码图片面板 -->
|
||||
<div class="verify-img-panel" :style="{ width: imgSize.width, height: imgSize.height }">
|
||||
<!-- 背景图片 -->
|
||||
<img v-if="backImgBase" :src="backImgBase" alt="背景图" class="back-img" />
|
||||
<div v-else class="verify-loading">加载中...</div>
|
||||
|
||||
<!-- 刷新按钮 -->
|
||||
<div class="verify-refresh" @click="refresh">
|
||||
<i class="iconfont icon-refresh"></i>
|
||||
</div>
|
||||
|
||||
<!-- 缺口 -->
|
||||
<div
|
||||
class="verify-gap"
|
||||
:style="{
|
||||
|
|
@ -16,12 +22,15 @@
|
|||
}"
|
||||
v-if="backImgBase"
|
||||
></div>
|
||||
|
||||
<!-- 拼图块 -->
|
||||
<div
|
||||
class="verify-sub-block"
|
||||
:style="{
|
||||
width: blockSize.width + 'px',
|
||||
height: blockSize.height + 'px',
|
||||
top: top + 'px',
|
||||
left: moveBlockLeft + 'px',
|
||||
background: `url(${blockImgBase})`,
|
||||
backgroundSize: `${imgSize.width} ${imgSize.height}`,
|
||||
backgroundPosition: `-${left}px -${top}px`
|
||||
|
|
@ -29,44 +38,44 @@
|
|||
v-if="blockImgBase"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- 滑动条区域 -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{ width: imgSize.width, height: barSize.height }"
|
||||
@mouseover="showTips"
|
||||
@mouseout="hideTips"
|
||||
>
|
||||
<span class="verify-msg" v-text="text"></span>
|
||||
<!-- 提示文本 -->
|
||||
<span class="verify-msg">{{ text }}</span>
|
||||
|
||||
<!-- 已滑动的进度条 -->
|
||||
<div
|
||||
class="verify-left-bar"
|
||||
:style="{
|
||||
width: leftBarWidth,
|
||||
height: barSize.height,
|
||||
borderTopLeftRadius: barSize.height / 2 + 'px',
|
||||
borderBottomLeftRadius: barSize.height / 2 + 'px'
|
||||
width: leftBarWidth + 'px',
|
||||
height: barSize.height + 'px'
|
||||
}"
|
||||
>
|
||||
<span class="verify-msg" v-text="finishText"></span>
|
||||
<div
|
||||
class="verify-move-block"
|
||||
@touchstart="start"
|
||||
@mousedown="start"
|
||||
:style="{
|
||||
width: barSize.height,
|
||||
height: barSize.height,
|
||||
left: moveBlockLeft,
|
||||
borderRadius: barSize.height / 2 + 'px'
|
||||
}"
|
||||
>
|
||||
<i :class="iconClass" :style="{ lineHeight: barSize.height + 'px' }"></i>
|
||||
<div class="verify-sub-block" :style="{ transform: `translate(${moveBlockLeft}px, ${-top}px)` }"></div>
|
||||
</div>
|
||||
<span class="verify-msg">{{ finishText }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 滑块 -->
|
||||
<div
|
||||
class="verify-move-block"
|
||||
@mousedown="start"
|
||||
:style="{
|
||||
width: barSize.height + 'px',
|
||||
height: barSize.height + 'px',
|
||||
left: moveBlockLeft + 'px'
|
||||
}"
|
||||
>
|
||||
<i :class="iconClass"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import * as LoginApi from '@/api/login'
|
||||
|
||||
|
|
@ -79,10 +88,6 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: 'fixed'
|
||||
},
|
||||
vSpace: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
explain: {
|
||||
type: String,
|
||||
default: '向右滑动完成验证'
|
||||
|
|
@ -111,7 +116,6 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const emit = defineEmits(['success', 'error', 'ready'])
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// 验证码状态
|
||||
|
|
@ -124,16 +128,10 @@ const text = ref(props.explain)
|
|||
const finishText = ref('')
|
||||
const top = ref(0)
|
||||
const left = ref(0)
|
||||
const moveBlockBackgroundPosition = ref('')
|
||||
|
||||
// 滑动状态
|
||||
const startMoveTime = ref(null)
|
||||
const endMovetime = ref(null)
|
||||
const startX = ref(0)
|
||||
const oldX = ref(0)
|
||||
const currX = ref(0)
|
||||
const isMove = ref(false)
|
||||
const trail = reactive([])
|
||||
|
||||
// 样式计算
|
||||
const iconClass = computed(() => {
|
||||
|
|
@ -142,37 +140,25 @@ const iconClass = computed(() => {
|
|||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
console.log('验证码组件挂载')
|
||||
init()
|
||||
window.addEventListener('touchmove', move)
|
||||
window.addEventListener('mousemove', move)
|
||||
window.addEventListener('touchend', end)
|
||||
window.addEventListener('mouseup', end)
|
||||
})
|
||||
|
||||
// 清理事件监听
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('touchmove', move)
|
||||
window.removeEventListener('mousemove', move)
|
||||
window.removeEventListener('touchend', end)
|
||||
window.removeEventListener('mouseup', end)
|
||||
|
||||
// 添加全局事件监听
|
||||
document.addEventListener('mousemove', handleMouseMove)
|
||||
document.addEventListener('mouseup', handleMouseUp)
|
||||
document.addEventListener('touchmove', handleTouchMove)
|
||||
document.addEventListener('touchend', handleTouchEnd)
|
||||
})
|
||||
|
||||
// 初始化验证码
|
||||
const init = async () => {
|
||||
console.log('验证码初始化开始,类型:', props.captchaType)
|
||||
console.log('验证码初始化开始')
|
||||
try {
|
||||
console.log('开始请求验证码API')
|
||||
const res = await LoginApi.getCode({ captchaType: props.captchaType })
|
||||
console.log('验证码API响应:', res)
|
||||
|
||||
if (res && res.repCode === '0000') {
|
||||
const { repData } = res
|
||||
console.log('验证码数据:', {
|
||||
x: repData.x,
|
||||
y: repData.y,
|
||||
hasOriginalImage: !!repData.originalImageBase64,
|
||||
hasJigsawImage: !!repData.jigsawImageBase64
|
||||
})
|
||||
|
||||
backImgBase.value = 'data:image/png;base64,' + repData.originalImageBase64
|
||||
blockImgBase.value = 'data:image/png;base64,' + repData.jigsawImageBase64
|
||||
|
|
@ -207,59 +193,56 @@ const refresh = () => {
|
|||
init()
|
||||
}
|
||||
|
||||
// 显示提示
|
||||
const showTips = () => {
|
||||
if (!status.value) {
|
||||
text.value = props.explain
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏提示
|
||||
const hideTips = () => {
|
||||
if (!status.value) {
|
||||
text.value = props.explain
|
||||
}
|
||||
}
|
||||
|
||||
// 开始滑动
|
||||
const start = (e) => {
|
||||
if (status.value) return
|
||||
text.value = ''
|
||||
startMoveTime.value = new Date().getTime()
|
||||
|
||||
console.log('开始滑动')
|
||||
isMove.value = true
|
||||
startX.value = e.clientX || e.touches[0].clientX
|
||||
oldX.value = moveBlockLeft.value
|
||||
trail.length = 0
|
||||
startX.value = e.clientX || (e.touches && e.touches[0].clientX)
|
||||
}
|
||||
|
||||
// 滑动中
|
||||
const move = (e) => {
|
||||
// 鼠标移动
|
||||
const handleMouseMove = (e) => {
|
||||
if (!isMove.value) return
|
||||
moveSlider(e.clientX)
|
||||
}
|
||||
|
||||
// 触摸移动
|
||||
const handleTouchMove = (e) => {
|
||||
if (!isMove.value) return
|
||||
moveSlider(e.touches[0].clientX)
|
||||
}
|
||||
|
||||
// 移动滑块
|
||||
const moveSlider = (clientX) => {
|
||||
const moveX = clientX - startX.value
|
||||
const newLeft = Math.max(0, Math.min(moveX, parseInt(props.barSize.width) - parseInt(props.barSize.height)))
|
||||
|
||||
const eventX = e.clientX || (e.touches ? e.touches[0].clientX : 0)
|
||||
if (eventX === 0) return
|
||||
|
||||
const moveX = eventX - startX.value
|
||||
const newMoveBlockLeft = oldX.value + moveX
|
||||
|
||||
// 限制滑块移动范围
|
||||
if (newMoveBlockLeft < 0) {
|
||||
moveBlockLeft.value = 0
|
||||
} else if (newMoveBlockLeft > props.barSize.width - props.barSize.height) {
|
||||
moveBlockLeft.value = props.barSize.width - props.barSize.height
|
||||
} else {
|
||||
moveBlockLeft.value = newMoveBlockLeft
|
||||
leftBarWidth.value = newMoveBlockLeft + props.barSize.height / 2
|
||||
}
|
||||
|
||||
trail.push(moveBlockLeft.value)
|
||||
moveBlockLeft.value = newLeft
|
||||
leftBarWidth.value = newLeft
|
||||
}
|
||||
|
||||
// 鼠标松开
|
||||
const handleMouseUp = () => {
|
||||
if (!isMove.value) return
|
||||
endSlide()
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
const handleTouchEnd = () => {
|
||||
if (!isMove.value) return
|
||||
endSlide()
|
||||
}
|
||||
|
||||
// 结束滑动
|
||||
const end = async () => {
|
||||
const endSlide = async () => {
|
||||
if (!isMove.value) return
|
||||
|
||||
console.log('结束滑动')
|
||||
isMove.value = false
|
||||
endMovetime.value = new Date().getTime()
|
||||
|
||||
if (moveBlockLeft.value === 0) return
|
||||
|
||||
try {
|
||||
// 验证
|
||||
|
|
@ -272,13 +255,15 @@ const end = async () => {
|
|||
token: window.sessionStorage.getItem('token')
|
||||
})
|
||||
|
||||
console.log('验证结果:', res)
|
||||
|
||||
if (res && res.repCode === '0000') {
|
||||
status.value = true
|
||||
text.value = ''
|
||||
finishText.value = t('captcha.verifySuccess')
|
||||
|
||||
setTimeout(() => {
|
||||
if (props.mode === 'pop') {
|
||||
// 成功回调
|
||||
emit('success', {
|
||||
captchaVerification: res.repData.captchaVerification
|
||||
})
|
||||
|
|
@ -287,14 +272,24 @@ const end = async () => {
|
|||
} else {
|
||||
status.value = false
|
||||
text.value = t('captcha.verifyFail')
|
||||
|
||||
// 失败动画
|
||||
moveBlockLeft.value = 0
|
||||
leftBarWidth.value = 0
|
||||
|
||||
setTimeout(() => {
|
||||
refresh()
|
||||
}, 1000)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('验证失败', error)
|
||||
console.error('验证失败:', error)
|
||||
status.value = false
|
||||
text.value = t('captcha.verifyError')
|
||||
|
||||
// 错误动画
|
||||
moveBlockLeft.value = 0
|
||||
leftBarWidth.value = 0
|
||||
|
||||
setTimeout(() => {
|
||||
refresh()
|
||||
}, 1000)
|
||||
|
|
@ -312,12 +307,14 @@ const end = async () => {
|
|||
position: relative;
|
||||
background-color: #f5f5f5;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.verify-img-panel .back-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.verify-img-panel .verify-refresh {
|
||||
|
|
@ -334,11 +331,13 @@ const end = async () => {
|
|||
color: #fff;
|
||||
font-size: 20px;
|
||||
z-index: 10;
|
||||
border-radius: 0 4px 0 4px;
|
||||
}
|
||||
|
||||
.verify-img-panel .verify-gap {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +349,7 @@ const end = async () => {
|
|||
border-radius: 4px;
|
||||
line-height: 40px;
|
||||
margin-top: 5px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-msg {
|
||||
|
|
@ -361,35 +361,43 @@ const end = async () => {
|
|||
z-index: 2;
|
||||
color: #88949d;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-left-bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #d1e9fe;
|
||||
background: linear-gradient(to right, #1890ff, #36a6ff);
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
z-index: 1;
|
||||
transition: width 0.2s;
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-move-block {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #1890ff;
|
||||
background: linear-gradient(135deg, #1890ff, #36a6ff);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 0 2px #1890ff;
|
||||
transition: background 0.2s;
|
||||
cursor: grab;
|
||||
box-shadow: 0 0 4px rgba(24, 144, 255, 0.5);
|
||||
transition: all 0.2s;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-move-block:hover {
|
||||
background-color: #0c7ad9;
|
||||
background: linear-gradient(135deg, #0c7ad9, #1890ff);
|
||||
box-shadow: 0 0 8px rgba(24, 144, 255, 0.5);
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-move-block:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.verify-bar-area .verify-move-block .verify-sub-block {
|
||||
|
|
@ -397,7 +405,11 @@ const end = async () => {
|
|||
width: 50px;
|
||||
height: 50px;
|
||||
top: -55px;
|
||||
box-shadow: 0 0 2px #1890ff;
|
||||
background-size: 100% !important;
|
||||
box-shadow: 0 0 8px rgba(24, 144, 255, 0.5);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.verify-loading {
|
||||
|
|
@ -407,6 +419,7 @@ const end = async () => {
|
|||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
color: #88949d;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
|
|
@ -414,5 +427,34 @@ const end = async () => {
|
|||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
pointer-events: none;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* 增强拼图块样式 */
|
||||
.verify-img-panel .verify-sub-block {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.8) !important;
|
||||
z-index: 10 !important;
|
||||
}
|
||||
|
||||
/* 添加图标备用样式 */
|
||||
.icon-refresh::before {
|
||||
content: "↻";
|
||||
}
|
||||
|
||||
.icon-right::before {
|
||||
content: "→";
|
||||
}
|
||||
|
||||
.icon-check::before {
|
||||
content: "✓";
|
||||
}
|
||||
|
||||
/* 增强滑块样式 */
|
||||
.verify-bar-area .verify-move-block {
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.8) !important;
|
||||
box-shadow: 0 0 8px rgba(24, 144, 255, 0.8) !important;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue