feat(frontend):添加支持开源赞助计划

- 在关于页面中增加支持开源赞助计划的表格
- 列出不同赞助等级及其对应的权益说明
- 旨在鼓励用户支持项目发展,提供不同级别的赞助选项
This commit is contained in:
ArvinLovegood 2025-07-09 14:16:31 +08:00
parent 6ec0f5fbe0
commit fd905ff278
9 changed files with 99 additions and 19 deletions

View File

@ -46,11 +46,11 @@
### 支持开源💕计划
| 赞助计划 | 赞助等级 | 权益说明 |
|:--------------------|-------|:--------------------------------------------------------|
| 每月 0 RMB | vip0 | 🌟 全部功能,软件自动更新(从GitHub下载),自行解决github平台网络问题。 |
| 每月赞助 18.8 RMB | vip1 | 💕 全部功能,软件自动更新(从CDN下载),更新快速便捷。AI配置指导提示词参考等 |
| 每月赞助 X RMB | vipX | 🧩 更多计划视go-stock开源项目发展情况而定...(承接GitHub项目README广告推广💖) |
| 赞助计划 | 赞助等级 | 权益说明 |
|:--------------------------------|-------|:-------------------------------------------------------|
| 每月 0 RMB | vip0 | 🌟 全部功能,软件自动更新(从GitHub下载),自行解决github平台网络问题。 |
| 每月赞助 18.8 RMB<br>每年赞助 120 RMB | vip1 | 💕 全部功能,软件自动更新(从CDN下载),更新快速便捷。AI配置指导提示词参考等 |
| 每月赞助 X RMB | vipX | 🧩 更多计划视go-stock开源项目发展情况而定...(承接GitHub项目README广告推广💖) |
## 🧩 重大功能开发计划
| 功能说明 | 状态 | 备注 |

59
app.go
View File

@ -4,7 +4,10 @@ import (
"bytes"
"context"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
"github.com/inconshreveable/go-update"
"go-stock/backend/data"
"go-stock/backend/db"
@ -27,11 +30,12 @@ import (
// App struct
type App struct {
ctx context.Context
cache *freecache.Cache
cron *cron.Cron
cronEntrys map[string]cron.EntryID
AiTools []data.Tool
ctx context.Context
cache *freecache.Cache
cron *cron.Cron
cronEntrys map[string]cron.EntryID
AiTools []data.Tool
SponsorInfo map[string]any
}
// NewApp creates a new App application struct
@ -102,6 +106,9 @@ func AddTools(tools []data.Tool) []data.Tool {
return tools
}
func (a *App) GetSponsorInfo() map[string]any {
return a.SponsorInfo
}
func (a *App) CheckUpdate() {
releaseVersion := &models.GitHubReleaseVersion{}
_, err := resty.New().R().
@ -134,17 +141,51 @@ func (a *App) CheckUpdate() {
go runtime.EventsEmit(a.ctx, "updateVersion", releaseVersion)
return
}
downloadUrl := fmt.Sprintf("https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-windows-amd64.exe", releaseVersion.TagName)
if IsMacOS() {
downloadUrl = fmt.Sprintf("https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-darwin-universal", releaseVersion.TagName)
}
sponsorCode := a.GetConfig().SponsorCode
if sponsorCode != "" {
encrypted, err := hex.DecodeString(sponsorCode)
if err != nil {
logger.SugaredLogger.Error(err.Error())
return
}
key, err := hex.DecodeString(BuildKey)
if err != nil {
logger.SugaredLogger.Error(err.Error())
return
}
decrypt := string(cryptor.AesEcbDecrypt(encrypted, key))
logger.SugaredLogger.Errorf("赞助码: %s", decrypt)
err = json.Unmarshal([]byte(decrypt), &a.SponsorInfo)
if err != nil {
logger.SugaredLogger.Error(err.Error())
return
}
if IsWindows() {
if a.SponsorInfo["winDownUrl"] == nil {
downloadUrl = fmt.Sprintf("https://gitproxy.click/https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-windows-amd64.exe", releaseVersion.TagName)
} else {
downloadUrl = a.SponsorInfo["winDownUrl"].(string)
}
}
if IsMacOS() {
if a.SponsorInfo["macDownUrl"] == nil {
downloadUrl = fmt.Sprintf("https://gitproxy.click/https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-darwin-universal", releaseVersion.TagName)
} else {
downloadUrl = a.SponsorInfo["macDownUrl"].(string)
}
}
}
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{
"time": "发现新版本:" + releaseVersion.TagName,
"isRed": false,
"source": "go-stock",
"content": fmt.Sprintf("当前版本:%s, 最新版本:%s,开始下载...", Version, releaseVersion.TagName),
})
downloadUrl := fmt.Sprintf("https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-windows-amd64.exe", releaseVersion.TagName)
if IsMacOS() {
downloadUrl = fmt.Sprintf("https://github.com/ArvinLovegood/go-stock/releases/download/%s/go-stock-darwin-universal", releaseVersion.TagName)
}
resp, err := resty.New().R().Get(downloadUrl)
if err != nil {
go runtime.EventsEmit(a.ctx, "newsPush", map[string]any{

View File

@ -35,6 +35,7 @@ type Settings struct {
BrowserPoolSize int `json:"browserPoolSize"`
EnableFund bool `json:"enableFund"`
EnablePushNews bool `json:"enablePushNews"`
SponsorCode string `json:"sponsorCode"`
}
func (receiver Settings) TableName() string {
@ -80,6 +81,7 @@ func (s SettingsApi) UpdateConfig() string {
"dark_theme": s.Config.DarkTheme,
"enable_fund": s.Config.EnableFund,
"enable_push_news": s.Config.EnablePushNews,
"sponsor_code": s.Config.SponsorCode,
})
} else {
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
@ -108,6 +110,7 @@ func (s SettingsApi) UpdateConfig() string {
DarkTheme: s.Config.DarkTheme,
EnableFund: s.Config.EnableFund,
EnablePushNews: s.Config.EnablePushNews,
SponsorCode: s.Config.SponsorCode,
})
}
return "保存成功!"

View File

@ -3,7 +3,7 @@
// preview.cssstyle.css
import 'md-editor-v3/lib/preview.css';
import {h, onBeforeUnmount, onMounted, ref} from 'vue';
import {CheckUpdate, GetVersionInfo} from "../../wailsjs/go/main/App";
import {CheckUpdate, GetVersionInfo,GetSponsorInfo} from "../../wailsjs/go/main/App";
import {EventsOff, EventsOn} from "../../wailsjs/runtime";
import {NAvatar, NButton, useNotification} from "naive-ui";
const updateLog = ref('');
@ -12,6 +12,9 @@ const icon = ref('https://raw.githubusercontent.com/ArvinLovegood/go-stock/maste
const alipay =ref('https://github.com/ArvinLovegood/go-stock/raw/master/build/screenshot/alipay.jpg')
const wxpay =ref('https://github.com/ArvinLovegood/go-stock/raw/master/build/screenshot/wxpay.jpg')
const notify = useNotification()
const vipLevel=ref("");
const vipStartTime=ref("");
const vipEndTime=ref("");
onMounted(() => {
document.title = '关于软件';
@ -21,7 +24,17 @@ onMounted(() => {
icon.value = res.icon;
alipay.value=res.alipay;
wxpay.value=res.wxpay;
GetSponsorInfo().then((res) => {
vipLevel.value = res.vipLevel;
vipStartTime.value = res.vipStartTime;
vipEndTime.value = res.vipEndTime;
})
});
})
onBeforeUnmount(() => {
notify.destroyAll()
@ -87,10 +100,14 @@ EventsOn("updateVersion",async (msg) => {
<n-space vertical >
<n-image width="100" :src="icon" />
<h1>
<n-badge :value="versionInfo" :offset="[50,10]" type="success">
<n-badge v-if="!vipLevel" :value="versionInfo" :offset="[50,10]" type="success">
<n-gradient-text type="info" :size="50" >go-stock</n-gradient-text>
</n-badge>
<n-badge v-if="vipLevel" :value="versionInfo" :offset="[50,10]" type="success">
<n-gradient-text type="warning" :size="50" >go-stock</n-gradient-text><n-tag :bordered="false" size="small" type="warning">VIP{{vipLevel}}</n-tag>
</n-badge>
</h1>
<n-gradient-text type="warning" v-if="vipLevel" >vip到期时间{{vipEndTime}}</n-gradient-text>
<n-button size="tiny" @click="CheckUpdate" type="info" tertiary >检查更新</n-button>
<div style="justify-self: center;text-align: left" >
<p>自选股行情实时监控基于Wails和NaiveUI构建的AI赋能股票分析工具</p>
@ -126,7 +143,7 @@ EventsOn("updateVersion",async (msg) => {
<n-td>每月 0 RMB</n-td><n-td>vip0</n-td><n-td>🌟 全部功能,软件自动更新(从GitHub下载),自行解决github平台网络问题</n-td>
</n-tr>
<n-tr>
<n-td>每月赞助 18.8 RMB</n-td><n-td>vip1</n-td><n-td>💕 全部功能,软件自动更新(从CDN下载),更新快速便捷AI配置指导提示词参考等</n-td>
<n-td>赞助 18.8 RMB/<br>赞助 120 RMB/</n-td><n-td>vip1</n-td><n-td>💕 全部功能,软件自动更新(从CDN下载),更新快速便捷AI配置指导提示词参考等</n-td>
</n-tr>
<n-tr>
<n-td>每月赞助 X RMB</n-td><n-td>vipX</n-td><n-td>🧩 更多计划视go-stock开源项目发展情况而定...(承接GitHub项目README广告推广💖)</n-td>

View File

@ -46,6 +46,7 @@ const formValue = ref({
darkTheme:true,
enableFund:false,
enablePushNews:false,
sponsorCode:"",
})
const promptTemplates=ref([])
onMounted(()=>{
@ -80,6 +81,8 @@ onMounted(()=>{
formValue.value.darkTheme = res.darkTheme
formValue.value.enableFund = res.enableFund
formValue.value.enablePushNews = res.enablePushNews
formValue.value.sponsorCode = res.sponsorCode
//console.log(res)
})
@ -120,7 +123,8 @@ function saveConfig(){
enableNews:formValue.value.enableNews,
darkTheme:formValue.value.darkTheme,
enableFund:formValue.value.enableFund,
enablePushNews:formValue.value.enablePushNews
enablePushNews:formValue.value.enablePushNews,
sponsorCode:formValue.value.sponsorCode
})
@ -199,6 +203,7 @@ function importConfig(){
formValue.value.darkTheme = config.darkTheme
formValue.value.enableFund = config.enableFund
formValue.value.enablePushNews = config.enablePushNews
formValue.value.sponsorCode = config.sponsorCode
// formRef.value.resetFields()
};
reader.readAsText(file);
@ -293,9 +298,12 @@ function deletePrompt(ID){
<n-form-item-gi :span="10" label="浏览器安装路径:" path="browserPath" >
<n-input type="text" placeholder="浏览器安装路径" v-model:value="formValue.browserPath" clearable />
</n-form-item-gi>
<n-form-item-gi :span="6" label="指数基金:" path="enableFund" >
<n-form-item-gi :span="3" label="指数基金:" path="enableFund" >
<n-switch v-model:value="formValue.enableFund" />
</n-form-item-gi>
<n-form-item-gi :span="11" label="赞助码:" path="sponsorCode" >
<n-input :show-count="true" placeholder="赞助码" v-model:value="formValue.sponsorCode" />
</n-form-item-gi>
</n-grid>
</n-card>

View File

@ -49,6 +49,8 @@ export function GetMoneyRankSina(arg1:string):Promise<Array<Record<string, any>>
export function GetPromptTemplates(arg1:string,arg2:string):Promise<any>;
export function GetSponsorInfo():Promise<Record<string, any>>;
export function GetStockCommonKLine(arg1:string,arg2:string,arg3:number):Promise<any>;
export function GetStockKLine(arg1:string,arg2:string,arg3:number):Promise<any>;

View File

@ -94,6 +94,10 @@ export function GetPromptTemplates(arg1, arg2) {
return window['go']['main']['App']['GetPromptTemplates'](arg1, arg2);
}
export function GetSponsorInfo() {
return window['go']['main']['App']['GetSponsorInfo']();
}
export function GetStockCommonKLine(arg1, arg2, arg3) {
return window['go']['main']['App']['GetStockCommonKLine'](arg1, arg2, arg3);
}

View File

@ -343,6 +343,7 @@ export namespace data {
browserPoolSize: number;
enableFund: boolean;
enablePushNews: boolean;
sponsorCode: string;
static createFrom(source: any = {}) {
return new Settings(source);
@ -379,6 +380,7 @@ export namespace data {
this.browserPoolSize = source["browserPoolSize"];
this.enableFund = source["enableFund"];
this.enablePushNews = source["enablePushNews"];
this.sponsorCode = source["sponsorCode"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {

View File

@ -347,6 +347,9 @@ func checkDir(dir string) {
os.Mkdir(dir, os.ModePerm)
log.SugaredLogger.Info("create dir: " + dir)
}
if BuildKey == "" {
BuildKey = "cc1e0d684e32f176c56ff1fcf384dcd9"
}
}
// PanicHandler 捕获 panic 的包装函数