feat(views): 添加订单确认页面并更新图标引用

- 添加新的订单确认页面模板 (order_confirm.html)
- 启用 remixicon 图标库的样式引用
- 将成功图标从 ri-check-line 更新为 ri-check-double-fill- 添加 CLAUDE.md 开发指南文件
- 添加 Claude Code 本地设置文件
This commit is contained in:
danial
2025-09-23 19:59:18 +08:00
parent cc48364eb3
commit 553027b9cf
4 changed files with 570 additions and 3 deletions

View File

@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"Bash(cat:*)"
],
"deny": [],
"ask": []
}
}

117
CLAUDE.md Normal file
View File

@@ -0,0 +1,117 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Development Commands
### Build and Run
```bash
# Build for production (Linux AMD64)
./build.sh
# Development mode
go run main.go
# Docker build
docker build -t kami_shop . -f deploy/Dockerfile
```
### Testing
```bash
# Run all tests
go test ./...
# Run specific test file
go test ./internal/service/scan_shop_test.go
# Run tests with verbose output
go test -v ./...
```
### Docker Deployment
```bash
# Build and deploy with Docker Compose
export VERSION=latest
docker-compose -f deploy/docker-compose.yaml up -d
```
## Project Architecture
This is a **payment processing platform** built with Go and Beego framework, supporting multiple payment methods including WeChat Pay, Alipay, JD.com, Taobao, Pinduoduo, Apple Pay, Walmart, and various gift cards.
### Key Components
**Application Structure**:
- `main.go` - Application entry point with OpenTelemetry initialization
- `internal/controllers/` - HTTP handlers for payment processing
- `internal/service/` - Business logic layer
- `internal/models/` - Data models and database operations
- `internal/routers/` - Route definitions
- `views/` - HTML templates for payment pages (30+ payment method templates)
- `conf/` - Configuration files (app.conf for production, app.local.conf for development)
**External Dependencies**:
- **Database**: MySQL (development: `juhe_pay`, production: `kami`)
- **Cache**: Redis for session management and caching
- **Gateway Service**: `http://localhost:12309` (development) / `http://127.0.0.1:12309` (production)
- **Partial Service**: `http://localhost:12310` (development) / `http://127.0.0.1:12310` (production)
### Configuration
**Development** (`conf/app.local.conf`):
- Port: 12305, Host: localhost
- Database: MySQL on localhost:3306
- Redis: localhost:6379
- Run mode: dev
**Production** (`conf/app.conf`):
- Port: 12305, Host: 0.0.0.0
- Database: MySQL on 127.0.0.1:3306
- Redis: redis:6379 (Docker service)
- Run mode: prod
### Technology Stack
- **Framework**: Beego v2.3.7
- **Language**: Go 1.23.0
- **Observability**: Complete OpenTelemetry stack (tracing, metrics, logging)
- **Logging**: Zap structured logging
- **Concurrency**: Goroutine pooling with ants/v2
- **Security**: AES encryption, Edwards25519 cryptographic operations
### Development Patterns
**Code Organization**:
- Controllers handle HTTP requests and validation
- Service layer implements business logic
- Models manage data persistence
- Utils provide common functionality
- Schema defines request/response structures
**Testing Strategy**:
- Unit tests focused on service layer
- Test files follow `*_test.go` naming convention
- Use standard Go testing package
### Payment Processing Flow
1. Order creation through controller endpoints
2. Service layer processes payment logic
3. Integration with external payment gateways
4. Notification handling for payment callbacks
5. Template-based payment page generation
6. Profit margin calculation and reporting
### Deployment
**Docker Environment**:
- Multi-stage build using golang:1.23 builder
- Alpine Linux runtime image
- Volume mounts for configuration and logs
- Network: 1panel-network
- Health checks and automatic restarts
**CI/CD**:
- Drone CI pipeline with SSH deployment
- Docker image registry push
- Production server deployment via Docker Compose

View File

