feat: 更换模板
This commit is contained in:
parent
3b77a4bfa9
commit
25cf6f1c02
@ -3,11 +3,14 @@
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"DirectiveBinding": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
@ -65,6 +68,7 @@
|
||||
"onUnload": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"onWatcherCleanup": true,
|
||||
"provide": true,
|
||||
"reactive": true,
|
||||
"readonly": true,
|
||||
@ -82,20 +86,15 @@
|
||||
"useAttrs": true,
|
||||
"useCssModule": true,
|
||||
"useCssVars": true,
|
||||
"useId": true,
|
||||
"useModel": true,
|
||||
"useRequest": true,
|
||||
"useSlots": true,
|
||||
"useTemplateRef": true,
|
||||
"useUpload": true,
|
||||
"useUpload2": true,
|
||||
"watch": true,
|
||||
"watchEffect": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"DirectiveBinding": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"onWatcherCleanup": true,
|
||||
"useId": true,
|
||||
"useModel": true,
|
||||
"useTemplateRef": true
|
||||
"watchSyncEffect": true
|
||||
}
|
||||
}
|
||||
|
||||
16
env/.env
vendored
16
env/.env
vendored
@ -1,15 +1,15 @@
|
||||
VITE_APP_TITLE = 'unibest'
|
||||
VITE_APP_PORT = 9000
|
||||
VITE_APP_TITLE='星星勤务'
|
||||
VITE_APP_PORT=9000
|
||||
|
||||
VITE_UNI_APPID = 'H57F2ACE4'
|
||||
VITE_WX_APPID = 'wxa2abb91f64032a2b'
|
||||
VITE_UNI_APPID='__UNI__58536F2'
|
||||
VITE_WX_APPID='wxa2abb91f64032a2b'
|
||||
|
||||
# h5部署网站的base,配置到 manifest.config.ts 里的 h5.router.base
|
||||
VITE_APP_PUBLIC_BASE=/unibest/
|
||||
VITE_APP_PUBLIC_BASE=/
|
||||
|
||||
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload'
|
||||
VITE_SERVER_BASEURL='https://ukw0y1.laf.run'
|
||||
VITE_UPLOAD_BASEURL='https://ukw0y1.laf.run/upload'
|
||||
|
||||
# h5是否需要配置代理
|
||||
VITE_APP_PROXY=false
|
||||
VITE_APP_PROXY_PREFIX = '/api'
|
||||
VITE_APP_PROXY_PREFIX='/api'
|
||||
|
||||
6
env/.env.development
vendored
6
env/.env.development
vendored
@ -1,6 +1,6 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV = 'development'
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE = false
|
||||
VITE_DELETE_CONSOLE=false
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP = true
|
||||
VITE_SHOW_SOURCEMAP=true
|
||||
|
||||
6
env/.env.production
vendored
6
env/.env.production
vendored
@ -1,6 +1,6 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV = 'development'
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE = true
|
||||
VITE_DELETE_CONSOLE=true
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP = false
|
||||
VITE_SHOW_SOURCEMAP=false
|
||||
|
||||
4
env/.env.test
vendored
4
env/.env.test
vendored
@ -1,4 +1,4 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV = 'development'
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE = false
|
||||
VITE_DELETE_CONSOLE=false
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
"pinia-plugin-persistedstate": "3.2.1",
|
||||
"qs": "6.5.3",
|
||||
"vue": "3.4.21",
|
||||
"wot-design-uni": "^1.4.0",
|
||||
"wot-design-uni": "1.4.0",
|
||||
"z-paging": "^2.8.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -72,8 +72,8 @@ importers:
|
||||
specifier: 3.4.21
|
||||
version: 3.4.21(typescript@5.7.2)
|
||||
wot-design-uni:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0(vue@3.4.21(typescript@5.7.2))
|
||||
specifier: 1.5.1
|
||||
version: 1.5.1(vue@3.4.21(typescript@5.7.2))
|
||||
z-paging:
|
||||
specifier: ^2.8.4
|
||||
version: 2.8.4
|
||||
@ -5456,8 +5456,8 @@ packages:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
wot-design-uni@1.4.0:
|
||||
resolution: {integrity: sha512-h6sjrgfg7mP0nJwGTiHn/iTLPFyRswMpQV6MKhWN3skTnXe+FAyndvtXofpXp+uLkTXefGfw5BPI0uuCMD874w==}
|
||||
wot-design-uni@1.5.1:
|
||||
resolution: {integrity: sha512-jiDRuF8r7+xAldc4Dp+2T1VnqDnOoMWsXu6aRpDg2QG7ZH+/bJl7W8H8hHbKFgA9lu1By/HCDmpG7JC45nYtBw==}
|
||||
engines: {HBuilderX: ^3.8.7}
|
||||
peerDependencies:
|
||||
vue: '>=3.2.47'
|
||||
@ -12236,7 +12236,7 @@ snapshots:
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
wot-design-uni@1.4.0(vue@3.4.21(typescript@5.7.2)):
|
||||
wot-design-uni@1.5.1(vue@3.4.21(typescript@5.7.2)):
|
||||
dependencies:
|
||||
vue: 3.4.21(typescript@5.7.2)
|
||||
|
||||
|
||||
25
src/App.vue
25
src/App.vue
@ -30,29 +30,4 @@
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
// 单行省略,优先使用 unocss: text-ellipsis
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// 两行省略
|
||||
.ellipsis-2 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
// 三行省略
|
||||
.ellipsis-3 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
</style>
|
||||
|
||||
73
src/components/CustomTabBar/CustomTabBar.vue
Normal file
73
src/components/CustomTabBar/CustomTabBar.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<view>
|
||||
<wd-tabbar
|
||||
v-model="index"
|
||||
fixed
|
||||
safeAreaInsetBottom
|
||||
active-color="#255cf7"
|
||||
inactive-color="#0d0f10"
|
||||
placeholder
|
||||
@change="change"
|
||||
>
|
||||
<wd-tabbar-item
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:is-dot="item.isDot || false"
|
||||
:title="item.title"
|
||||
:value="item.value || 0"
|
||||
:icon="item.icon"
|
||||
></wd-tabbar-item>
|
||||
</wd-tabbar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const index = ref<number>(0)
|
||||
|
||||
defineOptions({
|
||||
options: {
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
defaultIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
list: {
|
||||
type: Array<TabBarItem>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['change'])
|
||||
|
||||
onMounted(() => {
|
||||
index.value = props.defaultIndex
|
||||
})
|
||||
|
||||
const change = (index: number) => {
|
||||
emits('change', index)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.wd-icon) {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
:deep(.wd-tabbar-item__body-title) {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
:deep(.wd-badge__content) {
|
||||
top: 5px !important;
|
||||
}
|
||||
|
||||
:deep(.wd-tabbar) {
|
||||
background: #f4f5fa;
|
||||
}
|
||||
</style>
|
||||
95
src/components/Modal/Modal.vue
Normal file
95
src/components/Modal/Modal.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<view>
|
||||
<wd-popup v-model="show" custom-style="border-radius:24rpx;" :close-on-click-modal="false">
|
||||
<view class="w-75">
|
||||
<view v-if="title" class="font-bold text-4 text-center pt-4">{{ title }}</view>
|
||||
<view class="text-3.5 w-60 pl-7.5 py-4 custom-color-black">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<view class="break-all" v-else>{{ content }}</view>
|
||||
</view>
|
||||
<view class="flex flex-items-center text-center border-[#ebebeb] border-t-1 border-t-solid">
|
||||
<view
|
||||
v-if="showCancel"
|
||||
class="w-1/2 py-3 text-4 font-bold border-r-1 border-r-solid border-[#ebebeb]"
|
||||
:style="{ color: cancelColor }"
|
||||
@click="cancel"
|
||||
>
|
||||
{{ cancelText }}
|
||||
</view>
|
||||
<view
|
||||
class="w-1/2 py-3 text-4 font-bold"
|
||||
:class="[showCancel ? 'w-1/2' : 'w-full']"
|
||||
:style="{ color: confirmColor }"
|
||||
@click="confirm"
|
||||
>
|
||||
{{ confirmText }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const show = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确定'
|
||||
},
|
||||
showCancel: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#0d0f10'
|
||||
},
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#255cf7'
|
||||
},
|
||||
controlModal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const showModal = () => {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
const hideModal = () => {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
const emits = defineEmits(['cancel', 'confirm'])
|
||||
|
||||
const cancel = async () => {
|
||||
emits('cancel')
|
||||
show.value = props.controlModal
|
||||
}
|
||||
|
||||
const confirm = async () => {
|
||||
emits('confirm')
|
||||
show.value = props.controlModal
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
hideModal
|
||||
})
|
||||
</script>
|
||||
75
src/components/TopNavigation/TopNavigation.vue
Normal file
75
src/components/TopNavigation/TopNavigation.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="systemInfo" :style="{ marginTop: systemInfo.safeAreaInsets?.top + 'px' }">
|
||||
<view
|
||||
v-if="mini"
|
||||
class="h-12 pt-1 pos-relative flex flex-justify-between flex-items-center text-4 font-bold custom-color-black"
|
||||
>
|
||||
<view class="ml-4 line-clamp-1 max-w-60 break-all">
|
||||
{{ title }}
|
||||
</view>
|
||||
<view class="mr-3 border-1 border-solid border-[#ebebeb] w-25 h-7 rounded-4">
|
||||
<view class="flex flex-items-center flex-justify-around px-2 h-7">
|
||||
<image class="w-6 h-6" src="/static/images/icon_nav_more.png"></image>
|
||||
<view class="h-4 w-0.25 bg-[#ebebeb]"></view>
|
||||
<image class="w-6 h-6" src="/static/images/icon_nav_close.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-else
|
||||
class="h-12 pt-1 pos-relative flex flex-justify-center flex-items-center text-4 font-bold custom-color-black"
|
||||
>
|
||||
<image
|
||||
v-if="haveBack"
|
||||
:src="backUrl"
|
||||
class="pos-absolute left-3 h-5 w-5"
|
||||
@click="back"
|
||||
></image>
|
||||
<view class="flex flex-items-center">
|
||||
<view class="line-clamp-1 max-w-60 break-all">
|
||||
{{ title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useBasicStore } from '@/store'
|
||||
|
||||
const $basic = useBasicStore()
|
||||
|
||||
const systemInfo = ref(null)
|
||||
|
||||
defineProps({
|
||||
mini: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
haveBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
backUrl: {
|
||||
type: String,
|
||||
default: '/static/images/icon_back.png'
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['back'])
|
||||
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
emits('back')
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
systemInfo.value = await $basic.getSystemInfo()
|
||||
})
|
||||
</script>
|
||||
3
src/constants/regular-expressions.js
Normal file
3
src/constants/regular-expressions.js
Normal file
@ -0,0 +1,3 @@
|
||||
export const phoneRegExp = /^1[3-9]\d{9}$/
|
||||
|
||||
export const passwordRegExp = /^(?![0-9]+$)(?![a-zA-Z]+$)(?![^0-9a-zA-Z]+$).{8,20}$/
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "unibest",
|
||||
"appid": "H57F2ACE4",
|
||||
"name": "星星勤务",
|
||||
"appid": "__UNI__58536F2",
|
||||
"description": "",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": "100",
|
||||
@ -105,7 +105,7 @@
|
||||
"vueVersion": "3",
|
||||
"h5": {
|
||||
"router": {
|
||||
"base": "/unibest/"
|
||||
"base": "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,7 @@
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"path": "pages/home/home",
|
||||
"type": "home",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
@ -59,12 +59,53 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/about/about",
|
||||
"path": "pages/code/code",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "关于"
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/get-code/get-code",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/CustomTab",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/mine",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "pages/notification/notification",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "pages/reset-password/reset-password",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/workbench/workbench",
|
||||
"type": "page"
|
||||
}
|
||||
],
|
||||
"subPackages": []
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '关于'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view
|
||||
class="bg-white overflow-hidden pt-2 px-4"
|
||||
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
|
||||
>
|
||||
<view class="text-center text-3xl mt-8">
|
||||
鸽友们好,我是
|
||||
<text class="text-red-500">菲鸽</text>
|
||||
</view>
|
||||
<RequestComp />
|
||||
<UploadComp />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import RequestComp from './components/request.vue'
|
||||
import UploadComp from './components/upload.vue'
|
||||
|
||||
// 获取屏幕边界到安全区域距离
|
||||
const { safeAreaInsets } = uni.getSystemInfoSync()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.test-css {
|
||||
// mt-4=>1rem=>16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
@ -1,56 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'demo',
|
||||
style: {
|
||||
navigationBarTitleText: '请求'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="p-6 text-center">
|
||||
<view class="my-2">使用的是 laf 云后台</view>
|
||||
<view class="text-green-400">我的推荐码,可以获得佣金</view>
|
||||
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="my-2">
|
||||
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- http://localhost:9000/#/pages/index/request -->
|
||||
<wd-button @click="run" class="my-6">发送请求</wd-button>
|
||||
<view class="h-12">
|
||||
<view v-if="loading">loading...</view>
|
||||
<block v-else>
|
||||
<view class="text-xl">请求数据如下</view>
|
||||
<view class="text-green leading-8">{{ JSON.stringify(data) }}</view>
|
||||
</block>
|
||||
</view>
|
||||
<wd-button type="error" @click="reset" class="my-6" :disabled="!data">重置数据</wd-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
|
||||
|
||||
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
|
||||
|
||||
// const initialData = {
|
||||
// name: 'initialData',
|
||||
// id: '1234',
|
||||
// }
|
||||
const initialData = undefined
|
||||
// 适合少部分全局性的接口————多个页面都需要的请求接口,额外编写一个 Service 层
|
||||
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'), {
|
||||
immediate: true,
|
||||
initialData
|
||||
})
|
||||
const reset = () => {
|
||||
data.value = initialData
|
||||
}
|
||||
</script>
|
||||
@ -1,30 +0,0 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '上传-状态一体化'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="p-4 text-center">
|
||||
<wd-button @click="run">选择图片并上传</wd-button>
|
||||
<view v-if="loading" class="text-blue h-10">上传...</view>
|
||||
<template v-else>
|
||||
<view class="m-2">上传后返回的接口数据:</view>
|
||||
<view class="m-2">{{ data }}</view>
|
||||
<view class="h-80 w-full">
|
||||
<image v-if="data" :src="data || data" mode="scaleToFill" />
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const { loading, data, run } = useUpload({ user: '菲鸽' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
</style>
|
||||
100
src/pages/code/code.vue
Normal file
100
src/pages/code/code.vue
Normal file
@ -0,0 +1,100 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: true
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view>
|
||||
<TopNavigation></TopNavigation>
|
||||
<view class="text-6 ml-4 pt-7 custom-color-black font-bold">请输入验证码</view>
|
||||
<view class="text-3.5 ml-4 mt-2 mb-4 custom-color-grey">
|
||||
<view>已发送验证码至{{ maskedPhone }}</view>
|
||||
<view v-if="countDown > 0">
|
||||
如未收到请
|
||||
<text class="text-red">{{ countDown }}s</text>
|
||||
后重新获取
|
||||
</view>
|
||||
<view v-else class="custom-color-blue" @click="reset">重新获取</view>
|
||||
</view>
|
||||
<view class="pt-8">
|
||||
<wd-password-input
|
||||
v-model="code"
|
||||
:gutter="10"
|
||||
:mask="false"
|
||||
:focused="showKeyboard"
|
||||
@focus="showKeyboard = true"
|
||||
/>
|
||||
<wd-number-keyboard
|
||||
v-model="code"
|
||||
v-model:visible="showKeyboard"
|
||||
:maxlength="6"
|
||||
@blur="showKeyboard = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const phone = ref<string>('')
|
||||
|
||||
const code = ref<string>('')
|
||||
|
||||
const countDown = ref<number>(60)
|
||||
|
||||
const showKeyboard = ref<boolean>(true)
|
||||
|
||||
const type = ref<string>('')
|
||||
|
||||
onLoad(async options => {
|
||||
phone.value = options.phone
|
||||
type.value = options.type
|
||||
|
||||
countDownStart()
|
||||
})
|
||||
|
||||
watch(code, newVal => {
|
||||
if (newVal.length === 6) {
|
||||
// 校验验证码
|
||||
if (type.value === 'login') {
|
||||
console.log('login')
|
||||
} else if (type.value === 'reset-password') {
|
||||
uni.navigateTo({
|
||||
url: `/pages/reset-password/reset-password`
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const reset = () => {
|
||||
countDownStart()
|
||||
}
|
||||
|
||||
const maskedPhone = computed(() => {
|
||||
if (phone.value.length === 11) {
|
||||
return phone.value.slice(0, 3) + '****' + phone.value.slice(7)
|
||||
}
|
||||
return phone.value
|
||||
})
|
||||
|
||||
const countDownStart = () => {
|
||||
countDown.value = 60
|
||||
const timestamp = new Date().getTime()
|
||||
const timer = setInterval(() => {
|
||||
if (countDown.value > 0) {
|
||||
countDown.value = 60 - Math.floor((new Date().getTime() - timestamp) / 1000)
|
||||
} else {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.wd-password-input__item) {
|
||||
border: #b8b8b8 solid 2rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
</style>
|
||||
59
src/pages/get-code/get-code.vue
Normal file
59
src/pages/get-code/get-code.vue
Normal file
@ -0,0 +1,59 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: true
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view>
|
||||
<TopNavigation></TopNavigation>
|
||||
<view class="text-6 ml-4 pt-7 custom-color-black font-bold">请输入手机号</view>
|
||||
<view class="p-5">
|
||||
<wd-input
|
||||
v-model="phone"
|
||||
:maxlength="11"
|
||||
clearable
|
||||
placeholder="请输入手机号码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
size="large"
|
||||
type="number"
|
||||
@change="phoneChange"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-5">
|
||||
<wd-button :block="true" :disabled="!phonePass" :round="false" size="large" @click="codeLogin">
|
||||
获取验证码
|
||||
</wd-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { phoneRegExp } from '@/constants/regular-expressions'
|
||||
|
||||
const phone = ref<string>('')
|
||||
const phonePass = computed(() => phoneRegExp.test(phone.value))
|
||||
|
||||
onLoad(options => {
|
||||
if (options.phone) {
|
||||
phone.value = options.phone
|
||||
}
|
||||
})
|
||||
|
||||
const codeLogin = () => {
|
||||
if (!phonePass.value) {
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/code/code?phone=${phone.value}&type=reset-password`
|
||||
})
|
||||
}
|
||||
|
||||
const phoneChange = (value: string) => {
|
||||
phone.value = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
44
src/pages/home/CustomTab.vue
Normal file
44
src/pages/home/CustomTab.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<view class="m-2 p-2 bg-white rounded-2">
|
||||
<wd-tabs v-model="tab" auto-line-width swipeable animated>
|
||||
<wd-tab v-for="(item, index) in list" :key="index" :title="item.title" :name="index">
|
||||
<view class="flex flex-wrap">
|
||||
<view
|
||||
v-for="subItem in item.list"
|
||||
:key="subItem.id"
|
||||
class="text-center my-2 w-21.4375"
|
||||
@click="clickItem(subItem)"
|
||||
>
|
||||
<image :src="subItem.icon" class="w-7 h-7 m-a"></image>
|
||||
<view class="text-3 mt-2">{{ subItem.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-tab>
|
||||
</wd-tabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const tab = ref<number>(0)
|
||||
|
||||
const props = defineProps({
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
list: {
|
||||
type: Array<HomeTab>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['clickItem'])
|
||||
|
||||
onMounted(() => {
|
||||
tab.value = props.index
|
||||
})
|
||||
|
||||
const clickItem = (item: HomeTabItem) => {
|
||||
emits('clickItem', item)
|
||||
}
|
||||
</script>
|
||||
254
src/pages/home/home.vue
Normal file
254
src/pages/home/home.vue
Normal file
@ -0,0 +1,254 @@
|
||||
<route lang="json5" type="home">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '首页'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view class="custom-bg-default">
|
||||
<TopNavigation :title="appName"></TopNavigation>
|
||||
<TopNavigation mini :title="appName"></TopNavigation>
|
||||
<button class="mt-12" @click="toLogin">去登录</button>
|
||||
<CustomTab class="mt-10" :list="featuresList" :index="2" @clickItem="clickItem"></CustomTab>
|
||||
<view class="pt-10">
|
||||
<CustomTabBar :list="list" :default-index="1" @change="change"></CustomTabBar>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store'
|
||||
import CustomTab from '@/pages/home/CustomTab.vue'
|
||||
|
||||
const $user = useUserStore()
|
||||
|
||||
const appName = import.meta.env.VITE_APP_TITLE
|
||||
|
||||
const list = ref<Array<TabBarItem>>([
|
||||
{
|
||||
title: '首页',
|
||||
isDot: true,
|
||||
icon: 'home'
|
||||
},
|
||||
{
|
||||
title: '我的',
|
||||
value: 0,
|
||||
icon: '/static/tabbar/home.png'
|
||||
},
|
||||
{
|
||||
title: '最大值',
|
||||
value: 200,
|
||||
icon: '/static/tabbar/home.png'
|
||||
},
|
||||
{
|
||||
title: '客服',
|
||||
value: 3,
|
||||
icon: '/static/tabbar/home.png'
|
||||
}
|
||||
])
|
||||
|
||||
const featuresList = ref<Array<HomeTab>>([
|
||||
{
|
||||
title: '视频',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '视频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '视频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '视频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '视频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '视频中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '音频',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '音频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '音频中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '音频中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '图文',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '图文中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '图文中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '图文中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '直播',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '直播中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '直播中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '直播中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '其他',
|
||||
list: [
|
||||
{
|
||||
id: 0,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '其他中心',
|
||||
icon: '/static/logo.png'
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
// 测试 uni API 自动引入
|
||||
onLoad(() => {
|
||||
$user.setUserInfo({ nickname: '1', avatar: '1', token: '1' })
|
||||
|
||||
console.log($user.userInfo.nickname)
|
||||
})
|
||||
|
||||
const change = data => {
|
||||
console.log(data.value)
|
||||
if (data.value === 3) {
|
||||
list.value[data.value].value = 0
|
||||
}
|
||||
}
|
||||
|
||||
const toLogin = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
|
||||
const clickItem = item => {
|
||||
console.log(item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background: #f3f5fa;
|
||||
}
|
||||
</style>
|
||||
@ -1,56 +0,0 @@
|
||||
<!-- 使用 type="home" 属性设置首页,其他页面不需要设置,默认为page;推荐使用json5,更强大,且允许注释 -->
|
||||
<route lang="json5" type="home">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '首页'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view
|
||||
class="bg-white overflow-hidden pt-2 px-4"
|
||||
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
|
||||
>
|
||||
<view class="mt-12">
|
||||
<image src="/static/logo.svg" alt="" class="w-28 h-28 block mx-auto" />
|
||||
</view>
|
||||
<view class="text-center text-4xl main-title-color mt-4">unibest</view>
|
||||
<view class="text-center text-2xl mt-2 mb-8">最好用的 uniapp 开发模板</view>
|
||||
|
||||
<view class="text-justify max-w-100 m-auto text-4 indent mb-2">{{ description }}</view>
|
||||
<view class="text-center mt-8">
|
||||
当前平台是:
|
||||
<text class="text-green-500">{{ PLATFORM.platform }}</text>
|
||||
</view>
|
||||
<view class="text-center mt-4">
|
||||
模板分支是:
|
||||
<text class="text-green-500">base</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import PLATFORM from '@/utils/platform'
|
||||
|
||||
defineOptions({
|
||||
name: 'Home'
|
||||
})
|
||||
|
||||
// 获取屏幕边界到安全区域距离
|
||||
const { safeAreaInsets } = uni.getSystemInfoSync()
|
||||
const author = ref('菲鸽')
|
||||
const description = ref(
|
||||
'unibest 是一个集成了多种工具和技术的 uniapp 开发模板,由 uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode 构建,模板具有代码提示、自动格式化、统一配置、代码片段等功能,并内置了许多常用的基本组件和基本功能,让你编写 uniapp 拥有 best 体验。'
|
||||
)
|
||||
// 测试 uni API 自动引入
|
||||
onLoad(() => {
|
||||
console.log(author)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.main-title-color {
|
||||
color: #d14328;
|
||||
}
|
||||
</style>
|
||||
242
src/pages/login/login.vue
Normal file
242
src/pages/login/login.vue
Normal file
@ -0,0 +1,242 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: true
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view class="bg-white">
|
||||
<TopNavigation v-if="systemInfo && systemInfo?.uniPlatform === 'app'"></TopNavigation>
|
||||
<swiper
|
||||
v-if="systemInfo"
|
||||
:circular="true"
|
||||
:current="index"
|
||||
:disable-touch="true"
|
||||
:style="{
|
||||
height: 'calc(100vh - ' + (systemInfo.safeAreaInsets?.top + 48) + 'px)'
|
||||
}"
|
||||
>
|
||||
<swiper-item v-for="item in 4" :key="item">
|
||||
<view
|
||||
:class="[systemInfo && systemInfo?.uniPlatform === 'app' ? 'pt-5' : 'pt-20']"
|
||||
class="pos-relative"
|
||||
>
|
||||
<view class="text-6 ml-4 mt-2 custom-color-black font-bold">欢迎使用{{ appName }}</view>
|
||||
<view class="text-3 ml-4 mt-2 mb-4 custom-color-grey">
|
||||
未注册手机号验证号将创建{{ appName }}通行证
|
||||
</view>
|
||||
<view class="p-5">
|
||||
<wd-input
|
||||
v-model="phone"
|
||||
:maxlength="11"
|
||||
clearable
|
||||
placeholder="请输入手机号码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
size="large"
|
||||
type="number"
|
||||
@change="phoneChange"
|
||||
/>
|
||||
<wd-input
|
||||
v-if="index % 2 === 1"
|
||||
v-model="password"
|
||||
:maxlength="20"
|
||||
class="mt-6"
|
||||
clearable
|
||||
placeholder="请输入密码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
show-password
|
||||
size="large"
|
||||
@change="passwordChange"
|
||||
/>
|
||||
</view>
|
||||
<view v-if="index % 2 === 0" class="p-5">
|
||||
<wd-button
|
||||
:block="true"
|
||||
:disabled="!phonePass"
|
||||
:round="false"
|
||||
size="large"
|
||||
@click="codeLogin"
|
||||
>
|
||||
获取验证码
|
||||
</wd-button>
|
||||
</view>
|
||||
<view v-else class="p-5">
|
||||
<wd-button
|
||||
@click="passwordLogin"
|
||||
:block="true"
|
||||
:disabled="!(passwordPass && phonePass)"
|
||||
size="large"
|
||||
:round="false"
|
||||
>
|
||||
登录
|
||||
</wd-button>
|
||||
</view>
|
||||
<view
|
||||
class="pt-2 pb-1 pl-5 pr-5 flex flex-items-center flex-justify-center custom-color-grey"
|
||||
>
|
||||
<view v-if="index % 2 === 0" @click="index = index + 1">密码登录</view>
|
||||
<view v-if="index % 2 === 1" @click="index === 3 ? (index = 0) : (index = index + 1)">
|
||||
验证码登录
|
||||
</view>
|
||||
<view v-if="index % 2 === 1" class="mx-4">|</view>
|
||||
<view v-if="index % 2 === 1" @click="resetPassword">忘记密码</view>
|
||||
</view>
|
||||
<view class="pos-fixed bottom-1 pb-safe">
|
||||
<view v-if="systemInfo" class="text-center text-3">
|
||||
<view>{{ systemInfo?.uniPlatform === 'app' ? '第三方登录方式' : '扫码登录' }}</view>
|
||||
<image
|
||||
v-if="systemInfo?.uniPlatform === 'app'"
|
||||
class="h-10 w-10 mt-2"
|
||||
mode="aspectFit"
|
||||
src="/static/images/icon_wechat.png"
|
||||
></image>
|
||||
<image
|
||||
v-if="systemInfo?.uniPlatform !== 'app'"
|
||||
class="h-10 w-10 mt-2"
|
||||
mode="aspectFit"
|
||||
src="/static/images/icon_scan_code.png"
|
||||
></image>
|
||||
</view>
|
||||
<view class="flex p-5">
|
||||
<view class="pt-0.8">
|
||||
<wd-checkbox
|
||||
:modelValue="consentAgreement"
|
||||
class="flex-shrink-0"
|
||||
shape="circle"
|
||||
size="larger"
|
||||
@click="changeConsentAgreement"
|
||||
></wd-checkbox>
|
||||
</view>
|
||||
<view class="ml-1.5 text-3">
|
||||
<text>
|
||||
登录后即同意
|
||||
<text class="custom-color-blue">《天翼账号认证服务条款》</text>
|
||||
和
|
||||
<text class="custom-color-blue">《{{ appName }}登录政策》</text>
|
||||
、
|
||||
<text class="custom-color-blue">《{{ appName }}服务协议》</text>
|
||||
、
|
||||
<text class="custom-color-blue">《{{ appName }}隐私政策》</text>
|
||||
并授权{{ appName }}获取本机号码及{{ appName }}通行证账号信息进行统一管理
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<Modal
|
||||
ref="agreementModal"
|
||||
:title="`欢迎使用${appName}`"
|
||||
confirm-text="同意并继续"
|
||||
@confirm="confirm"
|
||||
>
|
||||
<text>
|
||||
登录后即同意
|
||||
<text class="custom-color-blue">《天翼账号认证服务条款》</text>
|
||||
和
|
||||
<text class="custom-color-blue">《{{ appName }}登录政策》</text>
|
||||
、
|
||||
<text class="custom-color-blue">《{{ appName }}服务协议》</text>
|
||||
、
|
||||
<text class="custom-color-blue">《{{ appName }}隐私政策》</text>
|
||||
</text>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useBasicStore } from '@/store'
|
||||
import { passwordRegExp, phoneRegExp } from '@/constants/regular-expressions'
|
||||
|
||||
const $basic = useBasicStore()
|
||||
|
||||
const appName = import.meta.env.VITE_APP_TITLE
|
||||
|
||||
const phone = ref<string>('')
|
||||
const password = ref<string>('')
|
||||
|
||||
const consentAgreement = ref<boolean>(false)
|
||||
|
||||
const index = ref<number>(0)
|
||||
|
||||
const systemInfo = ref<GetSystemInfoResult>(null)
|
||||
|
||||
const phonePass = computed(() => phoneRegExp.test(phone.value))
|
||||
|
||||
const passwordPass = computed(() => passwordRegExp.test(password.value))
|
||||
|
||||
const agreementModal = ref(null)
|
||||
|
||||
const type = ref('code')
|
||||
|
||||
onMounted(async () => {
|
||||
systemInfo.value = await $basic.getSystemInfo()
|
||||
})
|
||||
|
||||
const passwordLogin = () => {
|
||||
if (!phonePass.value || !passwordPass.value) {
|
||||
return
|
||||
}
|
||||
if (!consentAgreement.value) {
|
||||
type.value = 'password'
|
||||
agreementModal.value.showModal()
|
||||
return
|
||||
}
|
||||
console.log('登录')
|
||||
}
|
||||
|
||||
const codeLogin = () => {
|
||||
if (!phonePass.value) {
|
||||
return
|
||||
}
|
||||
if (!consentAgreement.value) {
|
||||
type.value = 'code'
|
||||
agreementModal.value.showModal()
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/code/code?phone=${phone.value}&type=login`
|
||||
})
|
||||
}
|
||||
|
||||
const resetPassword = () => {
|
||||
if (!consentAgreement.value) {
|
||||
type.value = 'reset'
|
||||
agreementModal.value.showModal()
|
||||
return
|
||||
}
|
||||
let params = ''
|
||||
if (phonePass.value) {
|
||||
params = `?phone=${phone.value}`
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/get-code/get-code${params}`
|
||||
})
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
consentAgreement.value = true
|
||||
if (type.value === 'code') {
|
||||
codeLogin()
|
||||
} else if (type.value === 'password') {
|
||||
passwordLogin()
|
||||
} else if (type.value === 'reset') {
|
||||
resetPassword()
|
||||
}
|
||||
}
|
||||
|
||||
const phoneChange = (value: string) => {
|
||||
phone.value = value
|
||||
}
|
||||
|
||||
const passwordChange = (value: string) => {
|
||||
password.value = value
|
||||
}
|
||||
|
||||
const changeConsentAgreement = () => {
|
||||
consentAgreement.value = !consentAgreement.value
|
||||
}
|
||||
</script>
|
||||
7
src/pages/mine/mine.vue
Normal file
7
src/pages/mine/mine.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
7
src/pages/notification/notification.vue
Normal file
7
src/pages/notification/notification.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
74
src/pages/reset-password/reset-password.vue
Normal file
74
src/pages/reset-password/reset-password.vue
Normal file
@ -0,0 +1,74 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: true
|
||||
}
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view>
|
||||
<TopNavigation></TopNavigation>
|
||||
<view class="text-6 ml-4 pt-7 custom-color-black font-bold">请输入手机号</view>
|
||||
<view class="p-5">
|
||||
<wd-input
|
||||
v-model="password"
|
||||
:maxlength="20"
|
||||
class="mt-6"
|
||||
clearable
|
||||
placeholder="请输入新密码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
show-password
|
||||
size="large"
|
||||
@change="passwordChange"
|
||||
/>
|
||||
<wd-input
|
||||
v-model="confirmPassword"
|
||||
:maxlength="20"
|
||||
class="mt-6"
|
||||
clearable
|
||||
placeholder="再次输入新密码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
show-password
|
||||
size="large"
|
||||
@change="confirmPasswordChange"
|
||||
/>
|
||||
</view>
|
||||
<view class="bg-[#eeeff4] p-2 mx-5 rounded-2">
|
||||
<view class="p-2">
|
||||
<view class="text-3 color-[#525458]">密码为8-20位,至少含数字/字母/字符中的2种</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-5">
|
||||
<wd-button
|
||||
:block="true"
|
||||
:disabled="!(passwordPass && confirmPasswordPass && password === confirmPassword)"
|
||||
:round="false"
|
||||
size="large"
|
||||
@click="codeLogin"
|
||||
>
|
||||
提交
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { passwordRegExp } from '@/constants/regular-expressions'
|
||||
|
||||
const password = ref<string>('')
|
||||
const confirmPassword = ref<string>('')
|
||||
|
||||
const passwordPass = computed(() => passwordRegExp.test(password.value))
|
||||
const confirmPasswordPass = computed(() => password.value === confirmPassword.value)
|
||||
|
||||
const passwordChange = (value: string) => {
|
||||
password.value = value
|
||||
}
|
||||
|
||||
const confirmPasswordChange = (value: string) => {
|
||||
confirmPassword.value = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
7
src/pages/workbench/workbench.vue
Normal file
7
src/pages/workbench/workbench.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
BIN
src/static/images/icon_back.png
Normal file
BIN
src/static/images/icon_back.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
BIN
src/static/images/icon_nav_close.png
Normal file
BIN
src/static/images/icon_nav_close.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/static/images/icon_nav_more.png
Normal file
BIN
src/static/images/icon_nav_more.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/static/images/icon_scan_code.png
Normal file
BIN
src/static/images/icon_scan_code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/static/images/icon_wechat.png
Normal file
BIN
src/static/images/icon_wechat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/static/logo.png
Normal file
BIN
src/static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
22
src/store/basic.ts
Normal file
22
src/store/basic.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import GetSystemInfoResult = UniNamespace.GetSystemInfoResult
|
||||
|
||||
export const useBasicStore = defineStore('basic', () => {
|
||||
// 系统信息
|
||||
let systemInfo: GetSystemInfoResult = uni.getSystemInfoSync()
|
||||
// 获取系统信息
|
||||
const getSystemInfo = (): Promise<GetSystemInfoResult> => {
|
||||
return new Promise(resolve => {
|
||||
if (systemInfo.uniPlatform) {
|
||||
resolve(systemInfo)
|
||||
} else {
|
||||
systemInfo = uni.getSystemInfoSync()
|
||||
resolve(systemInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
getSystemInfo
|
||||
}
|
||||
})
|
||||
@ -15,3 +15,4 @@ export default store
|
||||
|
||||
// 模块统一导出
|
||||
export * from './user'
|
||||
export * from './basic'
|
||||
|
||||
2
src/types/auto-import.d.ts
vendored
2
src/types/auto-import.d.ts
vendored
@ -79,12 +79,10 @@ declare global {
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useNavbarWeixin: (typeof import('../hooks/useNavbarWeixin'))['default']
|
||||
const useRequest: typeof import('../hooks/useRequest')['default']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const useUpload: typeof import('../hooks/useUpload')['default']
|
||||
const useUpload2: typeof import('../hooks/useUpload2')['default']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
|
||||
11
src/types/uni-pages.d.ts
vendored
11
src/types/uni-pages.d.ts
vendored
@ -4,8 +4,15 @@
|
||||
// Generated by vite-plugin-uni-pages
|
||||
|
||||
interface NavigateToOptions {
|
||||
url: "/pages/index/index" |
|
||||
"/pages/about/about";
|
||||
url: "/pages/home/home" |
|
||||
"/pages/code/code" |
|
||||
"/pages/get-code/get-code" |
|
||||
"/pages/home/CustomTab" |
|
||||
"/pages/login/login" |
|
||||
"/pages/mine/mine" |
|
||||
"/pages/notification/notification" |
|
||||
"/pages/reset-password/reset-password" |
|
||||
"/pages/workbench/workbench";
|
||||
}
|
||||
interface RedirectToOptions extends NavigateToOptions {}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// 全局要用的类型放到这里
|
||||
|
||||
type IResData<T> = {
|
||||
code: number
|
||||
msg: string
|
||||
errorCode: number
|
||||
errorMsg: string
|
||||
data: T
|
||||
}
|
||||
|
||||
@ -18,12 +18,24 @@ type IUniUploadFileOptions = {
|
||||
type IUserInfo = {
|
||||
nickname?: string
|
||||
avatar?: string
|
||||
/** 微信的 openid,非微信没有这个字段 */
|
||||
openid?: string
|
||||
token?: string
|
||||
}
|
||||
|
||||
enum TestEnum {
|
||||
A = 'a',
|
||||
B = 'b'
|
||||
type TabBarItem = {
|
||||
icon: string
|
||||
title: string
|
||||
isDot?: boolean
|
||||
value?: number
|
||||
}
|
||||
|
||||
type HomeTabItem = {
|
||||
icon: string
|
||||
title: string
|
||||
id: number
|
||||
}
|
||||
|
||||
type HomeTab = {
|
||||
title: string
|
||||
list: HomeTabItem[]
|
||||
}
|
||||
|
||||
@ -13,20 +13,20 @@ export const http = <T>(options: CustomRequestOptions) => {
|
||||
success(res) {
|
||||
// 状态码 2xx,参考 axios 的设计
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
// 2.1 提取核心数据 res.data
|
||||
resolve(res.data as IResData<T>)
|
||||
} else if (res.statusCode === 401) {
|
||||
// 401错误 -> 清理用户信息,跳转到登录页
|
||||
// userStore.clearUserInfo()
|
||||
// uni.navigateTo({ url: '/pages/login/login' })
|
||||
reject(res)
|
||||
if (res.data.errorCode === 403) {
|
||||
// 401错误 -> 清理用户信息,跳转到登录页
|
||||
// userStore.clearUserInfo()
|
||||
// uni.navigateTo({ url: '/pages/login/login' })
|
||||
reject(res)
|
||||
} else {
|
||||
resolve(res.data as IResData<T>)
|
||||
}
|
||||
} else {
|
||||
// 其他错误 -> 根据后端错误信息轻提示
|
||||
!options.hideErrorToast &&
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: (res.data as IResData<T>).msg || '请求错误'
|
||||
})
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '网络错误,请重试'
|
||||
})
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
@ -34,7 +34,7 @@ export const http = <T>(options: CustomRequestOptions) => {
|
||||
fail(err) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '网络错误,换个网络试试'
|
||||
title: '网络错误,请重试'
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
|
||||
@ -1,9 +1,3 @@
|
||||
/*
|
||||
* @Author: 菲鸽
|
||||
* @Date: 2024-03-28 19:13:55
|
||||
* @Last Modified by: 菲鸽
|
||||
* @Last Modified time: 2024-03-28 19:24:55
|
||||
*/
|
||||
export const platform = __UNI_PLATFORM__
|
||||
export const isH5 = __UNI_PLATFORM__ === 'h5'
|
||||
export const isApp = __UNI_PLATFORM__ === 'app'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user