refactor: replace direct WeChat/Alipay with unified pay-api gateway
Switch from direct WeChat Pay / Alipay integrations to the unified
宇之然 pay-api gateway (HMAC-SHA256 auth). Removes wechat_pay.py,
keeps PaymentGateway abstraction, adds UnifiedPayService. Simplifies
payment.py create_order to {plan, pay_type} params. Single webhook
endpoint replaces separate WeChat/Alipay notify handlers.
This commit is contained in:
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 203 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -66,14 +66,47 @@
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>TradeMate © {{ new Date().getFullYear() }}</span>
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<div class="footer-brand">TradeMate</div>
|
||||
<p class="footer-tagline">AI 外贸小助手 · 让外贸更简单</p>
|
||||
<div class="qrcode-row">
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran.jpg" alt="微信公众号" class="qrcode-img" />
|
||||
<span>微信公众号</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran-tech.jpg" alt="微信服务号" class="qrcode-img" />
|
||||
<span>微信服务号</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran-yhl.jpg" alt="小程序" class="qrcode-img" />
|
||||
<span>小程序</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/kefu.png" alt="客服" class="qrcode-img" />
|
||||
<span>微信客服</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© {{ new Date().getFullYear() }} TradeMate 外贸小助手. 保留所有权利.</p>
|
||||
<div class="footer-links">
|
||||
<a href="http://beian.miit.gov.cn/" target="_blank">{{ beianInfo.icp }}</a>
|
||||
<a v-if="beianInfo.showGongan" :href="beianInfo.gonganLink" target="_blank" rel="noreferrer" class="gongan-link">
|
||||
<img src="/images/beian/gongan-beian.png" alt="公安备案" class="gongan-icon" />
|
||||
{{ beianInfo.gongan }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { getUnreadCount } from '@/api'
|
||||
@@ -85,6 +118,17 @@ const collapsed = ref(false)
|
||||
const showMobileMenu = ref(false)
|
||||
const unread = ref(0)
|
||||
|
||||
const beianInfo = computed(() => {
|
||||
const hostname = window.location.hostname
|
||||
if (hostname === 'yuzhiran.com' || hostname === 'www.yuzhiran.com') {
|
||||
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
|
||||
}
|
||||
if (hostname === 'yuzhiran.com.cn' || hostname === 'www.yuzhiran.com.cn') {
|
||||
return { icp: '京ICP备2026007249号-2', gongan: '京公网安备11011502039622号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039622', showGongan: true }
|
||||
}
|
||||
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const res = await getUnreadCount()
|
||||
@@ -114,7 +158,20 @@ function handleLogout() {
|
||||
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
|
||||
.notif-badge :deep(.el-badge__content) { top: 8px; right: 4px; }
|
||||
.content { flex: 1; padding: 24px; overflow-y: auto; background: #f5f5f5; }
|
||||
.footer { text-align: center; padding: 12px; color: #999; font-size: 12px; border-top: 1px solid #e8e8e8; background: #fff; flex-shrink: 0; }
|
||||
.footer { text-align: center; color: #999; font-size: 12px; border-top: 1px solid #e8e8e8; background: #fff; flex-shrink: 0; }
|
||||
.footer-content { padding: 16px 24px 12px; }
|
||||
.footer-section { margin-bottom: 12px; }
|
||||
.footer-brand { font-size: 14px; font-weight: 700; color: #1890ff; margin-bottom: 2px; }
|
||||
.footer-tagline { color: #999; font-size: 11px; margin-bottom: 10px; }
|
||||
.qrcode-row { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
|
||||
.qrcode-item { display: flex; flex-direction: column; align-items: center; gap: 3px; color: #999; font-size: 10px; }
|
||||
.qrcode-img { width: 44px; height: 44px; border-radius: 6px; }
|
||||
.footer-bottom { border-top: 1px solid #eee; padding-top: 10px; display: flex; justify-content: center; align-items: center; gap: 14px; flex-wrap: wrap; }
|
||||
.footer-links { display: flex; gap: 14px; align-items: center; }
|
||||
.footer-links a { color: #999; text-decoration: none; }
|
||||
.footer-links a:hover { color: #1890ff; }
|
||||
.gongan-link { display: inline-flex; align-items: center; gap: 4px; }
|
||||
.gongan-icon { height: 14px; vertical-align: middle; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sidebar { position: fixed; left: -220px; top: 0; bottom: 0; z-index: 1000; transition: left 0.3s; }
|
||||
|
||||
@@ -75,7 +75,42 @@
|
||||
</section>
|
||||
|
||||
<footer class="landing-footer">
|
||||
<span>TradeMate 外贸小助手 © {{ new Date().getFullYear() }}</span>
|
||||
<div class="footer-inner">
|
||||
<div class="footer-top">
|
||||
<div class="footer-info">
|
||||
<div class="footer-brand">TradeMate</div>
|
||||
<p class="footer-desc">AI 外贸小助手 · 让外贸更简单</p>
|
||||
</div>
|
||||
<div class="qrcode-row">
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran.jpg" alt="微信公众号" class="qrcode-img" />
|
||||
<span>公众号</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran-tech.jpg" alt="微信服务号" class="qrcode-img" />
|
||||
<span>服务号</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/yuzhiran-yhl.jpg" alt="小程序" class="qrcode-img" />
|
||||
<span>小程序</span>
|
||||
</div>
|
||||
<div class="qrcode-item">
|
||||
<img src="/images/yzr/kefu.png" alt="客服" class="qrcode-img" />
|
||||
<span>客服</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© {{ new Date().getFullYear() }} TradeMate 外贸小助手. 保留所有权利.</p>
|
||||
<div class="footer-links">
|
||||
<a href="http://beian.miit.gov.cn/" target="_blank">{{ beianInfo.icp }}</a>
|
||||
<a v-if="beianInfo.showGongan" :href="beianInfo.gonganLink" target="_blank" rel="noreferrer" class="gongan-link">
|
||||
<img src="/images/beian/gongan-beian.png" alt="公安备案" class="gongan-icon" />
|
||||
{{ beianInfo.gongan }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
@@ -87,6 +122,17 @@ import { useAuthStore } from '@/stores/auth'
|
||||
import { register as registerApi } from '@/api'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const beianInfo = computed(() => {
|
||||
const hostname = window.location.hostname
|
||||
if (hostname === 'yuzhiran.com' || hostname === 'www.yuzhiran.com') {
|
||||
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
|
||||
}
|
||||
if (hostname === 'yuzhiran.com.cn' || hostname === 'www.yuzhiran.com.cn') {
|
||||
return { icp: '京ICP备2026007249号-2', gongan: '京公网安备11011502039622号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039622', showGongan: true }
|
||||
}
|
||||
return { icp: '京ICP备2026007249号-1', gongan: '京公网安备11011502039545号', gonganLink: 'https://beian.mps.gov.cn/#/query/webSearch?code=11011502039545', showGongan: true }
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const auth = useAuthStore()
|
||||
@@ -195,7 +241,21 @@ function goWorkspace() { router.push('/workspace') }
|
||||
.feature-icon { width: 52px; height: 52px; border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
|
||||
.feature-card h3 { font-size: 16px; margin-bottom: 8px; color: #333; }
|
||||
.feature-card p { font-size: 13px; color: #999; line-height: 1.5; }
|
||||
.landing-footer { text-align: center; padding: 24px; color: #999; font-size: 12px; margin-top: auto; border-top: 1px solid #e8e8e8; background: #fff; }
|
||||
.landing-footer { text-align: center; color: #999; font-size: 12px; margin-top: auto; border-top: 1px solid #e8e8e8; background: #fff; padding: 24px 20px 16px; }
|
||||
.footer-inner { max-width: 1200px; margin: 0 auto; }
|
||||
.footer-top { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px; margin-bottom: 16px; }
|
||||
.footer-info { text-align: left; }
|
||||
.footer-brand { font-size: 18px; font-weight: 700; color: #1890ff; margin-bottom: 4px; }
|
||||
.footer-desc { color: #999; font-size: 13px; }
|
||||
.qrcode-row { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; }
|
||||
.qrcode-item { display: flex; flex-direction: column; align-items: center; gap: 4px; color: #999; font-size: 11px; }
|
||||
.qrcode-img { width: 60px; height: 60px; border-radius: 8px; }
|
||||
.footer-bottom { border-top: 1px solid #eee; padding-top: 14px; display: flex; justify-content: center; align-items: center; gap: 16px; flex-wrap: wrap; }
|
||||
.footer-links { display: flex; gap: 16px; align-items: center; }
|
||||
.footer-links a { color: #999; text-decoration: none; }
|
||||
.footer-links a:hover { color: #1890ff; }
|
||||
.gongan-link { display: inline-flex; align-items: center; gap: 4px; }
|
||||
.gongan-icon { height: 16px; vertical-align: middle; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-inner { flex-direction: column; padding: 40px 20px; }
|
||||
|
||||
Reference in New Issue
Block a user