This commit is contained in:
Петрищев Алексей 2025-11-19 16:31:11 +03:00
parent 279dc69a29
commit c303e7526c
91 changed files with 7104 additions and 1621 deletions

View File

@ -0,0 +1,58 @@
select e.id,
date(e.execDate) as 'дата',
apt.value as 'время',
apt.`index` as 'индекс',
apa_nom.value as 'тикет',
at.code as 'тип записи',
api_nes.value as 'не для вс',
api_uo.value as 'уо',
api_tm.value as 'ТМ',
concat_ws(' ', p.id, p.lastName, p.firstName, p.patrName) as 'врач',
a2.createDatetime as 'Когда записан',
concat_ws(' ', c.id, c.lastName, c.firstName, c.patrName) as 'клиент',
a2.note
from Event e
join Action a on e.id = a.event_id
join ActionType at on a.actionType_id = at.id
join Person p on e.execPerson_id = p.id
join ActionPropertyType apT1 on a.actionType_id = apT1.actionType_id and apT1.name like '%times%'
join ActionProperty ap1 on a.id = ap1.action_id and ap1.type_id = apT1.id
left join ActionProperty_Time apt on ap1.id = apt.id
join ActionPropertyType apt_nom on a.actionType_id = apt_nom.actionType_id and apt_nom.name = REPLACE(apT1.name, 'times', 'queue')
join ActionProperty ap_now on a.id = ap_now.action_id and ap_now.type_id = apt_nom.id and ap_now.deleted=0
left join ActionProperty_Action apa_nom on ap_now.id = apa_nom.id and apt.`index` = apa_nom.`index`
join ActionPropertyType apt_new on a.actionType_id = apt_new.actionType_id and apt_new.name = 'notExternalSystems'
join ActionProperty ap_nes on a.id = ap_nes.action_id and ap_nes.type_id = apt_new.id and ap_nes.deleted=0
left join ActionProperty_Integer api_nes on ap_nes.id = api_nes.id and apt.`index` = api_nes.`index`
join ActionPropertyType apt_uo on a.actionType_id = apt_uo.actionType_id and apt_uo.name = 'uos'
join ActionProperty ap_uo on a.id = ap_uo.action_id and ap_uo.type_id = apt_uo.id and ap_uo.deleted=0
left join ActionProperty_Integer api_uo on ap_uo.id = api_uo.id and apt.`index` = api_uo.`index`
left join ActionPropertyType apt_tm on a.actionType_id = apt_tm.actionType_id and apt_tm.name = 'tms'
left join ActionProperty ap_tm on a.id = ap_tm.action_id and ap_tm.type_id = apt_tm.id and ap_tm.deleted=0
left join ActionProperty_Integer api_tm on ap_tm.id = api_tm.id and apt.`index` = api_tm.`index`
left join Action a2 on apa_nom.value = a2.id
left join Event e2 on a2.event_id = e2.id
left join Client c on e2.client_id = c.id
where e.eventType_id = 5
and at.code = 'amb'
and a.deleted = 0
and (a2.deleted = 0 or a2.deleted is null)
and (e2.deleted = 0 or e2.deleted is null)
and e.deleted = 0
and ap1.deleted = 0
and ap_now.deleted = 0
and e.execPerson_id in (566) -- тут врача подставляй
#and apa_nom.value is null -- если нужны свободные слоты
# and date(e.execDate) between '2025-06-18 00:00:00' and adddate('2025-06-18 00:00:00', 50) -- интервал на которые смотрим даты
and date(e.execDate) between current_date and adddate(current_date, 14) -- интервал на которые смотрим даты
order by e.execDate, apt.value, p.id;

View File

