From e33422867fe240a31a7b6bb4262aa937e8ca137e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B8=85?= <6581896+oncream@user.noreply.gitee.com> Date: Wed, 2 Apr 2025 19:04:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(1.0.2):=E5=AE=8C=E5=96=84=E6=94=B6?= =?UTF-8?q?=E8=B4=B9=E6=96=87=E7=AB=A0=E5=92=8C=E5=85=8D=E8=B4=B9=E6=96=87?= =?UTF-8?q?=E7=AB=A0=E7=9A=84=E8=8E=B7=E5=8F=96=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/application/article/service.go | 7 ++- .../persistence/column/column_repo.go | 2 +- ui/src/app/app.component.html | 2 +- ui/src/app/app.component.scss | 1 + ui/src/app/app.component.ts | 23 ++++++- .../app/core/interceptors/auth.interceptor.ts | 2 - .../article-detail/article-detail.page.html | 9 +++ .../article-detail/article-detail.page.scss | 37 +++++++++++ .../article-item/article-item.component.ts | 23 +++++-- .../column-describe/column-describe.page.ts | 2 +- .../special-column/special-column.page.html | 18 +++--- .../special-column/special-column.page.scss | 23 ++++--- .../special-column/special-column.page.ts | 63 +++++++++++++------ ui/src/app/mine/login/login.page.ts | 23 ++++--- 14 files changed, 177 insertions(+), 58 deletions(-) diff --git a/internal/application/article/service.go b/internal/application/article/service.go index f1f9d44..34199b6 100644 --- a/internal/application/article/service.go +++ b/internal/application/article/service.go @@ -39,6 +39,7 @@ func NewArticleService(repo article.ArticleRepository, var class_type = map[uint64]string{ 20014: "狙击龙虎榜", + 20013: "九点特供", 20015: "盘中宝", 20021: "风口研报", 20022: "公告全知道", @@ -50,6 +51,7 @@ var class_type = map[uint64]string{ var class_type_reverse = map[string]uint64{ "狙击龙虎榜": 20014, + "九点特供": 20013, "盘中宝": 20015, "风口研报": 20021, "公告全知道": 20022, @@ -68,7 +70,7 @@ func (a *ArticleService) Find(ePhone string, page *page.Page, searchParams map[s conds = append(conds, builder.Eq{"type": classCode}) } } - conds = append(conds, builder.And(builder.Gt{"ctime": time.Now().AddDate(0, 0, -2).Unix()})) + conds = append(conds, builder.And(builder.Gt{"ctime": time.Now().AddDate(0, 0, -2).Unix()}).And(builder.Eq{"is_free": 0})) articles := make([]*article.LianV1Article, 0) page.Content = &articles err := a.repo.Find(page, conds) @@ -211,8 +213,7 @@ func (a *ArticleService) FindFree(page *page.Page, searchParams map[string]strin conds = append(conds, builder.Eq{"type": classCode}) } } - conds = append(conds, builder.And(builder.Lt{"ctime": time.Now().AddDate(0, 0, -7).Unix()})) - page.PageSize = 20 + conds = append(conds, builder.And(builder.Lt{"ctime": time.Now().AddDate(0, 0, -2).Unix()}).And(builder.Eq{"is_free": 1})) articles := make([]*article.LianV1Article, 0) page.Content = &articles err := a.repo.Find(page, conds) diff --git a/internal/infrastructure/persistence/column/column_repo.go b/internal/infrastructure/persistence/column/column_repo.go index a321ff1..308f81e 100644 --- a/internal/infrastructure/persistence/column/column_repo.go +++ b/internal/infrastructure/persistence/column/column_repo.go @@ -71,7 +71,7 @@ func (r *ColumnRepositoryORM) FindByName(name string) (*column.Column, error) { return nil, err } if !exists { - return nil, errors.New("未找到用户") + return nil, errors.New("未找到专栏") } return &col, nil } diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index c65cfab..d490311 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -1,7 +1,7 @@ - + 首页 diff --git a/ui/src/app/app.component.scss b/ui/src/app/app.component.scss index e69de29..73b3f70 100644 --- a/ui/src/app/app.component.scss +++ b/ui/src/app/app.component.scss @@ -0,0 +1 @@ +// 移除之前的样式,因为 ion-tab-bar 已经有内置的样式 diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index da2f9aa..816fcfb 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; @Component({ selector: 'app-root', @@ -6,6 +7,22 @@ import { Component } from '@angular/core'; styleUrls: ['app.component.scss'], standalone: false, }) -export class AppComponent { - constructor() {} +export class AppComponent implements OnInit { + showTabs = true; + + constructor(private router: Router) {} + + ngOnInit() { + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + // 检查当前路由是否应该显示底部导航栏 + this.showTabs = this.shouldShowTabs(event.url); + } + }); + } + + private shouldShowTabs(url: string): boolean { + // 在首页和我的页面显示底部导航栏 + return url === '/home' || url === '/mine' || url === '/mine/login'; + } } diff --git a/ui/src/app/core/interceptors/auth.interceptor.ts b/ui/src/app/core/interceptors/auth.interceptor.ts index 8a761dd..272ba69 100644 --- a/ui/src/app/core/interceptors/auth.interceptor.ts +++ b/ui/src/app/core/interceptors/auth.interceptor.ts @@ -15,10 +15,8 @@ export class AuthInterceptor implements HttpInterceptor { //从请求头获取token intercept(req: HttpRequest, next: HttpHandler): Observable> { const token = localStorage.getItem('token'); - console.log(token) let authHeader = req.headers; if (token != null && tokenNotExpired()) { - console.log("is valid") const bearer = AuthConfigConsts.HEADER_PREFIX_BEARER + token; authHeader = authHeader.set(AuthConfigConsts.DEFAULT_HEADER_NAME, bearer); const authReq = req.clone({headers: authHeader}); diff --git a/ui/src/app/home/article-detail/article-detail.page.html b/ui/src/app/home/article-detail/article-detail.page.html index 2ab81da..0dc85b2 100644 --- a/ui/src/app/home/article-detail/article-detail.page.html +++ b/ui/src/app/home/article-detail/article-detail.page.html @@ -26,6 +26,15 @@
+ +
+ 相关个股: + {{ article?.stocks != '' ? article?.stocks : '暂无' }} +
+
+ 路诚声明: + 文章内容仅供参考,不构成投资建议。投资都据此操作,风险自担。 +
diff --git a/ui/src/app/home/article-detail/article-detail.page.scss b/ui/src/app/home/article-detail/article-detail.page.scss index 72b6c4c..0cc7e49 100644 --- a/ui/src/app/home/article-detail/article-detail.page.scss +++ b/ui/src/app/home/article-detail/article-detail.page.scss @@ -60,3 +60,40 @@ ion-back-button { } } } + +.stocks-content { + display: flex; + flex-direction: row; + align-content: center; + margin-bottom: 24px; + .sc-title { + font-size: 12px; + color: #8B8D93; + font-weight: 500; + margin-right: 10px; + } + .sc-content { + font-size: 12px; + color: #1D1E22; + font-weight: 500; + } +} + +.public-content { + display: flex; + flex-direction: row; + align-content: center; + margin-bottom: 24px; + span{ + opacity: 0.75; + font-size: 12px; + color: #8B8D93; + font-weight: 400; + } + .pb-title { + width: 60px; + } + .pb-content { + + } +} diff --git a/ui/src/app/home/component/article-item/article-item.component.ts b/ui/src/app/home/component/article-item/article-item.component.ts index 883f3b0..0dee74c 100644 --- a/ui/src/app/home/component/article-item/article-item.component.ts +++ b/ui/src/app/home/component/article-item/article-item.component.ts @@ -3,6 +3,7 @@ import {Article} from "../../../shared/model/article"; import {AlertController, NavController, ToastController} from "@ionic/angular"; import {getGiftCount, getUser, useGiftCount} from "../../../mine/mine.service"; import {HomeService} from "../../home.service"; +import {Router} from "@angular/router"; import {debounceTime, Subject, takeUntil} from "rxjs"; @@ -22,7 +23,8 @@ export class ArticleItemComponent implements OnInit,AfterViewInit { private alertCtrl: AlertController, private cdr: ChangeDetectorRef, private toastCtrl: ToastController, - private homeService: HomeService) { + private homeService: HomeService, + private router: Router) { } ngOnInit() { @@ -39,7 +41,21 @@ export class ArticleItemComponent implements OnInit,AfterViewInit { this.alertCtrl.create({ header: '提示', message: '请先登录后再进行操作', - buttons: ['确定'] + buttons: [ + { + text: '取消', + role: 'cancel' + }, + { + text: '去登录', + handler: () => { + // 保存当前路径并跳转到登录页 + this.navCtrl.navigateForward('/mine/login', { + state: { returnUrl: this.router.url } + }); + } + } + ] }).then(alert => alert.present()); } else { this.homeService.getArticlePrice(this.article.eventId).subscribe((res) => { @@ -50,7 +66,6 @@ export class ArticleItemComponent implements OnInit,AfterViewInit { } this.username = res.username }) - } getFreeReadCount():number{ @@ -121,7 +136,7 @@ export class ArticleItemComponent implements OnInit,AfterViewInit { } detail() { - if (this.article.unlock && this.article.stocks != "" && this.article.content != "") { + if (this.article.unlock && this.article.content != "") { this.navCtrl.navigateForward('/home/article-detail', { state: {article: this.article} }); diff --git a/ui/src/app/home/special-column/column-describe/column-describe.page.ts b/ui/src/app/home/special-column/column-describe/column-describe.page.ts index 93aa5d1..71100bf 100644 --- a/ui/src/app/home/special-column/column-describe/column-describe.page.ts +++ b/ui/src/app/home/special-column/column-describe/column-describe.page.ts @@ -28,7 +28,7 @@ export class ColumnDescribePage implements OnInit { const iconMap: { [key: string]: string } = { '盘中宝': 'pzb.png', '风口研报': 'fkyb.png', - '狙击龙虎榜': 'jjlhb.png', + '狙击龙虎榜': 'lhb.png', '电报解读': 'dbjd.png', '财联社早知道': 'clzzd.png', '研选': 'yx.png', diff --git a/ui/src/app/home/special-column/special-column.page.html b/ui/src/app/home/special-column/special-column.page.html index dea41aa..a2eb8db 100644 --- a/ui/src/app/home/special-column/special-column.page.html +++ b/ui/src/app/home/special-column/special-column.page.html @@ -41,10 +41,14 @@ -
-
-

盘中宝

-

重磅信息挖掘

-
- -
+ + +
+
+

盘中宝

+

重磅信息挖掘

+
+ +
+
+
diff --git a/ui/src/app/home/special-column/special-column.page.scss b/ui/src/app/home/special-column/special-column.page.scss index 2b2d9f4..c50f966 100644 --- a/ui/src/app/home/special-column/special-column.page.scss +++ b/ui/src/app/home/special-column/special-column.page.scss @@ -132,18 +132,21 @@ } } +.footer-toolbar { + --padding-start: 0; + --padding-end: 0; + --padding-top: 0; + --padding-bottom: 0; + --background: linear-gradient(90deg, #474D5D 0%, #333742 75%); +} + .fixed-bottom { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 60px; - background: linear-gradient(90deg, #474D5D 0%, #333742 75%); display: flex; justify-content: space-between; align-items: center; - z-index: 1000; - padding-left:16px; + height: 60px; + padding-left: 16px; + .price { text-align: center; display: flex; @@ -177,8 +180,8 @@ text-align: center; font-weight: 400; cursor: pointer; - height:60px; - width:40%; + height: 60px; + width: 40%; &:active { background: darken(#e74c3c, 10%); } diff --git a/ui/src/app/home/special-column/special-column.page.ts b/ui/src/app/home/special-column/special-column.page.ts index b58792a..9cded48 100644 --- a/ui/src/app/home/special-column/special-column.page.ts +++ b/ui/src/app/home/special-column/special-column.page.ts @@ -1,9 +1,11 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { ModalController, NavController, AlertController } from "@ionic/angular"; import { Router } from "@angular/router"; import { HomeService } from '../home.service'; import { Column } from '../../shared/model/column'; import { getUser } from "../../mine/mine.service"; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-special-column', @@ -11,9 +13,10 @@ import { getUser } from "../../mine/mine.service"; styleUrls: ['./special-column.page.scss'], standalone: false, }) -export class SpecialColumnPage implements OnInit { +export class SpecialColumnPage implements OnInit, OnDestroy { name: string = "" - column!: Column; + column: Column | null = null; + private destroy$ = new Subject(); constructor( private navCtrl: NavController, @@ -33,36 +36,58 @@ export class SpecialColumnPage implements OnInit { ngOnInit() { } + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + getColumnData() { - this.homeService.getColumnByName(this.name).subscribe(data => { - this.column = data; - }) + this.homeService.getColumnByName(this.name) + .pipe(takeUntil(this.destroy$)) + .subscribe(data => { + this.column = data; + }) } onBuyClick() { // 检查用户是否已登录 - getUser().subscribe(user => { - if (!user?.username) { + getUser().pipe(takeUntil(this.destroy$)).subscribe((res)=>{ + if(res.username == "") { // 未登录,显示提示框 this.alertCtrl.create({ header: '提示', message: '请先登录后再进行操作', - buttons: ['确定'] + buttons: [ + { + text: '取消', + role: 'cancel' + }, + { + text: '去登录', + handler: () => { + // 保存当前路径并跳转到登录页 + this.navCtrl.navigateForward('/mine/login', { + state: { returnUrl: this.router.url } + }); + } + } + ] }).then(alert => alert.present()); - return; + } else { + // 已登录,获取价格并跳转到购买页面 + this.getColumnPrice(); } - - // 已登录,获取价格并跳转到购买页面 - this.getColumnPrice(); - }); + }) } getColumnPrice() { - this.homeService.getColumnPrice(this.column.id).subscribe((res)=>{ - this.navCtrl.navigateForward('/home/column-buy', { - state: { column: this.column, price: res } - }); - }) + this.homeService.getColumnPrice(this.column!.id) + .pipe(takeUntil(this.destroy$)) + .subscribe((res)=>{ + this.navCtrl.navigateForward('/home/column-buy', { + state: { column: this.column, price: res } + }); + }) } describe(){ diff --git a/ui/src/app/mine/login/login.page.ts b/ui/src/app/mine/login/login.page.ts index 327d32a..ee366d6 100644 --- a/ui/src/app/mine/login/login.page.ts +++ b/ui/src/app/mine/login/login.page.ts @@ -17,6 +17,7 @@ import { SlideRef } from "go-captcha-angular"; import {CaptchaModalComponent} from "../component/captcha-modal/captcha-modal.component"; + @Component({ selector: 'app-login', templateUrl: './login.page.html', @@ -24,7 +25,7 @@ import {CaptchaModalComponent} from "../component/captcha-modal/captcha-modal.co standalone: false, }) export class LoginPage implements OnInit, OnDestroy,AfterViewInit { - loginForm: FormGroup ; + loginForm: FormGroup; loginType: 'sms' | 'password' = 'sms'; canSendSms = true; smsButtonText = '发送验证码'; @@ -32,6 +33,7 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { private countdown = 60; private timer: any; private verifyToken: string | null = null; + private returnUrl: string | null = null; constructor( private fb: FormBuilder, @@ -47,6 +49,12 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { password: [''], smsCode: [''] }); + + // 获取返回路径 + const navigation = this.router.getCurrentNavigation(); + if (navigation?.extras?.state?.['returnUrl']) { + this.returnUrl = navigation.extras.state['returnUrl']; + } } ngOnInit() { @@ -59,8 +67,6 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { this.stopCountdown() ; } - - private createForm() { // 根据登录类型动态设置验证器 this.loginForm.get('password')?.setValidators( @@ -73,7 +79,6 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { // 显示滑动验证码 showSlideVerify(type: 'sms' | 'password') { - const phone = this.loginForm.get('phone')?.value; if (!phone || !this.loginForm.get('phone')?.valid) { @@ -103,7 +108,6 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { } }) }) - }); } @@ -155,8 +159,13 @@ export class LoginPage implements OnInit, OnDestroy,AfterViewInit { loginRequest.subscribe({ next: (response) => { this.showToast('登录成功'); - localStorage.setItem("token",response) - this.navCtrl.back() + localStorage.setItem("token",response); + // 如果有返回路径,则导航到该路径 + if (this.returnUrl) { + this.router.navigateByUrl(this.returnUrl); + } else { + this.navCtrl.back(); + } }, error: (error) => { let errorMessage = '登录失败,请重试';