Compare commits
3 Commits
back_alpha
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 704320d3a4 | |||
|
|
0b78b5b95c | ||
|
|
34f1defb0b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,3 +22,4 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
/backed-old/
|
||||||
2652
package-lock.json
generated
2652
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,15 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"express": "^5.2.1",
|
||||||
"naive-ui": "^2.43.2",
|
"naive-ui": "^2.43.2",
|
||||||
"vue": "^3.5.25"
|
"sqlite3": "^5.1.7",
|
||||||
|
"vue": "^3.5.25",
|
||||||
|
"vue-router": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^6.0.2",
|
"@vitejs/plugin-vue": "^6.0.2",
|
||||||
|
|||||||
41
server.js
Normal file
41
server.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import express from 'express'
|
||||||
|
import Database from 'sqlite3'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
import { dirname, join } from 'path'
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const app = express()
|
||||||
|
const PORT = 3000
|
||||||
|
|
||||||
|
const db = new Database.Database(join(__dirname, 'Buh-nr'))
|
||||||
|
|
||||||
|
app.use(express.static(join(__dirname, 'dist')))
|
||||||
|
|
||||||
|
app.get('/api/regions', (_req, res) => {
|
||||||
|
db.all('SELECT id, name, slug FROM regions ORDER BY id', (err, rows) => {
|
||||||
|
if (err) return res.status(500).json({ error: 'Ошибка получения регионов' })
|
||||||
|
res.json(rows)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/api/tariffs', (req, res) => {
|
||||||
|
const mode = req.query.mode || 'special'
|
||||||
|
const sql = `
|
||||||
|
SELECT t.id, t.title, t.description, p.price
|
||||||
|
FROM tariffs t
|
||||||
|
JOIN prices p ON p.tariff_id = t.id
|
||||||
|
JOIN tax_modes tm ON tm.id = p.tax_mode_id
|
||||||
|
WHERE tm.slug = ?
|
||||||
|
ORDER BY t.sort_order
|
||||||
|
`
|
||||||
|
db.all(sql, [mode], (err, rows) => {
|
||||||
|
if (err) return res.status(500).json({ error: 'Ошибка получения тарифов' })
|
||||||
|
res.json(rows)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/{*splat}', (_req, res) => {
|
||||||
|
res.sendFile(join(__dirname, 'dist', 'index.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(PORT, () => console.log(`Сервер запущен: http://localhost:${PORT}`))
|
||||||
47
src/App.vue
47
src/App.vue
@@ -1,31 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<n-config-provider :theme-overrides="selectTheme">
|
||||||
<div class="app">
|
<n-message-provider>
|
||||||
<SiteHeader />
|
<router-view />
|
||||||
<main class="container">
|
</n-message-provider>
|
||||||
<TaxModeSelector v-model="selectedMode" />
|
</n-config-provider>
|
||||||
<TariffCards :mode="selectedMode" />
|
|
||||||
<MarqueeBar />
|
|
||||||
<PriceTable />
|
|
||||||
<ServicesGrid />
|
|
||||||
<AdvantagesSection />
|
|
||||||
|
|
||||||
</main>
|
|
||||||
<Footer />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
const selectTheme = {
|
||||||
import SiteHeader from './components/SiteHeader.vue'
|
common: {
|
||||||
import TaxModeSelector from './components/TaxModeSelector.vue'
|
primaryColor: "#ff4d00",
|
||||||
import TariffCards from './components/TariffCards.vue'
|
primaryColorHover: "#ff6a00",
|
||||||
import MarqueeBar from './components/MarqueeBar.vue'
|
primaryColorPressed: "#e63e00",
|
||||||
import PriceTable from './components/PriceTable.vue'
|
borderRadius: "10px"
|
||||||
import ServicesGrid from './components/ServicesGrid.vue'
|
},
|
||||||
import AdvantagesSection from './components/AdvantagesSection.vue'
|
Select: {
|
||||||
import Footer from './components/Footer.vue'
|
peers: {
|
||||||
const selectedMode = ref('special')
|
InternalSelection: {
|
||||||
|
color: "rgba(255,255,255,0.45)",
|
||||||
|
textColor: "#000",
|
||||||
|
border: "1px solid rgba(255,255,255,0.35)",
|
||||||
|
borderHover: "1px solid rgba(255,255,255,0.6)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,29 +1,98 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted } from "vue"
|
||||||
|
import { useRoute, useRouter } from "vue-router"
|
||||||
|
import { useMessage } from "naive-ui"
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const city = ref(route.params.region || 'moscow')
|
||||||
|
const cities = ref([])
|
||||||
|
|
||||||
|
const phone = "8 (800) 000-00-00"
|
||||||
|
const phoneRaw = "88000000000"
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const res = await fetch('/api/regions')
|
||||||
|
const data = await res.json()
|
||||||
|
cities.value = data.map(r => ({ label: r.name, value: r.slug }))
|
||||||
|
})
|
||||||
|
|
||||||
|
// синхронизируем селектор при навигации (кнопка «назад» и т.п.)
|
||||||
|
watch(() => route.params.region, (val) => {
|
||||||
|
if (val && val !== city.value) city.value = val
|
||||||
|
})
|
||||||
|
|
||||||
|
// переходим на страницу выбранного региона
|
||||||
|
watch(city, (val) => {
|
||||||
|
if (val !== route.params.region) router.push(`/${val}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
function handlePhoneClick() {
|
||||||
|
const isMobile = /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i
|
||||||
|
.test(navigator.userAgent)
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
|
window.location.href = `tel:${phoneRaw}`
|
||||||
|
} else {
|
||||||
|
navigator.clipboard.writeText(phone)
|
||||||
|
message.success("Номер скопирован")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
|
|
||||||
<div class="col left">
|
<div class="col left">
|
||||||
<div class="logo">LOGO</div>
|
<div class="logo">LOGO</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col center">
|
<div class="col center">
|
||||||
<div class="title">Удалённый бухгалтер</div>
|
<div class="title">Удалённый бухгалтер</div>
|
||||||
<select class="city">
|
<n-select
|
||||||
<option>Москва</option>
|
v-model:value="city"
|
||||||
<option>Санкт-Петербург</option>
|
:options="cities"
|
||||||
<option>Казань</option>
|
size="small"
|
||||||
</select>
|
class="city"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col right">
|
<div class="col right">
|
||||||
<div class="phone">8 (800) 000-00-00</div>
|
<div
|
||||||
|
class="phone"
|
||||||
|
@click="handlePhoneClick"
|
||||||
|
title="Нажмите чтобы скопировать"
|
||||||
|
>
|
||||||
|
{{ phone }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
padding: 25px 0;
|
padding: 26px 0;
|
||||||
|
background: linear-gradient(120deg, #ffd000, #ff7a00, #ff2a00);
|
||||||
|
background-size: 300% 300%;
|
||||||
|
animation: gradientMove 10s ease infinite, headerAppear .7s ease;
|
||||||
|
box-shadow: 0 8px 22px rgba(0,0,0,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes gradientMove {
|
||||||
|
0% { background-position: 0% 50%; }
|
||||||
|
50% { background-position: 100% 50%; }
|
||||||
|
100% { background-position: 0% 50%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes headerAppear {
|
||||||
|
from { opacity: 0; transform: translateY(-40px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
@@ -31,7 +100,7 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 60px;
|
padding: 0 60px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3,1fr);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,35 +109,58 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left { justify-content: flex-start; }
|
||||||
justify-content: flex-start;
|
.center { flex-direction: column; text-align: center; }
|
||||||
}
|
.right { justify-content: flex-end; }
|
||||||
|
|
||||||
.center {
|
|
||||||
flex-direction: column;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
font-size: 22px;
|
font-size: 24px;
|
||||||
font-weight: bold;
|
font-weight: 800;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: black;
|
||||||
|
transition: transform .25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo:hover { transform: scale(1.08); }
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 18px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.city {
|
.city { margin-top: 8px; width: 190px; }
|
||||||
margin-top: 6px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.phone {
|
.phone {
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
color: black;
|
||||||
|
padding: 7px 16px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgba(255,255,255,0.35);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
border: 1px solid rgba(255,255,255,0.35);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all .25s ease;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
.phone:hover {
|
||||||
|
background: rgba(255,255,255,0.6);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.inner {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0 25px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.left, .right { justify-content: center; }
|
||||||
|
.logo { font-size: 22px; }
|
||||||
|
.title { font-size: 18px; }
|
||||||
|
.phone { font-size: 16px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -11,27 +11,27 @@
|
|||||||
bordered
|
bordered
|
||||||
>
|
>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Кому подходит</h4>
|
<h4>Кому подходит</h4>
|
||||||
<p>Малому и среднему бизнесу</p>
|
<p>Малому и среднему бизнесу</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4>Какие задачи решает</h4>
|
<h4>Какие задачи решает</h4>
|
||||||
<p>Сдача отчётности, расчёт налогов</p>
|
<p>Сдача отчётности, расчёт налогов</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4>Преимущества</h4>
|
<h4>Преимущества</h4>
|
||||||
<p>Экономия времени и снижение рисков</p>
|
<p>Экономия времени и снижение рисков</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="price">
|
<div class="price">
|
||||||
{{ tariff.price }} ₽
|
{{ tariff.price }} ₽
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<n-button type="primary" block>
|
<n-button type="primary" block @click="selectTariff(tariff.title)">
|
||||||
Выбрать
|
Выбрать
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-card>
|
</n-card>
|
||||||
@@ -40,7 +40,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
mode: {
|
mode: {
|
||||||
@@ -49,56 +50,37 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const priceSets = {
|
const route = useRoute()
|
||||||
special: [1437, 3037, 2992],
|
const router = useRouter()
|
||||||
general: [1890, 3790, 3490]
|
const tariffs = ref([])
|
||||||
|
|
||||||
|
async function fetchTariffs(mode) {
|
||||||
|
const res = await fetch(`/api/tariffs?mode=${mode}`)
|
||||||
|
tariffs.value = await res.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseTariffs = [
|
onMounted(() => fetchTariffs(props.mode))
|
||||||
{
|
watch(() => props.mode, fetchTariffs)
|
||||||
id: 1,
|
|
||||||
title: 'Базовый',
|
|
||||||
description: 'Подходит для ИП без сотрудников. Минимальный пакет услуг.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'Стандарт',
|
|
||||||
description: 'Оптимальный вариант для малого бизнеса с небольшим оборотом.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: 'Премиум',
|
|
||||||
description: 'Полное бухгалтерское сопровождение и расширенные консультации.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const tariffs = computed(() => {
|
function selectTariff(title) {
|
||||||
const currentMode = props.mode || 'special'
|
router.push(`/${route.params.region}/order?tariff=${encodeURIComponent(title)}`)
|
||||||
const prices = priceSets[currentMode]
|
}
|
||||||
|
|
||||||
return baseTariffs.map((tariff, index) => ({
|
|
||||||
...tariff,
|
|
||||||
price: prices[index]
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.tariff-wrapper {
|
.tariff-wrapper {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column; /* 🔥 вертикально */
|
flex-direction: column;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.column{
|
|
||||||
|
.column {
|
||||||
width: 33%
|
width: 33%
|
||||||
}
|
}
|
||||||
|
|
||||||
.columns {
|
.columns {
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 40px;
|
gap: 40px;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { createApp } from 'vue'
|
|||||||
import './style.css'
|
import './style.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import naive from 'naive-ui'
|
import naive from 'naive-ui'
|
||||||
|
import router from './router/index.js'
|
||||||
|
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(naive)
|
app.use(naive)
|
||||||
|
app.use(router)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
28
src/pages/HomePage.vue
Normal file
28
src/pages/HomePage.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<SiteHeader />
|
||||||
|
<main class="container">
|
||||||
|
<TaxModeSelector v-model="selectedMode" />
|
||||||
|
<TariffCards :mode="selectedMode" />
|
||||||
|
<MarqueeBar />
|
||||||
|
<PriceTable />
|
||||||
|
<ServicesGrid />
|
||||||
|
<AdvantagesSection />
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import SiteHeader from '../components/SiteHeader.vue'
|
||||||
|
import TaxModeSelector from '../components/TaxModeSelector.vue'
|
||||||
|
import TariffCards from '../components/TariffCards.vue'
|
||||||
|
import MarqueeBar from '../components/MarqueeBar.vue'
|
||||||
|
import PriceTable from '../components/PriceTable.vue'
|
||||||
|
import ServicesGrid from '../components/ServicesGrid.vue'
|
||||||
|
import AdvantagesSection from '../components/AdvantagesSection.vue'
|
||||||
|
import Footer from '../components/Footer.vue'
|
||||||
|
|
||||||
|
const selectedMode = ref('special')
|
||||||
|
</script>
|
||||||
44
src/pages/OrderPage.vue
Normal file
44
src/pages/OrderPage.vue
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<div class="order-page">
|
||||||
|
<h1>Оформление заказа</h1>
|
||||||
|
<p v-if="tariff">Выбранный тариф: <strong>{{ tariff }}</strong></p>
|
||||||
|
<router-link :to="`/${region}`">← Вернуться назад</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const region = computed(() => route.params.region)
|
||||||
|
const tariff = computed(() => route.query.tariff || '')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.order-page {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 100px auto;
|
||||||
|
padding: 0 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #ff4d00;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
14
src/router/index.js
Normal file
14
src/router/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import HomePage from '../pages/HomePage.vue'
|
||||||
|
import OrderPage from '../pages/OrderPage.vue'
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{ path: '/', redirect: '/moscow' },
|
||||||
|
{ path: '/:region', component: HomePage },
|
||||||
|
{ path: '/:region/order', component: OrderPage }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes
|
||||||
|
})
|
||||||
@@ -5,8 +5,13 @@ import vue from '@vitejs/plugin-vue'
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'vue': 'vue/dist/vue.esm-bundler.js'
|
'vue': 'vue/dist/vue.esm-bundler.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/api': 'http://localhost:3000'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user