@ -0,0 +1,73 @@
<style>
tr.unvis_1 > td {
color: #6c757d !important;
}
tr.unvis_1 {
opacity: .6;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12" id="colTable">
<div class="bg-white rounded p-2">
<h2 class="mb-2"><?php echo \htmlentities($cat->cat_name, ENT_QUOTES, 'UTF-8', false); ?></h2>
<div class="p-2 bg-light">
<?php if($module->add): ?>
<a href="?cat=<?php echo \htmlentities($cat->cat, ENT_QUOTES, 'UTF-8', false); ?>&act=edit&id=0" data-fancybox data-type="ajax" class="btn btn-success btn-sm"><i class="far fa-plus"></i> Создать</a>
<?php endif; ?>
<button class="btn btn-primary btn-sm" type="button" data-toggle="collapse" data-target="#pageFilter" aria-expanded="false" aria-controls="multiCollapseExample2"><i class="far fa-filter"></i> Фильтр</button>
</div>
<div class="q_filter collapse bg-light p-2 mt-2" id="pageFilter">
<form>
<input type="hidden" name="cat" value="<?php echo \htmlentities($cat->cat, ENT_QUOTES, 'UTF-8', false); ?>">
<?php echo $filter; ?>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">Показать</button>
</div>
</form>
</div>
<div class="table-responsive mt-3">
<table class="table table-sm small table-hover table2excel">
<thead>
<tr>
<th>ID</th>
<?php $__currentLoopData = $cols; $this->addLoop($__currentLoopData);$this->getFirstLoop();
foreach($__currentLoopData as $colName => $colTitle): $loop = $this->incrementLoopIndices(); ?>
<th><?php echo \htmlentities($colTitle, ENT_QUOTES, 'UTF-8', false); ?></th>
<?php endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>
<?php if($module->del): ?>
<th>Уд.</th>
<?php endif; ?>
</tr>
</thead>
<tbody>
<?php while($row->next()): ?>
<tr class="unvis_<?php echo \htmlentities($row->get('_sys_unvisible'), ENT_QUOTES, 'UTF-8', false); ?>">
<td class="text-nowrap">
<a href="?cat=<?php echo \htmlentities($cat->cat, ENT_QUOTES, 'UTF-8', false); ?>&act=edit&id=<?php echo \htmlentities($row->id, ENT_QUOTES, 'UTF-8', false); ?>&curpage=<?php echo \htmlentities($page, ENT_QUOTES, 'UTF-8', false); ?><?php echo \htmlentities($filterUrl, ENT_QUOTES, 'UTF-8', false); ?>" data-fancybox data-type="ajax"><i class="fas fa-edit"></i></a>
<?php echo \htmlentities($row->id, ENT_QUOTES, 'UTF-8', false); ?>
</td>
<?php $__currentLoopData = $cols; $this->addLoop($__currentLoopData);$this->getFirstLoop();
foreach($__currentLoopData as $colName => $colTitle): $loop = $this->incrementLoopIndices(); ?>
<td>
<?php echo $row->render($colName,true); ?>
</td>
<?php endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>
<?php if($module->del): ?>
<td><a href="?cat=<?php echo \htmlentities($cat->cat, ENT_QUOTES, 'UTF-8', false); ?>&act=del&id=<?php echo \htmlentities($row->id, ENT_QUOTES, 'UTF-8', false); ?>&curpage=<?php echo \htmlentities($page, ENT_QUOTES, 'UTF-8', false); ?><?php echo \htmlentities($filterUrl, ENT_QUOTES, 'UTF-8', false); ?>" onClick="return confirm('Удалить?');" title="Удалить"><i class="fas fa-times text-danger "></i></a></td>
<?php endif; ?>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<?php echo $walker; ?>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,13 @@
<div>
<div class="width-fixed-300 width-fixed-md-600 width-fixed-lg-800 width-fixed-xxl-900 mx-auto p-0">
<?php if($module->id): ?>
<h3>Редактирование (id: <?php echo \htmlentities(intval($module->id), ENT_QUOTES, 'UTF-8', false); ?>)</h3>
<?php else: ?>
<h3>Создание</h3>
<?php endif; ?>
<div class="bg-light mt-3 p-2 form-sm small">
<?php echo $form; ?>
</div>
</div>
</div>

View File

@ -0,0 +1,67 @@
<style>
tr.unvis_1 > td {
color: #6c757d !important;
}
tr.unvis_1 {
opacity: .6;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12" id="colTable">
<div class="bg-white rounded p-2">
<h2 class="mb-2">{{$cat->cat_name}}</h2>
<div class="p-2 bg-light">
@if($module->add)
<a href="?cat={{$cat->cat}}&act=edit&id=0" data-fancybox data-type="ajax" class="btn btn-success btn-sm"><i class="far fa-plus"></i> Создать</a>
@endif
<button class="btn btn-primary btn-sm" type="button" data-toggle="collapse" data-target="#pageFilter" aria-expanded="false" aria-controls="multiCollapseExample2"><i class="far fa-filter"></i> Фильтр</button>
</div>
<div class="q_filter collapse bg-light p-2 mt-2" id="pageFilter">
<form>
<input type="hidden" name="cat" value="{{$cat->cat}}">
{!! $filter !!}
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">Показать</button>
</div>
</form>
</div>
<div class="table-responsive mt-3">
<table class="table table-sm small table-hover table2excel">
<thead>
<tr>
<th>ID</th>
@foreach($cols as $colName => $colTitle)
<th>{{$colTitle}}</th>
@endforeach
@if($module->del)
<th>Уд.</th>
@endif
</tr>
</thead>
<tbody>
@while($row->next())
<tr class="unvis_{{$row->get('_sys_unvisible')}}">
<td class="text-nowrap">
<a href="?cat={{$cat->cat}}&act=edit&id={{$row->id}}&curpage={{$page}}{{$filterUrl}}" data-fancybox data-type="ajax"><i class="fas fa-edit"></i></a>
{{$row->id}}
</td>
@foreach($cols as $colName => $colTitle)
<td>
{!! $row->render($colName,true) !!}
</td>
@endforeach
@if($module->del)
<td><a href="?cat={{$cat->cat}}&act=del&id={{$row->id}}&curpage={{$page}}{{$filterUrl}}" onClick="return confirm('Удалить?');" title="Удалить"><i class="fas fa-times text-danger "></i></a></td>
@endif
</tr>
@endwhile
</tbody>
</table>
</div>
{!! $walker !!}
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,12 @@
<div>
<div class="width-fixed-300 width-fixed-md-600 width-fixed-lg-800 width-fixed-xxl-900 mx-auto p-0">
@if($module->id)
<h3>Редактирование (id: {{intval($module->id)}})</h3>
@else
<h3>Создание</h3>
@endif
<div class="bg-light mt-3 p-2 form-sm small">
{!! $form !!}
</div>
</div>
</div>

View File

@ -7,6 +7,7 @@ class admin_polygon extends module {
public $_get_vars = [ 'act', 'id' ];
public $_post_vars = [ 'act', 'geom' ];
public $_loc_vars = ['obj_name'];
public $obj_name;
public function _init() {
$this->obj = new cobject($this->obj_name);
@ -18,14 +19,13 @@ class admin_polygon extends module {
$data = [];
$db2 = $this->obj->getDB()->q($this->obj->getSelectEx('id, title, ASTEXT(`geom`) as `geom` '));
$db2 = $this->obj->getDB()->q($this->obj->getSelectEx('id, ASTEXT(`geom`) as `geom` '));
while($db2->nr()) {
$coords = $this->mysql2json($db2->f('geom'));
$row = [];
$row['coords'] = $coords;
$row['id'] = $db2->f('id');
$row['title'] = $db2->f('title');
$data['rows'][] = $row;
}
@ -47,13 +47,15 @@ class admin_polygon extends module {
public function _ajax_getForm() {
$this->obj->byId($this->id);
$this->obj->set_hidden('geom');
$this->obj->setSqlWhere('zone_id', 'order by title asc');
$form = new form($this->obj);
$form->setTempl('attrs/poly_form.htm');
$formdata = $form->render();
$polycolor = $this->obj->get('color') ? $this->obj->get('color') : '#00FF00';
$returndata = ['html' => $formdata, 'color' => $polycolor, 'title' => $this->obj->get('title') ];
$returndata = ['html' => $formdata, 'color' => $polycolor ];
echo json_encode($returndata);
// echo $form->render();
@ -66,9 +68,8 @@ class admin_polygon extends module {
$this->obj->byId($id);
if ($this->geom) {
if (!$this->obj->id) {
$this->obj->set('title', 'Новая зона');
$this->obj->set('color', '#000000');
$this->obj->save();
$id = $this->obj->id;
}
@ -83,7 +84,6 @@ class admin_polygon extends module {
$ret = [];
$ret['id'] = $id;
$ret['title'] = htmlspecialchars_decode($this->obj->get('title'));
echo json_encode($ret);
die();

View File

@ -1,113 +1,113 @@
<?php
class object_admin extends module {
var $_loc_vars = array( 'templ', 'obj_name', 'del', 'add','onPage' );
var $_get_vars = array( 'act', 'id' );
var $obj;
var $templ = 'object_admin.htm';
var $del = true;
var $add = true;
var $onPage=10;
function _init() {
$this->obj = new cobject( $this->obj_name );
return parent::_init();
}
public $_loc_vars = [ 'templ', 'obj_name', 'del', 'add','onPage' ];
public $_get_vars = [ 'act', 'id' ];
public $obj;
public $templBlade = 'core_object_admin';
function _on_() {
global $R;
$db = $this->obj->getDB();
public $del = true;
public $add = true;
public $onPage = 10;
$tpl = $R->getTpl( $this->templ, 'body' );
$tplr = $R->getTpl( $this->templ, 'row' );
$tpltd = $R->getTpl( $this->templ, 'td' );
$tplth = $R->getTpl( $this->templ, 'th' );
$tpl_del_td = $R->getTpl( $this->templ, 'del_td' );
$tpl_del_th = $R->getTpl( $this->templ, 'del_th' );
public function _init() {
$this->obj = new cobject($this->obj_name);
return parent::_init();
}
foreach( $this->obj->attrs as $attr_name => $attrs ) {
if ( $attrs['hide'] ) continue;
$tt = $R->set('attr_name', $attrs['desc'], $tplth );
$tpl = $R->parse( 'head_cols', $tt, $tpl );
$tt = $R->set('attr_name', $attr_name, $tpltd );
$tplr = $R->parse( 'row_cols', $tt, $tplr);
}
if ( $this->del ) {
$tpl = $R->parse( 'head_cols', $tpl_del_th, $tpl );
$tplr = $R->parse( 'row_cols', $tpl_del_td, $tplr);
}
$filter = new filter( $this->obj_name );
$filter->parse();
public function _on_() {
global $blade;
$db = $this->obj->getDB();
$db2 = $db->q( $this->obj->getSelectEx( 'COUNT(*) as `cnt`', $filter->getSQL() ) );
$db2->r();
$size = $db2->f('cnt');
$pw = new Walker( $size, $this->onPage );
$data = [];
$tpl = $R->set( 'filter', $filter->getHTML() , $tpl);
$db2 = $db->q( $this->obj->getSelect( $filter->getSQL() . ' ORDER BY `ID` DESC ' . $pw->getSQL() ) );
while( $db2->r() ) {
$this->obj->lRow($db2);
$tt = $this->obj->assign( $tplr, true );
$tpl = $R->parse( 'rows', $tt, $tpl );
}
$this->obj->byId($this->id);
if ( !$this->id && !$this->add ) {
$tpl = $R->set( 'form', '' , $tpl);
} else {
$tpl = $R->set( 'form', $this->r_form() , $tpl);
}
$tpl = $R->set( 'walker', $pw->getHTML() , $tpl);
$tpl = $R->set( 'cur_page', $pw->page, $tpl );
$tpl = $R->set( 'filter_url', $this->_get_filter_url(), $tpl );
return $R->clear( $tpl );
}
function r_form() {
$form = new form( $this->obj );
return $form->render();
}
function _on_save_edit() {
global $cat;
if ( !$this->id && !$this->add ) _redirect('?cat=' . $cat->cat );
$cols = [];
foreach ($this->obj->attrs as $attr_name => $attrs) {
if ($attrs['hide']) {
continue;
}
$this->obj->lPost();
if ( $this->obj->validate() ) {
$this->obj->save();
} else {
return $this->r_form();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'] );
}
function _on_del() {
global $cat;
if ( $this->del ) {
$this->obj->byId( $this->id );
$this->obj->del();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage']);
}
function _get_filter_url() {
foreach( $_GET as $k => $v ) {
if ( strpos($k, $this->obj_name.'_') === 0 ) {
$ret = '&'.$k.'='.$v;
}
}
return $ret;
}
$cols[$attr_name] = $attrs['desc'];
}
}
$data['cols'] = $cols;
$filter = new filter($this->obj_name);
$filter->parse();
$data['filter'] = $filter->getHTML();
;
$db2 = $db->q($this->obj->getSelectEx('COUNT(*) as `cnt`', $filter->getSQL()));
$db2->r();
$size = $db2->f('cnt');
$pw = new Walker($size, $this->onPage);
$data['walker'] = $pw->getHTML();
$data['page'] = $pw->page;
$data['row'] = $this->obj->getCollection($filter->getSQL() . ' ORDER BY `ID` DESC ' . $pw->getSQL(), false, true);
$data['filterUrl'] = $this->_get_filter_url();
return $blade->run($this->getBladeTempl('body'), $data);
}
public function _on_edit() {
global $blade;
$id = intval($this->id);
if ($id) {
$this->obj->byId($id);
}
$data = [];
$data['form'] = $this->r_form();
return $blade->run($this->getBladeTempl('form'), $data);
}
public function r_form() {
$form = new form($this->obj);
return $form->render();
}
public function _on_save_edit() {
global $cat;
$this->obj->lPost();
if (!$this->obj->id && !$this->add) {
_redirect('?cat=' . $cat->cat);
}
if ($this->obj->validate()) {
$this->obj->save();
} else {
return $this->r_form();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'], 'Данные сохранены');
}
public function _on_del() {
global $cat;
if ($this->del) {
$this->obj->byId($this->id);
$this->obj->del();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'], 'Успешно удалено');
}
public function _get_filter_url() {
foreach ($_GET as $k => $v) {
if (strpos($k, $this->obj_name.'_') === 0) {
$ret = '&'.$k.'='.$v;
}
}
return $ret;
}
}
?>

View File

@ -1,24 +1,42 @@
#[body]#
<span id="resp{id}{cur_cat}{send_act}">
<form method="POST" id="form{id}{cur_cat}{send_act}" onSubmit="submit_form({id}, '{id}{cur_cat}{send_act}'); return false;" ENCTYPE="multipart/form-data">
<table>
{form_rows}
<tr>
<td colspan="2">
{hidden_attrs}
<input type="hidden" name="id" value="{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="{send_act}">
<input type="submit" name="is_ajax" value="Сохранить">
</td>
</tr>
</table>
</form>
</span>
<span id="resp{id}{cur_cat}{send_act}">
<form method="POST"
id="form{id}{cur_cat}{send_act}"
onsubmit="submit_form({id}, '{id}{cur_cat}{send_act}'); return false;"
enctype="multipart/form-data"
class="card p-3 shadow-sm">
<h5 class="mb-3">Редактирование</h5>
<div class="form-row">
{form_rows}
</div>
{hidden_attrs}
<input type="hidden" name="id" value="{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="{send_act}">
<div class="text-right mt-3">
<button type="submit" name="is_ajax" class="btn btn-success w-100 btn-sm">
<i class="fa fa-save"></i> Сохранить
</button>
</div>
</form>
</span>
#[!body]#
#[row]#
<tr><td>{attr_title}{attr_mand}:</td><td>{attr_html}<span id="error">{attr_error}</span></td></tr>
<div class="form-group col-12">
<label>{attr_title}{attr_mand}</label>
<div>
{attr_html}
</div>
<div class="invalid-feedback d-block">{attr_error}</div>
</div>
#[!row]#
#[mand]#
<span id="error">*</span>
<span class="text-danger">*</span>
#[!mand]#

View File

@ -80,6 +80,17 @@ class db {
}
}
public function getRow()
{
return $this->lastRow;
}
public function fetchAll() {
return mysqli_fetch_all($this->r, MYSQLI_ASSOC);
}
function nr() {
return $this->r();
}
@ -100,9 +111,6 @@ class db {
mysqli_close( $this->database );
}
public function fetchAll() {
return mysqli_fetch_all($this->r, MYSQLI_ASSOC);
}
}

View File

@ -0,0 +1,147 @@
<?php
error_reporting(E_ALL & ~E_NOTICE);
define('_PROJECT_DIR', getcwd() . '/../../../');
require_once(_PROJECT_DIR . 'engine/bootstrap.php');
// -------------------------------------------------
// CONFIG
// -------------------------------------------------
$DRY_RUN = false; // ← поставить true для тестового запуска
// Источник (старая МИС)
$src = new db();
$src->connect("192.168.0.2", "root", "Xx29Pz33", "pnd8");
// Приёмник (новая база)
$dst = $core_db->new_db();
// =====================================================================
// 1. СОЗДАЁМ ВРЕМЕННЫЕ ТАБЛИЦЫ С ИДЕНТИЧНОЙ СТРУКТУРОЙ
// =====================================================================
function recreateTmpTables($dst, $DRY_RUN)
{
$sql = [
"DROP TABLE IF EXISTS pnd_zones_tmp",
"DROP TABLE IF EXISTS pnd_doctors_tmp",
"CREATE TABLE pnd_zones_tmp LIKE pnd_zones",
"CREATE TABLE pnd_doctors_tmp LIKE pnd_doctors",
];
foreach ($sql as $q) {
echo "[INIT] $q\n";
if (!$DRY_RUN) $dst->q($q);
}
}
recreateTmpTables($dst, $DRY_RUN);
// =====================================================================
// 2. ПЕРЕНОСИМ УЧАСТКИ (ID = внешний ID)
// =====================================================================
$sqlZones = "
SELECT id, name
FROM OrgStructure
WHERE deleted = 0 and parent_id = 45
";
$zones = $src->q($sqlZones)->fetchAll();
echo "Loaded zones: " . count($zones) . "\n";
foreach ($zones as $z) {
$id = (int)$z['id'];
$title = db_escape_string($z['name']);
echo "[TMP ZONE] INSERT id={$id}, title={$title}\n";
if (!$DRY_RUN) {
$dst->q("
INSERT INTO pnd_zones_tmp (id, title)
VALUES ({$id}, '{$title}')
");
}
}
// =====================================================================
// 3. ПЕРЕНОСИМ ВРАЧЕЙ (ID = внешний id, zone_id = внешний id участка)
// =====================================================================
$sqlDoctors = "
SELECT
p.id AS external_id,
CONCAT(p.lastName, ' ', p.firstName, ' ', p.patrName) AS full_name,
rp.name AS post_name,
rs.name AS speciality_name,
p.office,
p.orgStructure_id
FROM Person p
LEFT JOIN rbPost rp ON rp.id = p.post_id
LEFT JOIN rbSpeciality rs ON rs.id = p.speciality_id
WHERE p.deleted = 0
AND p.orgStructure_id > 0
AND `retireDate` IS NULL
AND speciality_id = 127
";
$docs = $src->q($sqlDoctors)->fetchAll();
echo "Loaded doctors: " . count($docs) . "\n";
foreach ($docs as $d) {
$id = (int)$d['external_id'];
$name = db_escape_string($d['full_name']);
$post = db_escape_string($d['post_name']);
$spec = db_escape_string($d['speciality_name']);
$office = db_escape_string($d['office']);
// zone_id = внешний ID участка
$zoneId = (int)$d['orgStructure_id'];
echo "[TMP DOC] INSERT id={$id}, name={$name}\n";
if (!$DRY_RUN) {
$dst->q("
INSERT INTO pnd_doctors_tmp
(id, name, post_name, speciality_name, office, zone_id)
VALUES (
{$id}, '{$name}', '{$post}', '{$spec}', '{$office}', {$zoneId}
)
");
}
}
// =====================================================================
// 4. ЧИСТАЯ ПОДМЕНА ДАННЫХ БЕЗ RENAME TABLE
// =====================================================================
function replaceTables($dst, $DRY_RUN)
{
$ops = [
// очищаем основные таблицы
"TRUNCATE TABLE pnd_zones",
"TRUNCATE TABLE pnd_doctors",
// переносим обновлённые данные из временных таблиц
"INSERT INTO pnd_zones SELECT * FROM pnd_zones_tmp",
"INSERT INTO pnd_doctors SELECT * FROM pnd_doctors_tmp",
// удаляем временные таблицы
"DROP TABLE pnd_zones_tmp",
"DROP TABLE pnd_doctors_tmp",
];
foreach ($ops as $q) {
echo "[REPLACE] $q\n";
if (!$DRY_RUN) $dst->q($q);
}
}
replaceTables($dst, $DRY_RUN);
echo "\n--- DONE (DRY_RUN = " . ($DRY_RUN ? "YES" : "NO") . ") ---\n";

View File

@ -0,0 +1,2 @@
-- [2025-11-13 19:22:41] Изменение атрибута title;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Внешнее название зоны" , "0" , "0" , "100" , "0" , "pnd_zones" , "title");

View File

@ -0,0 +1,8 @@
-- [2025-11-13 19:27:47] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctor_zones` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctor_zones` ADD `doctor_id` int(12) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctor_zones","doctor_id","int12","","","100");
-- [2025-11-13 19:27:53] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctor_zones` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctor_zones` ADD `zone_id` int(12) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctor_zones","zone_id","int12","","","100");

View File

@ -0,0 +1,4 @@
-- [2025-11-13 19:27:05] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `external_id` int(12) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","external_id","int12","","","100");

View File

@ -0,0 +1,3 @@
-- [2025-11-13 19:34:22] Удаление атрибута title;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'shop_delivery_zones' AND `attr_name` = 'title';
ALTER TABLE `shop_delivery_zones` DROP `title`;

View File

@ -0,0 +1,16 @@
-- [2025-11-13 19:38:05] Изменение атрибута name;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Имя" , "0" , "0" , "100" , "0" , "pnd_doctors" , "name");
-- [2025-11-13 19:38:05] Изменение атрибута external_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Внешний Id" , "0" , "0" , "100" , "0" , "pnd_doctors" , "external_id");
-- [2025-11-13 19:38:26] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `post_name` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","post_name","input","","","100");
-- [2025-11-13 19:38:29] Изменение атрибута post_name;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Должность" , "0" , "0" , "100" , "0" , "pnd_doctors" , "post_name");
-- [2025-11-13 19:38:39] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `speciality_name` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","speciality_name","input","","","100");
-- [2025-11-13 19:38:51] Изменение атрибута speciality_name;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Специальность" , "0" , "0" , "100" , "0" , "pnd_doctors" , "speciality_name");

View File

@ -0,0 +1,10 @@
-- [2025-11-13 19:39:30] Изменение атрибута doctor_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Врач" , "0" , "0" , "100" , "0" , "pnd_doctor_zones" , "doctor_id");
-- [2025-11-13 19:39:30] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Зона" , "0" , "0" , "100" , "0" , "pnd_doctor_zones" , "zone_id");
-- [2025-11-13 19:39:41] Удаление атрибута doctor_id;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_doctor_zones' AND `attr_name` = 'doctor_id';
ALTER TABLE `pnd_doctor_zones` DROP `doctor_id`;
-- [2025-11-13 19:39:43] Удаление атрибута zone_id;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_doctor_zones' AND `attr_name` = 'zone_id';
ALTER TABLE `pnd_doctor_zones` DROP `zone_id`;

View File

@ -0,0 +1,6 @@
-- [2025-11-13 19:39:02] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `office` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","office","input","","","100");
-- [2025-11-13 19:39:05] Изменение атрибута office;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Кабинет" , "0" , "0" , "100" , "0" , "pnd_doctors" , "office");

View File

@ -0,0 +1,9 @@
-- [2025-11-13 19:40:02] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `external_zone_id` int(12) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","external_zone_id","int12","","","100");
-- [2025-11-13 19:40:07] Изменение атрибута external_zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Связь с зоной" , "0" , "0" , "100" , "0" , "pnd_doctors" , "external_zone_id");
-- [2025-11-13 19:40:33] Удаление атрибута external_zone_id;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_doctors' AND `attr_name` = 'external_zone_id';
ALTER TABLE `pnd_doctors` DROP `external_zone_id`;

View File

@ -0,0 +1,4 @@
-- [2025-11-13 19:41:08] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "[title]" , "Участок" , "0" , "0" , "50" , "0" , "shop_delivery_zones" , "zone_id");
-- [2025-11-13 19:41:13] Изменение атрибута geom;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("geometry" , "" , "Полигон" , "0" , "0" , "999" , "0" , "shop_delivery_zones" , "geom");

View File

@ -0,0 +1,7 @@
-- [2025-11-13 19:42:16] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_doctors` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_doctors` ADD `zone_id` int(12) NOT NULL;
ALTER TABLE `pnd_doctors` ADD INDEX ( `zone_id` );
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_doctors","zone_id","LINK|pnd_zones","","","100");
-- [2025-11-13 19:42:26] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "[title]" , "Участок" , "0" , "0" , "100" , "0" , "pnd_doctors" , "zone_id");

View File

@ -0,0 +1,5 @@
-- [2025-11-13 19:42:52] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_zone_geometry` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_zone_geometry` ADD `zone_id` int(12) NOT NULL;
ALTER TABLE `pnd_zone_geometry` ADD INDEX ( `zone_id` );
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_zone_geometry","zone_id","LINK|pnd_zones","","","100");

View File

@ -0,0 +1,2 @@
-- [2025-11-13 19:43:57] Изменение комментария pnd_doctors;
ALTER TABLE `pnd_doctors` COMMENT = 'Список врачей';;

View File

@ -0,0 +1,20 @@
-- [2025-11-13 19:43:01] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_zone_geometry` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_zone_geometry` ADD `color` char(7) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_zone_geometry","color","color","","","100");
-- [2025-11-13 19:43:13] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_zone_geometry` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_zone_geometry` ADD `geom` GEOMETRY NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_zone_geometry","geom","geometry","","","100");
-- [2025-11-13 19:43:24] Изменение атрибута color;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("color" , "" , "Цвет" , "0" , "0" , "100" , "0" , "pnd_zone_geometry" , "color");
-- [2025-11-13 19:43:24] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "" , "Участок" , "0" , "0" , "100" , "0" , "pnd_zone_geometry" , "zone_id");
-- [2025-11-13 19:43:24] Изменение атрибута geom;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("geometry" , "" , "Геометрия" , "0" , "0" , "100" , "0" , "pnd_zone_geometry" , "geom");
-- [2025-11-13 19:43:30] Изменение атрибута geom;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("geometry" , "" , "Геометрия" , "0" , "0" , "999" , "0" , "pnd_zone_geometry" , "geom");
-- [2025-11-13 19:43:34] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "" , "Участок" , "0" , "0" , "10" , "0" , "pnd_zone_geometry" , "zone_id");
-- [2025-11-13 19:43:39] Изменение комментария pnd_zone_geometry;
ALTER TABLE `pnd_zone_geometry` COMMENT = 'Геометрия зон';;

View File

@ -0,0 +1,4 @@
-- [2025-11-13 19:43:44] Изменение комментария pnd_zones;
ALTER TABLE `pnd_zones` COMMENT = 'Список зон';;
-- [2025-11-13 19:43:51] Изменение атрибута external_zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Внешний ID зоны" , "0" , "0" , "999" , "0" , "pnd_zones" , "external_zone_id");

View File

@ -0,0 +1 @@
UPDATE `_sys_cat_admin` SET `_sys_cat_admin`.`data` = "$obj_name=pnd_zone_geometry;" WHERE `_sys_cat_admin`.`cat_id` = "core-zone-admin";

View File

@ -0,0 +1,4 @@
-- [2025-11-13 19:44:24] Изменение комментария pnd_zone_geometry;
ALTER TABLE `pnd_zone_geometry` COMMENT = 'Геометрия зон (учестков)';;
-- [2025-11-13 19:44:25] Изменение комментария pnd_zone_geometry;
ALTER TABLE `pnd_zone_geometry` COMMENT = 'Геометрия зон (участков)';;

View File

@ -0,0 +1,6 @@
-- [2025-11-13 19:44:04] Изменение комментария pnd_zones;
ALTER TABLE `pnd_zones` COMMENT = 'Список зон (учествков)';;
-- [2025-11-13 19:44:12] Изменение атрибута title;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Название участка" , "0" , "0" , "100" , "0" , "pnd_zones" , "title");
-- [2025-11-13 19:44:17] Изменение комментария pnd_zones;
ALTER TABLE `pnd_zones` COMMENT = 'Список зон (участков)';;

View File

@ -0,0 +1,3 @@
-- [2025-11-13 20:20:07] Удаление атрибута external_zone_id;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_zones' AND `attr_name` = 'external_zone_id';
ALTER TABLE `pnd_zones` DROP `external_zone_id`;

View File

@ -0,0 +1,2 @@
-- [2025-11-13 20:26:00] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "id: [id] [title]" , "Участок" , "0" , "0" , "10" , "0" , "pnd_zone_geometry" , "zone_id");

View File

@ -0,0 +1,4 @@
-- [2025-11-13 20:27:10] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "[title] ([id])" , "Участок" , "0" , "0" , "10" , "0" , "pnd_zone_geometry" , "zone_id");
-- [2025-11-13 20:27:27] Изменение атрибута zone_id;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("LINK|pnd_zones" , "[title] (id: [id])" , "Участок" , "0" , "0" , "10" , "0" , "pnd_zone_geometry" , "zone_id");

View File

@ -0,0 +1,4 @@
-- [2025-11-13 20:38:59] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_zone_geometry` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_zone_geometry` ADD `_sys_deleted` int(1) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_zone_geometry","_sys_deleted","checkbox","","","100");

View File

@ -0,0 +1,4 @@
-- [2025-11-13 20:39:02] Изменение атрибута _sys_deleted;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("checkbox" , "" , "Удалён" , "0" , "0" , "100" , "0" , "pnd_zone_geometry" , "_sys_deleted");
-- [2025-11-13 20:39:06] Изменение атрибута _sys_deleted;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("checkbox" , "" , "Удалён" , "1" , "0" , "100" , "0" , "pnd_zone_geometry" , "_sys_deleted");

View File

@ -0,0 +1,3 @@
-- [2025-11-13 21:05:37] Удаление атрибута external_id;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_doctors' AND `attr_name` = 'external_id';
ALTER TABLE `pnd_doctors` DROP `external_id`;

View File

@ -0,0 +1,12 @@
-- [2025-11-18 19:06:34] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_docs` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_docs` ADD `btn_name` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_docs","btn_name","input","","","100");
-- [2025-11-18 19:06:46] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_docs` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_docs` ADD `html` text NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_docs","html","redactor_html","","","100");
-- [2025-11-18 19:06:56] Изменение атрибута btn_name;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Название кнопки" , "0" , "0" , "100" , "0" , "pnd_docs" , "btn_name");
-- [2025-11-18 19:06:56] Изменение атрибута html;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("redactor_html" , "" , "Текст" , "0" , "0" , "100" , "0" , "pnd_docs" , "html");

View File

@ -0,0 +1,8 @@
-- [2025-11-18 19:07:06] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_docs` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_docs` ADD `_sys_unvisible` int(1) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_docs","_sys_unvisible","checkbox","","","100");
-- [2025-11-18 19:07:08] Изменение атрибута _sys_unvisible;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("checkbox" , "" , "Скрыть" , "0" , "0" , "100" , "0" , "pnd_docs" , "_sys_unvisible");
-- [2025-11-18 19:07:16] Изменение комментария pnd_docs;
ALTER TABLE `pnd_docs` COMMENT = 'Кнопки с документами';;

View File

@ -0,0 +1,2 @@
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `parent_cat`) VALUES ( "docs", "Нормативная документация", "index");
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `parent_cat`) VALUES ( "faq", "Часто задаваемые вопросы", "index");

View File

@ -0,0 +1,2 @@
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `parent_cat`) VALUES ( "license", "Лицензия", "index");
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `parent_cat`) VALUES ( "extened_docs", "Справки", "index");

View File

@ -0,0 +1,12 @@
-- [2025-11-18 19:30:45] Изменение атрибута page_title;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "seo title" , "1" , "0" , "501" , "0" , "_sys_static" , "page_title");
-- [2025-11-18 19:30:45] Изменение атрибута page_h1;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "seo H1" , "1" , "0" , "502" , "0" , "_sys_static" , "page_h1");
-- [2025-11-18 19:30:45] Изменение атрибута page_keywords;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "seo keywords" , "1" , "0" , "503" , "0" , "_sys_static" , "page_keywords");
-- [2025-11-18 19:30:45] Изменение атрибута page_description;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "seo description" , "1" , "0" , "504" , "0" , "_sys_static" , "page_description");
-- [2025-11-18 19:30:45] Изменение атрибута _sys_order;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("int12" , "" , "Порядок сортировки" , "1" , "0" , "800" , "0" , "_sys_static" , "_sys_order");
-- [2025-11-18 19:30:45] Изменение атрибута _sys_unvisible;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("checkbox" , "" , "Невидимый" , "1" , "0" , "999" , "0" , "_sys_static" , "_sys_unvisible");

