Доработка страницы товаров и их администрирования
This commit is contained in:
parent
4c61ccbb65
commit
7ca19da826
|
@ -351,16 +351,16 @@
|
|||
},
|
||||
{
|
||||
"name": "egulias/email-validator",
|
||||
"version": "3.1.0",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/egulias/EmailValidator.git",
|
||||
"reference": "62c3b73c581c834885acf6e120b412b76acc495a"
|
||||
"reference": "c81f18a3efb941d8c4d2e025f6183b5c6d697307"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/62c3b73c581c834885acf6e120b412b76acc495a",
|
||||
"reference": "62c3b73c581c834885acf6e120b412b76acc495a",
|
||||
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/c81f18a3efb941d8c4d2e025f6183b5c6d697307",
|
||||
"reference": "c81f18a3efb941d8c4d2e025f6183b5c6d697307",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -407,7 +407,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/egulias/EmailValidator/issues",
|
||||
"source": "https://github.com/egulias/EmailValidator/tree/3.1.0"
|
||||
"source": "https://github.com/egulias/EmailValidator/tree/3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -415,7 +415,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-07T14:33:28+00:00"
|
||||
"time": "2021-04-01T18:37:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
|
@ -783,7 +783,7 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://git.hood.su/mirzaev/yii2/arangodb",
|
||||
"reference": "a7abed56d6a3d8d03b1c99e620a9c0ef3887bfcb"
|
||||
"reference": "7a6e6fbadafc65ecb516d5a2dc87bd83f7c19274"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0.0",
|
||||
|
@ -825,7 +825,7 @@
|
|||
"ArangoDb",
|
||||
"yii2"
|
||||
],
|
||||
"time": "2021-03-21T19:01:43+00:00"
|
||||
"time": "2021-03-29T00:20:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mirzaev/yii2-arangodb-sessions",
|
||||
|
@ -833,12 +833,11 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://git.hood.su/mirzaev/yii2/arangodb/sessions/",
|
||||
"reference": "80c16734945a35a0d49170b9a1a854efb322fefb"
|
||||
"reference": "e709d3d9145ccdec0dc2c50390d3b73b73fb1109"
|
||||
},
|
||||
"require": {
|
||||
"mirzaev/yii2-arangodb": "~2.1.x-dev",
|
||||
"php": "^8.0.0",
|
||||
"triagens/arangodb": "~3.2",
|
||||
"yiisoft/yii2": "2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -863,14 +862,14 @@
|
|||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Yii\\web\\DbSession implementation for use with ArangoDB",
|
||||
"description": "yii\\web\\DbSession implementation for use with ArangoDB",
|
||||
"homepage": "https://git.hood.su/mirzaev/yii2/arangodb/sessions",
|
||||
"keywords": [
|
||||
"ArangoDb",
|
||||
"DbSession",
|
||||
"yii2"
|
||||
],
|
||||
"time": "2021-03-21T18:39:52+00:00"
|
||||
"time": "2021-03-29T00:19:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "moonlandsoft/yii2-phpexcel",
|
||||
|
@ -2384,16 +2383,16 @@
|
|||
},
|
||||
{
|
||||
"name": "codeception/codeception",
|
||||
"version": "4.1.19",
|
||||
"version": "4.1.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Codeception.git",
|
||||
"reference": "138dc9345a81ec994dcd6b9680c501a752a37b00"
|
||||
"reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/138dc9345a81ec994dcd6b9680c501a752a37b00",
|
||||
"reference": "138dc9345a81ec994dcd6b9680c501a752a37b00",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/d8b16e13e1781dbc3a7ae8292117d520c89a9c5a",
|
||||
"reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2467,7 +2466,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Codeception/Codeception/issues",
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.19"
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.20"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2475,7 +2474,7 @@
|
|||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-28T13:26:08+00:00"
|
||||
"time": "2021-04-02T16:41:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/lib-asserts",
|
||||
|
@ -3057,20 +3056,22 @@
|
|||
},
|
||||
{
|
||||
"name": "fakerphp/faker",
|
||||
"version": "v1.13.0",
|
||||
"version": "v1.14.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FakerPHP/Faker.git",
|
||||
"reference": "ab3f5364d01f2c2c16113442fb987d26e4004913"
|
||||
"reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ab3f5364d01f2c2c16113442fb987d26e4004913",
|
||||
"reference": "ab3f5364d01f2c2c16113442fb987d26e4004913",
|
||||
"url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1",
|
||||
"reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
"php": "^7.1 || ^8.0",
|
||||
"psr/container": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.2"
|
||||
},
|
||||
"conflict": {
|
||||
"fzaninotto/faker": "*"
|
||||
|
@ -3078,9 +3079,20 @@
|
|||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.4.1",
|
||||
"ext-intl": "*",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.4.2"
|
||||
"symfony/phpunit-bridge": "^4.4 || ^5.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "Required by Faker\\Provider\\Image to download images.",
|
||||
"ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
|
||||
"ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
|
||||
"ext-mbstring": "Required for multibyte Unicode string functionality."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "v1.15-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Faker\\": "src/Faker/"
|
||||
|
@ -3103,9 +3115,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/FakerPHP/Faker/issues",
|
||||
"source": "https://github.com/FakerPHP/Faker/tree/v1.13.0"
|
||||
"source": "https://github.com/FakerPHP/Faker/tree/v.1.14.1"
|
||||
},
|
||||
"time": "2020-12-18T16:50:48+00:00"
|
||||
"time": "2021-03-30T06:27:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
|
@ -5409,16 +5421,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.2.5",
|
||||
"version": "v5.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "938ebbadae1b0a9c9d1ec313f87f9708609f1b79"
|
||||
"reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/938ebbadae1b0a9c9d1ec313f87f9708609f1b79",
|
||||
"reference": "938ebbadae1b0a9c9d1ec313f87f9708609f1b79",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d",
|
||||
"reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5486,7 +5498,7 @@
|
|||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.5"
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5502,7 +5514,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-06T13:42:15+00:00"
|
||||
"time": "2021-03-28T09:42:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
|
@ -6400,16 +6412,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v5.2.4",
|
||||
"version": "v5.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "4e78d7d47061fa183639927ec40d607973699609"
|
||||
"reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/4e78d7d47061fa183639927ec40d607973699609",
|
||||
"reference": "4e78d7d47061fa183639927ec40d607973699609",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572",
|
||||
"reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6463,7 +6475,7 @@
|
|||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.4"
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6479,7 +6491,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-16T10:20:28+00:00"
|
||||
"time": "2021-03-17T17:12:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
|
|
|
@ -4,6 +4,7 @@ $config = [
|
|||
'id' => 'skillparts',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
'defaultRoute' => 'main',
|
||||
'aliases' => [
|
||||
'@vendor' => dirname(__DIR__) . '/../../../vendor',
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
|
@ -76,7 +77,7 @@ $config = [
|
|||
'controller' => 'main'
|
||||
],
|
||||
'product/<catn:[^/]+>' => 'product/index',
|
||||
'product/<catn:[^/]+>/<action:(write|edit|delete)>/<target:(title|catn|desc|image)>' => 'product/<action>-<target>',
|
||||
'product/<catn:[^/]+>/<action:(write|edit|delete)>/<target:(title|catn|dscr|image)>' => 'product/<action>-<target>',
|
||||
'orders' => 'order/index'
|
||||
],
|
||||
],
|
||||
|
|
|
@ -106,8 +106,8 @@ class ProductController extends Controller
|
|||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
|
||||
$model->catn = $text;
|
||||
|
||||
|
@ -138,7 +138,7 @@ class ProductController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
public function actionEditDesc(string $catn): array|string|null
|
||||
public function actionEditDscr(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
|
@ -159,7 +159,7 @@ class ProductController extends Controller
|
|||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
|
||||
$product->desc = $text;
|
||||
$product->dscr = $text;
|
||||
|
||||
if ($product->save()) {
|
||||
// Товар обновлён
|
||||
|
@ -188,6 +188,63 @@ class ProductController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
public function actionEditDmns(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
if (is_null($catn)) {
|
||||
// Не получен артикул
|
||||
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($product = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
||||
$text or $text = '0';
|
||||
$dimension = yii::$app->request->post('dimension') ?? yii::$app->request->get('dimension') ?? 'x';
|
||||
|
||||
$product->dmns = array_merge(
|
||||
$product->dmns ?? [],
|
||||
[
|
||||
$dimension => $text
|
||||
]
|
||||
);
|
||||
|
||||
if ($product->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['dimension'] = $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function actionWriteImage(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
|
@ -203,17 +260,137 @@ class ProductController extends Controller
|
|||
goto end;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
if ($product = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$model->file_image = UploadedFile::getInstancesByName('images');
|
||||
$model->scenario = $model::SCENARIO_IMPORT_IMAGE;
|
||||
$product->file_image = UploadedFile::getInstancesByName('images');
|
||||
$product->scenario = $product::SCENARIO_IMPORT_IMAGE;
|
||||
|
||||
if ($model->importImages() > 0) {
|
||||
if ($product->importImages() > 0) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['main'] = $this->renderPartial('index', compact('model'));
|
||||
$return['main'] = $this->renderPartial('index', ['model' => $product]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function actionDeleteImage(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
$index = yii::$app->request->post('index') ?? yii::$app->request->get('index');
|
||||
|
||||
if (is_null($catn) || is_null($index)) {
|
||||
// Не получены обязательные параметры
|
||||
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($product = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация (буфер нужен из-за кривых сеттеров)
|
||||
$buffer = $product->imgs;
|
||||
|
||||
// Удаление
|
||||
unset($buffer[$index]);
|
||||
|
||||
// Запись
|
||||
$product->imgs = $buffer;
|
||||
|
||||
if ($product->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['main'] = $this->renderPartial('index', ['model' => $product]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function actionWriteCover(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
$index = yii::$app->request->post('index') ?? yii::$app->request->get('index');
|
||||
|
||||
if (is_null($catn) || is_null($index)) {
|
||||
// Не получены обязательные параметры
|
||||
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($product = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация (буфер нужен из-за кривых сеттеров)
|
||||
$buffer = $product->imgs;
|
||||
|
||||
foreach($buffer as $image_index => &$image) {
|
||||
// Перебор изображений
|
||||
|
||||
if ($image_index === (int) $index) {
|
||||
// Найдено запрашиваемое изображение
|
||||
|
||||
// Установка обложки
|
||||
$image['covr'] = true;
|
||||
} else {
|
||||
$image['covr'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Запись
|
||||
$product->imgs = $buffer;
|
||||
|
||||
if ($product->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['main'] = $this->renderPartial('index', ['model' => $product]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class SearchController extends Controller
|
|||
$timer = 0;
|
||||
|
||||
// Период пропуска запросов (в секундах)
|
||||
$period = 5;
|
||||
$period = 3;
|
||||
$keep_connect = false;
|
||||
$sanction = false;
|
||||
$sanction_condition = ($session['last_request'] + $period - time()) < $period;
|
||||
|
@ -128,7 +128,17 @@ class SearchController extends Controller
|
|||
|
||||
$limit = yii::$app->request->isPost ? 10 : 20;
|
||||
|
||||
if ($response = Product::searchByPartialCatn($query, $limit, ['catn' => 'catn', '_key' => '_key'])) {
|
||||
if ($response = Product::searchByPartialCatn($query, $limit, [
|
||||
'_key' => '_key',
|
||||
'catn' => 'catn',
|
||||
'name' => 'name',
|
||||
// Баг с названием DESC
|
||||
'dscr' => 'dscr',
|
||||
'catg' => 'catg',
|
||||
'imgs' => 'imgs',
|
||||
'prod' => 'prod',
|
||||
'dmns' => 'dmns',
|
||||
])) {
|
||||
// Данные найдены по поиску в полях Каталожного номера
|
||||
|
||||
foreach ($response as &$row) {
|
||||
|
@ -205,7 +215,9 @@ class SearchController extends Controller
|
|||
goto keep_connect_wait;
|
||||
}
|
||||
|
||||
return $this->render('/search/index', compact('response', 'timer'));
|
||||
$advanced = true;
|
||||
|
||||
return $this->render('/search/index', compact('response', 'timer', 'advanced'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,12 +157,39 @@ abstract class Document extends ActiveRecord
|
|||
/**
|
||||
* Проверка на то, что в свойство передан массив
|
||||
*/
|
||||
public function arrayValidator(string $attribute, array $params = null): bool
|
||||
public function arrayValidator(string $attribute, array $params = null): void
|
||||
{
|
||||
if (is_array($this->$attribute)) {
|
||||
return true;
|
||||
return;
|
||||
} else {
|
||||
$this->addError($attribute, 'Передан не массив');
|
||||
}
|
||||
|
||||
return false;
|
||||
$this->addError($attribute, 'Неизвестная ошибка');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на то, что в свойство передан массив и он хранит циферные значения
|
||||
*/
|
||||
public function arrayWithNumbersValidator(string $attribute, array $params = null): void
|
||||
{
|
||||
try {
|
||||
if (is_array($this->$attribute)) {
|
||||
|
||||
foreach ($this->$attribute as $value) {
|
||||
if (!(bool) preg_match('/^[0-9]*$/m', $value)) {
|
||||
$this->addError($attribute, 'В массиве найдены запрещённые символы');
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
$this->addError($attribute, 'Передан не массив');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->addError($attribute, $e->getMessage());
|
||||
}
|
||||
|
||||
$this->addError($attribute, 'Неизвестная ошибка');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,11 @@ class Notification extends Document
|
|||
*/
|
||||
const TYPE_WARNING = 'warning';
|
||||
|
||||
/**
|
||||
* Тип уведомления: ошибка
|
||||
*/
|
||||
const TYPE_ERROR = 'error';
|
||||
|
||||
/**
|
||||
* Цель для отправки уведомления
|
||||
*
|
||||
|
|
|
@ -9,7 +9,7 @@ use yii\web\UploadedFile;
|
|||
use yii\imagine\Image;
|
||||
|
||||
use app\models\traits\SearchByEdge;
|
||||
|
||||
use Exception;
|
||||
use moonland\phpexcel\Excel;
|
||||
|
||||
/**
|
||||
|
@ -75,12 +75,12 @@ class Product extends Document
|
|||
[
|
||||
'catn',
|
||||
'name',
|
||||
'desc',
|
||||
'ocid',
|
||||
// В библеотеке есть баг на название DESC (неизвестно в моей или нет)
|
||||
'dscr',
|
||||
'prod',
|
||||
'dmns',
|
||||
'imgs',
|
||||
'time',
|
||||
'oemn',
|
||||
'cost'
|
||||
'time'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -95,12 +95,11 @@ class Product extends Document
|
|||
[
|
||||
'catn' => 'Каталожный номер (catn)',
|
||||
'name' => 'Название (name)',
|
||||
'desc' => 'Описание (desc)',
|
||||
'ocid' => 'Идентификатор 1C (ocid)',
|
||||
'dscr' => 'Описание (dscr)',
|
||||
'prod' => 'Производитель (prod)',
|
||||
'dmns' => 'Габариты (dmns)',
|
||||
'imgs' => 'Изображения (imgs)',
|
||||
'time' => 'Срок доставки (time)',
|
||||
'oemn' => 'OEM номера (oemn)',
|
||||
'cost' => 'Стоимость (cost)',
|
||||
'file_excel' => 'Документ (file_excel)',
|
||||
'file_image' => 'Изображение (file_image)',
|
||||
'group' => 'Группа (group)'
|
||||
|
@ -129,12 +128,14 @@ class Product extends Document
|
|||
'message' => '{attribute} должен быть строкой'
|
||||
],
|
||||
[
|
||||
[
|
||||
'oemn',
|
||||
'imgs'
|
||||
],
|
||||
'imgs',
|
||||
'arrayValidator',
|
||||
'message' => '{attribute} должен быть массивом.'
|
||||
'message' => '{attribute} должен быть массивом'
|
||||
],
|
||||
[
|
||||
'dmns',
|
||||
'arrayWithNumbersValidator',
|
||||
'message' => '{attribute} должен быть массивом и хранить циферные значения'
|
||||
],
|
||||
[
|
||||
'file_excel',
|
||||
|
@ -176,52 +177,6 @@ class Product extends Document
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация продукта
|
||||
*
|
||||
* @param string $catn Артикул, каталожный номер
|
||||
*/
|
||||
public static function initEmpty(string $catn): self|array
|
||||
{
|
||||
$oemn = self::searchOemn($catn);
|
||||
|
||||
if (count($oemn) === 1) {
|
||||
// Передан только один артикул
|
||||
|
||||
if ($model = self::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
// Запись пустого продукта
|
||||
return self::writeEmpty($catn);
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$models = [];
|
||||
|
||||
foreach ($oemn as $catn) {
|
||||
// Перебор всех найденных артикулов
|
||||
|
||||
if ($model = self::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись
|
||||
if ($model = self::writeEmpty($catn)) {
|
||||
// Записано
|
||||
|
||||
// Запись в массив сохранённых моделей
|
||||
$models[] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись пустого продукта
|
||||
*/
|
||||
|
@ -237,28 +192,6 @@ class Product extends Document
|
|||
return $model->save() ? $model : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск OEM номеров
|
||||
*
|
||||
* @param string $oemn Необработанная строка с OEM-номерами
|
||||
* @param string $delimiters Разделители
|
||||
*
|
||||
* @todo НЕ ЗАБЫТЬ СДЕЛАТЬ НАСТРОЙКУ РАЗДЕЛИТЕЛЕЙ
|
||||
*
|
||||
* @return array OEM-номера
|
||||
*/
|
||||
public static function searchOemn(string $oemn, string $delimiters = '\s\+\/,'): array
|
||||
{
|
||||
// Инициализация
|
||||
$catn = [];
|
||||
|
||||
// Конвертация
|
||||
preg_match_all("/[^$delimiters]+/", $oemn, $catn);
|
||||
|
||||
return $catn[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Импорт изображений
|
||||
*
|
||||
|
@ -266,12 +199,12 @@ class Product extends Document
|
|||
*/
|
||||
public function importImages(): int
|
||||
{
|
||||
// Инициализация
|
||||
$amount = 0;
|
||||
|
||||
if ($this->validate()) {
|
||||
// Проверка пройдена
|
||||
|
||||
// Инициализация
|
||||
$amount = 0;
|
||||
|
||||
foreach ($this->file_image as $file) {
|
||||
// Перебор обрабатываемых изображений
|
||||
|
||||
|
@ -307,16 +240,19 @@ class Product extends Document
|
|||
Image::resize(YII_PATH_PUBLIC . $catalog . '/' . $file->baseName . '.' . $file->extension, 150, 150)
|
||||
->save(YII_PATH_PUBLIC . $catalog_h150 . '/' . $file->baseName . '.' . $file->extension, ['quality' => 80]);
|
||||
|
||||
// Инициализация
|
||||
$this->imgs ?? $this->imgs = [];
|
||||
|
||||
// Запись в базу данных
|
||||
$this->imgs = array_merge(
|
||||
$this->imgs ?? [],
|
||||
$this->imgs,
|
||||
[[
|
||||
'covr' => count($this->imgs) === 0 ? true : false,
|
||||
'orig' => $catalog . '/' . $file->baseName . '.' . $file->extension,
|
||||
'h150' => $catalog_h150 . '/' . $file->baseName . '.' . $file->extension
|
||||
]]
|
||||
);
|
||||
|
||||
|
||||
$this->scenario = self::SCENARIO_WRITE;
|
||||
|
||||
if ($this->save()) {
|
||||
|
@ -328,6 +264,22 @@ class Product extends Document
|
|||
}
|
||||
}
|
||||
|
||||
if ($this->hasErrors()) {
|
||||
// Получены ошибки
|
||||
|
||||
foreach ($this->getErrors() as $attribute => $errors) {
|
||||
// Перебор атрибутов
|
||||
|
||||
foreach ($errors as $error) {
|
||||
// Перебор ошибок атрибутов
|
||||
|
||||
$label = $this->getAttributeLabel($attribute);
|
||||
|
||||
Notification::_write("$label: $error", type: Notification::TYPE_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@ class Supply extends Product implements ProductInterface
|
|||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'onec'
|
||||
'cost',
|
||||
'onec',
|
||||
'ocid'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -65,7 +67,28 @@ class Supply extends Product implements ProductInterface
|
|||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'onec' => 'Данные 1С'
|
||||
'cost' => 'Стоимость (cost)',
|
||||
'onec' => 'Данные 1С',
|
||||
'ocid' => 'Идентификатор 1C (ocid)'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
// [
|
||||
// [
|
||||
// 'oemn'
|
||||
// ],
|
||||
// 'arrayValidator',
|
||||
// 'message' => '{attribute} должен быть массивом.'
|
||||
// ]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -281,7 +304,7 @@ class Supply extends Product implements ProductInterface
|
|||
// Создание продукта (временно заблокировано)
|
||||
|
||||
// // Инициализация п̸̨͇͑͋͠р̷̬̂́̀̊о̸̜̯̹̅͒͘͝д̴̨̨̨̟̈́̆у̴̨̭̮̠́͋̈́к̴̭͊̋̎т̵̛̣͈̔̐͆а̵̨͖͑
|
||||
// $product = Product::initEmpty($this->catn);
|
||||
// $product = self::initEmpty($this->catn);
|
||||
|
||||
// if (!is_array($product)) {
|
||||
// // Создался только один товар и вернулся в виде модели
|
||||
|
@ -296,7 +319,7 @@ class Supply extends Product implements ProductInterface
|
|||
// // Перебор артикулов из массива ОЕМ-номеров
|
||||
|
||||
// // Инициализация и запись
|
||||
// $product[] = Product::initEmpty($oem);
|
||||
// $product[] = self::initEmpty($oem);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
@ -380,6 +403,73 @@ class Supply extends Product implements ProductInterface
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация продукта
|
||||
*
|
||||
* @param string $catn Артикул, каталожный номер
|
||||
*/
|
||||
public static function initEmpty(string $catn): self|array
|
||||
{
|
||||
$oemn = self::searchOemn($catn);
|
||||
|
||||
if (count($oemn) === 1) {
|
||||
// Передан только один артикул
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
// Запись пустого продукта
|
||||
return Product::writeEmpty($catn);
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$models = [];
|
||||
|
||||
foreach ($oemn as $catn) {
|
||||
// Перебор всех найденных артикулов
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись
|
||||
if ($model = Product::writeEmpty($catn)) {
|
||||
// Записано
|
||||
|
||||
// Запись в массив сохранённых моделей
|
||||
$models[] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск OEM номеров
|
||||
*
|
||||
* @param string $oemn Необработанная строка с OEM-номерами
|
||||
* @param string $delimiters Разделители
|
||||
*
|
||||
* @todo НЕ ЗАБЫТЬ СДЕЛАТЬ НАСТРОЙКУ РАЗДЕЛИТЕЛЕЙ
|
||||
*
|
||||
* @return array OEM-номера
|
||||
*/
|
||||
public static function searchOemn(string $oemn, string $delimiters = '\s\+\/,'): array
|
||||
{
|
||||
// Инициализация
|
||||
$catn = [];
|
||||
|
||||
// Конвертация
|
||||
preg_match_all("/[^$delimiters]+/", $oemn, $catn);
|
||||
|
||||
return $catn[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись цены из 1С
|
||||
*/
|
||||
|
|
|
@ -6,11 +6,12 @@ $this->title = $name;
|
|||
|
||||
?>
|
||||
|
||||
<div id="page_error" class="container py-3">
|
||||
<h1><?= Html::encode($this->title) ?></h1>
|
||||
<div id="page_error" class="container d-flex flex-column">
|
||||
<div class="my-auto">
|
||||
<h1 class="text-center mb-4 gilroy"><b><?= Html::encode($this->title) ?></b></h1>
|
||||
|
||||
<div class="alert alert-danger">
|
||||
<?= nl2br(Html::encode($message)) ?>
|
||||
<div class="col-md-8 col-lg-6 mx-auto alert alert_white">
|
||||
<?= nl2br(Html::encode($message)) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -16,16 +16,34 @@ use app\models\Product;
|
|||
<div id="product_slider" class="row px-3 profile_panel">
|
||||
<div class="col-1 product_slider_preview p-0 pr-3 mb-3">
|
||||
<?php
|
||||
foreach ($model['imgs'] ?? [null] as $key => $image) {
|
||||
// Перебор изображений
|
||||
// Инициализация
|
||||
$covr_not_found = true;
|
||||
|
||||
// Проверка на то, что обложка установлена
|
||||
foreach (!empty($model['imgs']) && is_array($model['imgs']) ? $model['imgs'] : [] as $image) {
|
||||
if ($image['covr'] ?? false) {
|
||||
$covr_not_found = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (!empty($model['imgs']) && is_array($model['imgs']) ? $model['imgs'] : [] as $key => $image) {
|
||||
// Перебор изображений для генерации обложек
|
||||
|
||||
// Инициализация
|
||||
$h150 = $image['h150'] ?? '/img/covers/h150/product.png';
|
||||
|
||||
// Генерация предпросмотра изображения
|
||||
if (($image['covr'] ?? false) || ($covr_not_found && $key === 0)) {
|
||||
echo <<<HTML
|
||||
<label class="p-0 mb-2 rounded unselectable active" for="product_slider_image_$key" onclick="return product_image_choose('$key', this.parentElement);">
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<label class="p-0 mb-2 rounded unselectable" for="product_slider_image_$key" onclick="return product_image_choose('$key', this.parentElement);">
|
||||
HTML;
|
||||
}
|
||||
|
||||
echo <<<HTML
|
||||
<label class="p-0 mb-2" for="product_slider_image_$key">
|
||||
<img class="img-fluid rounded" src="$h150"/>
|
||||
<img class="img-fluid" src="$h150"/>
|
||||
</label>
|
||||
HTML;
|
||||
}
|
||||
|
@ -37,39 +55,57 @@ use app\models\Product;
|
|||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) : ?>
|
||||
<input id="product_slider_image_new" type="file" class="d-none" onchange="return product_panel_images_write('<?= $model['catn'] ?>', this);" multiple />
|
||||
<label class="p-0 mb-2" for="product_slider_image_new" role="button">
|
||||
<label class="p-0 mb-2 button_write unselectable" for="product_slider_image_new" role="button">
|
||||
<img class="img-fluid rounded" src="/img/covers/h150/product_new.png" />
|
||||
</label>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="product_slider_image">
|
||||
<?php
|
||||
|
||||
// Инициализация
|
||||
$imgs = $model['imgs'] ?? [null];
|
||||
$checked = '';
|
||||
|
||||
foreach ($model['imgs'] ?? [null] as $key => $image) {
|
||||
// Перебор изображений
|
||||
foreach (!empty($model['imgs']) && is_array($model['imgs']) ? $model['imgs'] : [] as $key => $image) {
|
||||
// Перебор изображений для генерации полных версий
|
||||
|
||||
// Инициализация
|
||||
$name = $image['name'] ?? 'Без названия';
|
||||
$orig = $image['orig'] ?? '/img/covers/product.png';
|
||||
$covr = $image['covr'] ?? false;
|
||||
|
||||
if ($covr || count($imgs) < 2) {
|
||||
// Если это изображение является обложкой
|
||||
if (($image['covr'] ?? false) || ($covr_not_found && $key === 0)) {
|
||||
// Если это изображение является обложкой или обложка не найдена
|
||||
|
||||
// Реинициализация
|
||||
$checked = 'checked';
|
||||
}
|
||||
|
||||
// Генерация изображения
|
||||
echo <<<HTML
|
||||
<input type="radio" id="product_slider_image_$key" name="slider" $checked/>
|
||||
<div class="col p-0">
|
||||
<img class="img-fluid rounded" src="$orig"/>
|
||||
</div>
|
||||
HTML;
|
||||
if (
|
||||
!yii::$app->user->isGuest
|
||||
&& (yii::$app->user->identity->type === 'administrator'
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) {
|
||||
$catn = $model['catn'];
|
||||
|
||||
echo <<<HTML
|
||||
<input type="radio" id="product_slider_image_$key" name="slider" $checked/>
|
||||
<div class="col p-0 unselectable">
|
||||
<img class="mb-3 img-fluid w-100 rounded" src="$orig"/>
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="flex-grow-1 mr-3 btn button_blue button_clean" onclick="return product_panel_images_cover_write('$catn', '$key');">Сделать основной обложкой</button>
|
||||
<button class="btn button_red button_clean" onclick="return product_panel_images_delete('$catn', '$key');">Удалить</button>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<input type="radio" id="product_slider_image_$key" name="slider" $checked/>
|
||||
<div class="col p-0 unselectable">
|
||||
<img class="img-fluid rounded" src="$orig"/>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
// Деинициализация
|
||||
$checked = '';
|
||||
|
@ -87,14 +123,16 @@ use app\models\Product;
|
|||
<?php else : ?>
|
||||
<h3 id="title_<?= $model['catn'] ?>" class="my-auto"><?= $model['name'] ?? 'Без названия' ?></h3>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
<div class="row mb-2">
|
||||
<?php if (
|
||||
!yii::$app->user->isGuest
|
||||
&& (yii::$app->user->identity->type === 'administrator'
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) : ?>
|
||||
<h5 id="catn_<?= $model['catn'] ?>" class="ml-auto my-auto d-flex pointer-event" role="button" onclick="return product_panel_catn_edit('<?= $model['catn'] ?>', this, true);">
|
||||
<?= $model['catn'] ?>
|
||||
<h6 id="catn_<?= $model['catn'] ?>" class="mr-auto my-auto pointer-event" role="button" onclick="return product_panel_catn_edit('<?= $model['catn'] ?>', this, true);">
|
||||
<?= $model['catn'] ?? '' ?>
|
||||
<!-- <small class="d-flex">
|
||||
<a class="text-dark my-auto ml-3" title="Редактировать" role="button" onclick="return product_panel_edit('<?= $model['catn'] ?>');">
|
||||
<i class="fas fa-edit"></i>
|
||||
|
@ -103,21 +141,60 @@ use app\models\Product;
|
|||
<i class="fas fa-trash-alt"></i>
|
||||
</a>
|
||||
</small> -->
|
||||
</h5>
|
||||
</h6>
|
||||
<h6 id="prod_<?= $model['catn'] ?>" class="my-0">
|
||||
<?= $model['prod'] ?? 'Неизвестно' ?>
|
||||
</h6>
|
||||
<?php else : ?>
|
||||
<h5 id="catn_<?= $model['catn'] ?>" class="ml-auto my-auto d-flex">
|
||||
<h6 id="catn_<?= $model['catn'] ?>" class="mr-auto my-0">
|
||||
<?= $model['catn'] ?>
|
||||
</h5>
|
||||
</h6>
|
||||
<h6 id="prod_<?= $model['catn'] ?>" class="my-0">
|
||||
<?= $model['prod'] ?? 'Неизвестно' ?>
|
||||
</h6>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="dropdown-divider px-0 mb-3"></div>
|
||||
|
||||
<div class="dropdown-divider px-0 mb-2"></div>
|
||||
|
||||
<?php if (
|
||||
!yii::$app->user->isGuest
|
||||
&& (yii::$app->user->identity->type === 'administrator'
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) : ?>
|
||||
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
||||
<p class="form-control-sm">
|
||||
<b class="mr-1">Габариты:</b>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'x');"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span>
|
||||
<span class="mr-1">см</span>
|
||||
<small>x</small>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'y');"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span>
|
||||
<span class="mr-1">см</span>
|
||||
<small>x</small>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'z');"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span>
|
||||
<span class="mr-1">см</span>
|
||||
</p>
|
||||
</section>
|
||||
<?php else : ?>
|
||||
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
||||
<p class="form-control-sm">
|
||||
<b class="mr-1">Габариты:</b>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_x" class="mx-1"><?= $model['dmns']['x'] ?? '0' ?></span>
|
||||
<small>x</small>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_y" class="mx-1"><?= $model['dmns']['y'] ?? '0' ?></span>
|
||||
<small>x</small>
|
||||
<span id="prod_<?= $model['catn'] ?>_dmns_z" class="mx-1"><?= $model['dmns']['z'] ?? '0' ?></span>
|
||||
</p>
|
||||
</section>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="row mb-3 h-100 product_panel d-flex flex-column">
|
||||
<?php if (
|
||||
!yii::$app->user->isGuest
|
||||
&& (yii::$app->user->identity->type === 'administrator'
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) : ?>
|
||||
<p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break pointer-event product_description" role="button" onclick="return product_panel_description_edit('<?= $model['catn'] ?>', this);"><?= $model['desc'] ?? 'Без описания' ?></p>
|
||||
<p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break pointer-event product_description" role="button" onclick="return product_panel_description_edit('<?= $model['catn'] ?>', this);"><?= $model['dscr'] ?? 'Без описания' ?></p>
|
||||
<?php else : ?>
|
||||
<p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break product_description"><?= $model['name'] ?? 'Без описания' ?></p>
|
||||
<?php endif ?>
|
||||
|
|
|
@ -1,150 +1,166 @@
|
|||
<link href="/css/pages/search.css" rel="stylesheet">
|
||||
|
||||
<div id="page_search" class="container h-100">
|
||||
<div class="row py-3">
|
||||
<section class="col">
|
||||
<?php
|
||||
if (isset($timer) && $timer > 0) {
|
||||
echo <<<HTML
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="px-2 mb-1 text-center d-flex justify-content-center">Слишком частые запросы, повторите попытку через: $timer секунд</p>
|
||||
<small class="mb-3 text-center d-flex justify-content-center">Подождите или нажмите на кнопку вручную</small>
|
||||
<a class="btn text-white button_clean button_blue mx-auto" title="Перезагрузить страницу" role="button" onclick="window.location.reload();">Повторить</a>
|
||||
<div id="page_search" class="container flex-grow-1 d-flex">
|
||||
<?php if (isset($timer) && $timer > 0) : ?>
|
||||
|
||||
<div class="row py-3 w-100">
|
||||
<section class="col">
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="px-2 mb-1 text-center d-flex justify-content-center">Слишком частые запросы, повторите попытку через: $timer секунд</p>
|
||||
<small class="mb-3 text-center d-flex justify-content-center">Подождите или нажмите на кнопку вручную</small>
|
||||
<a class="btn text-white button_clean button_blue mx-auto" title="Перезагрузить страницу" role="button" onclick="window.location.reload();">Повторить</a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
setTimeout('window.location.reload()', $timer + '000');
|
||||
</script>
|
||||
|
||||
<?php else : ?>
|
||||
<?php if (isset($response) && is_array($response) && $response) : ?>
|
||||
|
||||
<div class="row py-3 w-100">
|
||||
<section class="col">
|
||||
|
||||
<?php
|
||||
// Инициализация
|
||||
$covr_not_found = true;
|
||||
$i = 0;
|
||||
$amount = count($response);
|
||||
?>
|
||||
|
||||
<?php foreach ($response as $row) : ?>
|
||||
|
||||
<?php
|
||||
// Инициализация
|
||||
extract($row);
|
||||
$name ?? $name = 'Без названия';
|
||||
// $dscr ?? $dscr = 'Описание';
|
||||
$catg ?? $catg = 'Категория';
|
||||
$covr = null;
|
||||
|
||||
foreach ($imgs ?? [] as $img) {
|
||||
// Перебор изображений для обложки
|
||||
|
||||
if ($img['covr'] ?? false) {
|
||||
// Обложка найдена
|
||||
|
||||
$covr = $img['h150'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($covr)) {
|
||||
// Обложка не инициализирована
|
||||
|
||||
if (!$covr = $imgs[0]['h150'] ?? false) {
|
||||
$covr = '/img/covers/h150/product.png';
|
||||
}
|
||||
}
|
||||
|
||||
$supplies_html = '';
|
||||
?>
|
||||
|
||||
<?php foreach ($supplies as $supply) : ?>
|
||||
|
||||
<?php
|
||||
// Инициализация артикула
|
||||
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
|
||||
|
||||
// Инициализация цены
|
||||
$price_raw = $supply['prce'] ?? $supply['onec']['Цены']['Цена']['ЦенаЗаЕдиницу'];
|
||||
$price = $price_raw . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
|
||||
|
||||
// Инициализация количества
|
||||
$amount_raw = $amount = $supply['amnt'] ?? $supply['onec']['Количество'];
|
||||
|
||||
if (empty($amount_raw) || $amount_raw < 1) {
|
||||
$amount = 'Под заказ';
|
||||
} else {
|
||||
$amount .= ' шт';
|
||||
}
|
||||
|
||||
if ($amount_raw < 1 || $price_raw < 1) {
|
||||
// Нет в наличии или цена 0 рублей
|
||||
|
||||
$button_cart = <<<HTML
|
||||
<div class="col-1 h-100 text-dark d-flex" title="Товар недоступен">
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
} else {
|
||||
$button_cart = <<<HTML
|
||||
<a class="col-1 h-100 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" href="/cart" role="button" onclick="return cart_write('$catn');">
|
||||
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
||||
</a>
|
||||
HTML;
|
||||
}
|
||||
|
||||
$supplies_html .= <<<HTML
|
||||
<div class="row my-auto m-0 h-100 text-right">
|
||||
<small class="col-2 my-auto ml-auto">
|
||||
$amount
|
||||
</small>
|
||||
<small class="col-2 my-auto ml-1">
|
||||
Доставка
|
||||
</small>
|
||||
<b class="col-2 my-auto">
|
||||
$price
|
||||
</b>
|
||||
$button_cart
|
||||
</div>
|
||||
HTML;
|
||||
?>
|
||||
|
||||
<?php endforeach ?>
|
||||
|
||||
<div class="col pb-2">
|
||||
<div class="row p-2 rounded">
|
||||
<img class="ml-0 h-100 img-fluid rounded" src="<?= $covr ?>" />
|
||||
<div class="col-3 ml-3 p-0 d-flex flex-column">
|
||||
<a class="my-auto text-dark" href="/product/<?= $catn ?>">
|
||||
<h5 class="m-0"><?= $name ?></h5>
|
||||
<h6 class="m-0"><small><?= $catn ?></small></h6>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-1 ml-2 p-0 d-flex flex-column">
|
||||
<a class="my-auto text-dark" href="/product/<?= $catn ?>">
|
||||
<small><?= $catg ?></small>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col ml-2 p-0 d-flex flex-column">
|
||||
<?= $supplies_html ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endforeach ?>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
<?php if ($advanced ?? false) : ?>
|
||||
|
||||
<h1 class="m-auto gilroy text-center"><b>Ничего не найдено</b></h1>
|
||||
|
||||
<?php else : ?>
|
||||
|
||||
<div class="row py-3 w-100">
|
||||
<section class="col">
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
setTimeout('window.location.reload()', $timer + '000');
|
||||
</script>
|
||||
HTML;
|
||||
} else {
|
||||
if (isset($response) && is_array($response) && $response) {
|
||||
|
||||
$i = 0;
|
||||
$amount = count($response);
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
|
||||
foreach ($response as $row) {
|
||||
// $name = $row['name'];
|
||||
// $catn = $row['catn'];
|
||||
</section>
|
||||
</div>
|
||||
|
||||
// Инициализация
|
||||
extract($row);
|
||||
isset($name) ?: $name = 'Без названия';
|
||||
isset($catg) ?: $catg = 'Категория';
|
||||
isset($covr) ?: $covr = '/img/covers/h150/product.png';
|
||||
$supplies_html = '';
|
||||
<?php endif ?>
|
||||
|
||||
|
||||
foreach ($supplies as $supply) {
|
||||
// Конкатенация HTML кода
|
||||
|
||||
// Инициализация артикула
|
||||
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
|
||||
|
||||
// Инициализация цены
|
||||
$price_raw = $supply['prce'] ?? $supply['onec']['Цены']['Цена']['ЦенаЗаЕдиницу'];
|
||||
$price = $price_raw . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
|
||||
|
||||
// Инициализация количества
|
||||
$amount_raw = $amount = $supply['amnt'] ?? $supply['onec']['Количество'];
|
||||
|
||||
if (empty($amount_raw) || $amount_raw < 1) {
|
||||
$amount = 'Под заказ';
|
||||
} else {
|
||||
$amount .= ' шт';
|
||||
}
|
||||
|
||||
|
||||
if ($amount_raw < 1 || $price_raw < 1) {
|
||||
// Нет в наличии или цена 0 рублей
|
||||
|
||||
$button_cart = <<<HTML
|
||||
<div class="col-1 h-100 text-dark d-flex" title="Товар недоступен">
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
} else {
|
||||
$button_cart = <<<HTML
|
||||
<a class="col-1 h-100 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" href="/cart" role="button" onclick="return cart_write('$catn');">
|
||||
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
||||
</a>
|
||||
HTML;
|
||||
}
|
||||
|
||||
|
||||
$supplies_html .= <<<HTML
|
||||
<div class="row my-auto m-0 h-100 text-right">
|
||||
<small class="col-2 my-auto ml-auto">
|
||||
$amount
|
||||
</small>
|
||||
<small class="col-2 my-auto ml-1">
|
||||
Доставка
|
||||
</small>
|
||||
<b class="col-2 my-auto">
|
||||
$price
|
||||
</b>
|
||||
$button_cart
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
echo <<<HTML
|
||||
<div class="col pb-2">
|
||||
<div class="row p-2 rounded">
|
||||
<img class="ml-0 h-100 img-fluid rounded" src="$covr"/>
|
||||
<div class="col-3 ml-3 p-0 d-flex flex-column">
|
||||
<a class="my-auto text-dark" href="/product/$catn">
|
||||
<h5 class="m-0">$name</h5>
|
||||
<h6 class="m-0"><small>$catn</small></h6>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-1 ml-2 p-0 d-flex flex-column">
|
||||
<a class="my-auto text-dark" href="/product/$catn">
|
||||
<small>$catg</small>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col ml-2 p-0 d-flex flex-column">
|
||||
$supplies_html
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
// echo <<<HTML
|
||||
// <div class="col-3 p-2 d-flex flex-column search_card rounded">
|
||||
// <div class="col">
|
||||
// <div class="row mb-2">
|
||||
// <img class="w-100 img-fluid rounded" src="$covr"/>
|
||||
// </div>
|
||||
// <div class="row mb-2">
|
||||
// <a class="mx-auto text-dark" href="/product/$catn"><h5 class="m-0">$catn</h5></a>
|
||||
// </div>
|
||||
// <div class="row px-2 mb-2">
|
||||
// <small class="mt-auto">{$amnt}шт</small>
|
||||
// <p class="mr-0">1000р</p>
|
||||
// </div>
|
||||
// <div class="row">
|
||||
// <button class="btn button_grey button_clean w-100 text-white">В корзину</button>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// HTML;
|
||||
|
||||
// if (++$i % 4 === 0 && $amount - $i !== 0) {
|
||||
// echo <<<HTML
|
||||
// <div class="dropdown-divider my-3 mx-4 w-100 "></div>
|
||||
// HTML;
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/cart.js" defer></script>
|
||||
|
@ -152,7 +168,7 @@
|
|||
<?php if (
|
||||
!yii::$app->user->isGuest
|
||||
&& (yii::$app->user->identity->type === 'administrator'
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
|| yii::$app->user->identity->type === 'moderator')
|
||||
) : ?>
|
||||
<script src="/js/product_panel.js" defer></script>
|
||||
<?php endif ?>
|
|
@ -1,4 +1,4 @@
|
|||
<link href="/css/loading.css" rel="stylesheet">
|
||||
|
||||
<p class="my-2 d-flex justify-content-center"><i class="loading mr-2"></i><br>Поиск</p>
|
||||
<p class="my-2 d-flex justify-content-center"><i class="loading mr-2"></i>Поиск</p>
|
||||
|
||||
|
|
|
@ -40,6 +40,15 @@ main {
|
|||
background-color: #f0eefb;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.inactive,
|
||||
.inactive:hover,
|
||||
.inactive:focus,
|
||||
|
@ -153,6 +162,10 @@ main {
|
|||
transition : 0s;
|
||||
}
|
||||
|
||||
.alert_white {
|
||||
background: #fbf9ff;
|
||||
}
|
||||
|
||||
.d-inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -13,25 +13,64 @@
|
|||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_image {
|
||||
max-width: 25vw;
|
||||
width: 25vw;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label {
|
||||
position: relative;
|
||||
border : none;
|
||||
overflow: hidden;
|
||||
transition: .1s;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label:hover>img {
|
||||
#page_product #product_slider>.product_slider_preview>label>div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label:hover>div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label>img {
|
||||
cursor: pointer;
|
||||
filter: brightness(0.9) contrast(1.1);
|
||||
filter: brightness(.85);
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label:hover>img,
|
||||
#page_product #product_slider>.product_slider_preview>label:active>img,
|
||||
#page_product #product_slider>.product_slider_preview>label:focus>img {
|
||||
cursor: pointer;
|
||||
filter: brightness(0.8) contrast(1.3);
|
||||
#page_product #product_slider>.product_slider_preview>label:focus>img,
|
||||
#page_product #product_slider>.product_slider_preview>label.active>img,
|
||||
#page_product #product_slider>.product_slider_preview>label.button_write>img {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label.active {
|
||||
left: -5px;
|
||||
/* border: 3px solid #123eab; */
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label.button_write:hover>img {
|
||||
filter: brightness(0.85) contrast(1.2);
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label.button_write:active>img,
|
||||
#page_product #product_slider>.product_slider_preview>label.button_write:focus>img {
|
||||
filter: brightness(0.8) contrast(1.25);
|
||||
}
|
||||
|
||||
#page_product article .product_description {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
#page_product article .product_options_edit {
|
||||
width: 100px;
|
||||
height: 1rem;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#page_product article .product_options_edit_small {
|
||||
width: 60px;
|
||||
height: 1rem;
|
||||
border: none;
|
||||
}
|
|
@ -6,6 +6,11 @@
|
|||
transition : 100ms ease-in;
|
||||
}
|
||||
|
||||
#page_search section>div>div>img {
|
||||
object-fit: cover;
|
||||
width : calc(65px - 1rem);
|
||||
}
|
||||
|
||||
/* #page_search nav > div, #page_search section > div:hover > div {
|
||||
height: 68px;
|
||||
border-right: 6px solid #e1e1ea;
|
||||
|
|
|
@ -15,7 +15,7 @@ function notification_last() {
|
|||
};
|
||||
|
||||
// Проверка уведомлений
|
||||
setInterval(notification_last, 5000);
|
||||
setInterval(notification_last, 10000);
|
||||
|
||||
function notification_popup_create(html, id) {
|
||||
// Инициализация
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
|
||||
function product_image_choose(key, wrap) {
|
||||
if (key !== undefined && key !== null && wrap !== undefined && wrap !== null) {
|
||||
// Инициализация
|
||||
let labels = wrap.getElementsByTagName('label');
|
||||
|
||||
for (let i = 0; i <= labels.length; i++) {
|
||||
// Перебор всех элементов label (обложки изображений)
|
||||
|
||||
// Инициализация
|
||||
let label = labels[i];
|
||||
|
||||
if (label.getAttribute('for') === 'product_slider_image_' + key) {
|
||||
label.classList.add('active');
|
||||
label.checked = 'true';
|
||||
} else {
|
||||
label.classList.remove('active');
|
||||
label.checked = 'false';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function product_response_success(data, status) {
|
||||
product_response(data, status);
|
||||
}
|
||||
|
|
|
@ -101,6 +101,76 @@ function product_panel_catn_save(catn, element, redirect = false) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function product_panel_dimensions_edit(catn, element, dimension) {
|
||||
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||
|
||||
let input = document.createElement('input');
|
||||
|
||||
input.setAttribute('id', element.id);
|
||||
input.setAttribute('class', 'ml-1 text-center product_options_edit_small');
|
||||
input.setAttribute('type', 'number');
|
||||
input.setAttribute('value', element.innerText);
|
||||
input.setAttribute('aria-invalid', 'false');
|
||||
|
||||
element.replaceWith(input);
|
||||
|
||||
product_panel_handler_save(product_panel_dimensions_save, catn, input, dimension);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function product_panel_dimensions_save(catn, element, dimension) {
|
||||
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||
// Инициализация
|
||||
let text = element.value;
|
||||
let span = document.createElement('span');
|
||||
|
||||
span.setAttribute('id', element.id);
|
||||
span.setAttribute('class', 'ml-1 pointer-event');
|
||||
span.setAttribute('role', 'button');
|
||||
span.setAttribute('onclick', 'return product_panel_dimensions_edit(\'' + catn + '\', this, \'' + dimension + '\');');
|
||||
|
||||
if (text.length === 0) {
|
||||
text = '0';
|
||||
}
|
||||
|
||||
span.innerText = text;
|
||||
|
||||
element.replaceWith(span);
|
||||
|
||||
$.ajax({
|
||||
url: '/product/' + catn + '/edit/dmns',
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'_csrf': yii.getCsrfToken(),
|
||||
'text': text,
|
||||
'dimension': dimension
|
||||
},
|
||||
success: function (data, status) {
|
||||
// Заголовок
|
||||
if (data.dimension !== undefined && span !== null && span !== undefined) {
|
||||
// Обновление заголовка
|
||||
span.innerText = data.dimension;
|
||||
|
||||
// Запись аттрибута
|
||||
span.setAttribute('onclick', 'return product_panel_dimensions_edit(\'' + catn + '\', this, \'' + dimension + '\');');
|
||||
};
|
||||
|
||||
product_response_success(data, status);
|
||||
},
|
||||
error: product_response_error
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function product_panel_description_edit(catn, element) {
|
||||
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||
element.innerHTML = '<textarea class="form-control" cols="50" rows="5" onchange = "return product_panel_description_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
|
||||
|
@ -125,7 +195,7 @@ function product_panel_description_save(catn, element) {
|
|||
element.setAttribute('onclick', 'return product_panel_description_edit(\'' + catn + '\', this);');
|
||||
|
||||
$.ajax({
|
||||
url: '/product/' + catn + '/edit/desc',
|
||||
url: '/product/' + catn + '/edit/dscr',
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
|
@ -179,3 +249,56 @@ function product_panel_images_write(catn, element) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
function product_panel_images_delete(catn, index) {
|
||||
if (catn !== null && catn !== undefined && index !== null && index !== undefined) {
|
||||
$.ajax({
|
||||
url: '/product/' + catn + '/delete/image',
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'_csrf': yii.getCsrfToken(),
|
||||
'index': index
|
||||
},
|
||||
success: product_response_success,
|
||||
error: product_response_error
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function product_panel_images_cover_write(catn, index) {
|
||||
if (catn !== null && catn !== undefined && index !== null && index !== undefined) {
|
||||
$.ajax({
|
||||
url: '/product/' + catn + '/write/cover',
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'_csrf': yii.getCsrfToken(),
|
||||
'index': index
|
||||
},
|
||||
success: product_response_success,
|
||||
error: product_response_error
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function product_panel_handler_save(save, catn, element, ...vars) {
|
||||
if (save !== undefined && save !== null) {
|
||||
let product_panel_handler_save_function = function (event) {
|
||||
if (event.target.id !== element.id) {
|
||||
save(catn, element, ...vars);
|
||||
document.body.removeEventListener('click', product_panel_handler_save_function, true);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.addEventListener('click', product_panel_handler_save_function, true);
|
||||
}
|
||||
}
|
Reference in New Issue