refactor: 项目架构清理 — 删除调试页面/冗余store/H5降级代码/无用文件
This commit is contained in:
+1
-1
@@ -1,2 +1,2 @@
|
||||
VITE_API_BASE_URL=http://localhost:80
|
||||
VITE_API_BASE_URL=http://localhost:48080
|
||||
VITE_APP_TITLE=湖南12301文旅专区
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// app.js
|
||||
App({
|
||||
onLaunch() {
|
||||
// 展示本地存储能力
|
||||
const logs = wx.getStorageSync('logs') || []
|
||||
logs.unshift(Date.now())
|
||||
wx.setStorageSync('logs', logs)
|
||||
|
||||
// 登录
|
||||
wx.login({
|
||||
success: res => {
|
||||
// 发送 res.code 到后台换取 openId, sessionKey, unionId
|
||||
}
|
||||
})
|
||||
},
|
||||
globalData: {
|
||||
userInfo: null
|
||||
}
|
||||
})
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/index/index",
|
||||
"pages/logs/logs"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "Weixin",
|
||||
"navigationBarBackgroundColor": "#ffffff"
|
||||
},
|
||||
"style": "v2",
|
||||
"componentFramework": "glass-easel",
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"lazyCodeLoading": "requiredComponents"
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**app.wxss**/
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 200rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
// index.js
|
||||
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
|
||||
|
||||
Page({
|
||||
data: {
|
||||
motto: 'Hello World',
|
||||
userInfo: {
|
||||
avatarUrl: defaultAvatarUrl,
|
||||
nickName: '',
|
||||
},
|
||||
hasUserInfo: false,
|
||||
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
|
||||
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
|
||||
},
|
||||
bindViewTap() {
|
||||
wx.navigateTo({
|
||||
url: '../logs/logs'
|
||||
})
|
||||
},
|
||||
onChooseAvatar(e) {
|
||||
const { avatarUrl } = e.detail
|
||||
const { nickName } = this.data.userInfo
|
||||
this.setData({
|
||||
"userInfo.avatarUrl": avatarUrl,
|
||||
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
|
||||
})
|
||||
},
|
||||
onInputChange(e) {
|
||||
const nickName = e.detail.value
|
||||
const { avatarUrl } = this.data.userInfo
|
||||
this.setData({
|
||||
"userInfo.nickName": nickName,
|
||||
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
|
||||
})
|
||||
},
|
||||
getUserProfile(e) {
|
||||
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
|
||||
wx.getUserProfile({
|
||||
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
this.setData({
|
||||
userInfo: res.userInfo,
|
||||
hasUserInfo: true
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<!--index.wxml-->
|
||||
<scroll-view class="scrollarea" scroll-y type="list">
|
||||
<view class="container">
|
||||
<view class="userinfo">
|
||||
<block wx:if="{{canIUseNicknameComp && !hasUserInfo}}">
|
||||
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
|
||||
<image class="avatar" src="{{userInfo.avatarUrl}}"></image>
|
||||
</button>
|
||||
<view class="nickname-wrapper">
|
||||
<text class="nickname-label">昵称</text>
|
||||
<input type="nickname" class="nickname-input" placeholder="请输入昵称" bind:change="onInputChange" />
|
||||
</view>
|
||||
</block>
|
||||
<block wx:elif="{{!hasUserInfo}}">
|
||||
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
|
||||
<view wx:else> 请使用2.10.4及以上版本基础库 </view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
|
||||
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
|
||||
</block>
|
||||
</view>
|
||||
<view class="usermotto">
|
||||
<text class="user-motto">{{motto}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -1,62 +0,0 @@
|
||||
/**index.wxss**/
|
||||
page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.scrollarea {
|
||||
flex: 1;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.userinfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #aaa;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.userinfo-avatar {
|
||||
overflow: hidden;
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.usermotto {
|
||||
margin-top: 200px;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
padding: 0;
|
||||
width: 56px !important;
|
||||
border-radius: 8px;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.nickname-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-top: .5px solid rgba(0, 0, 0, 0.1);
|
||||
border-bottom: .5px solid rgba(0, 0, 0, 0.1);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.nickname-label {
|
||||
width: 105px;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
|
||||
"rules": [{
|
||||
"action": "allow",
|
||||
"page": "*"
|
||||
}]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export * from './types'
|
||||
export * from './user'
|
||||
export * from './card'
|
||||
export * from './order'
|
||||
export { get, post, put, del, getToken, setToken, removeToken } from './request'
|
||||
@@ -16,12 +16,6 @@ export interface WxLoginResult {
|
||||
expiresTime: string
|
||||
}
|
||||
|
||||
/** 账号密码登录参数(降级方案) */
|
||||
export interface LoginParams {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
/** 年卡基本信息 */
|
||||
export interface CardInfo {
|
||||
id: string
|
||||
|
||||
+2
-7
@@ -1,19 +1,14 @@
|
||||
import { get, post } from './request'
|
||||
import type { UserInfo, WxLoginResult, LoginParams } from './types'
|
||||
import type { UserInfo, WxLoginResult } from './types'
|
||||
|
||||
/** 微信小程序登录(loginCode + phoneCode) */
|
||||
export function wxLogin(data: { loginCode: string; phoneCode: string }): Promise<WxLoginResult> {
|
||||
return post<WxLoginResult>('/auth/wx-login', data, false)
|
||||
}
|
||||
|
||||
/** 账号密码登录(降级方案) */
|
||||
export function login(params: LoginParams): Promise<WxLoginResult> {
|
||||
return post<WxLoginResult>('/auth/login', params, false)
|
||||
}
|
||||
|
||||
/** 获取当前用户信息 */
|
||||
export function getUserInfo(): Promise<UserInfo> {
|
||||
return get<UserInfo>('/user/info')
|
||||
}
|
||||
|
||||
export type { UserInfo, WxLoginResult, LoginParams }
|
||||
export type { UserInfo, WxLoginResult }
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<!-- 通用毛玻璃卡片 -->
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
<template>
|
||||
<view class="mc-glass" :class="customClass">
|
||||
<!-- 左上高光切面 -->
|
||||
<view class="mc-glass-cut" />
|
||||
<!-- 内容层 -->
|
||||
<view class="mc-glass-body" @click.stop>
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<style scoped>
|
||||
.mc-glass {
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 255, 0.10);
|
||||
backdrop-filter: blur(24rpx) saturate(1.4);
|
||||
-webkit-backdrop-filter: blur(24rpx) saturate(1.4);
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.10);
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.mc-glass-cut {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
background-image: linear-gradient(160deg, rgba(255,255,255,0.08) 0%, transparent 40%, transparent 70%, rgba(255,255,255,0.04) 100%);
|
||||
}
|
||||
.mc-glass-body {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
/* hover 增强 */
|
||||
.mc-glass-hover .mc-glass {
|
||||
background-color: rgba(255, 255, 255, 0.14) !important;
|
||||
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.35) !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1 +1,11 @@
|
||||
{
|
||||
"mp-weixin": {
|
||||
"appid": "wx636bc46a6570e9fd",
|
||||
"setting": {
|
||||
"urlCheck": false,
|
||||
"es6": true,
|
||||
"postcss": false,
|
||||
"minified": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { activateCard } from '../../../../api/card'
|
||||
import { showToast } from '../../../../utils'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const cardId = ref('')
|
||||
const cardName = ref('')
|
||||
const activating = ref(false)
|
||||
@@ -76,7 +75,7 @@ async function handleActivate() {
|
||||
if (!cardId.value) return
|
||||
activating.value = true
|
||||
try {
|
||||
await cardStore.activateCard(cardId.value, form)
|
||||
await activateCard(cardId.value, form)
|
||||
showToast('激活成功', 'success')
|
||||
// 激活成功后跳转入园码页
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { bindCard } from '../../../../api/card'
|
||||
import { showToast } from '../../../../utils'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const cardNo = ref('')
|
||||
const binding = ref(false)
|
||||
|
||||
@@ -38,7 +37,7 @@ async function handleBind() {
|
||||
}
|
||||
binding.value = true
|
||||
try {
|
||||
await cardStore.bindCard(cardNo.value.trim())
|
||||
await bindCard(cardNo.value.trim())
|
||||
showToast('绑定成功', 'success')
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
|
||||
@@ -54,10 +54,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { getCardDetail } from '../../../../api/card'
|
||||
import type { CardDetail } from '../../../../api/types'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const card = ref<CardDetail | null>(null)
|
||||
|
||||
/** 页面加载时获取年卡详情 */
|
||||
@@ -70,8 +69,7 @@ onLoad((options) => {
|
||||
/** 加载年卡详情数据 */
|
||||
async function loadDetail(id: string) {
|
||||
try {
|
||||
await cardStore.fetchCardDetail(id)
|
||||
card.value = cardStore.currentCard
|
||||
card.value = await getCardDetail(id)
|
||||
} catch (err) {
|
||||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
</view>
|
||||
<!-- 年卡列表 -->
|
||||
<view class="card-list">
|
||||
<view v-if="cardStore.loading" class="loading"><text>加载中...</text></view>
|
||||
<view v-else-if="cardStore.cardList.length === 0">
|
||||
<view v-if="loading" class="loading"><text>加载中...</text></view>
|
||||
<view v-else-if="cardList.length === 0">
|
||||
<empty-state icon="🎫" text="暂无符合条件的年卡" />
|
||||
</view>
|
||||
<view v-else>
|
||||
<card-item v-for="card in cardStore.cardList" :key="card.id" :card="card" @click="goDetail" />
|
||||
<card-item v-for="card in cardList" :key="card.id" :card="card" @click="goDetail" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -32,12 +32,13 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { getCardList } from '../../../../api/card'
|
||||
import CardItem from '../../../../components/card-item.vue'
|
||||
import EmptyState from '../../../../components/empty-state.vue'
|
||||
import type { CardInfo } from '../../../../api/types'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const cardList = ref<CardInfo[]>([])
|
||||
const loading = ref(false)
|
||||
const keyword = ref('')
|
||||
const currentCategory = ref('')
|
||||
|
||||
@@ -49,14 +50,24 @@ const categories = [
|
||||
{ label: '情侣年卡', value: 'couple' }
|
||||
]
|
||||
|
||||
/** 获取年卡列表 */
|
||||
async function fetchCardList(params?: { keyword?: string; category?: string }) {
|
||||
loading.value = true
|
||||
try {
|
||||
cardList.value = await getCardList(params)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 页面加载时获取年卡列表 */
|
||||
onLoad(() => {
|
||||
cardStore.fetchCardList()
|
||||
fetchCardList()
|
||||
})
|
||||
|
||||
/** 执行搜索 */
|
||||
function handleSearch() {
|
||||
cardStore.fetchCardList({ keyword: keyword.value, category: currentCategory.value })
|
||||
fetchCardList({ keyword: keyword.value, category: currentCategory.value })
|
||||
}
|
||||
|
||||
/** 选择分类 */
|
||||
|
||||
@@ -25,11 +25,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUnmount } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { getEntryQrCode } from '../../../../api/card'
|
||||
import { showToast } from '../../../../utils'
|
||||
import type { QrCodeInfo } from '../../../../api/types'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const cardId = ref('')
|
||||
const qrInfo = ref<QrCodeInfo | null>(null)
|
||||
let refreshTimer: ReturnType<typeof setInterval> | null = null
|
||||
@@ -54,7 +53,7 @@ onBeforeUnmount(() => {
|
||||
/** 加载入园码 */
|
||||
async function loadQrCode() {
|
||||
try {
|
||||
qrInfo.value = await cardStore.getEntryQrCode(cardId.value)
|
||||
qrInfo.value = await getEntryQrCode(cardId.value)
|
||||
} catch (err: any) {
|
||||
showToast(err.message || '获取入园码失败')
|
||||
}
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 顶部标题区 -->
|
||||
<view class="header">
|
||||
<text class="header-title">湖南12301文旅专区</text>
|
||||
</view>
|
||||
|
||||
<!-- 宫格功能入口 -->
|
||||
<view class="grid">
|
||||
<view class="grid-item" @click="goTo('/packages/user/pages/card/list')">
|
||||
<view class="grid-icon" style="background: #E8F0FE;">
|
||||
<text class="emoji">🎫</text>
|
||||
</view>
|
||||
<text class="grid-label">购买年卡</text>
|
||||
<text class="grid-desc">多种卡种可选</text>
|
||||
</view>
|
||||
|
||||
<view class="grid-item" @click="goTo('/packages/user/pages/card/bind')">
|
||||
<view class="grid-icon" style="background: #FFF3E0;">
|
||||
<text class="emoji">📱</text>
|
||||
</view>
|
||||
<text class="grid-label">激活/绑定</text>
|
||||
<text class="grid-desc">激活已购年卡</text>
|
||||
</view>
|
||||
|
||||
<view class="grid-item" @click="showComingSoon">
|
||||
<view class="grid-icon" style="background: #E8F8F0;">
|
||||
<text class="emoji">🏔️</text>
|
||||
</view>
|
||||
<text class="grid-label">景区预约</text>
|
||||
<text class="grid-desc">预约入园时间</text>
|
||||
</view>
|
||||
|
||||
<view class="grid-item" @click="showComingSoon">
|
||||
<view class="grid-icon" style="background: #FCE4EC;">
|
||||
<text class="emoji">📋</text>
|
||||
</view>
|
||||
<text class="grid-label">我的记录</text>
|
||||
<text class="grid-desc">预约/使用记录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 推荐年卡 -->
|
||||
<view class="section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">推荐年卡</text>
|
||||
<text class="section-more" @click="goTo('/packages/user/pages/card/list')">查看全部 ›</text>
|
||||
</view>
|
||||
|
||||
<view v-if="cardStore.loading" class="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<view v-else-if="cardStore.cardList.length === 0" class="empty">
|
||||
<empty-state icon="🎫" text="暂无年卡" />
|
||||
</view>
|
||||
|
||||
<view v-else>
|
||||
<card-item
|
||||
v-for="card in displayCards"
|
||||
:key="card.id"
|
||||
:card="card"
|
||||
@click="goToDetail"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import CardItem from '../../../../components/card-item.vue'
|
||||
import EmptyState from '../../../../components/empty-state.vue'
|
||||
import type { CardInfo } from '../../../../api/types'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
|
||||
// 首页最多展示 3 张年卡
|
||||
const displayCards = computed(() => cardStore.cardList.slice(0, 3))
|
||||
|
||||
onShow(() => {
|
||||
cardStore.fetchCardList()
|
||||
})
|
||||
|
||||
function goTo(url: string) {
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
|
||||
function goToDetail(card: CardInfo) {
|
||||
uni.navigateTo({ url: `/packages/user/pages/card/detail?id=${card.id}` })
|
||||
}
|
||||
|
||||
function showComingSoon() {
|
||||
uni.showToast({ title: '即将上线,敬请期待', icon: 'none' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #4A90D9;
|
||||
padding: 40rpx 30rpx 30rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16rpx;
|
||||
padding: 20rpx;
|
||||
margin: -20rpx 16rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
|
||||
.grid-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.grid-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.grid-desc {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.section-more {
|
||||
font-size: 24rpx;
|
||||
color: #4A90D9;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 60rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
+95
-101
@@ -1,103 +1,97 @@
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "湖南12301"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "packages/user",
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "文旅专区"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "年卡列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "年卡详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/buy",
|
||||
"style": {
|
||||
"navigationBarTitleText": "确认购买"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/activate",
|
||||
"style": {
|
||||
"navigationBarTitleText": "激活年卡"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/qrcode",
|
||||
"style": {
|
||||
"navigationBarTitleText": "入园码"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/bind",
|
||||
"style": {
|
||||
"navigationBarTitleText": "绑定年卡"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/profile/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "湖南12301",
|
||||
"navigationBarBackgroundColor": "#FFFFFF",
|
||||
"backgroundColor": "#F5F5F5"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#7A7E83",
|
||||
"selectedColor": "#4A90D9",
|
||||
"borderStyle": "white",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "packages/user/pages/index/index",
|
||||
"text": "首页",
|
||||
"iconPath": "static/tabbar/home.png",
|
||||
"selectedIconPath": "static/tabbar/home-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "packages/user/pages/profile/index",
|
||||
"text": "我的",
|
||||
"iconPath": "static/tabbar/profile.png",
|
||||
"selectedIconPath": "static/tabbar/profile-active.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "文旅专区"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/profile/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "packages/user",
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/card/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "年卡列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "年卡详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/buy",
|
||||
"style": {
|
||||
"navigationBarTitleText": "确认购买"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/activate",
|
||||
"style": {
|
||||
"navigationBarTitleText": "激活年卡"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/qrcode",
|
||||
"style": {
|
||||
"navigationBarTitleText": "入园码"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/card/bind",
|
||||
"style": {
|
||||
"navigationBarTitleText": "绑定年卡"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "湖南12301",
|
||||
"navigationBarBackgroundColor": "#FFFFFF",
|
||||
"backgroundColor": "#F5F5F5"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#7A7E83",
|
||||
"selectedColor": "#4A90D9",
|
||||
"borderStyle": "white",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"text": "首页",
|
||||
"iconPath": "static/tabbar/home.png",
|
||||
"selectedIconPath": "static/tabbar/home-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/profile/index",
|
||||
"text": "我的",
|
||||
"iconPath": "static/tabbar/profile.png",
|
||||
"selectedIconPath": "static/tabbar/profile-active.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+1
-107
@@ -7,36 +7,12 @@
|
||||
</view>
|
||||
|
||||
<view class="login-area">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="btn-wx-login"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="handleGetPhoneNumber"
|
||||
:disabled="loading">
|
||||
{{ loading ? '登录中...' : '微信一键登录' }}
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="h5-tip">
|
||||
<text>请在微信小程序中使用本应用</text>
|
||||
</view>
|
||||
<view class="form" v-if="showFallback">
|
||||
<view class="form-item">
|
||||
<text class="label">账号</text>
|
||||
<input class="input" v-model="form.username" placeholder="请输入账号" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">密码</text>
|
||||
<input class="input" v-model="form.password" placeholder="请输入密码" password />
|
||||
</view>
|
||||
<button class="btn-fallback" @click="handleFallbackLogin" :disabled="loading">
|
||||
{{ loading ? '登录中...' : '账号密码登录' }}
|
||||
</button>
|
||||
</view>
|
||||
<button class="btn-toggle" v-if="!showFallback" @click="showFallback = true">
|
||||
使用账号密码登录
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<view class="agreement">
|
||||
@@ -49,18 +25,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { useUserStore } from '../../store/user'
|
||||
import { showToast } from '../../utils'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const loading = ref(false)
|
||||
const showFallback = ref(false)
|
||||
|
||||
const form = reactive({
|
||||
username: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
/** 微信手机号授权回调 → 登录 */
|
||||
async function handleGetPhoneNumber(e: any) {
|
||||
@@ -104,26 +74,6 @@ async function handleGetPhoneNumber(e: any) {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 账号密码登录(降级方案 / H5 用) */
|
||||
async function handleFallbackLogin() {
|
||||
if (!form.username || !form.password) {
|
||||
showToast('请输入账号和密码')
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
await userStore.login({ username: form.username, password: form.password })
|
||||
showToast('登录成功', 'success')
|
||||
setTimeout(() => {
|
||||
uni.switchTab({ url: '/pages/index/index' })
|
||||
}, 1000)
|
||||
} catch (err: any) {
|
||||
console.error('登录失败:', err)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -181,62 +131,6 @@ async function handleFallbackLogin() {
|
||||
background: #9ED6B5;
|
||||
}
|
||||
|
||||
.form {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 24rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
font-size: 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.btn-fallback {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: #4A90D9;
|
||||
color: #fff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-toggle {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: transparent;
|
||||
color: #4A90D9;
|
||||
border: 2rpx solid #4A90D9;
|
||||
border-radius: 44rpx;
|
||||
font-size: 30rpx;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.h5-tip {
|
||||
text-align: center;
|
||||
padding: 40rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.agreement {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '../../../../store/user'
|
||||
import { useUserStore } from '../../store/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const defaultAvatar = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
|
||||
@@ -1,239 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="user-card">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="userStore.userInfo?.avatarUrl || defaultAvatar"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="user-info">
|
||||
<text class="nickname">{{ userStore.userInfo?.nickname || '未登录' }}</text>
|
||||
<text class="user-id">ID: {{ userStore.userInfo?.id || '---' }}</text>
|
||||
</view>
|
||||
<button v-if="!userStore.isLogin" class="login-btn" size="mini" @click="goLogin">
|
||||
登录
|
||||
</button>
|
||||
<button v-else class="login-btn" size="mini" @click="handleLogout">
|
||||
退出
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">功能菜单</view>
|
||||
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="goToLogs">
|
||||
<view class="menu-icon">📝</view>
|
||||
<text class="menu-text">查看日志</text>
|
||||
<view class="menu-arrow">›</view>
|
||||
</view>
|
||||
|
||||
<view class="menu-item" @click="showAbout">
|
||||
<view class="menu-icon">ℹ️</view>
|
||||
<text class="menu-text">关于应用</text>
|
||||
<view class="menu-arrow">›</view>
|
||||
</view>
|
||||
|
||||
<view class="menu-item" @click="clearCache">
|
||||
<view class="menu-icon">🗑️</view>
|
||||
<text class="menu-text">清除缓存</text>
|
||||
<view class="menu-arrow">›</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">技术栈</view>
|
||||
<view class="tech-list">
|
||||
<view class="tech-item">
|
||||
<text class="tech-label">框架</text>
|
||||
<text class="tech-value">uni-app</text>
|
||||
</view>
|
||||
<view class="tech-item">
|
||||
<text class="tech-label">Vue</text>
|
||||
<text class="tech-value">3.x</text>
|
||||
</view>
|
||||
<view class="tech-item">
|
||||
<text class="tech-label">构建</text>
|
||||
<text class="tech-value">Vite</text>
|
||||
</view>
|
||||
<view class="tech-item">
|
||||
<text class="tech-label">语言</text>
|
||||
<text class="tech-value">TypeScript</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '../../store/user'
|
||||
import { showToast } from '../../utils'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const defaultAvatar = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
|
||||
|
||||
function goLogin() {
|
||||
uni.navigateTo({ url: '/pages/login/login' })
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
userStore.logout()
|
||||
showToast('已退出登录', 'success')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function goToLogs() {
|
||||
uni.navigateTo({ url: '/pages/logs/logs' })
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
uni.showModal({
|
||||
title: '关于',
|
||||
content: 'zhy-test uni-app 项目\n\n支持多端发布:\n- 微信小程序\n- H5\n- Android/iOS App',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要清除缓存吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.clearStorageSync()
|
||||
showToast('缓存已清除', 'success')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
margin-left: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 20rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.menu-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
font-size: 36rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 36rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.tech-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.tech-item {
|
||||
width: calc(50% - 10rpx);
|
||||
background: #f8f8f8;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tech-label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.tech-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
@@ -1,64 +0,0 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import * as cardApi from '../api/card'
|
||||
import type { CardInfo, CardDetail, MyCard, ActivateParams, QrCodeInfo } from '../api/types'
|
||||
|
||||
export const useCardStore = defineStore('card', () => {
|
||||
const cardList = ref<CardInfo[]>([])
|
||||
const currentCard = ref<CardDetail | null>(null)
|
||||
const myCards = ref<MyCard[]>([])
|
||||
const loading = ref(false)
|
||||
|
||||
/** 获取年卡列表 */
|
||||
async function fetchCardList(params?: { keyword?: string; category?: string }) {
|
||||
loading.value = true
|
||||
try {
|
||||
cardList.value = await cardApi.getCardList(params)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取年卡详情 */
|
||||
async function fetchCardDetail(id: string) {
|
||||
loading.value = true
|
||||
try {
|
||||
currentCard.value = await cardApi.getCardDetail(id)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取我的年卡 */
|
||||
async function fetchMyCards() {
|
||||
myCards.value = await cardApi.getMyCards()
|
||||
}
|
||||
|
||||
/** 激活年卡 */
|
||||
async function activateCard(cardId: string, data: ActivateParams) {
|
||||
return await cardApi.activateCard(cardId, data)
|
||||
}
|
||||
|
||||
/** 绑定年卡 */
|
||||
async function bindCard(cardNo: string) {
|
||||
return await cardApi.bindCard(cardNo)
|
||||
}
|
||||
|
||||
/** 获取入园码 */
|
||||
async function getEntryQrCode(cardId: string): Promise<QrCodeInfo> {
|
||||
return await cardApi.getEntryQrCode(cardId)
|
||||
}
|
||||
|
||||
return {
|
||||
cardList,
|
||||
currentCard,
|
||||
myCards,
|
||||
loading,
|
||||
fetchCardList,
|
||||
fetchCardDetail,
|
||||
fetchMyCards,
|
||||
activateCard,
|
||||
bindCard,
|
||||
getEntryQrCode
|
||||
}
|
||||
})
|
||||
+2
-13
@@ -1,8 +1,8 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { getToken, setToken, removeToken } from '../api/request'
|
||||
import { wxLogin as apiWxLogin, login as apiLogin, getUserInfo as apiGetUserInfo } from '../api/user'
|
||||
import type { UserInfo, LoginParams } from '../api/types'
|
||||
import { wxLogin as apiWxLogin, getUserInfo as apiGetUserInfo } from '../api/user'
|
||||
import type { UserInfo } from '../api/types'
|
||||
import { TOKEN_KEY, REFRESH_TOKEN_KEY } from '../config'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
@@ -22,16 +22,6 @@ export const useUserStore = defineStore('user', () => {
|
||||
return result
|
||||
}
|
||||
|
||||
/** 账号密码登录(降级方案) */
|
||||
async function login(params: LoginParams) {
|
||||
const result = await apiLogin(params)
|
||||
token.value = result.accessToken
|
||||
refreshToken.value = result.refreshToken
|
||||
setToken(result.accessToken)
|
||||
uni.setStorageSync(REFRESH_TOKEN_KEY, result.refreshToken)
|
||||
return result
|
||||
}
|
||||
|
||||
/** 获取用户信息 */
|
||||
async function fetchUserInfo() {
|
||||
if (!token.value) return
|
||||
@@ -55,7 +45,6 @@ export const useUserStore = defineStore('user', () => {
|
||||
userInfo,
|
||||
isLogin,
|
||||
wxLogin,
|
||||
login,
|
||||
fetchUserInfo,
|
||||
logout
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
const formatTime = date => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
|
||||
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
|
||||
}
|
||||
|
||||
const formatNumber = n => {
|
||||
n = n.toString()
|
||||
return n[1] ? n : `0${n}`
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatTime
|
||||
}
|
||||
Reference in New Issue
Block a user