View File

@ -0,0 +1,2 @@
-- [2025-11-18 19:31:39] Изменение атрибута description;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("redactor_html" , "" , "Текстовый блок" , "0" , "0" , "100" , "0" , "_sys_static" , "description");

View File

@ -0,0 +1,2 @@
UPDATE `_sys_cat` SET `_sys_cat`.`module` = "static_page.php" , `_sys_cat`.`data` = "$id=3;" WHERE `_sys_cat`.`cat_id` = "license";
UPDATE `_sys_cat` SET `_sys_cat`.`module` = "static_page.php" , `_sys_cat`.`data` = "$id=4;" WHERE `_sys_cat`.`cat_id` = "extened_docs";

View File

@ -0,0 +1,12 @@
-- [2025-11-18 19:32:34] Удаление атрибута page_title;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = '_sys_static' AND `attr_name` = 'page_title';
ALTER TABLE `_sys_static` DROP `page_title`;
-- [2025-11-18 19:32:36] Удаление атрибута page_h1;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = '_sys_static' AND `attr_name` = 'page_h1';
ALTER TABLE `_sys_static` DROP `page_h1`;
-- [2025-11-18 19:32:37] Удаление атрибута page_keywords;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = '_sys_static' AND `attr_name` = 'page_keywords';
ALTER TABLE `_sys_static` DROP `page_keywords`;
-- [2025-11-18 19:32:38] Удаление атрибута page_description;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = '_sys_static' AND `attr_name` = 'page_description';
ALTER TABLE `_sys_static` DROP `page_description`;

View File

@ -0,0 +1,2 @@
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `parent_cat`) VALUES ( "--btns-", "Кнопки", "index");
UPDATE `_sys_cat` SET `_sys_cat`.`parent_cat` = "--btns-" WHERE `_sys_cat`.`cat_id` = "docs";

View File

@ -0,0 +1,4 @@
UPDATE `_sys_cat` SET `_sys_cat`.`parent_cat` = "--btns-" WHERE `_sys_cat`.`cat_id` = "faq";
UPDATE `_sys_cat` SET `_sys_cat`.`parent_cat` = "--btns-" WHERE `_sys_cat`.`cat_id` = "license";
UPDATE `_sys_cat` SET `_sys_cat`.`parent_cat` = "--btns-" WHERE `_sys_cat`.`cat_id` = "extened_docs";
INSERT INTO `_sys_cat` (`cat_id`, `cat_name`, `module`, `parent_cat`) VALUES ( "main", "Ваш участок", "site_index.php", "--btns-");

View File

@ -0,0 +1,2 @@
UPDATE `_sys_cat` SET `_sys_cat`.`_sys_order` = "1" WHERE `_sys_cat`.`cat_id` = "main";
UPDATE `_sys_cat` SET `_sys_cat`.`_sys_order` = "10" WHERE `_sys_cat`.`cat_id` = "docs";

View File

@ -0,0 +1,3 @@
UPDATE `_sys_cat` SET `_sys_cat`.`_sys_order` = "20" WHERE `_sys_cat`.`cat_id` = "faq";
UPDATE `_sys_cat` SET `_sys_cat`.`_sys_order` = "30" WHERE `_sys_cat`.`cat_id` = "license";
UPDATE `_sys_cat` SET `_sys_cat`.`_sys_order` = "40" WHERE `_sys_cat`.`cat_id` = "extened_docs";

View File

@ -0,0 +1 @@
UPDATE `_sys_cat` SET `_sys_cat`.`module` = "core_redirect.php" , `_sys_cat`.`data` = "$url=?cat=main;" WHERE `_sys_cat`.`cat_id` = "index";

View File

@ -0,0 +1 @@
INSERT INTO `_sys_cat_admin` (`access_group`, `cat_id`, `cat_name`, `data`, `module`, `parent_cat`) VALUES ( "1,2", "core-admin-static", "Текстовые страницы", "$obj_name=_sys_static;\r\n$del=0;\r\n$add=0;\r\n$onPage=1000;", "object_admin.php", "index");

View File

@ -0,0 +1,14 @@
-- [2025-11-18 20:37:27] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_faq` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_faq` ADD `question_text` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_faq","question_text","input","","","100");
-- [2025-11-18 20:37:41] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_faq` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_faq` ADD `answer_text` text NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_faq","answer_text","textarea","","","100");
-- [2025-11-18 20:37:44] Изменение атрибута question_text;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "" , "0" , "0" , "90" , "0" , "pnd_faq" , "question_text");
-- [2025-11-18 20:37:56] Изменение атрибута question_text;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Вопрос" , "0" , "0" , "90" , "0" , "pnd_faq" , "question_text");
-- [2025-11-18 20:37:56] Изменение атрибута answer_text;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("textarea" , "" , "Ответ" , "0" , "0" , "100" , "0" , "pnd_faq" , "answer_text");

View File

@ -0,0 +1 @@
INSERT INTO `_sys_cat_admin` (`access_group`, `cat_id`, `cat_name`, `data`, `module`, `parent_cat`) VALUES ( "1,2", "core-admin-faq", "FAQ", "$obj_name=pnd_faq;", "object_admin.php", "index");

View File

@ -0,0 +1 @@
UPDATE `_sys_cat` SET `_sys_cat`.`module` = "object_view.php" , `_sys_cat`.`data` = "$obj_name=pnd_faq;\r\n$templ=site_faq.htm;\r\n$onPage=200;" WHERE `_sys_cat`.`cat_id` = "faq";

View File

@ -0,0 +1,20 @@
-- [2025-11-18 20:57:08] Удаление атрибута btn_name;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_docs' AND `attr_name` = 'btn_name';
ALTER TABLE `pnd_docs` DROP `btn_name`;
-- [2025-11-18 20:57:11] Удаление атрибута html;
DELETE FROM `_sys_datatypes` WHERE `obj_name` = 'pnd_docs' AND `attr_name` = 'html';
ALTER TABLE `pnd_docs` DROP `html`;
-- [2025-11-18 20:57:21] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_docs` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_docs` ADD `title` varchar(255) NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_docs","title","input","","","100");
-- [2025-11-18 20:57:32] Создание атрибута;
CREATE TABLE IF NOT EXISTS `pnd_docs` ( `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pnd_docs` ADD `description` text NOT NULL;
REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("pnd_docs","description","redactor_html","","","100");
-- [2025-11-18 20:57:34] Изменение атрибута title;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "" , "0" , "0" , "50" , "0" , "pnd_docs" , "title");
-- [2025-11-18 20:57:42] Изменение атрибута title;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("input" , "" , "Название" , "0" , "0" , "50" , "0" , "pnd_docs" , "title");
-- [2025-11-18 20:57:42] Изменение атрибута description;
REPLACE INTO `_sys_datatypes` (`attr_type`, `attr_templ`, `attr_desc`, `attr_hide`, `attr_mand`, `attr_order`, `_sys_deleted`, `obj_name`, `attr_name`) VALUES ("redactor_html" , "" , "Текст" , "0" , "0" , "100" , "0" , "pnd_docs" , "description");

View File

@ -0,0 +1 @@
UPDATE `_sys_cat` SET `_sys_cat`.`module` = "object_view.php" , `_sys_cat`.`data` = "$templ=site_docs.htm;\r\n$obj_name=pnd_docs;\r\n" WHERE `_sys_cat`.`cat_id` = "docs";

View File

@ -0,0 +1 @@
INSERT INTO `_sys_cat_admin` (`access_group`, `cat_id`, `cat_name`, `data`, `module`, `parent_cat`) VALUES ( "1,2", "core-admin-docs", "Нормативная документация", "$obj_name=pnd_docs;", "object_admin.php", "index");

View File

@ -0,0 +1,3 @@
UPDATE `_sys_cat` SET `_sys_cat`.`data` = "$templ=site_docs.htm;\r\n$obj_name=pnd_docs;\r\n$onPage=2;\r\n" WHERE `_sys_cat`.`cat_id` = "docs";
UPDATE `_sys_cat` SET `_sys_cat`.`data` = "$templ=site_docs.htm;\r\n$obj_name=pnd_docs;\r\n$onPage=15;\r\n" WHERE `_sys_cat`.`cat_id` = "docs";
UPDATE `_sys_cat` SET `_sys_cat`.`data` = "$templ=site_docs.htm;\r\n$obj_name=pnd_docs;\r\n$onPage=10;\r\n" WHERE `_sys_cat`.`cat_id` = "docs";

View File

@ -0,0 +1,10 @@
<div class="card-header bg-danger text-white text-center">
Ошибка
</div>
<div class="card-body text-center">
<p class="mb-3">
Не удалось определить участок. <br>
Попробуйте ввести другой адрес.
</p>
</div>

View File

