Compare commits
16 Commits
7a6ecf6281
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dca7b4941c | |||
| d917fe7ed6 | |||
| fa1d417c2e | |||
| 166b402475 | |||
| 571ca6e021 | |||
| b1bff87a25 | |||
| c7de6977c0 | |||
| ed9de87f71 | |||
| 0a563c0a1a | |||
| a28d522709 | |||
| ba237a6f34 | |||
| cb6db95cea | |||
| dd95fc311d | |||
|
|
74717e4961 | ||
|
|
60b909015a | ||
|
|
e5195dd9c5 |
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.env
|
||||
*.log
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
140
README.md
Normal file
140
README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# InfraIT Landing + Admin
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> IT-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Flask <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram.
|
||||
|
||||
## <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> SEO-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, FAQ <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> SQLite (`data/infra.db`, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `leads`).
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, SEO-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram (bot token + chat id).
|
||||
- Healthcheck-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (`/health`).
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Docker-<2D><><EFBFBD><EFBFBD> (`Dockerfile` + `docker-compose.yml`).
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- Python 3.12
|
||||
- Flask 3.1
|
||||
- Gunicorn 23
|
||||
- SQLite
|
||||
- HTML/CSS/JS (Jinja2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
```text
|
||||
infraIT/
|
||||
app.py
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
gunicorn_conf.py
|
||||
requirements.txt
|
||||
templates/
|
||||
static/
|
||||
data/
|
||||
```
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `.env` (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> `.env.example`):
|
||||
|
||||
```env
|
||||
SECRET_KEY=replace-with-a-long-random-string
|
||||
```
|
||||
|
||||
`SECRET_KEY` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>).
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> (Docker)
|
||||
|
||||
1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `.env`:
|
||||
|
||||
```powershell
|
||||
Copy-Item .env.example .env
|
||||
```
|
||||
|
||||
2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
||||
|
||||
```powershell
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
||||
|
||||
- <20><><EFBFBD><EFBFBD>: `http://localhost:4545`
|
||||
- Healthcheck: `http://localhost:4545/health`
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
||||
|
||||
```powershell
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD> Docker)
|
||||
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.\.venv\Scripts\Activate.ps1
|
||||
pip install -r requirements.txt
|
||||
$env:SECRET_KEY = "your-strong-secret"
|
||||
python app.py
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> `http://127.0.0.1:5000` (<28><><EFBFBD><EFBFBD><EFBFBD> Flask debug).
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- URL: `http://localhost:4545/admin/login` (<28><><EFBFBD> `http://127.0.0.1:5000/admin/login` <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>: `/admin/settings`
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
||||
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- canonical URL
|
||||
- Yandex verification token
|
||||
- ID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- Telegram Bot Token / Telegram Chat ID
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> `app.py` <20> `ADMIN_PASSWORD_HASH`.
|
||||
<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
||||
|
||||
```powershell
|
||||
python -c "from werkzeug.security import generate_password_hash; print(generate_password_hash('NEW_PASSWORD'))"
|
||||
```
|
||||
|
||||
## Telegram-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram:
|
||||
|
||||
1. <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `Telegram Bot Token`.
|
||||
2. <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `Telegram Chat ID`.
|
||||
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- <20><><EFBFBD><EFBFBD>: `data/infra.db`
|
||||
- <20> Docker <20><><EFBFBD><EFBFBD><EFBFBD> `data/` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> volume (`./data:/app/data`)
|
||||
- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: `static/img/infrait-logo.png`
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> `data/infra.db`.
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `SECRET_KEY`.
|
||||
- <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `app.py` <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> `/admin/*` <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> reverse-proxy/VPN/IP allowlist.
|
||||
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTPS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Nginx/Caddy/Traefik).
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- `GET /` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- `POST /` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- `GET /admin/login` - <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- `GET/POST /admin/settings` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- `GET /admin/logout` - <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
- `GET /health` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Binary file not shown.
28
app.py
28
app.py
@@ -7,7 +7,7 @@ from functools import wraps
|
||||
from pathlib import Path
|
||||
from urllib import parse, request as urllib_request
|
||||
|
||||
from flask import Flask, redirect, render_template, request, session, url_for
|
||||
from flask import Flask, redirect, render_template, request, send_from_directory, session, url_for
|
||||
from werkzeug.security import check_password_hash
|
||||
|
||||
|
||||
@@ -27,6 +27,15 @@ DEFAULT_SETTINGS = {
|
||||
"telegram_chat_id": "",
|
||||
"geo_primary": "Казань и Татарстан — выезд в день запроса",
|
||||
"geo_secondary": "Россия — удалённая поддержка",
|
||||
"company_legal_name": "ООО «ИнфраИТ»",
|
||||
"company_inn": "",
|
||||
"company_kpp": "",
|
||||
"company_ogrn": "",
|
||||
"company_bank_name": "",
|
||||
"company_bik": "",
|
||||
"company_account": "",
|
||||
"company_correspondent_account": "",
|
||||
"company_legal_address": "",
|
||||
}
|
||||
|
||||
app = Flask(__name__)
|
||||
@@ -204,6 +213,12 @@ def index():
|
||||
return render_template("index.html", success=success, error=error, settings=settings)
|
||||
|
||||
|
||||
@app.route("/company-details")
|
||||
def company_details():
|
||||
settings = get_settings()
|
||||
return render_template("company_details.html", settings=settings)
|
||||
|
||||
|
||||
@app.route("/admin/login", methods=["GET", "POST"])
|
||||
def admin_login():
|
||||
error = None
|
||||
@@ -250,6 +265,17 @@ def health():
|
||||
return {"status": "error"}, 503
|
||||
|
||||
|
||||
@app.route("/favicon.ico")
|
||||
def favicon():
|
||||
response = send_from_directory(
|
||||
app.static_folder,
|
||||
"img/favicon.png",
|
||||
mimetype="image/png",
|
||||
)
|
||||
response.headers["Cache-Control"] = "no-store, max-age=0"
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
init_db()
|
||||
app.run(debug=True)
|
||||
|
||||
BIN
data/infra.db
BIN
data/infra.db
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
created_at,name,company,phone,email,city,computers,message
|
||||
2026-02-12T16:33:08,Иван,ООО Тест,123,,,10,
|
||||
created_at,name,company,phone,email,city,computers,message
|
||||
2026-02-12T16:33:08,Иван,ООО Тест,123,,,10,
|
||||
|
||||
|
BIN
static/img/favicon.png
Normal file
BIN
static/img/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -4,6 +4,9 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Вход в админку | InfraIT</title>
|
||||
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
|
||||
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
|
||||
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Montserrat:wght@600;700;800&display=swap" rel="stylesheet">
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Настройки сайта | InfraIT</title>
|
||||
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
|
||||
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
|
||||
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Montserrat:wght@600;700;800&display=swap" rel="stylesheet">
|
||||
@@ -69,6 +72,45 @@
|
||||
<input type="text" name="geo_secondary" value="{{ settings.geo_secondary }}">
|
||||
</label>
|
||||
|
||||
<hr style="border:0;border-top:1px solid #d6e0ea;margin:6px 0 2px;">
|
||||
<h3 style="margin:4px 0 2px;">Реквизиты компании</h3>
|
||||
|
||||
<label>Юридическое наименование
|
||||
<input type="text" name="company_legal_name" value="{{ settings.company_legal_name }}">
|
||||
</label>
|
||||
|
||||
<label>ИНН
|
||||
<input type="text" name="company_inn" value="{{ settings.company_inn }}">
|
||||
</label>
|
||||
|
||||
<label>КПП
|
||||
<input type="text" name="company_kpp" value="{{ settings.company_kpp }}">
|
||||
</label>
|
||||
|
||||
<label>ОГРН / ОГРНИП
|
||||
<input type="text" name="company_ogrn" value="{{ settings.company_ogrn }}">
|
||||
</label>
|
||||
|
||||
<label>Банк
|
||||
<input type="text" name="company_bank_name" value="{{ settings.company_bank_name }}">
|
||||
</label>
|
||||
|
||||
<label>БИК
|
||||
<input type="text" name="company_bik" value="{{ settings.company_bik }}">
|
||||
</label>
|
||||
|
||||
<label>Расчётный счёт
|
||||
<input type="text" name="company_account" value="{{ settings.company_account }}">
|
||||
</label>
|
||||
|
||||
<label>Корреспондентский счёт
|
||||
<input type="text" name="company_correspondent_account" value="{{ settings.company_correspondent_account }}">
|
||||
</label>
|
||||
|
||||
<label>Юридический адрес
|
||||
<textarea name="company_legal_address" rows="3">{{ settings.company_legal_address }}</textarea>
|
||||
</label>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Сохранить настройки</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<meta property="og:description" content="Компьютеры, серверы и сети для бизнеса без простоев. Татарстан и Казань с выездом, Россия удаленно.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:locale" content="ru_RU">
|
||||
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
|
||||
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
|
||||
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
|
||||
<meta name="yandex-verification" content="{{ settings.yandex_verification }}">
|
||||
{% if settings.yandex_metrika_id %}
|
||||
<script>
|
||||
|
||||
77
templates/company_details.html
Normal file
77
templates/company_details.html
Normal file
@@ -0,0 +1,77 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ settings.company_name }} — Реквизиты компании{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<header class="hero" id="top">
|
||||
<div class="container">
|
||||
<div class="topbar">
|
||||
<a class="brand" href="{{ url_for('index') }}" aria-label="{{ settings.company_name }}">
|
||||
<img src="{{ url_for('static', filename='img/infrait-logo.png') }}" alt="{{ settings.company_name }} logo" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-flex';">
|
||||
<span class="brand-fallback">{{ settings.company_name }}</span>
|
||||
</a>
|
||||
<nav class="nav">
|
||||
<a href="{{ url_for('index') }}#services">Услуги</a>
|
||||
<a href="{{ url_for('index') }}#pricing">Тарифы</a>
|
||||
<a href="{{ url_for('index') }}#faq">FAQ</a>
|
||||
<a href="{{ url_for('index') }}#contact">Контакты</a>
|
||||
<a href="{{ url_for('company_details') }}">Реквизиты</a>
|
||||
</nav>
|
||||
<a href="tel:{{ settings.phone_link }}" class="phone">{{ settings.phone_display }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="section">
|
||||
<div class="container two-col">
|
||||
<article class="panel">
|
||||
<h2>Реквизиты компании</h2>
|
||||
<p class="section-subtitle">Актуальные данные для договоров и бухгалтерских документов.</p>
|
||||
<ul class="contacts">
|
||||
<li><strong>Юридическое наименование:</strong> {{ settings.company_legal_name or "-" }}</li>
|
||||
<li><strong>ИНН:</strong> {{ settings.company_inn or "-" }}</li>
|
||||
<li><strong>КПП:</strong> {{ settings.company_kpp or "-" }}</li>
|
||||
<li><strong>ОГРН / ОГРНИП:</strong> {{ settings.company_ogrn or "-" }}</li>
|
||||
<li><strong>Банк:</strong> {{ settings.company_bank_name or "-" }}</li>
|
||||
<li><strong>БИК:</strong> {{ settings.company_bik or "-" }}</li>
|
||||
<li><strong>Расчётный счёт:</strong> {{ settings.company_account or "-" }}</li>
|
||||
<li><strong>Корреспондентский счёт:</strong> {{ settings.company_correspondent_account or "-" }}</li>
|
||||
<li><strong>Юридический адрес:</strong> {{ settings.company_legal_address or "-" }}</li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h2>Контакты</h2>
|
||||
<ul class="contacts">
|
||||
<li><strong>Компания:</strong> {{ settings.company_name }}</li>
|
||||
<li><strong>Телефон:</strong> <a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></li>
|
||||
<li><strong>Email:</strong> <a href="mailto:{{ settings.email }}">{{ settings.email }}</a></li>
|
||||
<li><strong>Выезды:</strong> {{ settings.geo_primary }}</li>
|
||||
<li><strong>По России:</strong> {{ settings.geo_secondary }}</li>
|
||||
</ul>
|
||||
<div class="cta-row">
|
||||
<a href="{{ url_for('index') }}#contact" class="btn btn-primary">Оставить заявку</a>
|
||||
<a href="{{ url_for('index') }}" class="btn btn-secondary">На главную</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container footer-inner">
|
||||
<div>
|
||||
<a class="footer-logo" href="{{ url_for('index') }}" aria-label="{{ settings.company_name }}">
|
||||
<img src="{{ url_for('static', filename='img/infrait-logo.png') }}" alt="{{ settings.company_name }} logo" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-flex';">
|
||||
<span class="brand-fallback">{{ settings.company_name }}</span>
|
||||
</a>
|
||||
<p>Комплексное IT-обслуживание бизнеса: компьютеры, серверы и сети.</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></p>
|
||||
<p><a href="mailto:{{ settings.email }}">{{ settings.email }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
{% endblock %}
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ settings.company_name }} — IT-обслуживание бизнеса в Татарстане и по России{% endblock %}
|
||||
{% block title %}{{ settings.company_name }} — IT-обслуживание бизнеса в Татарстанек и по России{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
<script type="application/ld+json">
|
||||
@@ -133,7 +133,7 @@
|
||||
<article class="price-card">
|
||||
<h3>Лайт</h3>
|
||||
<p class="for">Для офисов 5-10 ПК</p>
|
||||
<p class="price">от 2 500 ₽ / ПК</p>
|
||||
<p class="price">от 2 000 ₽ / ПК</p>
|
||||
<ul>
|
||||
<li>Удалённая поддержка пользователей</li>
|
||||
<li>Базовое администрирование сети</li>
|
||||
@@ -333,6 +333,7 @@
|
||||
<div>
|
||||
<p><a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></p>
|
||||
<p><a href="mailto:{{ settings.email }}">{{ settings.email }}</a></p>
|
||||
<p><a href="{{ url_for('company_details') }}">Реквизиты</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user