chore: 添加 CLAUDE.md 和 .env 配置文件
- 添加项目文档 CLAUDE.md,包含常用命令和架构说明 - 添加 packages/server/.env 环境变量配置文件 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -133,7 +133,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import CustomNavBar from '../../components/CustomNavBar.vue'
|
||||
import { getSystemLayout } from '../../utils/system'
|
||||
import { useAdminStore } from '../../stores/admin'
|
||||
@@ -202,9 +202,9 @@ async function loadOrders(reset = false) {
|
||||
if (activeFilter.value) params.status = activeFilter.value
|
||||
const result = await adminStore.fetchAdminOrders(params)
|
||||
if (reset) {
|
||||
orders.value = [...result.data]
|
||||
orders.value = [...result.items]
|
||||
} else {
|
||||
orders.value.push(...result.data)
|
||||
orders.value.push(...result.items)
|
||||
}
|
||||
hasMore.value = orders.value.length < result.total
|
||||
totalCount.value = result.total
|
||||
|
||||
@@ -103,15 +103,15 @@
|
||||
<view class="hero-badge">
|
||||
<text class="hero-badge-text">{{ typeLabel }}</text>
|
||||
</view>
|
||||
<text class="hero-name">{{ card.name }}</text>
|
||||
<text class="hero-name">{{ cardData.name }}</text>
|
||||
<view class="hero-price-row">
|
||||
<text class="hero-currency">¥</text>
|
||||
<text class="hero-price">{{ formatPrice(card.price) }}</text>
|
||||
<text class="hero-price">{{ formatPrice(cardData.price) }}</text>
|
||||
<text
|
||||
v-if="card.originalPrice && card.originalPrice > card.price"
|
||||
v-if="cardData.originalPrice && cardData.originalPrice > cardData.price"
|
||||
class="hero-original"
|
||||
>
|
||||
¥{{ formatPrice(card.originalPrice) }}
|
||||
¥{{ formatPrice(cardData.originalPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -121,28 +121,28 @@
|
||||
<!-- Key info grid -->
|
||||
<view class="info-card">
|
||||
<view class="info-grid">
|
||||
<view class="info-cell" v-if="card.totalTimes">
|
||||
<text class="cell-value">{{ card.totalTimes }}</text>
|
||||
<view class="info-cell" v-if="cardData.totalTimes">
|
||||
<text class="cell-value">{{ cardData.totalTimes }}</text>
|
||||
<text class="cell-label">课时次数</text>
|
||||
</view>
|
||||
<view class="info-cell">
|
||||
<text class="cell-value">{{ card.durationDays }}</text>
|
||||
<text class="cell-value">{{ cardData.durationDays }}</text>
|
||||
<text class="cell-label">有效天数</text>
|
||||
</view>
|
||||
<view class="info-cell">
|
||||
<text class="cell-value">{{ unitPrice }}</text>
|
||||
<text class="cell-label">{{ card.totalTimes ? '每次单价' : '按天均价' }}</text>
|
||||
<text class="cell-label">{{ cardData.totalTimes ? '每次单价' : '按天均价' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Description -->
|
||||
<view v-if="card.description" class="desc-card">
|
||||
<view v-if="cardData.description" class="desc-card">
|
||||
<view class="section-header">
|
||||
<view class="section-dot" />
|
||||
<text class="section-title">课程说明</text>
|
||||
</view>
|
||||
<text class="desc-content">{{ card.description }}</text>
|
||||
<text class="desc-content">{{ cardData.description }}</text>
|
||||
</view>
|
||||
|
||||
<!-- Features list -->
|
||||
@@ -153,13 +153,13 @@
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<text class="feature-dot">•</text>
|
||||
<text class="feature-text">购买后立即生效,有效期 {{ card.durationDays }} 天</text>
|
||||
<text class="feature-text">购买后立即生效,有效期 {{ cardData.durationDays }} 天</text>
|
||||
</view>
|
||||
<view v-if="card.totalTimes" class="feature-item">
|
||||
<view v-if="cardData.totalTimes" class="feature-item">
|
||||
<text class="feature-dot">•</text>
|
||||
<text class="feature-text">共 {{ card.totalTimes }} 次课时,可灵活安排上课时间</text>
|
||||
<text class="feature-text">共 {{ cardData.totalTimes }} 次课时,可灵活安排上课时间</text>
|
||||
</view>
|
||||
<view v-if="!card.totalTimes" class="feature-item">
|
||||
<view v-if="!cardData.totalTimes" class="feature-item">
|
||||
<text class="feature-dot">•</text>
|
||||
<text class="feature-text">有效期内可无限次预约课程</text>
|
||||
</view>
|
||||
@@ -182,7 +182,7 @@
|
||||
<view class="bottom-bar">
|
||||
<view class="price-summary">
|
||||
<text class="summary-label">实付金额</text>
|
||||
<text class="summary-price">¥{{ formatPrice(card.price) }}</text>
|
||||
<text class="summary-price">¥{{ formatPrice(cardData.price) }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="buy-btn"
|
||||
@@ -250,6 +250,8 @@ const unitPrice = computed(() => {
|
||||
return `¥${(pricePerDay / 100).toFixed(0)}`
|
||||
})
|
||||
|
||||
const cardData = computed<CardType>(() => card.value as CardType)
|
||||
|
||||
// ─── Data loading ─────────────────────────────────────────
|
||||
async function loadCard() {
|
||||
loading.value = true
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick } from 'vue'
|
||||
import { onShow, onUnmount, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
||||
import { ref, nextTick, onUnmounted } from 'vue'
|
||||
import { onShow, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
||||
|
||||
import BrandBanner from '../../components/BrandBanner.vue'
|
||||
import StudioInfo from '../../components/StudioInfo.vue'
|
||||
@@ -93,7 +93,7 @@ uni.$on('scrollToCardShop', () => {
|
||||
pendingScrollToCardShop.value = true
|
||||
})
|
||||
|
||||
onUnmount(() => {
|
||||
onUnmounted(() => {
|
||||
uni.$off('scrollToCardShop')
|
||||
})
|
||||
|
||||
@@ -142,14 +142,12 @@ function scrollToCardShop() {
|
||||
.select(`#${cardShopAnchorId}`)
|
||||
.boundingClientRect()
|
||||
.selectViewport()
|
||||
.scrollOffset()
|
||||
.exec((res) => {
|
||||
if (res && res[0] && res[1]) {
|
||||
const rectTop = (res[0] as UniApp.NodeInfo).top ?? 0
|
||||
const viewportScroll = (res[1] as UniApp.NodeInfo).scrollTop ?? 0
|
||||
scrollTop.value = viewportScroll + rectTop
|
||||
.scrollOffset((res) => {
|
||||
if (res) {
|
||||
scrollTop.value = (res as UniApp.NodeInfo).scrollTop ?? 0
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
21
packages/server/.env
Normal file
21
packages/server/.env
Normal file
@@ -0,0 +1,21 @@
|
||||
# Database
|
||||
DATABASE_URL=mysql://root:AK8jyLfsfMA5wNdC@129.204.155.94:13306/db_mp_focus
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=change-me-to-a-secure-random-string
|
||||
|
||||
# WeChat Mini Program
|
||||
WX_APPID=wx3e7a133d2305fa2c
|
||||
WX_SECRET=92f4f91af72ca0705d65e39e605cb98b
|
||||
|
||||
# WeChat Pay
|
||||
WX_MCH_ID=1110530023
|
||||
WX_MCH_KEY=ACbGcH3FNLBacmvmIVR4uWXjNf9h8jQ2
|
||||
WX_MCH_SERIAL_NO=7A90D96A7ED1A129E98DB5FD5F3A84EDC34B2AC6
|
||||
WX_MCH_KEY_PATH=./certs/apiclient_key.pem
|
||||
|
||||
# API Base URL (used for WeChat Pay callback notification)
|
||||
API_BASE_URL=https://focus.richarjiang.com/
|
||||
|
||||
# Server
|
||||
PORT=3000
|
||||
Reference in New Issue
Block a user