@@ -10,7 +10,7 @@
href="https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@400;500;600;700&family=SF+Pro+Text:wght@400;500;600&display=swap"
rel="stylesheet">
<!-- 引入图标库 -->
<!-- <link rel="stylesheet" href="../static/css/remixicon.min.css"> -->
<link rel="stylesheet" href="../static/css/remixicon.min.css">
<!-- 引入动画库 -->
<link rel="stylesheet" href="../static/css/animate.min.css">
<!-- 引入图标库 -->
@@ -335,7 +335,7 @@
<div class="laser-effect"></div>
<div class="laser-effect"></div>
<div class="success-icon">
<i class="ri-check-line"></i>
<i class="ri-check-double-fill"></i>
</div>
</div>
@@ -350,7 +350,7 @@
<div class="transaction-detail">
<span class="detail-label">交易状态</span>
<span class="detail-value" style="color: var(--success-green); display: flex; align-items: center;">
<span class="completed-icon"><i class="ri-check-line"></i></span>卡密已提交
<span class="completed-icon"><i class="ri-check-double-fill"></i></span>卡密已提交
</span>
</div>
<div class="transaction-detail">

441
views/order_confirm.html Normal file
View File

@@ -0,0 +1,441 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>订单确认</title>
<!-- 引入字体 -->
<link
href="https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@400;500;600;700&family=SF+Pro+Text:wght@400;500;600&display=swap"
rel="stylesheet">
<!-- 引入图标库 -->
<link rel="stylesheet" href="../static/css/remixicon.min.css">
<!-- 引入动画库 -->
<link rel="stylesheet" href="../static/css/animate.min.css">
<!-- 引入图标库 -->
<link rel="stylesheet" href="../static/css/index-anxin.css">
<style>
/* 全局样式和重置 */
:root {
--primary-blue: #007aff;
--primary-light-blue: rgba(0, 122, 255, 0.15);
--apple-white: #ffffff;
--apple-gray: #8e8e93;
--apple-light-gray: #f5f5f7;
--border-color: #e5e5ea;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
font-family: 'SF Pro Text', 'SF Pro Display', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: var(--apple-white);
color: #1d1d1f;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
/* 容器样式 */
.container {
position: relative;
text-align: center;
padding: 40px 30px;
max-width: 400px;
width: 90%;
z-index: 10;
}
/* 背景效果 */
.bg-shapes {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
overflow: hidden;
}
.bg-shape {
position: absolute;
border-radius: 50%;
filter: blur(70px);
}
.bg-shape:nth-child(1) {
top: -10%;
left: -10%;
width: 500px;
height: 500px;
background: linear-gradient(to right, rgba(0, 122, 255, 0.2), rgba(0, 122, 255, 0));
animation: float 15s ease-in-out infinite;
}
.bg-shape:nth-child(2) {
bottom: -15%;
right: -10%;
width: 600px;
height: 600px;
background: linear-gradient(to left, rgba(0, 122, 255, 0.15), rgba(0, 122, 255, 0));
animation: float 20s ease-in-out infinite reverse;
}
.bg-shape:nth-child(3) {
top: 40%;
left: 60%;
width: 300px;
height: 300px;
background: linear-gradient(to top, rgba(0, 122, 255, 0.1), rgba(0, 122, 255, 0));
animation: float 18s ease-in-out infinite 2s;
}
@keyframes float {
0% {
transform: translate(0, 0) rotate(0deg);
}
50% {
transform: translate(30px, 20px) rotate(5deg);
}
100% {
transform: translate(0, 0) rotate(0deg);
}
}
/* 玻璃态效果 */
.glass {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05);
border-radius: 20px;
}
/* 确认图标容器 */
.confirm-icon-container {
position: relative;
width: 100px;
height: 100px;
margin: 0 auto 30px;
}
/* 确认图标 */
.confirm-icon {
position: relative;
z-index: 2;
width: 100px;
height: 100px;
background: var(--primary-blue);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 40px;
box-shadow: 0 10px 25px rgba(0, 122, 255, 0.3);
animation: scaleIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}
/* 镭射效果 */
.laser-effect {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 150px;
height: 150px;
background: radial-gradient(circle, rgba(0, 122, 255, 0.8) 0%, rgba(0, 122, 255, 0) 70%);
border-radius: 50%;
z-index: 1;
opacity: 0;
animation: pulse 2s ease-in-out infinite;
}
.laser-effect:nth-child(2) {
width: 180px;
height: 180px;
animation-delay: 0.5s;
}
.laser-effect:nth-child(3) {
width: 210px;
height: 210px;
animation-delay: 1s;
}
/* 标题样式 */
h1 {
font-size: 28px;
font-weight: 700;
margin-bottom: 15px;
color: #1d1d1f;
font-family: 'SF Pro Display', sans-serif;
animation: fadeInUp 0.8s ease forwards;
animation-delay: 0.3s;
opacity: 0;
}
/* 描述文本样式 */
p {
font-size: 17px;
font-weight: 400;
line-height: 1.5;
margin-bottom: 30px;
color: var(--apple-gray);
animation: fadeInUp 0.8s ease forwards;
animation-delay: 0.5s;
opacity: 0;
}
/* 订单信息卡片 */
.order-card {
padding: 25px;
margin-bottom: 25px;
text-align: left;
animation: fadeInUp 0.8s ease forwards;
animation-delay: 0.7s;
opacity: 0;
}
.order-detail {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: 15px;
}
.order-detail:last-child {
margin-bottom: 0;
padding-top: 15px;
border-top: 1px solid rgba(0, 0, 0, 0.05);
font-weight: 600;
}
.detail-label {
color: var(--apple-gray);
}
.detail-value {
font-weight: 500;
color: #1d1d1f;
}
/* 按钮样式 */
.btn-container {
animation: fadeInUp 0.8s ease forwards;
animation-delay: 0.9s;
opacity: 0;
}
.btn {
width: 100%;
padding: 15px;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 15px;
font-family: 'SF Pro Text', sans-serif;
}
.btn-primary {
background: var(--primary-blue);
color: white;
box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
}
.btn-primary:hover {
background: #0051d5;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 122, 255, 0.4);
}
.btn-secondary {
background: transparent;
color: var(--primary-blue);
border: 2px solid var(--primary-blue);
}
.btn-secondary:hover {
background: var(--primary-light-blue);
}
/* 动画定义 */
@keyframes scaleIn {
0% {
transform: scale(0);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes pulse {
0% {
transform: translate(-50%, -50%) scale(0.8);
opacity: 0;
}
50% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.3;
}
100% {
transform: translate(-50%, -50%) scale(1.2);
opacity: 0;
}
}
@keyframes fadeInUp {
0% {
transform: translateY(20px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
/* 订单编号样式 */
.order-id {
font-size: 14px;
color: var(--apple-gray);
margin-top: 20px;
animation: fadeInUp 0.8s ease forwards;
animation-delay: 1.1s;
opacity: 0;
}
/* 状态标签 */
.status-badge {
display: inline-flex;
align-items: center;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
/* 旋转动画 */
.animate-spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.status-pending {
background: rgba(255, 149, 0, 0.15);
color: #ff9500;
}
.status-completed {
background: rgba(52, 199, 89, 0.15);
color: #34c759;
}
.status-processing {
background: rgba(0, 122, 255, 0.15);
color: #007aff;
}
</style>
</head>
<body>
<!-- 背景效果 -->
<div class="bg-shapes">
<div class="bg-shape"></div>
<div class="bg-shape"></div>
<div class="bg-shape"></div>
</div>
<div class="container">
<!-- 确认图标 -->
<div class="confirm-icon-container">
<div class="laser-effect"></div>
<div class="laser-effect"></div>
<div class="laser-effect"></div>
<div class="confirm-icon">
<i class="ri-loader-4-line animate-spin"></i>
</div>
</div>
<!-- 确认标题 -->
<h1>订单确认</h1>
<!-- 确认描述 -->
<p>请稍候,我们正在确认您的订单。完成后我们将通知您。</p>
<!-- 订单信息卡片 -->
<div class="order-card glass">
<div class="order-detail">
<span class="detail-label">订单编号</span>
<span class="detail-value">{{.orderId}}</span>
</div>
<div class="order-detail">
<span class="detail-label">订单金额</span>
<span class="detail-value" style="font-size: 18px; color: var(--primary-blue);">¥{{.amount}}</span>
</div>
<div class="order-detail">
<span class="detail-label">下单时间</span>
<span class="detail-value">{{.orderTime}}</span>
</div>
<div class="order-detail">
<span class="detail-label">订单状态</span>
<span class="detail-value">
<span class="status-badge status-processing">处理中</span>
</span>
</div>
</div>
</div>
<script>
// 模拟订单处理完成后的跳转
setTimeout(() => {
// 这里可以根据实际情况跳转到不同页面
// 例如window.location.href = '/order-completed/{{.orderId}}';
// 或者跳转到成功页面
console.log('订单处理完成,准备跳转...');
}, 5000); // 5秒后模拟处理完成
// 监听订单状态更新可以通过WebSocket或轮询实现
function checkOrderStatus() {
// 这里可以添加轮询检查订单状态的逻辑
// 当状态变为完成时,自动跳转到成功页面
}
// 每3秒检查一次订单状态
setInterval(checkOrderStatus, 3000);
</script>
</body>
</html>