feat: finish payment page layout

This commit is contained in:
RockYang 2023-11-07 18:10:28 +08:00
parent 4a81826d19
commit d0b8d666e4
8 changed files with 178 additions and 31 deletions

View File

@ -33,9 +33,10 @@ func NewDefaultConfig() *types.AppConfig {
BasePath: "./static/upload", BasePath: "./static/upload",
}, },
}, },
MjConfig: types.MidJourneyConfig{Enabled: false}, MjConfig: types.MidJourneyConfig{Enabled: false},
SdConfig: types.StableDiffusionConfig{Enabled: false, Txt2ImgJsonPath: "res/text2img.json"}, SdConfig: types.StableDiffusionConfig{Enabled: false, Txt2ImgJsonPath: "res/text2img.json"},
WeChatBot: false, WeChatBot: false,
AlipayConfig: types.AlipayConfig{SandBox: true},
} }
} }

View File

@ -61,7 +61,8 @@ type AliYunSmsConfig struct {
} }
type AlipayConfig struct { type AlipayConfig struct {
Enabled bool // 是否启用支付宝服务 Enabled bool // 是否启用该服务
SandBox bool // 是否沙箱环境
Company string // 公司名称 Company string // 公司名称
UserId string // 支付宝用户 ID UserId string // 支付宝用户 ID
AppId string // 支付宝 AppID AppId string // 支付宝 AppID

BIN
api/res/img/alipay.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -20,27 +20,27 @@ var logger = logger2.GetLogger()
func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) { func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
config := appConfig.AlipayConfig config := appConfig.AlipayConfig
if !config.Enabled { if !config.Enabled {
logger.Info("Disabled alipay service") logger.Info("Disabled Alipay service")
return nil, nil return nil, nil
} }
priKey, err := readKey(config.PrivateKey) priKey, err := readKey(config.PrivateKey)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("error with read App Private key: %v", err)
} }
xClient, err := alipay.New(config.AppId, priKey, true) xClient, err := alipay.New(config.AppId, priKey, !config.SandBox)
if err != nil { if err != nil {
return nil, fmt.Errorf("error with initialize alipay service: %v", err) return nil, fmt.Errorf("error with initialize alipay service: %v", err)
} }
if err = xClient.LoadAppCertPublicKeyFromFile(config.PublicKey); err != nil { if err = xClient.LoadAppCertPublicKeyFromFile(config.PublicKey); err != nil {
return nil, fmt.Errorf("error with loading alipay CertPublicKey: %v", err) return nil, fmt.Errorf("error with loading App PublicKey: %v", err)
} }
if err = xClient.LoadAliPayRootCertFromFile(config.RootCert); err != nil { if err = xClient.LoadAliPayRootCertFromFile(config.RootCert); err != nil {
return nil, fmt.Errorf("error with loading alipay RootCert: %v", err) return nil, fmt.Errorf("error with loading alipay RootCert: %v", err)
} }
if err = xClient.LoadAlipayCertPublicKeyFromFile(config.AlipayPublicKey); err != nil { if err = xClient.LoadAlipayCertPublicKeyFromFile(config.AlipayPublicKey); err != nil {
return nil, fmt.Errorf("error with loading alipay AlipayCertPublicKey: %v", err) return nil, fmt.Errorf("error with loading Alipay PublicKey: %v", err)
} }
return &AlipayService{config: &config, client: xClient}, nil return &AlipayService{config: &config, client: xClient}, nil

View File

