mirror of
https://github.com/Spythere/pragotron-td2.git
synced 2026-05-03 05:28:14 +00:00
chore: refreshed project
This commit is contained in:
@@ -1,2 +0,0 @@
|
|||||||
VITE_STACJOWNIK_API_URL=https://stacjownik.spythere.pl
|
|
||||||
VITE_USE_MOCK_DATA=0
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"eslint:recommended",
|
||||||
|
"@vue/eslint-config-typescript",
|
||||||
|
"@vue/eslint-config-prettier/skip-formatting",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
},
|
||||||
|
};
|
||||||
+2
-1
@@ -25,4 +25,5 @@ dist-ssr
|
|||||||
|
|
||||||
.firebase
|
.firebase
|
||||||
|
|
||||||
mockData/
|
mockData/
|
||||||
|
.env
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/prettierrc",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"trailingComma": "none"
|
||||||
|
}
|
||||||
+18
-9
@@ -1,24 +1,33 @@
|
|||||||
{
|
{
|
||||||
"name": "pragotron-td2",
|
"name": "pragotron-td2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"deploy": "yarn build && firebase deploy --only hosting"
|
"deploy": "yarn build && firebase deploy --only hosting",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||||
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sass": "^1.55.0",
|
"axios": "^1.6.2",
|
||||||
"vue": "^3.2.41",
|
"pinia": "^2.1.7",
|
||||||
"vue-router": "4"
|
"sass": "^1.69.5",
|
||||||
|
"vue": "^3.3.11",
|
||||||
|
"vue-router": "4.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/vue-router": "^2.0.0",
|
"@types/vue-router": "^2.0.0",
|
||||||
"@vitejs/plugin-vue": "^3.2.0",
|
"@vitejs/plugin-vue": "^4.5.2",
|
||||||
"typescript": "^4.6.4",
|
"@vue/eslint-config-prettier": "^8.0.0",
|
||||||
"vite": "^3.2.1",
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
"vue-tsc": "^1.0.9"
|
"eslint": "^8.55.0",
|
||||||
|
"eslint-plugin-vue": "^9.19.2",
|
||||||
|
"prettier": "^3.1.1",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.0.7",
|
||||||
|
"vue-tsc": "^1.8.25"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="800px" height="800px" viewBox="0 0 32 32" id="i-options" xmlns="http://www.w3.org/2000/svg" fill="white" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
||||||
|
<path d="M28 6 L4 6 M28 16 L4 16 M28 26 L4 26 M24 3 L24 9 M8 13 L8 19 M20 23 L20 29" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 295 B |
Binary file not shown.
+31
-46
@@ -1,13 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app_content">
|
<div class="app_content">
|
||||||
<nav class="navbar">
|
<Navbar :version="version" />
|
||||||
<router-link to="/">
|
|
||||||
Pragotron TD2 <span class="text--accent">v{{ VERSION }}</span> <sup>by Spythere</sup>
|
|
||||||
</router-link>
|
|
||||||
<!-- <button v-else class="back-btn btn--text" @click="selectedStation = null">< powrót</button> -->
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
<button @click="testAudio">test audio</button>
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="Component" :key="$route.path"></component>
|
<component :is="Component" :key="$route.path"></component>
|
||||||
@@ -18,27 +14,37 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from '@vue/runtime-core';
|
import { defineComponent } from 'vue';
|
||||||
import PragotronVue from './views/PragotronView.vue';
|
|
||||||
import IStationData from './types/ISceneryData';
|
|
||||||
|
|
||||||
import packageInfo from '../package.json';
|
import packageInfo from '../package.json';
|
||||||
|
import { useApiStore } from './stores/apiStore';
|
||||||
|
import Navbar from './components/Navbar.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: { Navbar },
|
||||||
PragotronVue,
|
|
||||||
},
|
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
onlineStations: [] as IStationData[],
|
version: packageInfo.version,
|
||||||
dataLoaded: false,
|
apiStore: useApiStore()
|
||||||
|
|
||||||
VERSION: packageInfo.version,
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.dataLoaded = true;
|
this.apiStore.fetchSceneriesData();
|
||||||
|
|
||||||
|
this.apiStore.fetchActiveData();
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
this.apiStore.fetchActiveData();
|
||||||
|
}, 30000);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
testAudio() {
|
||||||
|
const audio = new Audio('../public/pragotron.mp3');
|
||||||
|
audio.play();
|
||||||
|
audio.loop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -48,45 +54,24 @@ export default defineComponent({
|
|||||||
.app_content {
|
.app_content {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-rows: auto 1fr;
|
||||||
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
|
||||||
flex: 0 1 40px;
|
|
||||||
font-size: 1.35em;
|
|
||||||
|
|
||||||
padding: 0.25em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
background-color: $accentBg;
|
|
||||||
|
|
||||||
sup {
|
|
||||||
font-size: 0.8em;
|
|
||||||
color: $dimmedText;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
flex: 1 1 auto;
|
padding: 1em;
|
||||||
|
overflow-x: hidden;
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: gold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<div class="dropdown" v-click-outside="() => (store.optionsOpen = false)">
|
||||||
|
<button class="btn--image" @click="store.optionsOpen = !store.optionsOpen">
|
||||||
|
<img src="/options.svg" alt="options" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<transition name="dropdown-anim">
|
||||||
|
<div class="dropdown-body" v-if="store.optionsOpen">
|
||||||
|
<h3>Opcje</h3>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div style="margin: 0.5em 0">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" v-model="store.filters.nonPassenger" />
|
||||||
|
Relacje niepasażerskie
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" v-model="store.filters.terminating" />
|
||||||
|
Relacje kończące bieg
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isPragotronOpen">
|
||||||
|
<label for="checkpoint">
|
||||||
|
Posterunek:
|
||||||
|
<select id="checkpoint" v-model="store.selectedCheckpointName">
|
||||||
|
<option v-for="cp in store.selectedStation?.stationCheckpoints" :value="cp" :key="cp">
|
||||||
|
{{ cp }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div tabindex="0" @focus="() => (store.optionsOpen = false)"></div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useMainStore } from '../stores/mainStore';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
data: () => ({
|
||||||
|
store: useMainStore()
|
||||||
|
}),
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
isPragotronOpen() {
|
||||||
|
return this.$route.path == '/board';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
img {
|
||||||
|
max-width: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dropdown-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-body {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
padding: 0.25em;
|
||||||
|
transform: translateY(0.5em);
|
||||||
|
|
||||||
|
width: 500px;
|
||||||
|
max-width: calc(100% - 0.5em);
|
||||||
|
z-index: 105;
|
||||||
|
|
||||||
|
background-color: #000000e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-anim {
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active {
|
||||||
|
transition: all 90ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-enter-from,
|
||||||
|
&-leave-to {
|
||||||
|
transform: translateY(20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<nav class="navbar">
|
||||||
|
<div class="navbar-body">
|
||||||
|
<router-link class="brand" to="/">
|
||||||
|
Pragotron TD2 <span class="text--accent">v{{ version }}</span> <sup>by Spythere</sup>
|
||||||
|
</router-link>
|
||||||
|
|
||||||
|
<div class="options">
|
||||||
|
<Dropdown />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useMainStore } from '../stores/mainStore';
|
||||||
|
import Dropdown from './Dropdown.vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { Dropdown },
|
||||||
|
props: {
|
||||||
|
version: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
store: useMainStore()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../styles.scss';
|
||||||
|
|
||||||
|
nav.navbar {
|
||||||
|
background-color: $accentBg;
|
||||||
|
padding: 0 0.5em;
|
||||||
|
|
||||||
|
sup {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: $dimmedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-body {
|
||||||
|
padding: 0.25em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 1400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+129
-1
@@ -1 +1,129 @@
|
|||||||
["", "Aleksandrów Kujawski","Arkadia Zdrój","Babimost","Bargowice","Bargowice Zachód","Horz Zdrój","Bełchów","Blaszki","Borki","Brakowice","Buczek","Buk","Bystra Woda","Cenorzyce Nowe","Chełmik Wołowski","Chlorkowice","Cis","Czerepy","Czermin","Dobrzyca DTA","Dobrzyca DTB","Dobrzyca DTC","Dobrzyniec","Dobrzyniec Mącice","Drzewko","Dziewoszyce","Falewo","Glinnik","Grabów Miasto","Grabów Wieś","Góra Włodowska","Głogowo","Głębce","Głęboszów","Imielin","Jordanowo","Karszynek","Kcynia","Kieły","Kolsko","Kowalewo","Krzemienice","Krzęcz","Kszęty","Kudowa Zdrój","Głowno","Domaniewice","Ozorków","Chociszew","Skrzynki","Wykno","Żywiec","Węgierska Górka","Łodygowice","Wilkowice Bystra","BB Leszczyny","Legno","Lewków","Ligota Grabowska","Ligota Trzeszcze","Lisiczki","Lisków","TEFAMA","Lisków Miasto","Lublinek","Lutol Suchy","Luzino","Lębork","Milówka","Modlinków","Motławy","Naterki","Okoń Główny","Orniki","Otwocko","Parów","Piaskowo","Pilichowice","Poreńsk","Radostowice","Radowice","Radzikowo","Rajcza","Razemsko","Rebrowo Dolne","Redlin Sudecki","Santok Zdrój","Sieniawka","Skawce","Sowi Bór","Sroka","Stare Lipowo","Przęsy","Starzynki","Stefanowo","Stryków","Strączki","Sulechów","Szadek","Sól","Tarkowo","Tartakowo","Testowo","Trawniczki","Tłoki","Wełtawa","Wielichowo Główne","Wielichowo Główne gt","Wielichowo Wieś","Wijewo","Wilczyca","Witaszyczki","Witonia","Wodnica","Wola","Wola Nowska","Wschodna","Zgierz","Zgierz Kontrewers","Zwardoń","Łask","Łaskarzew","Łebnino","Łęczyca","Żerniki","Żory"]
|
[
|
||||||
|
"",
|
||||||
|
"Aleksandrów Kujawski",
|
||||||
|
"Arkadia Zdrój",
|
||||||
|
"Babimost",
|
||||||
|
"Bargowice",
|
||||||
|
"Bargowice Zachód",
|
||||||
|
"Horz Zdrój",
|
||||||
|
"Bełchów",
|
||||||
|
"Blaszki",
|
||||||
|
"Borki",
|
||||||
|
"Brakowice",
|
||||||
|
"Buczek",
|
||||||
|
"Buk",
|
||||||
|
"Bystra Woda",
|
||||||
|
"Cenorzyce Nowe",
|
||||||
|
"Chełmik Wołowski",
|
||||||
|
"Chlorkowice",
|
||||||
|
"Cis",
|
||||||
|
"Czerepy",
|
||||||
|
"Czermin",
|
||||||
|
"Dobrzyca DTA",
|
||||||
|
"Dobrzyca DTB",
|
||||||
|
"Dobrzyca DTC",
|
||||||
|
"Dobrzyniec",
|
||||||
|
"Dobrzyniec Mącice",
|
||||||
|
"Drzewko",
|
||||||
|
"Dziewoszyce",
|
||||||
|
"Falewo",
|
||||||
|
"Glinnik",
|
||||||
|
"Grabów Miasto",
|
||||||
|
"Grabów Wieś",
|
||||||
|
"Góra Włodowska",
|
||||||
|
"Głogowo",
|
||||||
|
"Głębce",
|
||||||
|
"Głęboszów",
|
||||||
|
"Imielin",
|
||||||
|
"Jordanowo",
|
||||||
|
"Karszynek",
|
||||||
|
"Kcynia",
|
||||||
|
"Kieły",
|
||||||
|
"Kolsko",
|
||||||
|
"Kowalewo",
|
||||||
|
"Krzemienice",
|
||||||
|
"Krzęcz",
|
||||||
|
"Kszęty",
|
||||||
|
"Kudowa Zdrój",
|
||||||
|
"Głowno",
|
||||||
|
"Domaniewice",
|
||||||
|
"Ozorków",
|
||||||
|
"Chociszew",
|
||||||
|
"Skrzynki",
|
||||||
|
"Wykno",
|
||||||
|
"Żywiec",
|
||||||
|
"Węgierska Górka",
|
||||||
|
"Łodygowice",
|
||||||
|
"Wilkowice Bystra",
|
||||||
|
"BB Leszczyny",
|
||||||
|
"Legno",
|
||||||
|
"Lewków",
|
||||||
|
"Ligota Grabowska",
|
||||||
|
"Ligota Trzeszcze",
|
||||||
|
"Lisiczki",
|
||||||
|
"Lisków",
|
||||||
|
"TEFAMA",
|
||||||
|
"Lisków Miasto",
|
||||||
|
"Lublinek",
|
||||||
|
"Lutol Suchy",
|
||||||
|
"Luzino",
|
||||||
|
"Lębork",
|
||||||
|
"Milówka",
|
||||||
|
"Modlinków",
|
||||||
|
"Motławy",
|
||||||
|
"Naterki",
|
||||||
|
"Okoń Główny",
|
||||||
|
"Orniki",
|
||||||
|
"Otwocko",
|
||||||
|
"Parów",
|
||||||
|
"Piaskowo",
|
||||||
|
"Pilichowice",
|
||||||
|
"Poreńsk",
|
||||||
|
"Radostowice",
|
||||||
|
"Radowice",
|
||||||
|
"Radzikowo",
|
||||||
|
"Rajcza",
|
||||||
|
"Razemsko",
|
||||||
|
"Rebrowo Dolne",
|
||||||
|
"Redlin Sudecki",
|
||||||
|
"Santok Zdrój",
|
||||||
|
"Sieniawka",
|
||||||
|
"Skawce",
|
||||||
|
"Sowi Bór",
|
||||||
|
"Sroka",
|
||||||
|
"Stare Lipowo",
|
||||||
|
"Przęsy",
|
||||||
|
"Starzynki",
|
||||||
|
"Stefanowo",
|
||||||
|
"Stryków",
|
||||||
|
"Strączki",
|
||||||
|
"Sulechów",
|
||||||
|
"Szadek",
|
||||||
|
"Sól",
|
||||||
|
"Tarkowo",
|
||||||
|
"Tartakowo",
|
||||||
|
"Testowo",
|
||||||
|
"Trawniczki",
|
||||||
|
"Tłoki",
|
||||||
|
"Wełtawa",
|
||||||
|
"Wielichowo Główne",
|
||||||
|
"Wielichowo Główne gt",
|
||||||
|
"Wielichowo Wieś",
|
||||||
|
"Wijewo",
|
||||||
|
"Wilczyca",
|
||||||
|
"Witaszyczki",
|
||||||
|
"Witonia",
|
||||||
|
"Wodnica",
|
||||||
|
"Wola",
|
||||||
|
"Wola Nowska",
|
||||||
|
"Wschodna",
|
||||||
|
"Zgierz",
|
||||||
|
"Zgierz Kontrewers",
|
||||||
|
"Zwardoń",
|
||||||
|
"Łask",
|
||||||
|
"Łaskarzew",
|
||||||
|
"Łebnino",
|
||||||
|
"Łęczyca",
|
||||||
|
"Żerniki",
|
||||||
|
"Żory"
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const http = axios.create({
|
||||||
|
baseURL: 'https://stacjownik.spythere.eu'
|
||||||
|
});
|
||||||
|
|
||||||
|
export default http;
|
||||||
+20
-2
@@ -1,6 +1,24 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, Directive } from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
|
||||||
createApp(App).use(router).mount('#app');
|
const pinia = createPinia();
|
||||||
|
|
||||||
|
const clickOutsideDirective: Directive = {
|
||||||
|
mounted(el, binding) {
|
||||||
|
el.clickOutsideEvent = (event: Event) => {
|
||||||
|
if (!(el == event.target || el.contains(event.target))) {
|
||||||
|
binding.value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('click', el.clickOutsideEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createApp(App)
|
||||||
|
.use(router)
|
||||||
|
.use(pinia)
|
||||||
|
.directive('click-outside', clickOutsideDirective)
|
||||||
|
.mount('#app');
|
||||||
|
|||||||
+4
-4
@@ -6,18 +6,18 @@ import PragotronView from './views/PragotronView.vue';
|
|||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: HomeView,
|
component: HomeView
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/board',
|
path: '/board',
|
||||||
component: PragotronView,
|
component: PragotronView,
|
||||||
props: (route) => ({ stationName: route.query.name }),
|
props: (route) => ({ stationName: route.query.name, region: route.query.region })
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes,
|
routes
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import { API } from '../typings/api';
|
||||||
|
import http from '../http';
|
||||||
|
|
||||||
|
export enum DataStatus {
|
||||||
|
LOADING = 0,
|
||||||
|
LOADED = 1,
|
||||||
|
ERROR = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useApiStore = defineStore('api', {
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
activeData: undefined as API.ActiveData.Response | undefined,
|
||||||
|
stationData: undefined as API.Sceneries.Response | undefined,
|
||||||
|
|
||||||
|
dataStatuses: {
|
||||||
|
activeData: DataStatus.LOADING,
|
||||||
|
stationData: DataStatus.LOADING
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
async fetchActiveData() {
|
||||||
|
try {
|
||||||
|
const response = (await http.get<API.ActiveData.Response | undefined>('api/getActiveData'))
|
||||||
|
.data;
|
||||||
|
|
||||||
|
this.dataStatuses.activeData = DataStatus.LOADED;
|
||||||
|
this.activeData = response;
|
||||||
|
} catch (error) {
|
||||||
|
this.dataStatuses.activeData = DataStatus.ERROR;
|
||||||
|
|
||||||
|
console.error('Wystąpił błąd podczas pobierania danych:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchSceneriesData() {
|
||||||
|
try {
|
||||||
|
const response = (await http.get<API.Sceneries.Response | undefined>('api/getSceneries'))
|
||||||
|
.data;
|
||||||
|
|
||||||
|
this.dataStatuses.stationData = DataStatus.LOADED;
|
||||||
|
this.stationData = response;
|
||||||
|
} catch (error) {
|
||||||
|
this.dataStatuses.stationData = DataStatus.ERROR;
|
||||||
|
|
||||||
|
console.error('Wystąpił błąd podczas pobierania danych:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import ISceneryData from '../types/ISceneryData';
|
||||||
|
import { useApiStore } from './apiStore';
|
||||||
|
|
||||||
|
export enum Region {
|
||||||
|
PL1 = 'eu',
|
||||||
|
PL2 = 'cae',
|
||||||
|
CZE = 'usw',
|
||||||
|
DE = 'us ',
|
||||||
|
ENG = 'ru'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const regionNames = {
|
||||||
|
[Region.PL1]: 'PL1',
|
||||||
|
[Region.PL2]: 'PL2',
|
||||||
|
[Region.CZE]: 'CZE',
|
||||||
|
[Region.DE]: 'DE',
|
||||||
|
[Region.ENG]: 'ENG'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useMainStore = defineStore('main', {
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
region: Region.PL1,
|
||||||
|
optionsOpen: false,
|
||||||
|
filters: {
|
||||||
|
nonPassenger: true,
|
||||||
|
terminating: true
|
||||||
|
},
|
||||||
|
selectedStationName: '',
|
||||||
|
selectedCheckpointName: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
selectedStation(state): ISceneryData | undefined {
|
||||||
|
const apiStore = useApiStore();
|
||||||
|
const station = apiStore.stationData?.find(({ name }) => name == state.selectedStationName);
|
||||||
|
|
||||||
|
if (!station) return undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
stationName: station.name,
|
||||||
|
stationCheckpoints:
|
||||||
|
station.checkpoints && station.checkpoints.length > 0
|
||||||
|
? station.checkpoints.split(';')
|
||||||
|
: [station.name],
|
||||||
|
nameAbbreviation: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
+67
-7
@@ -1,16 +1,16 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Monda:wght@400;700&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Monda:wght@400;700&display=swap');
|
||||||
@import 'theme.scss';
|
@import 'theme.scss';
|
||||||
|
|
||||||
|
|
||||||
body,
|
body,
|
||||||
html {
|
html {
|
||||||
background: $primaryBg;
|
background: $primaryBg;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
color: $primaryText;
|
color: $primaryText;
|
||||||
|
|
||||||
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
@@ -19,22 +19,82 @@ html {
|
|||||||
font-family: 'Monda', sans-serif;
|
font-family: 'Monda', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
option,
|
||||||
|
label {
|
||||||
|
font-size: inherit;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: white;
|
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
|
||||||
&.btn--text {
|
color: white;
|
||||||
background: none;
|
background-color: #1b1b1b;
|
||||||
border: none;
|
|
||||||
outline: none;
|
&:hover {
|
||||||
|
background-color: #252525;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
color: $accentText;
|
color: $accentText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn--image {
|
||||||
|
display: flex;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 1px solid $accentText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input radio
|
||||||
|
.g-selector {
|
||||||
|
label {
|
||||||
|
background-color: #202020;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #2b2b2b;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='radio'] {
|
||||||
|
opacity: 0;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&:checked + span {
|
||||||
|
color: $accentText;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible + span {
|
||||||
|
outline: 1px solid white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -8,9 +8,9 @@ $secondaryBg: #aaa;
|
|||||||
$accentBg: #327ea5;
|
$accentBg: #327ea5;
|
||||||
|
|
||||||
.text--accent {
|
.text--accent {
|
||||||
color: $accentText;
|
color: $accentText;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text--grayed {
|
.text--grayed {
|
||||||
color: $dimmedText;
|
color: $dimmedText;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ export default interface ISceneryData {
|
|||||||
stationName: string;
|
stationName: string;
|
||||||
nameAbbreviation: string;
|
nameAbbreviation: string;
|
||||||
stationCheckpoints: string[];
|
stationCheckpoints: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -1,28 +1,28 @@
|
|||||||
interface ITableRowValues {
|
interface ITableRowValues {
|
||||||
routeTo: string;
|
routeTo: string;
|
||||||
routeVia: string;
|
routeVia: string;
|
||||||
|
|
||||||
// routeTo, routeVia, date1, date2, date3, date4
|
// routeTo, routeVia, date1, date2, date3, date4
|
||||||
currentRowIndexes: [number, number, number, number, number, number];
|
currentRowIndexes: [number, number, number, number, number, number];
|
||||||
|
|
||||||
dateDigits: string[],
|
dateDigits: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITableRow {
|
export interface ITableRow {
|
||||||
trainNumber: string;
|
trainNumber: string;
|
||||||
timetableId: number;
|
timetableId: number;
|
||||||
|
|
||||||
routeTo: string;
|
routeTo: string;
|
||||||
routeVia: string;
|
routeVia: string;
|
||||||
|
|
||||||
checkpointName: string;
|
checkpointName: string;
|
||||||
|
|
||||||
arrivalTimestamp: number;
|
arrivalTimestamp: number;
|
||||||
departureTimestamp: number;
|
departureTimestamp: number;
|
||||||
|
|
||||||
delayMinutes: number,
|
delayMinutes: number;
|
||||||
date?: Date,
|
date?: Date;
|
||||||
dateDigits: string[],
|
dateDigits: string[];
|
||||||
|
|
||||||
tableValues: ITableRowValues;
|
tableValues: ITableRowValues;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
export namespace API {
|
||||||
|
export namespace ActiveData {
|
||||||
|
export interface Response {
|
||||||
|
activeSceneries: ActiveScenery[];
|
||||||
|
trains: ActiveTrain[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ActiveScenery {
|
||||||
|
dispatcherId: number;
|
||||||
|
dispatcherName: string;
|
||||||
|
dispatcherIsSupporter: boolean;
|
||||||
|
stationName: string;
|
||||||
|
stationHash: string;
|
||||||
|
region: string;
|
||||||
|
maxUsers: number;
|
||||||
|
currentUsers: number;
|
||||||
|
spawn: number;
|
||||||
|
lastSeen: number;
|
||||||
|
dispatcherExp: number;
|
||||||
|
nameFromHeader: string;
|
||||||
|
spawnString: string | null;
|
||||||
|
networkConnectionString: string;
|
||||||
|
isOnline: number;
|
||||||
|
dispatcherRate: number;
|
||||||
|
dispatcherStatus: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ActiveTrain {
|
||||||
|
trainNo: number;
|
||||||
|
|
||||||
|
mass: number;
|
||||||
|
length: number;
|
||||||
|
speed: number;
|
||||||
|
stockString: string;
|
||||||
|
|
||||||
|
signal: string;
|
||||||
|
distance: number;
|
||||||
|
connectedTrack: string;
|
||||||
|
|
||||||
|
driverName: string;
|
||||||
|
driverId: number;
|
||||||
|
driverIsSupporter: boolean;
|
||||||
|
driverLevel?: number;
|
||||||
|
|
||||||
|
currentStationName: string;
|
||||||
|
currentStationHash?: string;
|
||||||
|
|
||||||
|
online: number;
|
||||||
|
lastSeen: number;
|
||||||
|
|
||||||
|
region: string;
|
||||||
|
isTimeout: boolean;
|
||||||
|
|
||||||
|
timetable?: Timetable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TimetableStop {
|
||||||
|
stopName: string;
|
||||||
|
stopNameRAW: string;
|
||||||
|
stopType: string;
|
||||||
|
stopDistance: number;
|
||||||
|
pointId: string;
|
||||||
|
|
||||||
|
mainStop: boolean;
|
||||||
|
|
||||||
|
arrivalLine: string | null;
|
||||||
|
arrivalTimestamp: number;
|
||||||
|
arrivalRealTimestamp: number;
|
||||||
|
arrivalDelay: number;
|
||||||
|
|
||||||
|
departureLine: string | null;
|
||||||
|
departureTimestamp: number;
|
||||||
|
departureRealTimestamp: number;
|
||||||
|
departureDelay: number;
|
||||||
|
|
||||||
|
comments?: any;
|
||||||
|
|
||||||
|
beginsHere: boolean;
|
||||||
|
terminatesHere: boolean;
|
||||||
|
confirmed: number;
|
||||||
|
stopped: number;
|
||||||
|
stopTime: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Timetable {
|
||||||
|
timetableId: number;
|
||||||
|
category: string;
|
||||||
|
route: string;
|
||||||
|
|
||||||
|
stopList: TimetableStop[];
|
||||||
|
|
||||||
|
TWR: boolean;
|
||||||
|
SKR: boolean;
|
||||||
|
sceneries: string[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Sceneries {
|
||||||
|
export type Response = Scenery[];
|
||||||
|
|
||||||
|
export interface Scenery {
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt?: string;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
SUP: boolean;
|
||||||
|
authors: string;
|
||||||
|
availability: string;
|
||||||
|
backupJSON: any;
|
||||||
|
checkpoints?: string;
|
||||||
|
controlType: string;
|
||||||
|
lines?: string;
|
||||||
|
project?: string;
|
||||||
|
reqLevel: number;
|
||||||
|
routes?: string;
|
||||||
|
routesInfo: RoutesInfo[];
|
||||||
|
signalType: string;
|
||||||
|
supportersOnly?: boolean;
|
||||||
|
url?: string;
|
||||||
|
projectUrl?: string;
|
||||||
|
hash?: string;
|
||||||
|
abbr: string;
|
||||||
|
hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoutesInfo {
|
||||||
|
routeName: string;
|
||||||
|
isElectric: boolean;
|
||||||
|
isInternal: boolean;
|
||||||
|
isRouteSBL: boolean;
|
||||||
|
routeSpeed: number;
|
||||||
|
routeLength: number;
|
||||||
|
routeTracks: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+97
-40
@@ -1,75 +1,132 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home-view">
|
<div class="home-view">
|
||||||
|
<div>
|
||||||
|
<h1 style="margin: 0">Wybierz region i scenerię, aby otworzyć widok pragotronu</h1>
|
||||||
|
|
||||||
|
<div class="region-selector g-selector">
|
||||||
|
<label v-for="region in regions" :key="region">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="region"
|
||||||
|
@change="changeRegion(region)"
|
||||||
|
:checked="mainStore.region == region"
|
||||||
|
/>
|
||||||
|
<span>{{ regionNames[region] }}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="scenery-selector">
|
<div class="scenery-selector">
|
||||||
<h1 style="margin: 0">Wybierz scenerię, aby otworzyć widok pragotronu</h1>
|
<!-- <p style="margin: 0.5em; color: #ccc">Widoczne są jedynie scenerie aktywne na serwerze PL1</p> -->
|
||||||
<p style="margin: 0.5em; color: #ccc">Widoczne są jedynie scenerie aktywne na serwerze PL1</p>
|
|
||||||
|
|
||||||
<ul class="scenery-list" v-if="dataLoaded && onlineStations.length > 0">
|
<transition name="list-anim" tag="div" mode="out-in">
|
||||||
<li v-for="(stationName, i) in onlineStations">
|
<h3 v-if="apiStore.dataStatuses.activeData == DataStatus.LOADING">
|
||||||
<span v-if="i > 0">•</span>
|
Ładowanie listy aktywnych scenerii...
|
||||||
<button class="btn--text" @click="handleClick(stationName)">
|
</h3>
|
||||||
{{ stationName }}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 v-else-if="onlineStations.length == 0">Brak aktywnych scenerii</h3>
|
<h3 v-else-if="sceneriesOnline.length == 0">Brak aktywnych scenerii</h3>
|
||||||
<h3 v-else>Ładowanie listy aktywnych scenerii...</h3>
|
|
||||||
|
<ul v-else class="scenery-list">
|
||||||
|
<li v-for="station in sceneriesOnline" :key="station.stationName">
|
||||||
|
<button @click="handleClick(station.stationName)">
|
||||||
|
{{ station.stationName }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { IOnlineStationsResponse } from '../types/IOnlineStationsResponse';
|
import { DataStatus, useApiStore } from '../stores/apiStore';
|
||||||
|
import { Region, useMainStore, regionNames } from '../stores/mainStore';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
onlineStations: [] as string[],
|
apiStore: useApiStore(),
|
||||||
dataLoaded: false,
|
mainStore: useMainStore(),
|
||||||
|
regions: [Region.PL1, Region.PL2, Region.CZE, Region.DE, Region.ENG],
|
||||||
|
DataStatus: DataStatus,
|
||||||
|
regionNames
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted() {
|
computed: {
|
||||||
const stationsAPIResponse: IOnlineStationsResponse = await (
|
sceneriesOnline() {
|
||||||
await fetch('https://api.td2.info.pl/?method=getStationsOnline')
|
return (
|
||||||
).json();
|
this.apiStore.activeData?.activeSceneries
|
||||||
|
.filter((station) => {
|
||||||
this.dataLoaded = true;
|
return station.region == this.mainStore.region && station.isOnline;
|
||||||
|
}, [])
|
||||||
this.onlineStations = stationsAPIResponse.message
|
.sort((s1, s2) => s1.stationName.localeCompare(s2.stationName)) || []
|
||||||
.reduce((acc, station) => {
|
);
|
||||||
if (station.region != 'eu') return acc;
|
}
|
||||||
if (!station.isOnline) return acc;
|
|
||||||
|
|
||||||
acc.push(station.stationName);
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, [] as string[])
|
|
||||||
.sort((s1, s2) => (s1 > s2 ? 1 : -1));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleClick(stationName: string) {
|
handleClick(stationName: string) {
|
||||||
this.$router.push(`/board?name=${stationName}`);
|
this.$router.push({
|
||||||
// this.selectedStation = station;
|
path: '/board',
|
||||||
|
query: {
|
||||||
|
name: stationName,
|
||||||
|
region: this.mainStore.region
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
changeRegion(region: Region) {
|
||||||
|
this.mainStore.region = region;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style ;ang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.home-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.region-selector {
|
||||||
|
display: grid;
|
||||||
|
justify-content: center;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
max-width: 500px;
|
||||||
|
gap: 0.5em;
|
||||||
|
|
||||||
|
|
||||||
|
margin: 1em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scenery-selector > div {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
ul.scenery-list {
|
ul.scenery-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5em;
|
||||||
padding: 1em;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
|
// List animation
|
||||||
|
.list-anim-enter-active,
|
||||||
|
.list-anim-leave-active {
|
||||||
|
transition: all 90ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-anim-enter-from,
|
||||||
|
.list-anim-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
+501
-544
File diff suppressed because it is too large
Load Diff
Vendored
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue';
|
||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>;
|
||||||
export default component
|
export default component;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user