@ -1,57 +1,39 @@
<div class="text-center mb-4">
<h2 class="font-weight-bold">Ваш участок обслуживания</h2>
<div class="text-muted" style="font-size:18px;">
Адрес: ул. Примерная, дом 12
</div>
<h2>Ваш участок обслуживания</h2>
<h2 class="font-weight-bold"><?php echo \htmlentities($zone_name, ENT_QUOTES, 'UTF-8', false); ?></h2>
</div>
<div class="card mb-4 shadow-sm" style="border-radius:14px;">
<div class="card-body">
<?php $__currentLoopData = $doctors; $this->addLoop($__currentLoopData);$this->getFirstLoop();
foreach($__currentLoopData as $doc): $loop = $this->incrementLoopIndices(); ?>
<div class="card mb-4 shadow-sm" style="border-radius:14px;">
<div class="card-body">
<h4 class="mb-3">
Терапевт участка
<?php echo \htmlentities($doc['post_name'] ?: 'Врач', ENT_QUOTES, 'UTF-8', false); ?>
</h4>
<div class="d-flex align-items-start mb-3">
<div style="font-size:52px;line-height:52px;margin-right:15px;">
🩺
<div class="mr-3" style="font-size:52px;line-height:52px;">
<i class="fas fa-user-md text-primary"></i>
</div>
<div style="font-size:20px;">
<strong>Иванова Мария Сергеевна</strong><br>
Врач-терапевт высшей категории<br>
Кабинет: <strong>208</strong><br>
<strong><?php echo \htmlentities($doc['name'], ENT_QUOTES, 'UTF-8', false); ?></strong><br>
<?php if(!empty($doc['speciality_name'])): ?>
<?php echo \htmlentities($doc['speciality_name'], ENT_QUOTES, 'UTF-8', false); ?><br>
<?php endif; ?>
<?php if(!empty($doc['office'])): ?>
Кабинет: <strong><?php echo \htmlentities($doc['office'], ENT_QUOTES, 'UTF-8', false); ?></strong><br>
<?php endif; ?>
</div>
</div>
<h5 class="mt-4 mb-3">Расписание приема</h5>
<table class="table table-sm mb-0" style="font-size:18px;">
<tr>
<td class="font-weight-bold">Понедельник</td>
<td>09:00 — 17:00</td>
</tr>
<tr>
<td class="font-weight-bold">Вторник</td>
<td>12:00 — 20:00</td>
</tr>
<tr>
<td class="font-weight-bold">Среда</td>
<td>09:00 — 17:00</td>
</tr>
<tr>
<td class="font-weight-bold">Четверг</td>
<td>12:00 — 20:00</td>
</tr>
<tr>
<td class="font-weight-bold">Пятница</td>
<td>09:00 — 15:00</td>
</tr>
<tr class="table-secondary">
<td class="font-weight-bold">Суббота</td>
<td>Выходной</td>
</tr>
<tr class="table-secondary">
<td class="font-weight-bold">Воскресенье</td>
<td>Выходной</td>
</tr>
</table>
<div class="text-muted">Расписание не указано</div>
</div>
</div>
</div>
<?php endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>

View File

@ -3,7 +3,7 @@
<?php /* Верхняя панель поиска */ ?>
<div id="search-bar"
class="container-fluid py-3"
style="position:fixed;top:0;left:0;right:0;z-index:100;">
style="position:absolute;top:0;left:0;right:0;z-index:100;">
<div class="row">
<div class="col-md-6 mx-auto position-relative">
@ -51,6 +51,7 @@
</div>
<?php /* Модальное окно результата */ ?>
<div id="result-modal"
class="modal fade"
@ -85,7 +86,7 @@
let map, marker;
let typingTimer = null;
let lastTypedText = "";
let polygons = {}; // хранилище
let polygons = {};
/* -----------------------------------------------------------
КАРТА
@ -94,11 +95,10 @@
map = new ymaps.Map('map', {
center: SEARCH_CENTER,
zoom: 13,
controls: ['zoomControl'],
controls: [], // ← УБРАЛИ ВСЕ КОНТРОЛЫ
behaviors: ['drag', 'scrollZoom']
});
// Рендер существующих участков
<?php if(!empty($rows)): ?>
<?php $__currentLoopData = $rows; $this->addLoop($__currentLoopData);$this->getFirstLoop();
@ -106,7 +106,7 @@
addPolygon(
<?php echo $row['coords']; ?>,
<?php echo \htmlentities((int)$row['id'], ENT_QUOTES, 'UTF-8', false); ?>,
'<?php echo \htmlentities($row['color'], ENT_QUOTES, 'UTF-8', false); ?>' // hex
'<?php echo \htmlentities($row['color'], ENT_QUOTES, 'UTF-8', false); ?>'
);
<?php endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>
<?php endif; ?>
@ -118,7 +118,7 @@
var polygon = new ymaps.Polygon(
coords,
{ polygon_id: id }, // ← сохраняем id внутри объекта
{ polygon_id: id },
{
fillColor: color || '#00AAFF55',
strokeColor: '#0000FF',
@ -127,17 +127,16 @@
}
);
// КЛИК ПО ПОЛИГОНУ
polygon.events.add('click', function (e) {
polygon.events.add('click', function () {
var pid = polygon.properties.get('polygon_id');
openPolygonInfo(pid);
});
map.geoObjects.add(polygon);
polygons[id] = polygon;
}
/* -----------------------------------------------------------
ЭЛЕМЕНТЫ
----------------------------------------------------------- */
@ -146,6 +145,7 @@
var $typingStatus = $("#typing-status");
var $clearBtn = $("#clear-input-btn");
/* -----------------------------------------------------------
ФОКУС → ОЧИСТКА ПОЛЯ
----------------------------------------------------------- */
@ -158,8 +158,9 @@
}
});
/* -----------------------------------------------------------
ПОКАЗ/СКРЫТИЕ КРЕСТИКА
КРЕСТИК
----------------------------------------------------------- */
$input.on("input", function () {
if ($(this).val().length > 0) {
@ -171,7 +172,6 @@
}
});
/* Клик по крестику */
$clearBtn.on("click", function () {
$input.val("");
$input.focus();
@ -182,7 +182,7 @@
/* -----------------------------------------------------------
ОБРАБОТКА ВВОДА + ЗАДЕРЖКА ПЕРЕД ЗАПРОСОМ
ВВОД + ПОИСК ПОДСКАЗОК
----------------------------------------------------------- */
$input.on("input", function () {
var text = $(this).val().trim();
@ -203,9 +203,7 @@
}, SUGGEST_DELAY);
});
/* -----------------------------------------------------------
ЗАГРУЗКА ПОДСКАЗОК
----------------------------------------------------------- */
function loadSuggest(query) {
$.getJSON(API_SUGGEST, {
"apikey": SUGGEST_KEY,
@ -225,8 +223,9 @@
});
}
/* -----------------------------------------------------------
СПИСОК ПОДСКАЗОК
РЕНДЕР ПОДСКАЗОК
----------------------------------------------------------- */
function renderSuggest(list) {
$suggest.empty();
@ -239,30 +238,31 @@
}
list.forEach(function (item) {
var title = item.title && item.title.text ? item.title.text : "";
var subtitle = item.subtitle && item.subtitle.text ? item.subtitle.text : "";
var title = item.title?.text || "";
var subtitle = item.subtitle?.text || "";
var full = title + (subtitle ? ", " + subtitle : "");
var html =
$suggest.append(
'<a href="#" class="list-group-item list-group-item-action py-3" data-address="' + full + '">' +
'<div class="font-weight-bold">' + title + '</div>' +
'<div class="small text-muted">' + subtitle + '</div>' +
'</a>';
$suggest.append(html);
'</a>'
);
});
$suggest.show();
}
function renderSuggestError(msg) {
$suggest.empty().html(
'<div class="list-group-item py-3 text-danger text-center">' + msg + '</div>'
).show();
}
/* -----------------------------------------------------------
ВЫБОР ПОДСКАЗКИ → ГЕОКОДЕР
КЛИК ПО ПОДСКАЗКЕ → ГЕОКОДЕР
----------------------------------------------------------- */
$(document).on("click", "#suggest-box a", function (e) {
e.preventDefault();
@ -287,6 +287,7 @@
});
});
/* -----------------------------------------------------------
МАРКЕР
----------------------------------------------------------- */
@ -301,6 +302,7 @@
map.panTo(coords, { flying:true });
}
/* -----------------------------------------------------------
ОТПРАВКА НА СЕРВЕР
----------------------------------------------------------- */
@ -312,9 +314,10 @@
});
}
/* -----------------------------------------------------------
ОТКРЫТИЕ ИНФО ПО ПОЛИГОНУ
----------------------------------------------------------- */
ОТКРЫТИЕ ПО ПОЛИГОНУ
----------------------------------------------------------- */
function openPolygonInfo(id) {
$.post(API_URL, { polygon_id: id }, function (html) {
showModal(html);
@ -323,6 +326,7 @@
});
}
/* -----------------------------------------------------------
МОДАЛКА
----------------------------------------------------------- */
@ -347,3 +351,5 @@
.modal-content {
font-size: 20px;
}
</style>

View File

@ -1,57 +1,37 @@
<div class="text-center mb-4">
<h2 class="font-weight-bold">Ваш участок обслуживания</h2>
<div class="text-muted" style="font-size:18px;">
Адрес: ул. Примерная, дом 12
</div>
<h2>Ваш участок обслуживания</h2>
<h2 class="font-weight-bold">{{$zone_name}}</h2>
</div>
<div class="card mb-4 shadow-sm" style="border-radius:14px;">
<div class="card-body">
<h4 class="mb-3">
Терапевт участка
</h4>
@foreach($doctors as $doc)
<div class="card mb-4 shadow-sm" style="border-radius:14px;">
<div class="card-body">
<div class="d-flex align-items-start mb-3">
<div style="font-size:52px;line-height:52px;margin-right:15px;">
🩺
</div>
<div style="font-size:20px;">
<strong>Иванова Мария Сергеевна</strong><br>
Врач-терапевт высшей категории<br>
Кабинет: <strong>208</strong><br>
<h4 class="mb-3">
{{$doc['post_name'] ?: 'Врач'}}
</h4>
<div class="d-flex align-items-start mb-3">
<div class="mr-3" style="font-size:52px;line-height:52px;">
<i class="fas fa-user-md text-primary"></i>
</div>
<div style="font-size:20px;">
<strong>{{$doc['name']}}</strong><br>
@if(!empty($doc['speciality_name']))
{{$doc['speciality_name']}}<br>
@endif
@if(!empty($doc['office']))
Кабинет: <strong>{{$doc['office']}}</strong><br>
@endif
</div>
</div>
<h5 class="mt-4 mb-3">Расписание приема</h5>
<div class="text-muted">Расписание не указано</div>
</div>
<h5 class="mt-4 mb-3">Расписание приема</h5>
<table class="table table-sm mb-0" style="font-size:18px;">
<tr>
<td class="font-weight-bold">Понедельник</td>
<td>09:00 17:00</td>
</tr>
<tr>
<td class="font-weight-bold">Вторник</td>
<td>12:00 20:00</td>
</tr>
<tr>
<td class="font-weight-bold">Среда</td>
<td>09:00 17:00</td>
</tr>
<tr>
<td class="font-weight-bold">Четверг</td>
<td>12:00 20:00</td>
</tr>
<tr>
<td class="font-weight-bold">Пятница</td>
<td>09:00 15:00</td>
</tr>
<tr class="table-secondary">
<td class="font-weight-bold">Суббота</td>
<td>Выходной</td>
</tr>
<tr class="table-secondary">
<td class="font-weight-bold">Воскресенье</td>
<td>Выходной</td>
</tr>
</table>
</div>
</div>
@endforeach

View File

@ -3,7 +3,7 @@
{{-- Верхняя панель поиска --}}
<div id="search-bar"
class="container-fluid py-3"
style="position:fixed;top:0;left:0;right:0;z-index:100;">
style="position:absolute;top:0;left:0;right:0;z-index:100;">
<div class="row">
<div class="col-md-6 mx-auto position-relative">
@ -51,6 +51,7 @@
</div>
{{-- Модальное окно результата --}}
<div id="result-modal"
class="modal fade"
@ -85,7 +86,7 @@
let map, marker;
let typingTimer = null;
let lastTypedText = "";
let polygons = {}; // хранилище
let polygons = {};
/* -----------------------------------------------------------
КАРТА
@ -94,20 +95,19 @@
map = new ymaps.Map('map', {
center: SEARCH_CENTER,
zoom: 13,
controls: ['zoomControl'],
controls: [], // ← УБРАЛИ ВСЕ КОНТРОЛЫ
behaviors: ['drag', 'scrollZoom']
});
// Рендер существующих участков
@if (!empty($rows))
@foreach($rows as $row)
addPolygon(
{!! $row['coords'] !!},
{{ (int)$row['id'] }},
'{{ $row['color'] }}' // hex
);
@endforeach
@foreach($rows as $row)
addPolygon(
{!! $row['coords'] !!},
{{ (int)$row['id'] }},
'{{ $row['color'] }}'
);
@endforeach
@endif
});
@ -117,7 +117,7 @@
var polygon = new ymaps.Polygon(
coords,
{ polygon_id: id }, // ← сохраняем id внутри объекта
{ polygon_id: id },
{
fillColor: color || '#00AAFF55',
strokeColor: '#0000FF',
@ -126,17 +126,16 @@
}
);
// КЛИК ПО ПОЛИГОНУ
polygon.events.add('click', function (e) {
polygon.events.add('click', function () {
var pid = polygon.properties.get('polygon_id');
openPolygonInfo(pid);
});
map.geoObjects.add(polygon);
polygons[id] = polygon;
}
/* -----------------------------------------------------------
ЭЛЕМЕНТЫ
----------------------------------------------------------- */
@ -145,6 +144,7 @@
var $typingStatus = $("#typing-status");
var $clearBtn = $("#clear-input-btn");
/* -----------------------------------------------------------
ФОКУС ОЧИСТКА ПОЛЯ
----------------------------------------------------------- */
@ -157,8 +157,9 @@
}
});
/* -----------------------------------------------------------
ПОКАЗ/СКРЫТИЕ КРЕСТИКА
КРЕСТИК
----------------------------------------------------------- */
$input.on("input", function () {
if ($(this).val().length > 0) {
@ -170,7 +171,6 @@
}
});
/* Клик по крестику */
$clearBtn.on("click", function () {
$input.val("");
$input.focus();
@ -181,7 +181,7 @@
/* -----------------------------------------------------------
ОБРАБОТКА ВВОДА + ЗАДЕРЖКА ПЕРЕД ЗАПРОСОМ
ВВОД + ПОИСК ПОДСКАЗОК
----------------------------------------------------------- */
$input.on("input", function () {
var text = $(this).val().trim();
@ -202,9 +202,7 @@
}, SUGGEST_DELAY);
});
/* -----------------------------------------------------------
ЗАГРУЗКА ПОДСКАЗОК
----------------------------------------------------------- */
function loadSuggest(query) {
$.getJSON(API_SUGGEST, {
"apikey": SUGGEST_KEY,
@ -224,8 +222,9 @@
});
}
/* -----------------------------------------------------------
СПИСОК ПОДСКАЗОК
РЕНДЕР ПОДСКАЗОК
----------------------------------------------------------- */
function renderSuggest(list) {
$suggest.empty();
@ -238,30 +237,31 @@
}
list.forEach(function (item) {
var title = item.title && item.title.text ? item.title.text : "";
var subtitle = item.subtitle && item.subtitle.text ? item.subtitle.text : "";
var title = item.title?.text || "";
var subtitle = item.subtitle?.text || "";
var full = title + (subtitle ? ", " + subtitle : "");
var html =
$suggest.append(
'<a href="#" class="list-group-item list-group-item-action py-3" data-address="' + full + '">' +
'<div class="font-weight-bold">' + title + '</div>' +
'<div class="small text-muted">' + subtitle + '</div>' +
'</a>';
$suggest.append(html);
'</a>'
);
});
$suggest.show();
}
function renderSuggestError(msg) {
$suggest.empty().html(
'<div class="list-group-item py-3 text-danger text-center">' + msg + '</div>'
).show();
}
/* -----------------------------------------------------------
ВЫБОР ПОДСКАЗКИ ГЕОКОДЕР
КЛИК ПО ПОДСКАЗКЕ ГЕОКОДЕР
----------------------------------------------------------- */
$(document).on("click", "#suggest-box a", function (e) {
e.preventDefault();
@ -286,6 +286,7 @@
});
});
/* -----------------------------------------------------------
МАРКЕР
----------------------------------------------------------- */
@ -300,6 +301,7 @@
map.panTo(coords, { flying:true });
}
/* -----------------------------------------------------------
ОТПРАВКА НА СЕРВЕР
----------------------------------------------------------- */
@ -311,9 +313,10 @@
});
}
/* -----------------------------------------------------------
ОТКРЫТИЕ ИНФО ПО ПОЛИГОНУ
----------------------------------------------------------- */
ОТКРЫТИЕ ПО ПОЛИГОНУ
----------------------------------------------------------- */
function openPolygonInfo(id) {
$.post(API_URL, { polygon_id: id }, function (html) {
showModal(html);
@ -322,6 +325,7 @@
});
}
/* -----------------------------------------------------------
МОДАЛКА
----------------------------------------------------------- */

