提交 4a6f63f4 作者: 廖在望

feat: app样式调整和增加验证码登录

上级 17c12bdd
......@@ -100,6 +100,14 @@ export function editFarmbase(params = {}) {
params,
})
}
export function getFarmbaseDetail(params: any = {}) {
return getFarmbaseInfoById(params)
}
export function saveFarmbase(params: any = {}) {
return params?.id ? editFarmbase(params) : addFarmbase(params)
}
/**
* 基地列表
* @param {any} params
......
<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">&#8594;</text>
<text class="sv-check" v-else">&#10003;</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: 640rpx;
background: #fff;
border-radius: 24rpx;
padding: 48rpx 40rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.16);
}
.sv-title {
font-size: 34rpx;
font-weight: 700;
color: #222;
margin-bottom: 12rpx;
}
.sv-desc {
font-size: 26rpx;
color: #888;
margin-bottom: 40rpx;
}
.sv-track {
position: relative;
width: 560rpx;
height: 96rpx;
background: #f0f0f0;
border-radius: 48rpx;
overflow: hidden;
}
.sv-fill {
position: absolute;
left: 0;
top: 0;
height: 100%;
background: linear-gradient(90deg, #b8e8c0, #5db66f);
border-radius: 48rpx 0 0 48rpx;
transition: width 0.05s;
}
.sv-btn {
position: absolute;
left: 0;
top: 0;
width: 96rpx;
height: 96rpx;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 4rpx 16rpx 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: 40rpx;
color: #5db66f;
font-weight: 700;
}
.sv-check {
font-size: 40rpx;
color: #fff;
font-weight: 700;
}
.sv-close {
margin-top: 32rpx;
text {
font-size: 28rpx;
color: #aaa;
}
}
</style>
......@@ -141,7 +141,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 38rpx 382rpx;
background-image: url('/static/images/codefun/05019411cdb9383e51ab8923569568df.png');
background-image: url('../../../static/images/codefun/05019411cdb9383e51ab8923569568df.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -465,7 +465,7 @@
padding-bottom: 32rpx;
.section {
padding: 0 28rpx 8rpx;
background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-image: url('../../static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -163,7 +163,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 38rpx 382rpx;
background-image: url('/static/images/codefun/7f3f04389e8c4f41e9cf97f290ffa85d.png');
background-image: url('../../../static/images/codefun/7f3f04389e8c4f41e9cf97f290ffa85d.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -186,7 +186,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 42rpx 382rpx;
background-image: url('/static/images/codefun/319caa972700f74982472280d1edb65e.png');
background-image: url('../../../static/images/codefun/319caa972700f74982472280d1edb65e.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -146,7 +146,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 38rpx 382rpx;
background-image: url('/static/images/codefun/ad85a97458671a968e690f0108861184.png');
background-image: url('../../../static/images/codefun/ad85a97458671a968e690f0108861184.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -161,7 +161,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 38rpx 382rpx;
background-image: url('/static/images/codefun/d64598e1f76d3e1977d820f8b2f02843.png');
background-image: url('../../../static/images/codefun/d64598e1f76d3e1977d820f8b2f02843.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -153,7 +153,7 @@
overflow-x: hidden;
.section {
padding: 28rpx 38rpx 382rpx;
background-image: url('/static/images/codefun/b5493813a21cb38af4c6d8314e21b88c.png');
background-image: url('../../../static/images/codefun/b5493813a21cb38af4c6d8314e21b88c.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -498,7 +498,7 @@ return 'status-disconnected'
.section_5 {
padding: 12rpx 0 116rpx;
background-image: url('/static/images/codefun/4be80e2618f3c4b4aa1ce64fd9063abf.png');
background-image: url('../../static/images/codefun/4be80e2618f3c4b4aa1ce64fd9063abf.png');
background-size: 100% 100%;
background-repeat: no-repeat;
width: 160rpx;
......
......@@ -805,7 +805,7 @@
.section {
padding: 0 28rpx 30rpx 28rpx;
background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-image: url('../../static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......@@ -1159,7 +1159,7 @@
.section_7 {
padding: 20rpx 0 130rpx;
border-radius: 16rpx 16rpx 0rpx 0rpx;
background-image: url('/static/images/codefun/6082011896d83113283c720e943a4999.png');
background-image: url('../../static/images/codefun/6082011896d83113283c720e943a4999.png');
background-size: 100% 100%;
background-repeat: no-repeat;
}
......@@ -1178,7 +1178,7 @@
.section_9 {
padding: 20rpx 0 130rpx;
border-radius: 16rpx 16rpx 0rpx 0rpx;
background-image: url('/static/images/codefun/7a4ec325d59361d6716c2ec1394550bb.png');
background-image: url('../../static/images/codefun/7a4ec325d59361d6716c2ec1394550bb.png');
background-size: 100% 100%;
background-repeat: no-repeat;
}
......@@ -1197,7 +1197,7 @@
.section_8 {
padding: 20rpx 0 130rpx;
border-radius: 16rpx 16rpx 0rpx 0rpx;
background-image: url('/static/images/codefun/e812ea5af6105a808af058cb0796b7ee.png');
background-image: url('../../static/images/codefun/e812ea5af6105a808af058cb0796b7ee.png');
background-size: 100% 100%;
background-repeat: no-repeat;
}
......@@ -1322,14 +1322,14 @@
mix-blend-mode: NOTTHROUGH;
.section_15 {
padding-top: 96rpx;
background-image: url('/static/images/codefun/7d1feb7eb973f087dcabf21b283162bc.png');
background-image: url('../../static/images/codefun/7d1feb7eb973f087dcabf21b283162bc.png');
background-size: 100% 100%;
background-repeat: no-repeat;
height: 200rpx;
}
.section_16 {
padding-top: 96rpx;
background-image: url('/static/images/codefun/8d11e3cbcb918502bb6582a24cddb930.png');
background-image: url('../../static/images/codefun/8d11e3cbcb918502bb6582a24cddb930.png');
background-size: 100% 100%;
background-repeat: no-repeat;
height: 200rpx;
......
......@@ -315,7 +315,7 @@
}
.page-bg {
background: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png') no-repeat top center;
background: url('../../static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png') no-repeat top center;
background-size: 100%;
}
......
......@@ -1470,7 +1470,7 @@
.image-wrapper {
padding-bottom: 104rpx;
background-image: url('/static/images/codefun/e18202eb8182b8d77c464523c2305fa3.png');
background-image: url('../../static/images/codefun/e18202eb8182b8d77c464523c2305fa3.png');
background-size: 100% 100%;
background-repeat: no-repeat;
......@@ -1912,7 +1912,7 @@
}
.nongchang_box {
background-image: url('/static/images/nongchang/mynongchang-2.png');
background-image: url('../../static/images/nongchang/mynongchang-2.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
......
......@@ -254,7 +254,7 @@
overflow-x: hidden;
.group {
.section_2 {
background-image: url('/static/images/codefun/c122979639a1f9d27d7c57245ab420a6.png');
background-image: url('../../static/images/codefun/c122979639a1f9d27d7c57245ab420a6.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.section_3 {
......@@ -601,7 +601,7 @@
backdrop-filter: blur(4rpx);
.image-wrapper {
padding: 48rpx 0;
background-image: url('/static/images/codefun/5149f97303e2fa97daa823a1452dce11.png');
background-image: url('../../static/images/codefun/5149f97303e2fa97daa823a1452dce11.png');
background-size: 100% 100%;
background-repeat: no-repeat;
width: 240rpx;
......
......@@ -506,7 +506,7 @@ e:\Downloads\农场 (1).png
.section {
padding: 24rpx 28rpx;
background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-image: url('../../static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-size: 100% 100%;
background-repeat: no-repeat;
.group {
......
......@@ -911,7 +911,7 @@ export default {
.section {
padding: 10rpx 28rpx 220rpx;
padding-top: calc(10rpx + var(--status-bar-height));
background-image: url('/static/images/codefun/1086a098c06f7f52e77bd7a646747a13.png');
background-image: url('../../static/images/codefun/1086a098c06f7f52e77bd7a646747a13.png');
background-size: 100% 100%;
background-repeat: no-repeat;
......
......@@ -451,7 +451,7 @@ showAddDialog()
.group {
.section {
padding: 24rpx 20rpx 88rpx;
background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-image: url('../../static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-size: 100% 100%;
background-repeat: no-repeat;
......
......@@ -82,6 +82,42 @@ export const useUserStore = defineStore({
Storage.set(USER_INFO_KEY, info ? JSON.stringify(info) : null)
}
},
async login(params: { username: string; password: string }) {
if (this.loading) {
return
}
this.loading = true
try {
const body = await API.sysLogin(params)
if (body?.token) {
this.setToken(body.token)
}
const userInfo = await API.getUserInfo()
this.setUserInfo(userInfo)
return body
} finally {
this.loading = false
}
},
async phoneLogin(params: { mobile: string; captcha: string }) {
if (this.loading) {
return
}
this.loading = true
try {
const body = await API.phoneLogin(params)
if (body?.token) {
this.setToken(body.token)
}
const userInfo = await API.getUserInfo()
this.setUserInfo(userInfo)
return body
} finally {
this.loading = false
}
},
async logout() {
if (this.loading) {
return
......
......@@ -153,6 +153,7 @@ declare module 'vue' {
Mapbox: typeof import('./../src/components/Map/Mapbox/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SlideVerify: typeof import('./../src/components/slide-verify/SlideVerify.vue')['default']
Src: typeof import('./../src/components/Echarts/src/index.vue')['default']
SuccessfulDialog: typeof import('./../src/components/ConfirmDialog/successfulDialog.vue')['default']
Switch: typeof import('./../src/components/Map/Widgets/Switch/src/Switch.vue')['default']
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论