- strategies/strategies.vue: 清理未使用的btn-secondary样式,优化按钮样式 - strategies/edit/edit.vue: 已替换u-input为原生input - 添加OPTIMIZATION.md优化计划文档 - 保留index.vue的骨架屏自定义样式(小程序兼容性更好)
236 lines
6.4 KiB
Vue
Executable File
236 lines
6.4 KiB
Vue
Executable File
<template>
|
|
<view class="page-container">
|
|
|
|
<view class="header-section">
|
|
<view class="status-bar-height"></view>
|
|
|
|
<view class="flex-row justify-between items-start">
|
|
<view>
|
|
<text class="title-lg">策略实验室</text>
|
|
<text class="subtitle">选择或创建预设规则模型</text>
|
|
</view>
|
|
|
|
<view class="add-btn-box" @click="goToAdd">
|
|
<uni-icons type="plus" size="24" color="#064E3B"></uni-icons>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="strategy-list">
|
|
|
|
<view
|
|
class="strategy-card"
|
|
v-for="(item, index) in strategies"
|
|
:key="index"
|
|
>
|
|
<view class="watermark" v-if="index === 0">
|
|
<uni-icons type="bars" size="120" color="#000" style="opacity:0.03"></uni-icons>
|
|
</view>
|
|
|
|
<view class="flex-row items-center gap-3 mb-4 card-header-row">
|
|
<view class="icon-box" :class="item.bgClass">
|
|
<text class="icon-text">{{ item.iconChar }}</text>
|
|
</view>
|
|
<view class="flex-col">
|
|
<text class="card-head">{{ item.title }}</text>
|
|
<text class="card-tag" :class="item.tagClass">{{ item.tag }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<text class="desc-text">{{ item.desc }}</text>
|
|
|
|
<view class="footer-row">
|
|
<view class="flex-row gap-2">
|
|
<view class="tag-gray" v-for="(tag, tIndex) in item.tags" :key="tIndex">
|
|
<text class="tag-text">{{ tag }}</text>
|
|
</view>
|
|
</view>
|
|
<button
|
|
:class="item.btnClass"
|
|
@click="handleAction(item)"
|
|
>
|
|
{{ item.btnText }}
|
|
</button>
|
|
</view>
|
|
</view>
|
|
|
|
<view style="height: 100rpx;"></view>
|
|
</view>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, getCurrentInstance } from 'vue';
|
|
import { onShow } from '@dcloudio/uni-app';
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
const api = proxy.$api;
|
|
|
|
const strategies = ref([]);
|
|
|
|
// 防止重复请求的标志
|
|
let isFetching = false;
|
|
|
|
const fetchStrategies = async () => {
|
|
try {
|
|
const response = await api.strategies.getStrategies();
|
|
if (response.code === 200) {
|
|
strategies.value = response.data.map(item => ({
|
|
id: item.id,
|
|
title: item.name,
|
|
tag: item.tags?.[0] || '策略',
|
|
desc: item.description,
|
|
tags: item.tags || [],
|
|
riskLevel: item.riskLevel,
|
|
bgClass: item.type === 'ma_trend' ? 'bg-emerald-900' : item.type === 'risk_parity' ? 'bg-blue-600' : 'bg-orange-500',
|
|
tagClass: item.type === 'ma_trend' ? 'text-emerald-700' : item.type === 'risk_parity' ? 'text-blue-700' : 'text-orange-700',
|
|
iconChar: item.name?.charAt(0) || 'S',
|
|
btnClass: 'btn-primary',
|
|
btnText: '配置'
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error('获取策略数据失败:', error);
|
|
}
|
|
};
|
|
|
|
onShow(async () => {
|
|
isFetching = true;
|
|
await fetchStrategies();
|
|
isFetching = false;
|
|
});
|
|
|
|
const goToAdd = () => {
|
|
uni.navigateTo({ url: '/pages/strategies/edit/edit' });
|
|
};
|
|
|
|
const handleAction = (item) => {
|
|
console.log('点击策略:', item.title);
|
|
uni.navigateTo({ url: `/pages/strategies/edit/edit?id=${item.id}` });
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 全局布局 */
|
|
.page-container {
|
|
min-height: 100vh;
|
|
background-color: #F9FAFB;
|
|
}
|
|
.header-section {
|
|
padding: 40rpx 40rpx 20rpx 40rpx;
|
|
background-color: #F9FAFB;
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
}
|
|
.strategy-list {
|
|
padding: 0 40rpx;
|
|
}
|
|
|
|
/* 状态栏适配 */
|
|
.status-bar-height { height: var(--status-bar-height); }
|
|
|
|
/* 文字样式 */
|
|
.title-lg { font-size: 48rpx; font-weight: 800; color: #111827; display: block; }
|
|
.subtitle { font-size: 28rpx; color: #6B7280; margin-top: 8rpx; display: block; }
|
|
|
|
/* === 新增:添加按钮样式 === */
|
|
.add-btn-box {
|
|
width: 88rpx;
|
|
height: 88rpx;
|
|
background-color: #FFFFFF;
|
|
border-radius: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
|
|
border: 1rpx solid #E5E7EB;
|
|
}
|
|
.add-btn-box:active { background-color: #F3F4F6; }
|
|
|
|
/* 策略卡片 */
|
|
.strategy-card {
|
|
background-color: #FFFFFF;
|
|
border-radius: 32rpx;
|
|
padding: 40rpx;
|
|
margin-bottom: 32rpx;
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.06);
|
|
border: 1rpx solid #E5E7EB;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.strategy-card:active {
|
|
transform: translateY(2rpx);
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.04);
|
|
}
|
|
.watermark { position: absolute; right: -20rpx; top: -20rpx; z-index: 0; pointer-events: none; }
|
|
.card-header-row { position: relative; z-index: 1; }
|
|
|
|
/* 图标盒子 */
|
|
.icon-box {
|
|
width: 80rpx; height: 80rpx; border-radius: 20rpx;
|
|
display: flex; align-items: center; justify-content: center;
|
|
}
|
|
.bg-emerald-900 { background-color: #064e3b; }
|
|
.bg-blue-600 { background-color: #2563EB; }
|
|
.bg-orange-500 { background-color: #F97316; }
|
|
|
|
.icon-text { color: #fff; font-weight: bold; font-size: 32rpx; }
|
|
|
|
/* 卡片文本 */
|
|
.card-head { font-size: 32rpx; font-weight: 700; color: #111827; display: block;}
|
|
.card-tag { font-size: 22rpx; font-weight: 600; margin-top: 4rpx; }
|
|
.text-emerald-700 { color: #047857; }
|
|
.text-blue-700 { color: #1D4ED8; }
|
|
.text-orange-700 { color: #C2410C; }
|
|
|
|
.desc-text {
|
|
font-size: 26rpx;
|
|
color: #4B5563;
|
|
line-height: 1.6;
|
|
margin-bottom: 32rpx;
|
|
display: block;
|
|
margin-top: 24rpx;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* 底部操作区 */
|
|
.footer-row {
|
|
display: flex; justify-content: space-between; align-items: center;
|
|
padding-top: 32rpx;
|
|
border-top: 1rpx solid #F9FAFB;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
.tag-gray { background-color: #F3F4F6; padding: 6rpx 16rpx; border-radius: 12rpx; margin-right: 12rpx; }
|
|
.tag-text { font-size: 22rpx; color: #6B7280; font-weight: 500; }
|
|
|
|
/* 按钮样式 */
|
|
.btn-primary {
|
|
background-color: #064e3b;
|
|
color: #fff;
|
|
font-size: 24rpx;
|
|
font-weight: 600;
|
|
padding: 0 32rpx;
|
|
height: 64rpx;
|
|
line-height: 64rpx;
|
|
border-radius: 999rpx;
|
|
margin: 0;
|
|
border: none;
|
|
}
|
|
.btn-primary::after { border: none; }
|
|
|
|
/* 工具类 */
|
|
.flex-row { display: flex; flex-direction: row; }
|
|
.flex-col { display: flex; flex-direction: column; }
|
|
.items-center { align-items: center; }
|
|
.items-start { align-items: flex-start; }
|
|
.justify-between { justify-content: space-between; }
|
|
.gap-3 { gap: 24rpx; }
|
|
.gap-2 { gap: 16rpx; }
|
|
.mb-4 { margin-bottom: 32rpx; }
|
|
</style> |