View File

@ -0,0 +1,10 @@
<div class="card-header bg-danger text-white text-center">
Ошибка
</div>
<div class="card-body text-center">
<p class="mb-3">
Не удалось определить участок. <br>
Попробуйте ввести другой адрес.
</p>
</div>

View File

@ -0,0 +1,17 @@
<?php
class core_redirect extends module {
public $_loc_vars = ['url'];
public $url = '?cat=index';
public function _on_() {
if ($this->url) {
_redirect($this->url);
}
}
}
?>

View File

@ -13,8 +13,6 @@ class line_menu extends module {
$tplis = $R->getTpl($this->templ, 'item_sel');
$tplsep = $R->getTpl($this->templ, 'sep');
if (!$this->root) {
if (isset($this->autoLevel) && $this->autoLevel) {
$this->autoLevel = intval($this->autoLevel); // Приводим к числу
@ -34,22 +32,9 @@ class line_menu extends module {
$this->obj = new cobject(__REAL_CAT_OBJ_);
$sql_where = '';
if ($this->noexit) {
$sql_where = ' AND id not in (18) ';
global $auth;
if ($auth->is_login) {
$tpl = $R->set('current_user_name', $auth->user_obj->assign('{name}'), $tpl);
}
}
$tpl = $R->set('root', 'root'.crc32($this->root), $tpl);
$db2 = $core_db->q($this->obj->getSelect(' AND `cat_id` = "'.db_escape_string($this->root).'"'));
if ($db2->nr()) {
$this->obj->lRow($db2);
$tpl = $this->obj->assign($tpl);
}
$db2 = $core_db->q($this->obj->getSelect(' AND `parent_cat` = "' . $this->root . '" AND `_sys_unvisible` = "0" '.$sql_where.' ORDER BY `_sys_order`'));
$first = true;
while ($db2->r()) {

View File

@ -0,0 +1,82 @@
<?php
class object_view extends module {
public $_loc_vars = [ 'templ', 'obj_name', 'sql_where', 'onPage' ];
public $_get_vars = [ 'act', 'id' ];
public $obj;
public $templ = 'object_view.htm';
public $onPage = 20;
public function _init() {
$this->obj = new cobject($this->obj_name);
if ($this->id && !$this->act) {
$this->act = 'view';
}
return parent::_init();
}
public function _on_() {
global $R, $db, $core_db;
$tpl = $R->getTpl($this->templ, 'body');
$tpl_void = $R->getTpl($this->templ, 'body_void');
$tplr = $R->getTpl($this->templ, 'row');
if ($this->obj->global_type == 1) {
$curdb = $core_db;
} else {
$curdb = $db;
}
$db2 = $curdb->q($this->obj->getSelectEx('COUNT(*) as `cnt`', $this->sql_where));
$db2->r();
$size = $db2->f('cnt');
if (!$size) {
return $R->clear($tpl_void);
}
$pw = new Walker($size, $this->onPage);
$filter = new filter($this->obj_name);
$filter->parse();
$tpl = $R->set('filter', $filter->getHTML(), $tpl);
$db2 = $curdb->q($this->obj->getSelect($filter->getSQL() . $this->sql_where . $pw->getSQL()));
while ($db2->r()) {
$this->obj->lRow($db2);
$tt = $this->obj->assign($tplr);
$tpl = $R->parse('rows', $tt, $tpl);
}
$this->obj->byId($this->id);
$tpl = $R->set('walker', $pw->getHTML(), $tpl);
return $R->clear($tpl);
}
public function _on_view() {
global $R, $cat;
$this->obj->byId($this->id);
$tpl = $R->getTpl($this->templ, 'card');
$tpl = $this->obj->assign($tpl);
if ($this->obj->get('title')) {
$cat->addTitle($this->obj->get('title'));
}
if ($this->obj->get('page_keywords')) {
$cat->setKeywords($this->obj->get('page_keywords'));
}
if ($this->obj->get('page_description')) {
$cat->setDescription($this->obj->get('page_description'));
}
return $R->clear($tpl);
}
}
?>

View File

@ -8,7 +8,7 @@ class site_index extends module {
public $suggestKey = '1749711d-e092-4206-ae0a-a332c44d8cb0';
public $templBlade = 'site_index';
public $_get_vars = ['act'];
public $_get_vars = ['act', 'doc_id'];
public $_post_vars = ['act', 'coords', 'polygon_id'];
@ -19,23 +19,23 @@ class site_index extends module {
$data['suggest_apikey'] = $this->suggestKey;
$obj = new cobject('shop_delivery_zones');
$obj = new cobject('pnd_zone_geometry');
// полигоны
$db2 = $obj->getDB()->q($obj->getSelectEx('id, title, ASTEXT(`geom`) as `geom`, color '));
$db2 = $obj->getDB()->q($obj->getSelectEx('id, zone_id, ASTEXT(`geom`) as `geom`, color '));
while($db2->nr()) {
$coords = $this->mysql2json($db2->f('geom'));
$row = [];
$row['coords'] = $coords;
$row['id'] = $db2->f('id');
$row['title'] = $db2->f('title');
$row['zone_id'] = $db2->f('zone_id');
$row['color'] = $db2->f('color');
$data['rows'][] = $row;
}
return $blade->run($this->getBladeTempl('main'), $data);
return $blade->run($this->getBladeTempl('main'), $data);
}
function _on_getInfo()
@ -43,9 +43,49 @@ class site_index extends module {
global $blade;
$data = [];
$polyObj = new cobject('pnd_zone_geometry');
$polygon_id = intval($this->polygon_id);
if ($polygon_id == 0) {
$coords = $this->coords;
if (!empty($this->coords)) {
// Ищем полигон по координатам
$lat = floatval($coords[0]);
$lon = floatval($coords[1]);
$db2 = $polyObj->getDB()->q($polyObj->getSelectEx('id', " AND ST_WITHIN(GeomFromText('POINT( " . $lat . " " . $lon . ")'), `geom`) "));
if ($db2->nr()) {
$polygon_id = $db2->f('id');
}
}
}
$polyObj->byId($polygon_id);
$zone_id = $polyObj->get('zone_id');
$zoneObj = new cobject('pnd_zones');
$zoneObj->byId($zone_id);
if (!$zoneObj->id) {
return $blade->run($this->getBladeTempl('zone_not_found'));
}
$data['zone_name'] = $zoneObj->get('title');
$doctorObj = new cobject('pnd_doctors');
$db2 = $doctorObj->getDB()->q($doctorObj->getSelect(' AND `zone_id` = ' . intval($zone_id)));
while($db2->nr()) {
$data['doctors'][] = $db2->getRow();
}
return $blade->run($this->getBladeTempl('data'), $data);
}
public function mysql2json($str) {
// POLYGON((59.94778267548529 30.047386140625,60.12503918773836 30.468986482421876,59.92986664045532 30.963371248046883,59.84083181279909 30.456626863281247,59.960180395813275 30.38933560351563,59.94778267548529 30.047386140625))
preg_match_all('/POLYGON\(\((.*?)\)\)/', $str, $arr);

View File

@ -1,52 +0,0 @@
#[body]#
<a class="navbar-brand d-lg-none px-2" href="?cat={cat_id}">{cat_name}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#menuCore{root}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse bg-secondary autosize-menu" id="menuCore{root}" style="overflow-x: clip;">
<ul class="navbar-nav mr-auto flex-nowrap" id="menuCoreNavbar{root}">
{menu_item}
</ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.innerWidth < 768 ) return; // Только для широких экранов
var navList = document.getElementById('menuCoreNavbar{root}');
var navItems = navList.getElementsByClassName('nav-item');
var moreMenu = document.createElement('li');
moreMenu.className = 'dropdown dropdown py-0';
moreMenu.innerHTML = '<a class="nav-link text-nowrap text-right bg-secondary align-self-baseline px-2 text-primary dropdown-toggle" href="#" data-toggle="dropdown"><i class="far fa-bars"></i> Ещё</a>' +
'<div class="dropdown-menu dropdown-menu-right py-0" style="z-index: 999"></div>';
var dropdownMenu = moreMenu.getElementsByClassName('dropdown-menu')[0];
var fullWidth = 100; // Ширина кнопки Ещё
var hideNext = false;
for (var i = 0; i < navItems.length; i++) {
fullWidth += navItems[i].offsetWidth
if (fullWidth > window.innerWidth) {
hideNext = true;
}
if (hideNext) {
var clone = navItems[i].cloneNode(true);
dropdownMenu.appendChild(clone);
navItems[i].classList.add('d-none');
}
}
if (hideNext) {
navList.appendChild(moreMenu);
}
});
</script>
#[!body]#
#[item]#
<li class="nav-item"><a class="nav-link text-truncate bg-secondary align-middle px-2 text-primary" href="?cat={cat_id}"><img src="{img}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item]#
#[item_sel]#
<li class="nav-item active"><a class="nav-link text-truncate bg-grey px-2 text-primary" href="?cat={cat_id}"><img src="{img}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item_sel]#
#[sep]##[!sep]#

View File

@ -1,65 +0,0 @@
#[body]#
<nav class="navbar navbar-expand-lg navbar-light bg-secondary justify-content-between p-1 p-lg-0" id="menu">
<span class="navbar-brand mx-2 py-0 align-self-start"><img src="img/admin_logo.png" height="22" width="22"><span class="d-lg-none align-middle"> Админка Бамболо</span></span>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#menuCore{root}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse bg-secondary autosize-menu" id="menuCore{root}">
<ul class="navbar-nav mr-auto flex-wrap" id="menuCoreNavlist{root}">
{menu_item}
</ul>
<div id="rootMoreBtnWrapper"></div>
<div class="dropdown align-self-start" id="rootMenuBarDropper">
<a class="nav-link text-nowrap text-right bg-secondary align-self-baseline px-2 text-primary dropdown-toggle" data-toggle="dropdown" href="#">{current_user_name}</a>
<div class="dropdown-menu dropdown-menu-right small">
<a class="dropdown-item" href="?cat=admin_exit">Выйти</a>
</div>
</div>
</div>
</nav>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.innerWidth < 768 ) return; // Только для широких экранов
var navList = document.getElementById('menuCoreNavlist{root}');
var navItems = navList.getElementsByClassName('nav-item');
var moreMenu = document.createElement('li');
moreMenu.className = 'dropdown dropdown py-0';
moreMenu.innerHTML = '<a class="nav-link text-nowrap text-left bg-secondary align-self-baseline px-2 text-primary dropdown-toggle" href="#" data-toggle="dropdown"><i class="far fa-bars"></i> Ещё</a>' +
'<div class="dropdown-menu dropdown-menu-right py-0" style="z-index: 9999"></div>';
var dropdownMenu = moreMenu.getElementsByClassName('dropdown-menu')[0];
var fullWidth = 100;
fullWidth += document.getElementById('rootMenuBarDropper').offsetWidth;
console.log(fullWidth);
var hideNext = false;
for (var i = 0; i < navItems.length; i++) {
fullWidth += navItems[i].offsetWidth
if (fullWidth > window.innerWidth) {
hideNext = true;
}
if (hideNext) {
var clone = navItems[i].cloneNode(true);
dropdownMenu.appendChild(clone);
navItems[i].classList.add('d-none');
}
}
if (hideNext) {
navList.appendChild(moreMenu);
}
});
</script>
#[!body]#
#[item]#
<li class="nav-item"><a class="nav-link text-truncate bg-secondary align-middle px-2 text-primary" href="?cat={cat_id}"><img src="{img}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item]#
#[item_sel]#
<li class="nav-item active"><a class="nav-link text-truncate bg-grey px-2 text-primary" href="?cat={cat_id}"><img src="{img}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item_sel]#
#[sep]##[!sep]#

View File

@ -1,20 +1,122 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta charset="utf-8" />
<title>{auto_title}</title>
<meta name="keywords" content="{meta_keywords}">
<meta name="description" content="{meta_description}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="{_SITE_ROOT_}">
<link rel="icon" href="favicon.ico">
{include:include/_static_css_headers.htm}
{include:include/_static_js_headers.htm}
{add_headers}
{add_headers}
</head>
<body class="bg-light">
<div>
{body}
<body class="container-fluid h-100 px-0">
<div class="row h-100 no-gutters">
<!-- Левая колонка (меню) -->
<div class="col-3 left-col px-2 pt-3">
<div class="d-flex align-items-center mb-4">
<img src="assets/img/logo.png"
class="mr-3"
style="height:70px;width:auto;">
<div class="font-weight-bold" style="font-size:28px; line-height:1.2;">
Психоневрологический<br>диспансер №8
</div>
</div>
{menu}
</div>
<!-- Правая колонка (контент) -->
<div class="col pl-4 ml-4 right-col position-relative pr-0">
<div id="bigcontent-wrapper" class="h-100 position-relative">
<div id="bigcontent" class="h-100" style="overflow: hidden;">
{body}
</div>
<!-- Кнопки прокрутки -->
<button id="scroll-up" class="scroll-btn">&#9650;</button>
<button id="scroll-down" class="scroll-btn">&#9660;</button>
</div>
</div>
</div>
<script>
$(function () {
var $box = $('#bigcontent');
var $btnUp = $('#scroll-up');
var $btnDn = $('#scroll-down');
var interval = null;
var step = 250; // шаг скролла
var delay = 60; // частота скролла (мс)
function checkOverflow() {
var el = $box[0];
if (!el) return;
// немного страховки на округления браузера
if (el.scrollHeight - 2 > el.clientHeight) {
$btnUp.show();
$btnDn.show();
} else {
$btnUp.hide();
$btnDn.hide();
}
}
function startScroll(dir) {
stopScroll();
interval = setInterval(function () {
$box[0].scrollTop += dir * step;
}, delay);
}
function stopScroll() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
// Наверх
$btnUp.on('mousedown touchstart', function (e) {
e.preventDefault();
startScroll(-1);
});
// Вниз
$btnDn.on('mousedown touchstart', function (e) {
e.preventDefault();
startScroll(1);
});
// Остановка
$(document).on('mouseup mouseleave touchend touchcancel', function () {
stopScroll();
});
// 1) Проверка при старте
checkOverflow();
// 2) Периодический опрос — чтобы ловить любые изменения в runtime
setInterval(checkOverflow, 500);
// 3) Если используешь Bootstrap collapse / модалки / табы — дергаем ещё раз
$(document).on('shown.bs.collapse hidden.bs.collapse shown.bs.tab hidden.bs.tab', function () {
checkOverflow();
});
});
</script>
</body>
</html>
</html>

View File

@ -0,0 +1,21 @@
#[body]#
<div class="btn-group-vertical w-100 kiosk-btn-group">
{menu_item}
</div>
#[!body]#
#[item]#
<a href="?cat={cat_id}"
class="btn btn-secondary btn-lg text-left kiosk-btn">
<span>{cat_name}</span>
</a>
#[!item]#
#[item_sel]#
<a href="?cat={cat_id}"
class="btn btn-primary btn-lg text-left kiosk-btn kiosk-btn-active">
<span>{cat_name}</span>
</a>
#[!item_sel]#
#[sep]##[!sep]#

View File

@ -1,289 +0,0 @@
#[body]#
<style>
.content-vertical td {
vertical-align: middle !important;
}
.content-vertical td a {
text-decoration: none;
display: block;
}
</style>
{panel}
<div class="container-fluid">
<div class="card">
<div class="card-body">
<h2 class="card-title">Сотрудники</h2>
<div class="table-responsive">
<table class="table table-sm table-hover content-vertical">
<thead><tr><th>ID</th><th>Фото</th><th>Имя</th><th>Место работы</th><th>Ставка</th><th>Вн. номер</th><th style="text-align: right;">Посл. активность</th></tr></thead>
<tbody>
{rows}
</tbody>
</table>
</div>
{pagewalker}
</div>
</div>
</div>
#[!body]#
#[row]#
<tr>
<td><a href="?cat={cur_cat}&act=edit&id={id}">{id}</a></td>
<td><a href="?cat={cur_cat}&act=edit&id={id}"><img src="{_STATIC_ROOT_}/images/{user_photo}.jpg" width="48" height="48"></a></td>
<td><a href="?cat={cur_cat}&act=edit&id={id}">{full_name}</a></td>
<td><a href="?cat={cur_cat}&act=edit&id={id}">{user_office}</a></td>
<td><a href="?cat={cur_cat}&act=edit&id={id}">{default_work_tarif}</a></td>
<td><a href="?cat={cur_cat}&act=edit&id={id}">{sip_number}</a></td>
<td style="text-align: right;"><a href="?cat={cur_cat}&act=edit&id={id}">{time_ago}</a></td>
</tr>
#[!row]#
#[view]#
{panel}
<div class="container-fluid">
<div>
<div>
<h1 class="card-title">{full_name} <a href="?cat={cur_cat}&act=copyas&id={id}" title="Скопировать"><i class="far fa-copy"></i></a></h1>
<form id="main_form" method="POST" ENCTYPE="multipart/form-data">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="save">
<input type="hidden" name="id" value="{id}">
<div class="row">
<div class="col-12 col-md-2">
Фото:<br>
<img src="{_STATIC_ROOT_}/images/{user_photo}.jpg" class="img-fluid" style="margin-bottom: 5px;">
<div class="input-group mb-3">
<div class="custom-file">
<input type="file" name="user_photo" class="custom-file-input" id="inputGroupFile01" >
<label class="custom-file-label" for="inputGroupFile01">Выбрать файл</label>
</div>
</div>
<div class="card mb-2 mb-3">
<div class="card-header">Информация о входах</div>
<div class="card-body" style="min-height: 10vh;">
Последний вход:<br> {login_time}<br><br>
Адрес входа:<br> {login_ip}<br><br>
Последняя активность:<br> {update_time}<br><br>
Дата регистрации:<br> {regtime}<br>
</div>
</div>
</div>
<div class="col-12 col-md-6">
<div class="card mb-3">
<div class="card-header">Данные сотрудника</div>
<div class="card-body" style="min-height: 10vh;">
<h4>Основное</h4>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="login">Логин</label>
<div class="col-12 col-md-8 col-xl-9">
{login_html}
<div class="form-text text-danger">{login_error}</div>
</div>
</div>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="passwd">Пароль</label>
<div class="col-12 col-md-8 col-xl-9">
{passwd_html}
<div class="form-text text-danger">{passwd_error}</div>
</div>
</div>
<hr>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="full_name">Фамилия, Имя</label>
<div class="col-12 col-md-8 col-xl-9">
{full_name_html}
<div class="form-text small text-muted">полное имя, для отображения в системе</div>
<div class="form-text text-danger">{full_name_error}</div>
</div>
</div>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="name">Фамилия, Инициалы</label>
<div class="col-12 col-md-8 col-xl-9">
{name_html}
<div class="form-text small text-muted">будет отображаться в бухгалтерских документах и логах</div>
<div class="form-text text-danger">{name_error}</div>
</div>
</div>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="email">E-mail</label>
<div class="col-12 col-md-8 col-xl-9">
{email_html}
<div class="form-text small text-muted">для оповещений</div>
<div class="form-text text-danger">{email_error}</div>
</div>
</div>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="phone">Мобильный телефон</label>
<div class="col-12 col-md-8 col-xl-9">
{phone_html}
<div class="form-text small text-muted">для экстренной связи</div>
<div class="form-text text-danger">{phone_error}</div>
</div>
</div>
<hr>
<h4>Расписание и зарплата</h4>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="user_office">Отдел</label>
<div class="col-12 col-md-8 col-xl-9">
{user_office_html}
<div class="form-text text-danger">{user_office_error}</div>
</div>
</div>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="default_work_tarif">Тариф зарплаты</label>
<div class="col-12 col-md-8 col-xl-9">
{default_work_tarif_html}
<div class="form-text small text-muted">если учитывается почасовая ставка</div>
<div class="form-text text-danger">{default_work_tarif_error}</div>
</div>
</div>
<hr/>
<h4>Руководители отдела</h4>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="money_agent_admin">Из каких касс выдает зарплату</label>
<div class="col-12 col-md-8 col-xl-9">
{money_agent_admin_html}
<div class="form-text text-danger">{money_agent_admin_error}</div>
<div class="form-text small text-muted">выдает зарплаты из этих касс и может корректировать в них деньги</div>
</div>
</div>
<hr>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold" for="user_description">Комментарий</label>
<div class="col-12 col-md-8 col-xl-9">
{user_description_html}
<div class="form-text text-danger">{user_description_error}</div>
<div class="form-text small text-muted">виден только тут</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card mb-3">
<div class="card-header">Доступы</div>
<div class="card-body" style="min-height: 10vh;">
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold">Доступы</label>
<div class="col-12 col-md-8 col-xl-9">
{group_html}
<small class="form-text text-muted">{group_error}</small>
</div>
</div>
<hr>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3"></label>
<div class="col-12 col-md-8 col-xl-9">
<div class="custom-controls-stacked2">
<div class="custom-control custom-checkbox">
{long_session_html}
<label for="chbx_long_session" class="custom-control-label">Длинная сессия</label>
</div>
</div>
</div>
</div>
<hr>
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3"></label>
<div class="col-12 col-md-8 col-xl-9">
<div class="custom-controls-stacked2">
<div class="custom-control custom-checkbox">
{_sys_deleted_html}
<label for="chbx__sys_deleted" class="custom-control-label">Удалить пользователя</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="text-center mt-3 col-12">
<input type="submit" name="submit" value="Сохранить" class="btn btn-lg btn-success">
</div>
</div>
</form>
</div>
</div>
</div>
<script id="addposition" type="text/template" data-template="addposition">
<div class="position_row new_position mb-2">
<div class="input-group ~is_head_class~">
<input type="hidden" name="new_positions[~num_no~][dept_id]" class="form-control" aria-label="" value="~dept_id~">
<input type="hidden" name="new_positions[~num_no~][is_head]" class="form-control" aria-label="" value="~is_head~">
<div class="input-group-prepend w-75">
<input type="text" name="new_positions[~num_no~][title]" class="form-control" aria-label="" value="~title~" readonly>
</div>
<input type="text" name="new_positions[~num_no~][percent]" class="position_percent form-control" aria-label="" required>
<div class="input-group-append">
<span class="input-group-text"><a href="javascript: void(0);" onclick="delete_position(this)" class="text-danger"><i class="fas fa-times"></i></a></span>
</div>
</div>
<div class="small dept_title">Подразделение: ~dept_title~</div>
</div>
</script>
<script>
$(document).ready( function() {
$('.form-horizontal input[type=text]').addClass('form-control').attr('autocomplete', 'off');
$('.form-horizontal input[type=email]').addClass('form-control').attr('autocomplete', 'off');
$('.form-horizontal input[type=file]').addClass('form-control').attr('autocomplete', 'off');
$('.form-horizontal input[type=number]').addClass('form-control').attr('autocomplete', 'off');
$('.form-horizontal input[type=password]').addClass('form-control').attr('autocomplete', 'off');
$('.form-horizontal input[type=checkbox]').addClass('checkbox');
$('.form-horizontal select').addClass('form-control');
$('.form-horizontal textarea').addClass('form-control');
});
</script>
#[!view]#
#[panel]#
<nav class="navbar navbar-expand-lg navbar-light bg-secondary mb-3">
<a href="?cat={cur_cat}&act=edit&id=0" class="btn btn-success">Создать сотрудника</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#filterForm">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="filterForm">
<form class="form-inline my-2 my-lg-0" method="GET">
<input type="hidden" name="cat" value="{cur_cat}">
<select name="_f[user_office]" class="form-control input-sm mr-sm-2 mb-2 mb-lg-0">
<option value="0">Отдел</option>
{offices}
</select>
<input type="text" class="form-control input-sm mr-sm-2 mb-2 mb-lg-0" name="_f[str]" value="{str}" autocomplete="off" placeholder="Имя сотрудника">
<button type="submit" class="btn btn-warning mr-sm-2 mb-0 mb-lg-0">Найти</button>
</form>
</div>
</nav>
#[!panel]#

View File

@ -1,222 +0,0 @@
#[body]#
<style>
.content-vertical td {
vertical-align: middle !important;
}
.content-vertical td a {
text-decoration: none;
display: block;
}
</style>
{panel}
<div class="container-fluid">
<div class="row">
<div class="col-12 col-md-9 col-xxl-8 mb-3 px-0 px-lg-3">
<div class="card">
<div class="card-body p-2 p-lg-3">
<h2 class="card-title">Выдача зарплаты</h2>
<div class="btn-group mb-3">
{kassa_btns}
</div>
<div class="table-responsive">
<table class="table table-sm table-hover content-vertical w-100">
<thead>
<tr>
<th class="text-center d-none d-lg-table-cell" style="width: 48px;">Фото</th>
<th class="text-left">Сотрудник</th>
<th class="text-center d-none d-lg-table-cell">Последняя выдача</th>
<th class="text-center d-none d-lg-table-cell">Баланс</th>
<th class="text-center d-lg-table-cell" style="min-width: 100px;">Касса выдачи</th>
<th class="text-center width-fixed-200 width-fixed-lg-300" style="min-width: 100px;">К выдаче</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
<tfoot>
<tr><th colspan="5" class="text-right d-none d-lg-table-cell">Итого</th><th class="text-right d-none d-lg-table-cell">{balance_sum} руб.</th></tr>
</tfoot>
</table>
</div>
{pagewalker}
</div>
</div>
</div>
<div class="col-12 col-md-3 col-xxl-4">
<div class="card mb-3">
<div class="card-body">
<h3>Доступно средств</h3>
<table class="table table-sm small table-striped">
<thead>
<tr><th>Касса</th><th class="text-right">Баланс</th></tr>
</thead>
<tbody>
{kassa_rows}
</tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-body">
<h3 class="card-title">Информация</h3>
<p>Для выдачи зарплаты сотруднику введите сумму, которую выдаёте и нажмите "выдать"</p>
<p>Для корректировки баланса, начисления премий или штрафов кликните на сотрудника.</p>
<p>Оплата за часы начисляется 2 раза в месяц<br>
- 28 числа за смены с 1 по 14 число текущего месяца<br>
- 14 числа следующего за смены с 15 по конец предыдущего месяца<br>
- 14 числа следующего месяца начисляется окладная часть за предыдущий месяц<br>
</p>
<hr>
<p>
Например:<br>
Сотрудник получает 100 руб в час и 5000 руб оклада.<br>
C 1 по 31 января он работал каждый день по 1 часу (итого 31 час)<br>
<ul>
<li>28 января будет начисление за 1-14 января (14 часов, 1400 руб)</li>
<li>14 февраля будет начисление за 15-31 января (17 часов, 1700 руб)</li>
<li>14 февраля начислится окладная часть за январь (5000 руб)</li>
</ul>
</p>
</div>
</div>
</div>
</div>
</div>
#[!body]#
#[row]#
<tr>
<td class="d-none d-lg-table-cell"><a href="?cat={cur_cat}&act=showlog&id={id}"><img src="{_STATIC_ROOT_}/images/{user_photo}.jpg" width="48" height="48"></a></td>
<td><a href="?cat={cur_cat}&act=showlog&id={id}">{name}</a>
<div class="small text-muted">{inn}</div>
</td>
<td class="text-center d-none d-lg-table-cell"><a href="?cat={cur_cat}&act=showlog&id={id}">{last_dump} г.</a></td>
<td class="text-right d-none d-lg-table-cell pr-4"><a href="?cat={cur_cat}&act=showlog&id={id}" class="font-weight-bold"><u>{balance_formated} руб</u></a></td>
<td class="text-center d-lg-table-cell">
<select name="agentID" form="dumpForm{id}" class="form-control form-control-sm" >
{agent_select_html}
</select>
</td>
<td class="text-right pl-4">
<form method="POST" id="dumpForm{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="doDump">
<input type="hidden" name="id" value="{id}">
<div class="input-group input-group-sm">
<input class="form-control text-right" autocomplete="off" tabindex="1" name="money" type="number" step=".01" value="{balance_real}" required>
<div class="input-group-append">
<button class="btn btn-warning" onClick="return confirm('Вы уверены?');"><span class="d-none d-lg-block">Выдать</span><span class="d-lg-none">&rarr;</span></button>
</div>
</div>
</form>
</td>
</tr>
#[!row]#
#[logBody]#
<div class="container-fluid">
<div class="row">
<div class="col-12 col-md-9 col-xxl-8 px-0 px-lg-2 mb-3">
<div class="card">
<div class="card-body">
<h1 class="mb-1">{name}</h1>
<h3 class="mt-0" >баланс: {balance} руб.</h3>
<div class="table-responsive">
<table class="table table-sm small table-hover content-vertical mt-3">
<thead>
<tr>
<th class="text-left d-none d-lg-table-cell" style="width: 48px;">ID</th>
<th class="text-left">Дата</th>
<th class="text-right">Сумма (руб)</th>
<th class="text-left">Комментарий</th>
<th class="text-right d-none d-lg-table-cell">Ответственный</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
</div>
{walker}
</div>
</div>
</div>
<div class="col-12 col-md-3 col-xxl-4 px-0 px-lg-2">
<div class="card">
<div class="card-body">
<h3 class="card-title">Корректировка баланса</h3>
<form method="POST" class="mt-3" style="max-width: 320px;">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="addMoney">
<input type="hidden" name="id" value="{id}">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Сумма</span>
</div>
<input class="form-control text-right" tabindex="1" autocomplete="off" name="money" type="text" inputmode="numeric" step=".01" value="0.00" required>
<div class="input-group-append">
<span class="input-group-text">руб.</span>
</div>
</div>
</div>
<div class="form-group">
<input class="form-control text-left" autocomplete="off" tabindex="2" name="comment" type="text" placeholder="Комментарий" required>
</div>
<button class="btn btn-warning w-100" tabindex="3" onClick="return confirm('Вы уверены?');">Внести</button>
</form>
</div>
</div>
<div class="card mt-2">
<div class="card-body">
<p>В этом интерфейсе НЕ выдается зарплата, а только корректируется. Например, начисляются премии или штрафы.</p>
<p>Положительная сумма увеличивает зарплату, отрицательная уменьшает.</p>
<p>Примеры<br>100 руб - премия 100 руб.<br>-100 руб - штраф 100 руб.</p>
</div>
</div>
<div class="card mt-2">
<div class="card-body">
<div class="row">
<div class="col-3 col-xxl-4 px-0"><img src="{_STATIC_ROOT_}/images/{user_photo}.jpg" class="img-fluid"></div>
<div class="col-9 col-xxl-8">
<h3 class="card-title">{name}</h3>
ИНН: {inn}<br>
Оклад: {salary_sum_nf} руб.<br>
Неначисленные часы: <span class="text-nowrap">{nopaid_rubs} руб. ({nopaid_hours} ч.)</span><br>
<span class="small text-muted">Оплата за часы начисляется 14 и 28 числа.</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#[!logBody]#
#[logRow]#
<tr>
<td class="text-left d-none d-lg-table-cell">{id}</td>
<td class="text-left">{datetime}</td>
<td class="text-right">{summa_nf}</td>
<td class="text-left">{comment}</td>
<td class="text-right d-none d-lg-table-cell">{creator_id}</td>
</tr>
#[!logRow]#
#[agent_balance]#
<tr>
<td><a href="?cat={cur_cat}&act=agentbalance&id={id}">{title}</a></td>
<td class="text-right">{balance} руб.</td>
</tr>
#[!agent_balance]#

View File

@ -1,76 +0,0 @@
#[logBody]#
<div class="container-fluid">
<div class="row">
<div class="col-12 col-md-9 col-xxl-8 px-0 px-lg-2 mb-3">
<div class="card">
<div class="card-body">
<h1 class="mb-1">{name}</h1>
<h3 class="mt-0" >Доступно к получению: {balance} руб.</h2>
<div class="table-responsive">
<table class="table table-sm small table-hover content-vertical mt-3">
<thead>
<tr>
<th class="text-left d-none d-lg-table-cell" style="width: 48px;">ID</th>
<th class="text-left">Дата</th>
<th class="text-right">Сумма (руб)</th>
<th class="text-left">Комментарий</th>
<th class="text-right d-none d-lg-table-cell">Ответственный</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
</div>
{walker}
</div>
</div>
</div>
<div class="col-12 col-md-3 col-xxl-4 px-0 px-lg-2">
<div class="card mt-2">
<div class="card-body">
<div class="row">
<div class="col-3 col-xxl-4 px-0"><img src="{_STATIC_ROOT_}/images/{user_photo}.jpg" class="img-fluid"></div>
<div class="col-9 col-xxl-8">
<h3 class="card-title">{name}</h3>
ИНН: {inn}<br>
Оклад: {salary_sum_nf} руб.<br>
Неначисленные часы: <span class="text-nowrap">{nopaid_rubs} руб. ({nopaid_hours} ч.)</span>
</div>
<div class="col-12 mt-3">
<p>Оплата за часы начисляется 2 раза в месяц<br>
- 28 числа за смены с 1 по 14 число текущего месяца<br>
- 14 числа следующего за смены с 15 по конец предыдущего месяца<br>
- 14 числа следующего месяца начисляется окладная часть за предыдущий месяц<br>
</p>
<hr>
<p>
Например:<br>
Сотрудник получает 100 руб в час и 5000 руб оклада.<br>
C 1 по 31 января он работал каждый день по 1 часу (итого 31 час)<br>
<ul>
<li>28 января будет начисление за 1-14 января (14 часов, 1400 руб)</li>
<li>14 февраля будет начисление за 15-31 января (17 часов, 1700 руб)</li>
<li>14 февраля начислится окладная часть за январь (5000 руб)</li>
</ul>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#[!logBody]#
#[logRow]#
<tr>
<td class="text-left d-none d-lg-table-cell">{id}</td>
<td class="text-left">{datetime}</td>
<td class="text-right">{summa_nf}</td>
<td class="text-left">{comment}</td>
<td class="text-right d-none d-lg-table-cell">{creator_id}</td>
</tr>
#[!logRow]#

View File

@ -1,604 +0,0 @@
#[body]#
<script type="text/javascript" src="js/controllers/workline.js?v=210310"></script>
<link rel="stylesheet" type="text/css" href="js/bt4_slider/css/bootstrap-slider.css"/>
<script type="text/javascript" src="js/bt4_slider/bootstrap-slider.min.js"></script>
<script type="text/javascript" src="js/moment.js"></script>
<style>
.time-line {
display: flex;
flex-flow: wrap;
justify-content: space-between;
cursor: pointer;
position: relative;
}
.time-line.is-payed {
background-image: url(img/locked.png);
background-repeat: no-repeat;
background-position: center center;
}
.time-line:hover {
outline: 1px solid black;
z-index: 99;
}
.cell {
border-left: 2px solid #EFEFEF;
border-right: 2px solid #EFEFEF;
border-top: 2px solid transparent;
border-bottom: 2px solid transparent;
}
.cell.today {
border: 2px solid #faa;
}
.time-line > span {
display: flex;
align-self: center;
font-size: 10px;
line-height: 10px;
}
.draggable {
cursor: pointer;
}
.addWorkerPlaceholder {
width: 100%;
text-align: center;
height: 40px;
line-height: 40px;
background: #f5f5f5;
border: 2px dashed #eee;
color: #ccc;
cursor: pointer;
}
.bg-secondary .addWorkerPlaceholder {
display: none;
}
.worker-line.ui-draggable-dragging {
width: 200px;
z-index: 1090;
opacity: .7;
}
.worker-line.ui-draggable-dragging.copymove {
opacity: 1;
}
.droppable.drop-active {
background: #ffa !important;
}
.droppable.drop-hover {
border: 2px solid red;
}
.dropForDelete.drop-active {
background: #faa !important;
}
.dropForDelete > div {
display: none;
font-size: 1.2em;
}
.dropForDelete.drop-active > div {
display: block;
color: #8a0303;
}
.dropForDelete.drop-hover {
border: 2px solid red;
}
.my-neighbor {
display: none !important;
}
#rasptable.show-neighbor .my-neighbor {
display: flex !important;
}
.custom-control-label {
cursor: pointer;
}
.holyday {
color: #f66 !important;
}
a.no-underline:hover {
text-decoration: none;
}
.d-print-block .time-line {
border: 1px solid #555;
padding: 3px 0px;
}
.d-print-block .time-line > span {
font-size: 1em;
line-height: 1.1em;
}
@media screen and (max-width: 979px) {
.cell.bg-secondary {
display: none !important;
}
}
@media print {
/* @page { size: landscape; } */
.cell.today {
border: 2px solid #EFEFEF;
}
.addWorkerPlaceholder {
display: none;
}
.row-cols-lg-7 > * {
flex: 0 0 14.2857142857%;
max-width: 14.2857142857%;
}
.row-cols-lg-7 {
page-break-inside: avoid;
}
.cell {
border: 1px solid #EFEFEF;
padding: 2px !important;
margin: 0px !important;
}
.d-lg-flex {
display: flex;
}
.flex-lg-column {
flex-direction: column !important;
}
.d-lg-none {
display: none;
}
.px-lg-0 {
padding-left: 0px !important;
padding-right: 0px !important;
}
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-9 pr-lg-0 col-print-12 mb-3">
<div class="row">
<div class="col-lg-4 my-3 vertical-middle">
<div class="btn-group">
<a href="?cat={cur_cat}&month={prev_month}&office_id={office_id_id}" class="btn btn-sm btn-secondary">
<img style="height: 1.5em;" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pjxzdmcgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MnB4O308L3N0eWxlPjwvZGVmcz48dGl0bGUvPjxnIGlkPSJjaGV2cm9uLWxlZnQiPjxsaW5lIGNsYXNzPSJjbHMtMSIgeDE9IjExIiB4Mj0iMjAiIHkxPSIxNiIgeTI9IjciLz48bGluZSBjbGFzcz0iY2xzLTEiIHgxPSIyMCIgeDI9IjExIiB5MT0iMjUiIHkyPSIxNiIvPjwvZz48L3N2Zz4=">
</a>
<div class="btn">{selected_month} <small class="align-top readonly-mark text-muted">{readonlymark}</small></div>
<a href="?cat={cur_cat}&month={next_month}&office_id={office_id_id}"class="btn btn-sm btn-secondary">
<img style="height: 1.5em;" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pjxzdmcgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MnB4O308L3N0eWxlPjwvZGVmcz48dGl0bGUvPjxnIGlkPSJjaGV2cm9uLXJpZ2h0Ij48bGluZSBjbGFzcz0iY2xzLTEiIHgxPSIyMSIgeDI9IjEyIiB5MT0iMTYiIHkyPSIyNSIvPjxsaW5lIGNsYXNzPSJjbHMtMSIgeDE9IjEyIiB4Mj0iMjEiIHkxPSI3IiB5Mj0iMTYiLz48L2c+PC9zdmc+">
</a>
</div>
</div>
<div class="col-lg-8 my-3 text-right mt-auto">
{office_seletector}
{show_neighbor}
</div>
</div>
<div class="mt-1 bg-transparent" id="rasptable">
<div class="row-cols-lg-7 bg-white text-center d-print-flex d-none d-lg-flex align-items-center" style="height: 40px;">
<div>Понедельник</div>
<div>Вторник</div>
<div>Среда</div>
<div>Четверг</div>
<div>Пятница</div>
<div>Суббота</div>
<div>Воскресенье</div>
</div>
{days}
</div>
</div>
<div class="col-12 col-lg-3 d-print-none">
<div id="monthcont" class="sticky-top mt-2">
{monthstat}
</div>
<div id="del_smena_block" class="{hide_del_smena}">
<a href="?cat={cur_cat}&act=del_smena_block&office_id={office_id_id}&month={cur_month}" class="btn btn-secondary w-100" data-fancybox data-type="ajax">Сброс расписания <i class="fas fa-trash"></i></a>
</div>
</div>
<div class="col-12 col-lg-3" style="position: fixed; right: 0px; bottom: 0px; z-index: 1060;">
<div class="col-12 py-5 dropForDelete">
<div class="text-center">Удалить смену</div>
</div>
</div>
</div>
<script>
$( function() {
if ( {writemode} ) {
workline.init('{cur_cat}', '{month}');
{setOffice}
} else {
$('.addWorkerPlaceholder').remove();
}
} );
</script>
#[!body]#
#[del_smena]#
<script src="/admin/js/jquery.daterangepicker.js"></script>
<link rel="stylesheet" href="/admin/css/daterangepicker.css">
<style>
.employee_list .form-check-input {
width: 1.2rem;
height: 1.2rem;
}
.modal_custom {
padding: 5px !important;
}
.period_picker_box {
z-index: 99999999;
left: 0 !important;
right: 0 !important;
top: 0 !important;
bottom: 0 !important;
margin-left: auto !important;
margin-right: auto !important;
margin-top: auto !important;
margin-bottom: auto !important;
}
</style>
<div class="modal_custom" style="min-width: 600px;">
<form method="POST">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="del_smena_do">
<div class="modal-dialog my-2">
<div class="modal-content border-0">
<div class="header p-2">
<h1 class="modal-title font-weight-bold" id="exampleModalLabel">Сброс расписания</h1>
</div>
<div class="modal-body">
<div>
<h5>Выберите сотрудника <span class="text-muted">[<a href="#" class="text-muted" data-status="0" onclick="check_employees(this)">все</a>]</span>:</h5>
<div class="employee_list form-group">
{employee_rows}
</div>
</div>
<div class="mt-4">
<h5>Выберите даты:</h5>
<div class="form-check">
<input class="date_type form-check-input" type="radio" name="_f[date_type]" id="radio_all_month" value="month" checked>
<input type="hidden" name="_f[selected_month]" value="{selected_month}">
<label class="form-check-label" for="radio_all_month">
За весь месяц:
</label>
<span class="selected_month_text">{selected_month}</span>
</div>
<div class="form-check d-flex justify-content-start" style="min-height: 40px">
<input class="date_type form-check-input" type="radio" name="_f[date_type]" id="radio_pediod" value="period">
<label class="form-check-label" for="radio_pediod">
За период:
</label>
<div class="dateperiod_block d-inline-block show_0 pl-3">
<input id="dateperiod_from" name="_f[dateperiod_from]" type="text" class="dateperiod form-control" value="" autocomplete="off">
<input id="dateperiod_to" name="_f[dateperiod_to]" type="text" value="" class="dateperiod form-control" autocomplete="off">
<script>
$(function() {
$('#dateperiod_from').periodpicker({
startDate: moment().format('01.MM.YYYY'),
endDate: moment().format('DD.MM.YYYY'),
minDate: moment().format('DD.MM.YYYY'),
end: '#dateperiod_to',
lang: 'ru',
formatDate: 'DD.MM.YYYY',
yearsPeriod: [moment().format('YYYY'), moment().format('YYYY')],
draggable: true,
parentEl: ".fancybox-container .modal_custom",
drops: "auto"
});
});
</script>
</div>
</div>
</div>
</div>
<div class="footer mx-3 mb-3 mt-0">
<button type="submit" class="btn btn-primary w-100">Удалить смены</button>
</div>
</div>
</div>
</form>
</div>
<script>
$(function(){
$('.date_type').on('change', function(){
if($(this).attr('id') == 'radio_pediod'){
$('.dateperiod_block').removeClass('show_0');
$('.selected_month_text').addClass('show_0');
} else {
$('.dateperiod_block').addClass('show_0');
$('.selected_month_text').removeClass('show_0');
}
});
});
// Кнопка выделить всех сотрудников (при удалении смен)
function check_employees(chbx){
let status = $(chbx).attr('data-status');
if(status == "0"){
$('.employee_list input[type=checkbox]').each(function(){
$(this).prop('checked', true);
});
$(chbx).attr('data-status', 1);
} else {
$('.employee_list input[type=checkbox]').each(function(){
$(this).prop('checked', false);
});
$(chbx).attr('data-status', 0);
}
}
</script>
#[!del_smena]#
#[del_smena_emp]#
<div class="form-check d-flex align-items-center mb-2">
<input name="_f[employees][]" class="form-check-input" type="checkbox" id="inlineFormCheck{id}" value="{id}">
<label class="form-check-label" for="inlineFormCheck{id}">
<img class="pl-2" src="{_STATIC_ROOT_}images/{user_photo}.jpg" style="height: 2em;" title="{name}"><span class="pl-1">{name}</span>
</label>
</div>
#[!del_smena_emp]#
#[cell]#
<div class="bg-{color} {is_today} {droppable} cell px-3 px-lg-1 px-xxl-2 py-3 py-lg-0 my-1 d-flex flex-row flex-lg-column" data-date="{date-mysql}">
<div class="px-2 px-lg-0">
<div class="border-bottom d-flex flex-column flex-lg-row-reverse">
<div class="col-3 {holyday_class} h3 text-right px-0 col-print-12">
{date}
<span class="d-lg-none"><br>{dned}</span>
</div>
<div class="col-9 px-0 d-print-none">
{day_comments}
</div>
</div>
</div>
<div class="px-3 px-lg-0 w-100">
{workers}
<div class="addWorkerPlaceholder d-lg-none my-1" data-date="{date-mysql}">Добавить</div>
</div>
</div>
#[!cell]#
#[workerline]#
<div class="my-1 worker-line {is_my_neighbor} {is_payed}" data-date="{date-mysql}" data-userid="{_sys_users_id}">
<div class="d-print-none d-flex">
<div class="col-2 col-xxl-2 px-0">
<img src="{_STATIC_ROOT_}images/{user_photo}.jpg" class="img-fluid" title="{name}">
</div>
<div class="bg-light col-10 col-xxl-10 px-0 d-flex border-left border-right border-primary align-middle col-print-6">
{intervals}
</div>
</div>
<div class="d-none d-print-block">
<div class="text-truncate">{name}</div>
{intervals_text}
</div>
</div>
#[!workerline]#
#[user_table_body]#
<table class="table table-sm bg-white small">
<thead>
<tr><th>Сотрудник</th><th class="text-right">Часов</th><th class="text-right">Руб</th></tr>
</thead>
<tbody>
{userlist}
</tbody>
</table>
#[!user_table_body]#
#[userlist_row]#
<tr>
<td class="align-middle"><span class="draggable user bg-white p-1 align-middle" data-userid="{id}"><img src="{_STATIC_ROOT_}images/{user_photo}.jpg" style="height: 2em;" title="{name}"> {name}</span></td>
<td class="align-middle text-right text-nowrap">{hours}</td>
<td class="align-middle text-right text-nowrap">{summa} р.
<div class="text-muted small" title="Оклад">+{summa_oklad} р.</div>
</td>
</tr>
#[!userlist_row]#
#[userlist_tarif_row]#
<tr>
<td class="text-right text-nowrap">{tarif_name}</td>
</tr>
#[!userlist_tarif_row]#
#[cell_edit_form]#
<div>
<div class="width-fixed-300 width-fixed-md-700 width-fixed-lg-900" style="margin: -20px;">
<form method="POST" data-autoajaxsubmit="false">
<div class="row">
<div class="col-6 offset-3 offset-lg-0 col-lg-3 text-center">
<img src="{_STATIC_ROOT_}images/{user_photo}.jpg" class="img-fluid"><br>{user_name}
</div>
<div class="col-lg-9">
<div class="h2">{date}</div>
<div class="d-flex flex-wrap py-2 my-2 bg-light small">
<div class="col-12 col-lg-2 text-center text-lg-right border-right" id="hourFrom">{time_start_time}</div>
<div class="col-12 col-lg-8 py-2 py-lg-0" id="timecont">
<input id="timeblock" type="text" value="" data-slider-min="0" data-slider-max="{intervals_cnt}" data-slider-value="{cur_value}" data-slider-tooltip="hide"/>
</div>
<div class="col-12 col-lg-2 text-center text-lg-left border-left" id="hourTo">{time_end_time}</div>
</div>
<div class="font-weight-bold">{date_error}</div>
<input type="hidden" name="time_start" value="{time_start}">
<input type="hidden" name="time_end" value="{time_end}">
<input type="hidden" name="date" value="{date}">
<input type="hidden" name="id" value="{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="time_save">
<input type="hidden" name="user_id" value="{user_id_real}">
<input type="hidden" name="office_id" value="{office_id_real}">
<label>Ставка</label>
{tarif_id_html}
</div>
</div>
<div class="row mt-3">
<div class="col-6 text-left">
<label><input type="checkbox" name="delme"> удалить смену</label><br>
<label><input type="checkbox" name="paynow"> оплатить и заблокировать</label>
</div>
<div class="col-6 text-right">
<input type="submit" name="save" value="Сохранить" class="btn btn-info">
</div>
</div>
</form>
<script>
var firstHour = new moment('{startdate_js}');
initForm();
function initForm() {
$("#timeblock").bootstrapSlider({
ticks: [{ticks}],
ticks_labels: ['{ticks_label}']
});
$("#timeblock").on("slide", function(slideEvt) {
var fromVal = slideEvt.value[0];
var endVal = slideEvt.value[1];
var newDateObj = moment(firstHour).add(30 * fromVal, 'minutes')
$("#hourFrom").text(newDateObj.format('HH:mm'));
$('input[name=time_start]').val(newDateObj.format('YYYY-MM-DD HH:mm:ss'));
var newDateObj = moment(firstHour).add(30 * endVal, 'minutes')
$("#hourTo").text(newDateObj.format('HH:mm'));
$('input[name=time_end]').val(newDateObj.format('YYYY-MM-DD HH:mm:ss'));
});
}
</script>
</div>
</div>
#[!cell_edit_form]#
#[office_selector]#
<div class="btn-group d-print-none">
{office_row}
</div>
#[!office_selector]#
#[show_neighbor]#
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="showNeighbor" onChange="showNeighbor(this);">
<label class="custom-control-label" for="showNeighbor">Показывать коллег</label>
</div>
<script>
function showNeighbor(arg) {
var el = $(arg);
if (el.prop('checked') == true ) {
$('#rasptable').addClass('show-neighbor');
} else {
$('#rasptable').removeClass('show-neighbor');
}
}
</script>
#[!show_neighbor]#
#[day_comments]#
<div class="d-flex text-truncate">
<div>
<a href="?cat={cur_cat}&act=daycomments&date={date}&office_id={office_id}" class="no-underline" data-fancybox data-type="ajax" ><img src="img/msg_icon{full}.svg" style="height: .8em;"></a>
</div>
<div class="pl-1 pt-1 small text-muted">
{showed_comments}
</div>
</div>
#[!day_comments]#
#[comments_block_body]#
<div class="container" style="max-width: 600px;">
<h2 class="border-bottom pb-2">{weekday_name}, {date}</h2>
{rows}
<form method="POST" data-autoajaxsubmit="false">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="addDayComment">
<input type="hidden" name="date" value="{date_mysql}">
<input type="hidden" name="office_id" value="{office_id}">
<div class="input-group py-2 mt-3">
<input type="text" class="form-control" placeholder="Комментарий" name="text" autocomplete="off">
<div class="input-group-append">
<input type="submit" class="btn btn-primary" value="Добавить"/>
</div>
</div>
<div class="custom-control custom-switch">
<input type="checkbox" name="showInRasp" value="1" class="custom-control-input" id="showInRasp">
<label class="custom-control-label" for="showInRasp">показывать в расписании</label>
</div>
</form>
</div>
#[!comments_block_body]#
#[comment_block_row]#
<div class="row py-2" id="msgId{id}">
<div class="col-9">
<blockquote class="blockquote text-left">
<p class="mb-0">{showInRaspIcon} {text}</p>
<footer class="blockquote-footer">{user_name}</footer>
</blockquote>
</div>
<div class="col-3 text-right"><a href="javascript:workline.delMsg('{id}');" title="Удалить"><img src="img/del.png"></a></div>
</div>
#[!comment_block_row]#
#[selectUserList]#
<div class="width-fixed-300" style="margin: -20px;">
<h2>Добавить в расписание</h2>
<h3>на {date_str} г.</h3>
{rows}
</div>
#[!selectUserList]#
#[selectUserListItem]#
<div class="d-flex my-2 border" onClick="$.fancybox.close(); workline.addUserToRasp('{date}', '{id}');">
<div class="col-2 px-0">
<img src="{_STATIC_ROOT_}images/{user_photo}.jpg" class="img-fluid">
</div>
<div class="col-10 align-self-center">
{name}
</div>
</div>
#[!selectUserListItem]#

View File

@ -0,0 +1,78 @@
#[body]#
<div class="container mt-3">
<h1 class="mb-4">Нормативные документы</h1>
<div class="document-list">
{rows}
{walker}
</div>
</div>
<style>
.doc-item {
display: flex;
align-items: center;
padding: 18px 22px;
margin-bottom: 15px;
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 12px;
text-decoration: none !important;
transition: background 0.15s, box-shadow 0.15s;
}
.doc-item:hover {
background: #eef0f2;
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
}
.doc-icon {
font-size: 34px;
color: #6c757d;
margin-right: 18px;
}
.doc-title {
font-size: 22px;
font-weight: 600;
color: #333;
flex-grow: 1;
}
.doc-arrow {
font-size: 22px;
color: #999;
margin-left: 15px;
}
</style>
#[!body]#
#[row]#
<a href="?cat={cur_cat}&id={id}"
class="doc-item">
<i class="fa fa-file-alt doc-icon"></i>
<span class="doc-title">{title}</span>
<i class="fa fa-chevron-right doc-arrow"></i>
</a>
#[!row]#
#[body_void]#
<h1 class="mb-4">Нормативные документы</h1>
Документов пока нет.
#[!body_void]#
#[card]#
<div class="mb-3">
<h1 class="mb-4">{title}</h1>
<div style="font-size:20px; white-space:pre-wrap;">{description}</div>
<a href="{cur_cat}" class="btn btn-primary btn-lg">Назад</a>
</div>
#[!card]#

View File

@ -0,0 +1,105 @@
#[body]#
<div class="container-fluid h-100 d-flex flex-column pt-3">
<h1 class="mb-4">Часто задаваемые вопросы</h1>
<div id="faqAccordion" class="flex-grow-1 d-flex flex-column">
{rows}
{walker}
</div>
</div>
<style>
/* Вопрос */
.faq-question {
font-size: 22px;
font-weight: 600;
color: #333;
padding: 20px 25px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
border: 0;
background: none;
text-align: left;
}
/* Ответ: скролл внутри */
.faq-answer {
font-size: 19px;
white-space: pre-wrap;
padding: 20px 25px;
overflow-y: auto;
}
/* Карточка */
.faq-card {
border: 1px solid #ddd;
border-radius: 10px;
overflow: hidden;
flex-shrink: 0;
margin-bottom: 15px;
}
/* Стрелка */
.faq-arrow {
transition: transform 0.25s ease;
font-size: 22px;
}
.faq-arrow.rotate {
transform: rotate(90deg);
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
$('#faqAccordion').on('show.bs.collapse', function(e){
let arrow = $(e.target).prev('.card-header').find('.faq-arrow');
arrow.addClass('rotate');
});
$('#faqAccordion').on('hide.bs.collapse', function(e){
let arrow = $(e.target).prev('.card-header').find('.faq-arrow');
arrow.removeClass('rotate');
});
});
</script>
#[!body]#
#[row]#
<div class="card faq-card">
<div class="card-header p-0" id="heading{id}">
<button class="faq-question"
data-toggle="collapse"
data-target="#collapse{id}"
aria-expanded="false"
aria-controls="collapse{id}">
<span>{question_text}</span>
<span class="faq-arrow">&#9656;</span>
</button>
</div>
<div id="collapse{id}"
class="collapse"
aria-labelledby="heading{id}"
data-parent="#faqAccordion">
<div class="faq-answer">{answer_text}</div>
</div>
</div>
#[!row]#
#[body_void]#
<h1 class="mb-4">Часто задаваемые вопросы</h1>
Пока вопросов нет.
#[!body_void]#
#[card]#
#[!card]#

View File

@ -1,11 +1,11 @@
<div class="mt-4">
<div class="mt-2">
<div class="row">
<div class="col-12 col-xl-10 offset-xl-1 pt-2 pt-xxl-5 py-4">
<h1 class="text-left text-md-center">{title_or_h1}</h1>
<div class="col-12">
<h1 class="text-left">{title_or_h1}</h1>
</div>
</div>
<div class="row">
<div class="col-12 col-xl-10 offset-xl-1 static-text">
<div class="col-12 static-text">
{description}
</div>
</div>

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf8"?>
<templ filename="index.htm">
<menu>
<line_menu root="--btns-"/>
</menu>
</templ>

View File

@ -335,3 +335,8 @@ body {
.badge > a {
color: inherit;
}
.textarea.form-control {
height: 100px;
}

View File

@ -409,7 +409,7 @@ body .redactor_toolbar li a.redactor_btn_alignment { background-position: -62
font-family: Helvetica, Arial, Verdana, Tahoma, sans-serif;
top: 28px;
left: 0;
z-index: 2004;
z-index: 99999;
position: absolute;
width: 200px;
background-color: #fff;
@ -464,7 +464,7 @@ body .redactor_toolbar li a.redactor_btn_alignment { background-position: -62
left: 0;
width: 100%;
height: 100%;
z-index: 50000;
z-index: 99999;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
filter:alpha(opacity=50);

File diff suppressed because one or more lines are too long

View File

@ -38,4 +38,4 @@ $tmpObj->set('realname', $file['name']);
$tmpObj->set('ext', $file['type']);
$tmpObj->save();
die('{"filelink":"/images/' . $tmpObj->id . '.jpg"}');
die('{"filelink":"/images/' . getImagePath($tmpObj->id) . '.jpg"}');

View File

@ -1513,3 +1513,84 @@ a.filter-link.active {
vertical-align: text-bottom;
}
.kiosk-btn-group .kiosk-btn {
padding: 25px 30px;
margin-bottom: 15px;
font-size: 28px;
font-weight: 600;
border-radius: 14px !important;
display: flex;
align-items: center;
user-select: none;
touch-action: manipulation;
}
.kiosk-btn .kiosk-icon {
height: 34px;
width: 34px;
margin-right: 20px;
position: relative;
top: -2px;
}
html, body {
height: 100%;
margin: 0;
overflow: hidden; /* ← никакой прокрутки */
}
.left-col {
height: 100%;
overflow: hidden; /* без внутреннего скролла */
}
.right-col {
height: 100%;
overflow: hidden; /* без внутреннего скролла */
}
#bigcontent {
font-size: 1.5em;
}
#bigcontent h1{
font-size: 3em;
}
#bigcontent-wrapper {
position: relative;
height: 100%;
overflow: hidden;
}
#bigcontent {
height: 100%;
overflow: hidden; /* отключаем нативный скролл */
}
/* кнопки */
.scroll-btn {
position: absolute;
right: 20px;
width: 60px;
height: 60px;
border-radius: 50%;
border: none;
font-size: 32px;
color: #fff;
background: rgba(0,0,0,0.5);
cursor: pointer;
z-index: 100;
display: none;
}
#scroll-up { bottom: 90px; }
#scroll-down { bottom: 20px; }
.scroll-btn:active {
background: rgba(0,0,0,0.7);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -62,6 +62,7 @@ server {
}
location @static {
rewrite "^/images/(\d{1,}).jpg$" /img.php?id=$3 last;
rewrite "^/images/(\d{2})/(\d{2})/(\d{1,}).jpg$" /img.php?id=$3 last;
rewrite "^/images/([0-9]{2})([0-9]{2})([0-9]{1,}).webp$" /images/$1/$2/$1$2$3.webp permanent;
rewrite "^/video/(\d{1,}).flv$" /video.php?id=$1 last;

BIN
Договор/Счет.pdf Normal file

Binary file not shown.