Initial commit: TradeMate 外贸小助手 MVP

项目结构:
- backend/     Python FastAPI 后端
- uni-app/     uni-app跨端前端
- docs/        设计文档
- docker-compose.yml  Docker编排
- nginx/scripts/systemd 运维配置

已完成功能:
- 用户认证 (JWT)
- 智能翻译 + 回复建议
- 营销素材生成
- 客户管理 + 沉默检测
- 报价单管理
- 产品库管理
- 汇率换算
- 推送通知 (uni-push)
- WhatsApp Webhook框架
- Celery定时任务
This commit is contained in:
TradeMate Dev
2026-05-08 18:17:12 +08:00
commit c6206787da
121 changed files with 11743 additions and 0 deletions
@@ -0,0 +1,95 @@
<template>
<view class="custom-tabbar" v-if="showTabbar">
<view
class="tab-item"
v-for="(item, index) in tabList"
:key="index"
@click="switchTab(index)"
>
<text class="tab-icon" :class="{ active: current === index }">{{ item.icon }}</text>
<text class="tab-text" :class="{ active: current === index }">{{ item.text }}</text>
</view>
</view>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
const current = ref(0)
const tabList = ref([
{ pagePath: '/pages/index/index', text: '首页', icon: '🏠' },
{ pagePath: '/pages/translate/translate', text: '翻译', icon: '🔤' },
{ pagePath: '/pages/customers/customers', text: '客户', icon: '👥' },
{ pagePath: '/pages/marketing/marketing', text: '营销', icon: '📢' },
{ pagePath: '/pages/quotation/quotation', text: '报价', icon: '📄' },
])
onMounted(() => {
updateCurrent()
})
const showTabbar = computed(() => {
const pages = getCurrentPages()
if (pages.length) {
const currentPage = pages[pages.length - 1].route || ''
return !currentPage.includes('login')
}
return true
})
const updateCurrent = () => {
const pages = getCurrentPages()
if (pages.length) {
const currentPage = pages[pages.length - 1].$page?.fullPath || pages[pages.length - 1].route || ''
const index = tabList.value.findIndex(item => currentPage.includes(item.pagePath))
if (index !== -1) current.value = index
}
}
uni.onAppRoute(() => {
updateCurrent()
})
const switchTab = (index) => {
if (current.value === index) return
current.value = index
uni.switchTab({ url: tabList.value[index].pagePath })
}
</script>
<style lang="scss" scoped>
.custom-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: #fff;
display: flex;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
z-index: 999;
}
.tab-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-icon {
font-size: 44rpx;
margin-bottom: 4rpx;
}
.tab-text {
font-size: 22rpx;
color: #666;
}
.tab-text.active {
color: #1890ff;
}
</style>