Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
basic-uniapp-v3
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-uniapp-v3
Commits
dcb2c886
提交
dcb2c886
authored
4月 30, 2026
作者:
廖在望
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 优化登录和注册页面逻辑。
上级
2a2d7e73
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
0 行增加
和
211 行删除
+0
-211
SlideVerify.vue
src/components/slide-verify/SlideVerify.vue
+0
-211
login.vue
src/pages/login/login.vue
+0
-0
register.vue
src/pages/login/register.vue
+0
-0
没有找到文件。
src/components/slide-verify/SlideVerify.vue
deleted
100644 → 0
浏览文件 @
2a2d7e73
<
script
setup
lang=
"ts"
>
/**
* 滑动验证组件
* 用法:<SlideVerify v-model:show="showSlide" @success="onVerifySuccess" />
*/
const
props
=
defineProps
<
{
show
:
boolean
}
>
()
const
emit
=
defineEmits
<
{
(
e
:
'update:show'
,
val
:
boolean
):
void
(
e
:
'success'
):
void
(
e
:
'close'
):
void
}
>
()
const
TRACK_WIDTH
=
560
// rpx,滑道宽度(与样式保持一致)
const
BTN_WIDTH
=
96
// rpx,滑块宽度
const
maxRpx
=
TRACK_WIDTH
-
BTN_WIDTH
// 最大可拖动距离(rpx)
const
state
=
reactive
({
translateX
:
0
,
// 当前滑块位移(px,运行时换算)
isDragging
:
false
,
startX
:
0
,
maxPx
:
0
,
// 运行时根据屏幕宽度换算
verified
:
false
,
text
:
'按住滑块,拖动到最右侧'
,
})
// 将 rpx 换算为 px
function
rpxToPx
(
rpx
:
number
):
number
{
const
screenWidth
=
uni
.
getSystemInfoSync
().
windowWidth
return
(
rpx
/
750
)
*
screenWidth
}
watch
(()
=>
props
.
show
,
(
val
)
=>
{
if
(
val
)
{
reset
()
state
.
maxPx
=
rpxToPx
(
maxRpx
)
}
})
function
reset
()
{
state
.
translateX
=
0
state
.
isDragging
=
false
state
.
verified
=
false
state
.
text
=
'按住滑块,拖动到最右侧'
}
function
onTouchStart
(
e
:
any
)
{
if
(
state
.
verified
)
return
state
.
isDragging
=
true
state
.
startX
=
e
.
touches
[
0
].
clientX
}
function
onTouchMove
(
e
:
any
)
{
if
(
!
state
.
isDragging
||
state
.
verified
)
return
const
dx
=
e
.
touches
[
0
].
clientX
-
state
.
startX
state
.
translateX
=
Math
.
max
(
0
,
Math
.
min
(
dx
,
state
.
maxPx
))
}
function
onTouchEnd
()
{
if
(
!
state
.
isDragging
)
return
state
.
isDragging
=
false
// 距终点 10px 以内视为验证通过
if
(
state
.
translateX
>=
state
.
maxPx
-
rpxToPx
(
10
))
{
state
.
translateX
=
state
.
maxPx
state
.
verified
=
true
state
.
text
=
'验证通过'
setTimeout
(()
=>
{
emit
(
'success'
)
close
()
},
600
)
}
else
{
// 未拖到底,回弹
state
.
translateX
=
0
}
}
function
close
()
{
emit
(
'update:show'
,
false
)
emit
(
'close'
)
reset
()
}
</
script
>
<
template
>
<view
class=
"sv-mask"
v-if=
"show"
@
click
.
self=
"close"
>
<view
class=
"sv-panel"
>
<view
class=
"sv-title"
>
安全验证
</view>
<view
class=
"sv-desc"
>
{{
state
.
text
}}
</view>
<!-- 滑道 -->
<view
class=
"sv-track"
>
<!-- 已划过的高亮区 -->
<view
class=
"sv-fill"
:style=
"
{ width: state.translateX + 'px' }" />
<!-- 滑块 -->
<view
class=
"sv-btn"
:class=
"
{ success: state.verified }"
:style="{ transform: `translateX(${state.translateX}px)` }"
@touchstart.prevent="onTouchStart"
@touchmove.prevent="onTouchMove"
@touchend.prevent="onTouchEnd"
>
<text
class=
"sv-arrow"
v-if=
"!state.verified"
>
→
</text>
<text
class=
"sv-check"
v-else
"
>
✓
</text>
</view>
</view>
<view
class=
"sv-close"
@
click=
"close"
>
<text>
取消
</text>
</view>
</view>
</view>
</
template
>
<
style
lang=
"scss"
scoped
>
.sv-mask
{
position
:
fixed
;
inset
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0.45
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
z-index
:
9999
;
}
.sv-panel
{
width
:
640
rpx
;
background
:
#fff
;
border-radius
:
24
rpx
;
padding
:
48
rpx
40
rpx
40
rpx
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
box-shadow
:
0
16
rpx
48
rpx
rgba
(
0
,
0
,
0
,
0.16
);
}
.sv-title
{
font-size
:
34
rpx
;
font-weight
:
700
;
color
:
#222
;
margin-bottom
:
12
rpx
;
}
.sv-desc
{
font-size
:
26
rpx
;
color
:
#888
;
margin-bottom
:
40
rpx
;
}
.sv-track
{
position
:
relative
;
width
:
560
rpx
;
height
:
96
rpx
;
background
:
#f0f0f0
;
border-radius
:
48
rpx
;
overflow
:
hidden
;
}
.sv-fill
{
position
:
absolute
;
left
:
0
;
top
:
0
;
height
:
100%
;
background
:
linear-gradient
(
90deg
,
#b8e8c0
,
#5db66f
);
border-radius
:
48
rpx
0
0
48
rpx
;
transition
:
width
0.05s
;
}
.sv-btn
{
position
:
absolute
;
left
:
0
;
top
:
0
;
width
:
96
rpx
;
height
:
96
rpx
;
background
:
#fff
;
border-radius
:
48
rpx
;
box-shadow
:
0
4
rpx
16
rpx
rgba
(
0
,
0
,
0
,
0.18
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
transition
:
background
0.3s
;
z-index
:
2
;
&.success
{
background
:
#5db66f
;
}
}
.sv-arrow
{
font-size
:
40
rpx
;
color
:
#5db66f
;
font-weight
:
700
;
}
.sv-check
{
font-size
:
40
rpx
;
color
:
#fff
;
font-weight
:
700
;
}
.sv-close
{
margin-top
:
32
rpx
;
text
{
font-size
:
28
rpx
;
color
:
#aaa
;
}
}
</
style
>
src/pages/login/login.vue
浏览文件 @
dcb2c886
差异被折叠。
点击展开。
src/pages/login/register.vue
浏览文件 @
dcb2c886
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论