@ -81,7 +81,7 @@ func (s *Service) Run() {
// PushTask 推送任务到队列 // PushTask 推送任务到队列
func (s *Service) PushTask(task types.SdTask) { func (s *Service) PushTask(task types.SdTask) {
logger.Infof("add a new MidJourney Task: %+v", task) logger.Infof("add a new Stable Diffusion Task: %+v", task)
s.taskQueue.RPush(task) s.taskQueue.RPush(task)
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
web/public/images/vip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,39 +1,184 @@
<template> <template>
<div class="page-member" :style="{ height: winHeight + 'px' }"> <div class="member custom-scroll">
<div class="inner"> <div class="title">
<h1>会员充值中心</h1> 会员充值中心
<h2>页面正在紧锣密鼓开发中敬请期待</h2>
</div> </div>
<div class="inner" :style="{height: listBoxHeight + 'px'}">
<div class="info">
<el-alert type="info" show-icon :closable="false" effect="dark">
<strong>说明:</strong> 成为本站会员后每月有500次对话额度50 AI 绘画额度限制下月1号解除若在期间超过次数后可单独购买点卡
当月充值的点卡有效期可以延期到下个月底
</el-alert>
</div>
<ItemList :items="list" v-if="list.length > 0" :gap="30" :width="250">
<template #default="scope">
<div class="product-item" :style="{width: scope.width+'px'}" @click="pay(scope.item)">
<div class="image-container">
<el-image :src="vipImg" fit="cover"/>
</div>
<div class="product-title">
<span class="name">{{ scope.item.name }}</span>
</div>
<div class="product-info">
<div class="info-line">
<span class="label">商品原价</span>
<span class="price">{{ scope.item.price }}</span>
</div>
<div class="info-line">
<span class="label">促销立减</span>
<span class="price">{{ scope.item.discount }}</span>
</div>
<div class="info-line">
<span class="label">有效期</span>
<span class="expire" v-if="scope.item.days > 0">{{ scope.item.days }}</span>
<span class="expire" v-else>当月有效</span>
</div>
</div>
</div>
</template>
</ItemList>
</div>
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false"/>
</div> </div>
</template> </template>
<script setup> <script setup>
import {ref} from "vue" import {nextTick, onMounted, ref} from "vue"
import {ElMessage} from "element-plus";
import {httpGet, httpPost} from "@/utils/http";
import ItemList from "@/components/ItemList.vue";
import {Delete, Plus} from "@element-plus/icons-vue";
import LoginDialog from "@/components/LoginDialog.vue";
import {checkSession} from "@/action/session";
import {arrayContains, removeArrayItem, substr} from "@/utils/libs";
import router from "@/router";
const listBoxHeight = window.innerHeight - 97
const list = ref([])
const showLoginDialog = ref(false)
const elements = ref(null)
const vipImg = ref("/images/vip.png")
onMounted(() => {
httpGet("/api/product/list").then((res) => {
list.value = res.data
}).catch(e => {
ElMessage.error("获取产品套餐失败:" + e.message)
})
})
const pay = (row) => {
checkSession().then(user => {
console.log(row)
}).catch(() => {
showLoginDialog.value = true
})
}
const winHeight = ref(window.innerHeight)
</script> </script>
<style lang="stylus" scoped> <style lang="stylus">
.page-member { @import "@/assets/css/custom-scroll.styl"
display: flex; .member {
justify-content: center;
align-items center
background-color: #282c34; background-color: #282c34;
height 100vh
.title {
text-align center
background-color #25272d
font-size 24px
color #ffffff
padding 10px
border-bottom 1px solid #3c3c3c
}
.inner { .inner {
text-align center color #ffffff
padding 15px;
overflow-y visible
overflow-x hidden
h1 { .info {
color: #202020; .el-alert__description {
font-size: 80px; font-size 14px !important
font-weight: bold; margin 0
letter-spacing: 0.1em; }
text-shadow: -1px -1px 1px #111111, 2px 2px 1px #363636; padding 10px 20px
} }
h2 { .list-box {
color #ffffff; .product-item {
font-weight: bold; border 1px solid #666666
border-radius 6px
overflow hidden
cursor pointer
transition: all 0.3s ease; /* 添加过渡效果 */
.image-container {
display flex
justify-content center
.el-image {
padding 6px
.el-image__inner {
border-radius 10px
}
}
}
.product-title {
display flex
padding 10px
.name {
width 100%
text-align center
font-size 16px
font-weight bold
color #47fff1
}
}
.product-info {
padding 10px 20px
font-size 14px
color #999999
.info-line {
display flex
width 100%
padding 5px 0
.label {
display flex
width 100%
}
.price, .expire {
display flex
width 80px
justify-content right
}
.price {
color #f56c6c
}
.expire {
color #409eff
}
}
}
&:hover {
box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
transform: translateY(-10px); /* 向上移动10像素 */
}
}
} }
} }