Commit f102e8e2 authored by 铃兰's avatar 铃兰

Mobile adaptation

parent 14d38cf4
Pipeline #22573 failed with stages
...@@ -25,9 +25,10 @@ ...@@ -25,9 +25,10 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"src/styles.css" "src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
], ],
"scripts": [] "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"]
}, },
"configurations": { "configurations": {
"production": { "production": {
...@@ -87,9 +88,10 @@ ...@@ -87,9 +88,10 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.css" "src/styles.css"
], ],
"scripts": [] "scripts": ["node_modules/bootstrap/dist/js/bootstrap.min.js"]
} }
} }
} }
......
...@@ -16,8 +16,10 @@ ...@@ -16,8 +16,10 @@
"@angular/platform-browser": "^15.2.0", "@angular/platform-browser": "^15.2.0",
"@angular/platform-browser-dynamic": "^15.2.0", "@angular/platform-browser-dynamic": "^15.2.0",
"@angular/router": "^15.2.0", "@angular/router": "^15.2.0",
"bootstrap": "^5.3.0",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"yaml": "^2.3.1",
"zone.js": "~0.12.0" "zone.js": "~0.12.0"
}, },
"devDependencies": { "devDependencies": {
...@@ -3233,6 +3235,16 @@ ...@@ -3233,6 +3235,16 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@schematics/angular": { "node_modules/@schematics/angular": {
"version": "15.2.9", "version": "15.2.9",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.2.9.tgz", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.2.9.tgz",
...@@ -4203,6 +4215,24 @@ ...@@ -4203,6 +4215,24 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true "dev": true
}, },
"node_modules/bootstrap": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.7"
}
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
...@@ -4819,6 +4849,15 @@ ...@@ -4819,6 +4849,15 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/cosmiconfig/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/critters": { "node_modules/critters": {
"version": "0.0.16", "version": "0.0.16",
"resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz",
...@@ -11690,12 +11729,11 @@ ...@@ -11690,12 +11729,11 @@
"dev": true "dev": true
}, },
"node_modules/yaml": { "node_modules/yaml": {
"version": "1.10.2", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
"dev": true,
"engines": { "engines": {
"node": ">= 6" "node": ">= 14"
} }
}, },
"node_modules/yargs": { "node_modules/yargs": {
......
This diff is collapsed.
...@@ -2,8 +2,8 @@ import { Component } from '@angular/core'; ...@@ -2,8 +2,8 @@ import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', template: `<app-layout></app-layout>`,
styleUrls: ['./app.component.css'] styles: []
}) })
export class AppComponent { export class AppComponent {
title = 'mycardindex'; title = 'mycardindex';
......
import { NgModule } from '@angular/core'; import {NgModule} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module'; import {AppRoutingModule} from './app-routing.module';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
import {LayoutComponent} from './layout/layout.component';
import {HttpClientModule} from "@angular/common/http";
import { TableComponent } from './table/table.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent AppComponent,
AppComponent,
LayoutComponent,
TableComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
AppRoutingModule AppRoutingModule,
HttpClientModule
], ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule {
}
* {
color: white;
}
.my-custom-container {
padding-left: 5%;
padding-right: 5%;
}
.logo {
height: 2em;
float: left;
margin: 0 8px;
}
.nav-link {
color: gray;
font-weight: normal;
}
a {
font-weight: bold;
}
a:hover {
color: white;
}
#background {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#custom-nav {
z-index: 999;
position: relative;
background-color: #fff;
}
#banner {
flex: 1;
background-repeat: no-repeat;
background-size: 100% 100%; /* 将背景图片拉伸以填满元素 */
background-position: center;
background-image: url('src/assets/img/background.jpg');
height: calc(100vh - 70px); /* 填满视窗,减去导航栏的高度 */
}
@media (max-width: 768px) {
#banner {
background-size: cover;
background-position: left top;
}
svg {
height: 5vh;
}
.details p {
font-size: 0.7em
}
}
.cards {
transform: translateX(30%) translateY(-15%) scale(0.7);
}
@media (min-width: 768px) {
.cards {
transform: translateX(12%) translateY(-5%) scale(0.8);
}
.plant-grid .icon{
max-width: 10vw;
}
}
#down {
animation: slowBlink 1s infinite;
}
@keyframes slowBlink {
0% {
transform: translateY(0px);
opacity: 0.6;
}
50% {
transform: translateY(8px);
opacity: 1;
}
100% {
transform: translateY(0px);
opacity: 0.6;
}
}
:host {
overflow: hidden; /* 隐藏溢出内容 */
}
/*滚轮吸附*/
.priorityElements {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh; /* 将滚动容器的高度设置为100vh */
scroll-padding-top: 4em; /* 添加底部内边距 */
}
.priority {
scroll-snap-align: start;
height: 80vh; /* 将每个滚动目标的高度设置为80vh */
/*scroll-snap-stop: normal; !* 在滚动时不停止吸附效果 *!*/
}
/*颜色方案*/
.bg-blue-dark {
background-color: #021123;
}
.bg-blue-light {
background-color: #c5d0e8;
}
.text-blue-dark {
color: #021123;
}
.text-blue-light {
color: #c5d0e8;
}
.card-one {
position: relative;
display: inline;
transform: rotate(-15deg);
/*ms-transform: rotate(-15deg);*/
/*moz-transform: rotate(-15deg);*/
/*webkit-transform: rotate(-15deg);*/
/*o-transform: rotate(-15deg);*/
animation: card-one-move 4s infinite;
-webkit-animation: card-one-move 4s infinite; /* Safari 与 Chrome */
}
.card-two {
display: inline;
position: relative;
left: -140px;
top: 20px;
animation: card-two-move 4s infinite;
-webkit-animation: card-two-move 4s infinite;
}
.card-three {
display: inline;
position: relative;
left: -285px;
top: 60px;
transform: rotate(15deg);
/*ms-transform: rotate(15deg);*/
/*moz-transform: rotate(15deg);*/
/*webkit-transform: rotate(15deg);*/
/*o-transform: rotate(15deg);*/
animation: card-three-move 4s infinite;
-webkit-animation: card-three-move 4s infinite;
}
@keyframes card-one-move {
0% {
top: 0;
left: 0
}
25% {
top: 20px;
left: 10px
}
50% {
top: -20px;
left: -10px
}
100% {
top: 0;
left: 0
}
}
@-webkit-keyframes card-one-move /* Safari 与 Chrome */
{
0% {
top: 20px;
}
25% {
top: 10px;
}
50% {
top: 0px;
}
100% {
top: 20px;
}
}
@keyframes card-two-move {
0% {
top: 20px;
}
25% {
top: 10px;
}
50% {
top: -10px;
}
100% {
top: 20px;
}
}
@-webkit-keyframes card-two-move /* Safari 与 Chrome */
{
0% {
top: 20px;
}
25% {
top: 10px;
}
50% {
top: -10px;
}
100% {
top: 20px;
}
}
@keyframes card-three-move {
0% {
top: 60px;
left: -285px;
}
25% {
top: 40px;
left: -265px;
}
50% {
top: 20px;
left: -245px;
}
100% {
top: 60px;
left: -285px;
}
}
@-webkit-keyframes card-three-move /* Safari 与 Chrome */
{
0% {
top: 20px;
}
25% {
top: 10px;
}
50% {
top: -10px;
}
100% {
top: 20px;
}
}
.details svg {
animation: rotate 3s linear infinite;
}
@keyframes rotate {
0% {
transform: rotateY(0deg);
}
30% {
transform: rotateY(180deg);
}
60% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(0deg);
}
}
/*轮播图*/
.section-third-pic {
height: 25vh;
object-fit: cover;
overflow: hidden;
transition: transform 0.5s ease, box-shadow 0.5s ease;
}
.section-third-pic:hover {
transform: scale(0.95);
box-shadow: 0 0 20px rgba(0,0,0,0.2);
}
.carousel-fade .section-third-pic {
width: 80vw;
height: 30vh;
object-fit: cover;
overflow: hidden;
margin-bottom: 1em;
}
/*周边*/
.product-lg img{
width: 100%;
height: 100%;
object-fit: cover;
}
.image-container {
position: relative;
overflow: hidden;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
cursor: pointer;
}
.overlay-content {
text-align: center;
}
.image-container:hover .overlay {
opacity: 1;
}
.p-s{
font-size: 1vw;
}
@media (max-width: 768px) {
.p-s{
font-size: 0.5em;
}
}
This diff is collapsed.
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LayoutComponent } from './layout.component';
describe('LayoutComponent', () => {
let component: LayoutComponent;
let fixture: ComponentFixture<LayoutComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LayoutComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(LayoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {HttpClient} from "@angular/common/http";
import {map} from "rxjs/operators";
import yaml from 'yaml';
import {firstValueFrom} from "rxjs";
import {Component, Inject, LOCALE_ID, OnInit, ViewChild, ElementRef, AfterViewInit} from '@angular/core';
import { HostListener } from '@angular/core';
interface HomePageMatchCountDto {
count: number;
year: number;
month: number;
}
@Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.css']
})
export class LayoutComponent implements OnInit, AfterViewInit {
matchCount: HomePageMatchCountDto = {
count: 100,
year: 1000,
month: 1
};
latest_win32 = this.http
.get('https://cdn02.moecube.com:444/downloads/latest.yml', {responseType: 'text'})
.pipe(map(rawData => 'https://cdn02.moecube.com:444/downloads/' + yaml.parse(rawData).path));
latest_linux = this.http
.get('https://cdn02.moecube.com:444/downloads/latest-linux.yml', {responseType: 'text'})
.pipe(map(rawData => 'https://cdn02.moecube.com:444/downloads/' + yaml.parse(rawData).path));
latest_drawin = this.http
.get('https://cdn02.moecube.com:444/downloads/latest-mac.yml', {responseType: 'text'})
.pipe(map((rawData) => 'https://cdn02.moecube.com:444/downloads/' + yaml.parse(rawData).path.replace('-mac.zip', '.dmg')));
latest_current = ''
stats_signups = this.http
.get('https://ygobbs.com/admin/dashboard.json', {
params: {api_key: 'dc7298a754828b3d26b709f035a0eeceb43e73cbd8c4fa8dec18951f8a95d2bc', api_username: 'zh99998'}
})
.pipe(map((data: any) => data.global_reports.find((item: { type: any; }) => item.type === 'signups').total));
stats_online = this.http.get('https://api.moecube.com/stats/online', {responseType: 'text'}).pipe(
map(rawText => {
const doc = new DOMParser().parseFromString(rawText, 'text/xml');
const node = doc.querySelector('#content > table > tbody > tr:nth-child(2) > td:nth-child(2)');
return parseInt(node?.textContent ?? '0');
})
);
constructor(private http: HttpClient, @Inject(LOCALE_ID) public locale: string) {
}
@ViewChild('carousel', { static: true }) carousel!: ElementRef;
ngAfterViewInit(): void {
const carouselElement = this.carousel.nativeElement;
const carousel = new (window as any)['bootstrap'].Carousel(carouselElement, {
interval: 2000, // 设置轮播间隔时间为2秒
pause: 'hover', // 鼠标悬停时是否暂停轮播
ride: true, // 自动开始轮播
});
}
// 下载
async ngOnInit() {
if (navigator.platform.match(/Android/i)) {
this.latest_current = 'https://www.123pan.com/s/bKZKVv-m3sTd.html';
} else if (navigator.platform.match(/Mac/i)) {
this.latest_current = await firstValueFrom(this.latest_drawin);
} else if (navigator.platform.match(/Linux/i)) {
if (window.innerHeight > window.innerWidth) {
this.latest_current = 'https://www.123pan.com/s/bKZKVv-m3sTd.html';
} else {
this.latest_current = await firstValueFrom(this.latest_linux);
}
} else {
this.latest_current = await this.latest_win32.toPromise() as string;
}
this.matchCount = await this.http.get<HomePageMatchCountDto>('https://sapi.moecube.com:444/ygopro/arena/homepageCount', {
responseType: 'json'
}).toPromise() as HomePageMatchCountDto;
}
setLocale(locale: any) {
document.cookie = `locale=${locale}`;
location.reload();
}
navigateToUrl(url: string) {
location.href = url;
}
}
<table class="table table-white table-hover">
<thead>
<tr>
<th>Rank</th>
<th>Deck</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of listOfData | slice:0:10; let i = index">
<td>{{ i+1 }}</td>
<td>{{ data.name }}</td>
<td>{{ data.count }}</td>
</tr>
</tbody>
</table>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TableComponent } from './table.component';
describe('TableComponent', () => {
let component: TableComponent;
let fixture: ComponentFixture<TableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TableComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(TableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {
listOfData: ArenaDeck[] = [];
loading = true;
constructor(private http: HttpClient) {}
ngOnInit() {
this.http
.get<ArenaDeck[]>('https://sapi.moecube.com:444/ygopro/analytics/deck/type', {
params: {
type: 'day',
source: 'mycard-athletic'
}
})
.subscribe((data: ArenaDeck[]) => {
this.listOfData = data;
this.loading = false;
});
}
}
interface ArenaDeck {
count: string;
name: string;
recent_time: string;
source: string;
tags: string[];
}
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
::-webkit-scrollbar {height: 0;width: 0;color: transparent;}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
{ {
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": "./", "baseUrl": "./",
"outDir": "./dist/out-tsc", "outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
"enableI18nLegacyMessageIdFormat": false, "enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true, "strictInjectionParameters": true,
"strictInputAccessModifiers": true, "strictInputAccessModifiers": true,
"strictTemplates": true "strictTemplates": true,
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment