<template>
<v-menu
v-model="menu"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
:value="valueInput"
:label="label"
:placeholder="placeholder"
:hint="hint"
prepend-icon="mdi-calendar"
readonly
dense
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="pickerInput"
no-title
:max="maxValue"
:min="minValue"
:show-current="showCurrent"
@input="menu = false"
:active-picker="activePicker"
></v-date-picker>
</v-menu>
</template>
<script>
import { formatDate } from "@/functions"
// В параметре date в родительском компоненте нужно использовать модификатор .sync
export default {
name: "DatePicker",
props: ['date', 'label', 'hint', 'min', 'max', 'showCurrent', 'placeholder', 'picker'],
data () {
return {
menu: false,
activePicker: null
}
},
watch: {
menu (val) {
val && setTimeout(() => (this.activePicker = this.picker || 'DATE'))
}
},
computed: {
valueInput: {
set (newValue) {
this.$emit('update:date', newValue)
},
get: function() {
return formatDate(this.date)
}
},
pickerInput: {
set (newValue) {
this.$emit('update:date', newValue)
},
get: function() {
return this.date
}
},
minValue () {
return this.min || null
},
maxValue () {
return this.max || null
}
}
}
</script>
import store from '@/store'
import axios from 'axios'
...
router.beforeEach((to, from, next) => {
if (!store.state.Data) {
axios.post('https://site.ru/get_data').then(response => {
store.dispatch('setData', response.data.Data)
next()
} else {
next()
}
})
# Список серверов для балансировки запросов на запись (upload).
upstream storage_backend {
server s1.site.ru:80;
server s2.site.ru:80;
server s3.site.ru:80;
}
# Определение локации сервера для запросов на запись и удаление файла. Опция default нужна
# только для того, чтобы в случае неопределённого запроса получить 404, а не 500.
map $uri $storage_location {
"~/(storage|delete)/s1-" "s1.site.ru:80";
"~/(storage|delete)/s2-" "s2.site.ru:80";
"~/(storage|delete)/s3-" "s3.site.ru:80";
default "s1.site.ru:80";
}
server {
listen 80;
server_name s.site.ru;
location / {
proxy_pass http://$storage_location;
}
location /upload/ {
proxy_pass http://storage_backend;
}
}
import importlib
def auth(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
# В переменной конфигурации EXT_API_MODULE хранится имя модуля, который содержит класс extAPI
# для генерации вызовов к внешним API. Модулей два: ext_api.py и exp_api_test.py
# В первом реальные обработчики для продакшена, EXT_API_MODULE="exp_api"
# Во втором - заглушки для тестов, EXT_API_MODULE="exp_api_test"
ext_api = importlib.import_module('application.{0}'.format(current_app.config['EXT_API_MODULE']))
token = request.headers.get('X-Auth-Token')
if not get_from_cache(token):
res = ext_api.extAPI().auth_service(token)
if res.status_code == 200:
set_to_cache(token)
return fn(*args, **kwargs)
return Responce('{"error": "Invalid token"}', status=404)
return wrapper
upstream master {
server unix:/tmp/flask.sock;
}
upstream read_api {
server api.service.ru;
}
map $request_method $upstream_location {
GET read_api;
default master;
}
server {
listen 80;
server_name service.ru;
root /home/web/service;
include uwsgi_params;
include proxy_params;
location / {
if ($http_referer !~* ^($|http://) ){
return 403;
}
uwsgi_pass unix:/tmp/flask.sock;
}
location /restapi/v1/ {
if ($upstream_location = "master") {
uwsgi_pass unix:/tmp/flask.sock;
}
if ($upstream_location != "master") {
proxy_pass https://$upstream_location;
}
}
}