登录相关页和首页组件适配

This commit is contained in:
kron
2025-11-26 16:05:30 +08:00
parent 6830136957
commit ec48de4970
10 changed files with 239 additions and 197 deletions

View File

@@ -184,7 +184,7 @@ onMounted(async () => {
<template>
<view
class="container"
class="edit-option"
:style="{
maxHeight: expand ? '500px' : '50px',
marginTop: noArrow ? '0' : '10px',
@@ -207,14 +207,14 @@ onMounted(async () => {
}}</text>
<text v-if="!expand && itemIndex === 3">{{ formatSetAndAmount }}</text>
</block>
<button hover-class="none">
<view>
<image
v-if="!noArrow"
src="../static/arrow-grey.png"
mode="widthFix"
:style="{ transform: expand ? 'rotateX(180deg)' : 'rotateX(0deg)' }"
/>
</button>
</view>
</view>
<view v-if="itemIndex === 0" class="bow-items">
<view
@@ -342,7 +342,7 @@ onMounted(async () => {
</template>
<style scoped>
.container {
.edit-option {
width: calc(100% - 20px);
background-color: #fff;
border-radius: 10px;
@@ -352,25 +352,25 @@ onMounted(async () => {
transition: all 0.3s ease;
color: #333;
}
.container > view:first-child {
.edit-option > view:first-child {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
}
.container > view:first-child > view:first-child {
.edit-option > view:first-child > view:first-child {
width: 85px;
}
.container > view:first-child > text:nth-child(2) {
.edit-option > view:first-child > text:nth-child(2) {
font-weight: 500;
}
.container > view:first-child > button {
.edit-option > view:first-child > view {
width: 85px;
display: flex;
justify-content: flex-end;
}
.container > view:first-child > button > image {
.edit-option > view:first-child > view > image {
transition: all 0.5s ease;
width: 16px;
height: 16px;

View File

@@ -28,32 +28,27 @@ const hide = ref(true);
</script>
<template>
<view class="container" :style="{ width }">
<view class="input-row" :style="{ width }">
<input
:type="type"
@change="onChange"
:placeholder="placeholder"
placeholder-style="color: #999;"
/>
<button v-if="btnType === 'code'" hover-class="none" class="get-code">
<view v-if="btnType === 'code'" class="get-code">
get verification code
</button>
<button
v-if="type === 'password'"
hover-class="none"
class="eye-btn"
@click="hide = !hide"
>
</view>
<view v-if="type === 'password'" class="eye-btn" @click="hide = !hide">
<image
:src="`../static/${hide ? 'eye-close' : 'eye-open'}.png`"
mode="widthFix"
/>
</button>
</view>
</view>
</template>
<style scoped>
.container {
.input-row {
height: 100rpx;
display: flex;
justify-content: space-between;
@@ -72,7 +67,8 @@ const hide = ref(true);
.get-code {
color: #287fff;
font-size: 26rpx;
width: 80%;
width: 60%;
text-align: right;
}
.eye-btn {
padding: 20rpx;

View File

@@ -53,9 +53,8 @@ const onBtnClick = debounce(async () => {
</script>
<template>
<button
<view
class="sbtn"
hover-class="none"
:style="{
width: width,
borderRadius: rounded + 'rpx',
@@ -71,7 +70,7 @@ const onBtnClick = debounce(async () => {
<block v-else>
<image src="../static/btn-loading.png" mode="widthFix" class="loading" />
</block>
</button>
</view>
</template>
<style scoped>

View File

@@ -41,7 +41,7 @@ watch(
<template>
<view
class="container"
class="s-modal"
v-if="showContainer"
:style="{ opacity: show ? 1 : 0 }"
@click="onClose"
@@ -68,7 +68,7 @@ watch(
</template>
<style scoped>
.container {
.s-modal {
position: fixed;
top: 0;
left: 0;

View File

@@ -4,10 +4,10 @@
"path": "pages/index"
},
{
"path": "pages/signin"
"path": "pages/signup"
},
{
"path": "pages/signup"
"path": "pages/signin"
},
{
"path": "pages/create"
@@ -29,7 +29,11 @@
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#2c3e50",
"backgroundColor": "#ffffff",
"navigationStyle": "custom"
"navigationStyle": "custom",
"app-plus": {
"softinputMode": "adjustResize",
"softinputNavBar": "none"
}
},
"condition": {
"current": 0,

View File

@@ -4,6 +4,10 @@ import Score from "@/pages/score.vue";
import History from "@/pages/list.vue";
import Profile from "@/pages/profile.vue";
import Tabbar from "@/components/Tabbar.vue";
import SModal from "@/components/SModal.vue";
import EditOption from "@/components/EditOption.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import { removePointRecord } from "@/api";
import useStore from "@/store";
import { storeToRefs } from "pinia";
@@ -15,10 +19,50 @@ const isIOS = computed(() => {
});
const tabIndex = ref(0);
const editAvatar = ref(false);
const selectorIndex = ref(0);
const bowType = ref({});
const distance = ref(0);
const bowtargetType = ref({});
const showModal = ref(false);
const showTip = ref(false);
const removeId = ref("");
const dataSeq = ref(0);
const onTabChnage = (index) => {
tabIndex.value = index;
};
const editAvatar = ref(false);
const openSelector = (index) => {
selectorIndex.value = index;
showModal.value = true;
};
const onSelectOption = (itemIndex, value) => {
if (itemIndex === 0) {
bowType.value = value.name === bowType.value.name ? {} : value;
} else if (itemIndex === 1) {
distance.value = value === distance.value ? 0 : value;
} else if (itemIndex === 2) {
bowtargetType.value = value.name === bowtargetType.value.name ? {} : value;
}
showModal.value = false;
};
const onRemoveRecord = (item) => {
removeId.value = item.id;
showTip.value = true;
};
const confirmRemove = async () => {
try {
showTip.value = false;
await removePointRecord(removeId.value);
dataSeq.value += 1;
uni.showToast({ title: "Deleted", icon: "none" });
} catch (e) {
uni.showToast({ title: "Delete failed, please retry", icon: "none" });
}
};
</script>
<template>
@@ -35,7 +79,14 @@ const editAvatar = ref(false);
<Score />
</swiper-item>
<swiper-item>
<History />
<History
:openSelector="openSelector"
:onRemoveRecord="onRemoveRecord"
:bowType="bowType"
:distance="distance"
:bowtargetType="bowtargetType"
:seq="dataSeq"
/>
</swiper-item>
<swiper-item>
<Profile :editAvatar="() => (editAvatar = true)" />
@@ -58,6 +109,51 @@ const editAvatar = ref(false);
</view>
</view>
</view>
<SModal
:show="showModal"
:noBg="true"
height="auto"
:onClose="() => (showModal = false)"
>
<view class="selector">
<view @click="() => (showModal = false)">
<image src="../static/close-grey.png" mode="widthFix" />
</view>
<EditOption
v-show="selectorIndex === 0"
:itemIndex="0"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="bowType.name"
/>
<EditOption
v-show="selectorIndex === 1"
:itemIndex="1"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="distance + ''"
/>
<EditOption
v-show="selectorIndex === 2"
:itemIndex="2"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="bowtargetType.name"
/>
</view>
</SModal>
<ScreenHint :show="showTip">
<view class="tip-content">
<text>Are you sure to delete this record?</text>
<view>
<view @click="showTip = false">Cancel</view>
<view @click="confirmRemove">Confirm</view>
</view>
</view>
</ScreenHint>
<Tabbar :selected="tabIndex" :onClick="onTabChnage" />
</view>
</template>
@@ -108,4 +204,48 @@ const editAvatar = ref(false);
.edit-avatar > view > view > image {
width: 28rpx;
}
.selector {
padding: 10px;
background-color: #fff;
border-radius: 10px;
position: relative;
}
.selector > view {
position: absolute;
top: 0;
right: 0;
}
.selector > view > image {
width: 40px;
}
.tip-content {
width: 100%;
padding: 25px;
display: flex;
flex-direction: column;
color: #000;
}
.tip-content > text {
width: 100%;
text-align: center;
font-size: 14px;
margin-top: 5px;
}
.tip-content > view {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.tip-content > view > view {
width: 48%;
background: linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%);
border-radius: 22px;
border: 1px solid #eeeeee;
padding: 12px 0;
font-size: 14px;
color: #000;
}
.tip-content > view > view:last-child {
background: #fed847;
}
</style>

View File

@@ -1,28 +1,58 @@
<script setup>
import { ref, onMounted } from "vue";
import SModal from "@/components/SModal.vue";
import EditOption from "@/components/EditOption.vue";
import { ref, watch } from "vue";
import PointRecord from "@/components/PointRecord.vue";
import ScrollList from "@/components/ScrollList.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import { getPointBookListAPI, removePointRecord } from "@/api";
import { getPointBookListAPI } from "@/api";
const props = defineProps({
openSelector: {
type: Function,
default: () => {},
},
onRemoveRecord: {
type: Function,
default: () => {},
},
bowType: {
type: Object,
default: () => {},
},
distance: {
type: Number,
default: 0,
},
bowtargetType: {
type: Object,
default: () => {},
},
seq: {
type: Number,
default: 0,
},
});
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
const showTip = ref(false);
const bowType = ref({});
const distance = ref(0);
const bowtargetType = ref({});
const showModal = ref(false);
const selectorIndex = ref(0);
const list = ref([]);
const removeId = ref("");
const scrollListRef = ref(null);
watch(
() => [props.bowType, props.distance, props.bowtargetType, props.seq],
() => {
if (scrollListRef.value) {
scrollListRef.value.refresherrefresh();
}
},
{
deep: true,
}
);
const onListLoading = async (page) => {
const result = await getPointBookListAPI(
page,
bowType.value.id,
distance.value,
bowtargetType.value.id
props.bowType.id,
props.distance,
props.bowtargetType.id
);
if (page === 1) {
list.value = result;
@@ -31,39 +61,6 @@ const onListLoading = async (page) => {
}
return result.length;
};
const openSelector = (index) => {
selectorIndex.value = index;
showModal.value = true;
};
const onRemoveRecord = (item) => {
removeId.value = item.id;
showTip.value = true;
};
const confirmRemove = async () => {
try {
showTip.value = false;
await removePointRecord(removeId.value);
list.value = list.value.filter((it) => it.id !== removeId.value);
uni.showToast({ title: "Deleted", icon: "none" });
} catch (e) {
uni.showToast({ title: "Delete failed, please retry", icon: "none" });
}
};
const onSelectOption = (itemIndex, value) => {
if (itemIndex === 0) {
bowType.value = value.name === bowType.value.name ? {} : value;
} else if (itemIndex === 1) {
distance.value = value === distance.value ? 0 : value;
} else if (itemIndex === 2) {
bowtargetType.value = value.name === bowtargetType.value.name ? {} : value;
}
showModal.value = false;
onListLoading(1);
};
</script>
<template>
@@ -98,7 +95,7 @@ const onSelectOption = (itemIndex, value) => {
</view>
</view>
<view class="point-records">
<ScrollList :onLoading="onListLoading">
<ScrollList :onLoading="onListLoading" ref="scrollListRef">
<view v-for="(item, index) in list" :key="item.id">
<PointRecord :data="item" :onRemove="onRemoveRecord" />
<view
@@ -109,51 +106,6 @@ const onSelectOption = (itemIndex, value) => {
<view class="no-data" v-if="list.length === 0">No data</view>
</ScrollList>
</view>
<SModal
:show="showModal"
:noBg="true"
height="auto"
:onClose="() => (showModal = false)"
>
<view class="selector">
<button hover-class="none" @click="() => (showModal = false)">
<image src="../static/close-grey.png" mode="widthFix" />
</button>
<EditOption
v-show="selectorIndex === 0"
:itemIndex="0"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="bowType.name"
/>
<EditOption
v-show="selectorIndex === 1"
:itemIndex="1"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="distance + ''"
/>
<EditOption
v-show="selectorIndex === 2"
:itemIndex="2"
:expand="true"
:noArrow="true"
:onSelect="onSelectOption"
:value="bowtargetType.name"
/>
</view>
</SModal>
<ScreenHint :show="showTip">
<view class="tip-content">
<text>Are you sure to delete this record?</text>
<view>
<button hover-class="none" @click="showTip = false">Cancel</button>
<button hover-class="none" @click="confirmRemove">Confirm</button>
</view>
</view>
</ScreenHint>
</view>
</template>
@@ -201,20 +153,6 @@ const onSelectOption = (itemIndex, value) => {
width: 5vw;
margin-right: 3vw;
}
.selector {
padding: 10px;
background-color: #fff;
border-radius: 10px;
position: relative;
}
.selector > button {
position: absolute;
top: 0;
right: 0;
}
.selector > button > image {
width: 40px;
}
.point-records {
margin: 0 15px;
margin-top: 10px;
@@ -229,34 +167,4 @@ const onSelectOption = (itemIndex, value) => {
color: #999999;
font-size: 14px;
}
.tip-content {
width: 100%;
padding: 25px;
display: flex;
flex-direction: column;
color: #000;
}
.tip-content > text {
width: 100%;
text-align: center;
font-size: 14px;
margin-top: 5px;
}
.tip-content > view {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.tip-content > view > button {
width: 48%;
background: linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%);
border-radius: 22px;
border: 1px solid #eeeeee;
padding: 12px 0;
font-size: 14px;
color: #000;
}
.tip-content > view > button:last-child {
background: #fed847;
}
</style>

View File

@@ -9,8 +9,8 @@ const { user } = storeToRefs(store);
const props = defineProps({
editAvatar: {
type: String,
default: "",
type: Function,
default: () => {},
},
});

View File

@@ -25,35 +25,29 @@ const toResetPasswordPage = () => {
<InputRow type="text" placeholder="email" width="80vw" />
<InputRow type="password" placeholder="password" width="80vw" />
<view class="btn-row">
<button hover-class="none" @click="toResetPasswordPage">
Forgot Password?
</button>
<view @click="toResetPasswordPage"> Forgot Password? </view>
</view>
<SButton width="80vw">login</SButton>
<button
hover-class="none"
@click.stop="checked = !checked"
class="agreement"
>
<view @click.stop="checked = !checked" class="agreement">
<image :src="`../static/${checked ? 'checked' : 'unchecked'}.png`" />
<text>i read and accept</text>
<button hover-class="none" @click.stop="">user agreement</button>
<view @click.stop="">user agreement</view>
<text>and</text>
<button hover-class="none" @click.stop="">privacy policy</button>
</button>
<view @click.stop="">privacy policy</view>
</view>
<view class="thrid-signin">
<button hover-class="none">
<view>
<image src="../static/google-icon.png" mode="widthFix" />
<text>login with google</text>
</button>
<button hover-class="none">
</view>
<view>
<image src="../static/apple-icon.png" mode="widthFix" />
<text>login with apple</text>
</button>
</view>
</view>
<view class="to-sign-up">
<text>don't have an account? </text>
<button hover-class="none" @click.stop="toSignUpPage">sign up ></button>
<view @click.stop="toSignUpPage">sign up ></view>
</view>
</view>
</template>
@@ -71,6 +65,7 @@ const toResetPasswordPage = () => {
width: 176rpx;
height: 176rpx;
margin-top: 40rpx;
border-radius: 20rpx;
}
.app-name {
font-weight: 600;
@@ -83,7 +78,7 @@ const toResetPasswordPage = () => {
display: flex;
justify-content: flex-end;
}
.btn-row > button {
.btn-row > view {
font-size: 24rpx;
color: #287fff;
margin-bottom: 25rpx;
@@ -103,7 +98,7 @@ const toResetPasswordPage = () => {
height: 32rpx;
margin-right: 10rpx;
}
.agreement > button {
.agreement > view {
color: #333;
font-size: 24rpx;
margin: 0 10rpx;
@@ -114,7 +109,7 @@ const toResetPasswordPage = () => {
flex-direction: column;
margin: 60rpx 0;
}
.thrid-signin > button {
.thrid-signin > view {
width: 100%;
height: 88rpx;
display: flex;
@@ -126,7 +121,7 @@ const toResetPasswordPage = () => {
color: #333333;
margin: 20rpx 0;
}
.thrid-signin > button > image {
.thrid-signin > view > image {
width: 40rpx;
margin-right: 20rpx;
}
@@ -137,7 +132,7 @@ const toResetPasswordPage = () => {
justify-content: center;
align-items: center;
}
.to-sign-up > button {
.to-sign-up > view {
font-size: 24rpx;
color: #287fff;
margin-left: 20rpx;

View File

@@ -21,13 +21,13 @@ const toSignInPage = () => {
<SButton width="80vw">login</SButton>
<view class="agreement">
<text>By clicking Sign Up, you agree to our</text>
<button hover-class="none" @click.stop="">user agreement</button>
<view hover-class="none" @click.stop="">user agreement</view>
<text>and</text>
<button hover-class="none" @click.stop="">privacy policy</button>
<view hover-class="none" @click.stop="">privacy policy</view>
</view>
<view class="to-sign-up">
<text>have an account? </text>
<button hover-class="none" @click.stop="toSignInPage">sign in ></button>
<view hover-class="none" @click.stop="toSignInPage">sign in ></view>
</view>
</view>
</template>
@@ -70,7 +70,7 @@ const toSignInPage = () => {
height: 32rpx;
margin-right: 10rpx;
}
.agreement > button {
.agreement > view {
color: #333;
font-size: 24rpx;
margin: 0 10rpx;
@@ -83,7 +83,7 @@ const toSignInPage = () => {
align-items: center;
margin-top: 100rpx;
}
.to-sign-up > button {
.to-sign-up > view {
font-size: 24rpx;
color: #287fff;
margin-left: 20rpx;