diff --git a/antgoods/.gitignore b/antgoods/.gitignore
new file mode 100755
index 0000000..4b9a47c
--- /dev/null
+++ b/antgoods/.gitignore
@@ -0,0 +1,2 @@
+cert
+runtime
diff --git a/antgoods/assets/AppAsset.php b/antgoods/assets/AppAsset.php
new file mode 100755
index 0000000..6a7b360
--- /dev/null
+++ b/antgoods/assets/AppAsset.php
@@ -0,0 +1,26 @@
+ 'antgoods',
+ 'basePath' => dirname(__DIR__),
+ 'controllerNamespace' => 'antgoods\controllers',
+ 'bootstrap' => ['log'],
+ 'defaultRoute' => '/category',
+ 'modules' => [
+ ],
+ 'components' => [
+ 'request' => [
+ 'parsers' => [
+ 'application/json' => 'yii\web\JsonParser',
+ ],
+ 'csrfParam' => '_csrf-api',
+ ],
+ 'user' => [
+ 'identityClass' => 'common\models\User',
+ 'enableAutoLogin' => true,
+ 'identityCookie' => ['name' => '_identity-antgoods', 'httpOnly' => true],
+ ],
+ 'session' => [
+ // this is the name of the session cookie used for login on the app
+ 'name' => 'antgoods',
+ ],
+ 'log' => [
+ 'traceLevel' => YII_DEBUG ? 3 : 0,
+ 'targets' => [
+ [
+ 'class' => 'yii\log\FileTarget',
+ 'levels' => ['error', 'warning'],
+ ],
+ [
+ 'class' => 'yii\log\FileTarget',
+ 'levels' => ['info', 'error'],
+ 'categories' => ['imagetest'],
+ 'logFile' => '@app/runtime/logs/imagetest.log',
+ 'logVars' => [],
+ 'exportInterval' => 1,
+ 'prefix' => function ($message) {
+ }
+ ],
+ ],
+ ],
+ 'errorHandler' => [
+ 'errorAction' => 'site/error',
+ ],
+ 'urlManager' => [
+ 'enablePrettyUrl' => true,
+ 'showScriptName' => false,
+ 'rules' => [
+ ],
+ ],
+ 'file' => ['class' => 'backend\logic\file\FileManager'],
+ ],
+ 'params' => $params,
+];
diff --git a/antgoods/config/params.php b/antgoods/config/params.php
new file mode 100755
index 0000000..7f754b9
--- /dev/null
+++ b/antgoods/config/params.php
@@ -0,0 +1,4 @@
+ 'admin@example.com',
+];
diff --git a/antgoods/controllers/AttributeController.php b/antgoods/controllers/AttributeController.php
new file mode 100644
index 0000000..18061b6
--- /dev/null
+++ b/antgoods/controllers/AttributeController.php
@@ -0,0 +1,170 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Attribute models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new AttributeSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single Attribute model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Attribute model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Attribute();
+ $model->sort_order = 0;
+ $model->cat_id = 0;
+
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+ $model->value = str_replace(',', ',', $model->value);
+ $array = explode(',', $model->value);
+ if (count($array) != count(array_unique($array))) {
+ \Yii::$app->getSession()->setFlash('error', '不能有相同的属性值');
+ return $this->render('create', ['model' => $model]);
+ }
+ if ($model->save()) {
+ return $this->redirect(['index']);
+ }
+ }
+
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing Attribute model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+ $model->value = str_replace(',', ',', $model->value);
+ $array = explode(',', $model->value);
+ if (count($array) != count(array_unique($array))) {
+ \Yii::$app->getSession()->setFlash('error', '不能有相同的属性值');
+ return $this->render('create', ['model' => $model]);
+ }
+ if ($model->save()) {
+ return $this->redirect(['index']);
+ }
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Deletes an existing Attribute model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+ $model->is_delete = Attribute::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Attribute model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Attribute the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Attribute::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new AttributeSearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Attributes'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+}
diff --git a/antgoods/controllers/BrandController.php b/antgoods/controllers/BrandController.php
new file mode 100644
index 0000000..af957b2
--- /dev/null
+++ b/antgoods/controllers/BrandController.php
@@ -0,0 +1,151 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Brand models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new BrandSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single Brand model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Brand model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Brand();
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect('index');
+ }
+
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing Brand model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Deletes an existing Brand model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+ $model->is_delete = Brand::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Brand model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Brand the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Brand::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new BrandSearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Brands'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+}
diff --git a/antgoods/controllers/CategoryController.php b/antgoods/controllers/CategoryController.php
new file mode 100644
index 0000000..fcc2366
--- /dev/null
+++ b/antgoods/controllers/CategoryController.php
@@ -0,0 +1,276 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ public function actions()
+ {
+ return [
+ 'upload' => [
+ 'class' => 'iron\actions\UploadAction',
+ 'path' => 'xls/',
+ 'maxSize' => 20480,
+ ]
+ ];
+ }
+
+ /**
+ * Lists all Category models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new CategorySearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single Category model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Category model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Category();
+ $model->is_show = Category::IS_SHOW_DISPLAY;
+ $model->sort_order = 0;
+
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+
+ //类目图片上传保存处理
+ $icon_image_id_str = $model->iconImageId;
+ $model->save();
+ $save_icon_image_res = GoodsManager::saveFile(explode(',', $icon_image_id_str), $model, [], File::OWN_TYPE_CATEGORY_ICON);
+ if($save_icon_image_res['status']){
+ $model->icon = $save_icon_image_res['first_file_id'];
+ $model->save();
+ }
+
+ return $this->redirect('index');
+ }
+
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing Category model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+ $model->iconImageId = $model->icon;
+ //记录已保存的类目图片id,用于修改
+ $icon_image_old_id_arr = $model->icon;
+
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+
+ //类目图片上传保存处理
+ $icon_image_id_str = $model->iconImageId;
+ $model->save();
+ $save_icon_image_res = GoodsManager::saveFile(explode(',', $icon_image_id_str), $model, explode(',', $icon_image_old_id_arr), File::OWN_TYPE_CATEGORY_ICON);
+ if($save_icon_image_res['status'] && $save_icon_image_res['first_file_id'] !== 0){
+ $model->icon = $save_icon_image_res['first_file_id'];
+ $model->save();
+ }
+
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Deletes an existing Category model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+
+ $model->is_delete = Category::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Category model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Category the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Category::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new CategorySearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Categories'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * 处理文件上传成功后回调保存到临时文件表中,并返回临时文件id
+ */
+ public function actionSaveFile()
+ {
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\backend\logic\file\FileManager')){
+ return '';
+ }
+
+ $data = Yii::$app->request->get('data');
+ $file_name = Yii::$app->request->get('fileName')[0];
+
+ if ($data['status'] == true) {
+ $model = new \common\models\ars\TemFile();
+ $model->user_id = Yii::$app->user->identity->id;
+ $model->name = $file_name;
+ $file_manager = new \backend\logic\file\FileManager();
+ $type_res = $file_manager->searchType(\backend\logic\file\FileManager::$extension, pathinfo($data['path'])['extension']);
+ if ($type_res['status']) {
+ $model->type = $type_res['type'];
+ }
+ $model->alias = $data['alias'];
+ $model->path = $data['path'];
+ $model->save();
+ return $model->id;
+ }
+ }
+
+ /**
+ * @return string
+ * 点击删除按钮时同时删除字符串中的id
+ */
+ public function actionImgIdDel()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\common\models\ars\File')){
+ return '';
+ }
+
+ $img_id = Yii::$app->request->get('imgid');
+ $img_id_arr = explode(',', $img_id);
+ if(isset(Yii::$app->request->get('data')['alias'])) {
+ $alias = Yii::$app->request->get('data')['alias'];
+ $tem_file = \common\models\ars\TemFile::findOne(['alias' => $alias]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }else{
+ foreach (Yii::$app->request->get() as $key => $value) {
+ $tem_file = \common\models\ars\File::findOne(['alias' => $value]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }
+ }
+ $img_id_str = implode(',', $img_id_arr);
+ return $img_id_str;
+ }
+
+ /**
+ * @return bool|false|string
+ * 加载已有的文件
+ */
+ public function actionImageFile()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\File')){
+ return false;
+ }
+
+ $file_id_str = Yii::$app->request->get('fileidstr');
+ $file_id_arr = explode(',', $file_id_str);
+ $data = \common\models\ars\File::find()->where(['id' => $file_id_arr])->all();
+ $res = array();
+ if($data) {
+ $i = 0;
+ foreach ($data as $key => $value) {
+ $res[$i]['name'] = $value->alias;
+ $res[$i]['path'] = Yii::$app->request->hostInfo . '/' . $value->path;
+ $res[$i]['size'] = filesize($value->path);
+ $i++;
+ }
+ }
+ return json_encode($res);
+ }
+}
diff --git a/antgoods/controllers/ConfigController.php b/antgoods/controllers/ConfigController.php
new file mode 100755
index 0000000..4ae8433
--- /dev/null
+++ b/antgoods/controllers/ConfigController.php
@@ -0,0 +1,76 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Category models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ return $this->render('index');
+ }
+
+
+ /**
+ * Updates an existing Category model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Finds the Category model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Category the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Category::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+}
diff --git a/antgoods/controllers/GoodsController.php b/antgoods/controllers/GoodsController.php
new file mode 100644
index 0000000..c2891cc
--- /dev/null
+++ b/antgoods/controllers/GoodsController.php
@@ -0,0 +1,359 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ public function actions()
+ {
+ return [
+ 'upload' => [
+ 'class' => 'iron\actions\UploadAction',
+ 'path' => 'xls/',
+ 'maxSize' => 20480,
+ ],
+ 'ueditor' => [
+ 'class' => 'common\widgets\ueditor\UeditorAction',
+ 'config' => [
+ //上传图片配置
+ 'imageUrlPrefix' => "", /* 图片访问路径前缀 */
+ 'imagePathFormat' => "/uploads/origin/introduce/" . md5(time() . rand(000, 999)), /* 上传保存路径,可以自定义保存路径和文件名格式 */
+ ]
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Goods models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new GoodsSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single Goods model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Goods model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Goods();
+ $model->is_sale = Goods::IS_SALE_YES;
+ $model->stock = -1;
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+ //商品封面图和商品详情图上传保存处理
+ $res = GoodsManager::updateGoods(Yii::$app->request->post(), $model);
+ if ($res['status']) {
+ return $this->redirect('index');
+ }
+ } else {
+ $model->ruleVerify = 1;
+ }
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing Goods model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+ $model->coverImageId = $model->image;
+ $model->detailImageId = implode(',', File::find()->select('id')->where(['is_delete' => File::IS_DELETE_NO, 'own_id' => $model->id, 'own_type' => File::OWN_TYPE_GOODS_DETAILS])->column());
+ //记录已保存的商品图片id,用于修改
+ $cover_image_old_id_str = $model->image;
+ $detail_image_old_id_str = $model->detailImageId;
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+ //商品封面图和商品详情图上传保存处理
+ $res = GoodsManager::updateGoods(Yii::$app->request->post(), $model, $cover_image_old_id_str, $detail_image_old_id_str);
+ if ($res['status']) {
+ return $this->redirect('index');
+ }
+ }
+ $attributeModel = GoodsManager::getAttribute($id);
+ $checkAttr = GoodsManager::getSkuInfo($id);
+ $filterAttributeModel = GoodsManager::getFilterAttribute($id);
+ $judgeGoodsCategory = GoodsManager::judgeGoodsCategory($model);
+ return $this->render('update', [
+ 'model' => $model,
+ 'attributeModel' => $attributeModel,
+ 'attrValue' => $checkAttr,
+ 'filterAttributeModel' => $filterAttributeModel,
+ 'judgeGoodsCategory' => $judgeGoodsCategory,
+ ]);
+ }
+
+ /**
+ * Deletes an existing Goods model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+ $model->is_delete = Goods::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Goods model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Goods the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Goods::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new GoodsSearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Goods'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * 处理文件上传成功后回调保存到临时文件表中,并返回临时文件id
+ */
+ public function actionSaveFile()
+ {
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\backend\logic\file\FileManager')){
+ return '';
+ }
+
+ $data = Yii::$app->request->get('data');
+ $file_name = Yii::$app->request->get('fileName')[0];
+
+ if ($data['status'] == true) {
+ $model = new \common\models\ars\TemFile();
+ $model->user_id = Yii::$app->user->identity->id;
+ $model->name = $file_name;
+ $file_manager = new \backend\logic\file\FileManager();
+ $type_res = $file_manager->searchType(\backend\logic\file\FileManager::$extension, pathinfo($data['path'])['extension']);
+ if ($type_res['status']) {
+ $model->type = $type_res['type'];
+ }
+ $model->alias = $data['alias'];
+ $model->path = $data['path'];
+ $model->save();
+ return $model->id;
+ }
+ }
+
+ /**
+ * @return string
+ * 点击删除按钮时同时删除字符串中的id
+ */
+ public function actionImgIdDel()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\common\models\ars\File')){
+ return '';
+ }
+
+ $img_id = Yii::$app->request->get('imgid');
+ $img_id_arr = explode(',', $img_id);
+ if(isset(Yii::$app->request->get('data')['alias'])) {
+ $alias = Yii::$app->request->get('data')['alias'];
+ $tem_file = \common\models\ars\TemFile::findOne(['alias' => $alias]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }else{
+ foreach (Yii::$app->request->get() as $key => $value) {
+ $tem_file = \common\models\ars\File::findOne(['alias' => $value]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }
+ }
+ $img_id_str = implode(',', $img_id_arr);
+ return $img_id_str;
+ }
+
+ /**
+ * @return bool|false|string
+ * 加载已有的文件
+ */
+ public function actionImageFile()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\File')){
+ return false;
+ }
+
+ $rule_verify = Yii::$app->request->get('ruleverify');
+ $file_id_str = Yii::$app->request->get('fileidstr');
+ $file_id_arr = explode(',', $file_id_str);
+ if ($rule_verify == 1) {
+ $data = \common\models\ars\TemFile::find()->where(['id' => $file_id_arr])->all();
+ } else {
+ $data = \common\models\ars\File::find()->where(['id' => $file_id_arr])->all();
+ }
+ $res = array();
+ if($data) {
+ $i = 0;
+ foreach ($data as $key => $value) {
+ $res[$i]['name'] = $value->alias;
+ $res[$i]['path'] = Yii::$app->request->hostInfo . '/' . $value->path;
+ $res[$i]['size'] = filesize($value->path);
+ $i++;
+ }
+ }
+ return json_encode($res);
+ }
+
+ /**
+ * @param $id
+ * @return string
+ * 商品编辑sku
+ */
+
+ public function actionEditSku($id)
+ {
+ $sku = GoodsManager::getCreatedSku($id);
+ $attributes = GoodsManager::getAttrs($id);
+ return $this->render('sku_edit', [
+ 'attributes' => $attributes,
+ 'sku' => $sku,]);
+ }
+
+ /**
+ * @return array
+ * @throws \Throwable
+ * 添加sku
+ */
+ public function actionAddSku()
+ {
+ $data = [];
+ Yii::$app->response->format = 'json';
+ $res = Yii::$app->request->post('sku');
+ $goodsId = Yii::$app->request->post('goodsId');
+ $tra = Yii::$app->db->beginTransaction();
+ try {
+ $data['originalIds'] = GoodsManager::getOriginalIds($res['type'], $goodsId);
+ $data['acceptIds'] = [];
+ foreach ($res['data'] as $sku) {
+ GoodsManager::AddOrUpdateData($sku, $res['type'], $goodsId);
+ if ($sku['id'] > 0) {
+ $data['acceptIds'][] = $sku['id'];
+ }
+ }
+ GoodsManager::deleteSku($res['type'], $data, $goodsId);
+ $tra->commit();
+ return ['status' => true];
+ } catch (\Exception $e) {
+ $tra->rollBack();
+ return ['status' => false, 'info' => $e->getMessage()];
+ }
+ }
+
+ public function actionSwitch()
+ {
+ Yii::$app->response->format = 'json';
+ $data = [];
+ $type = Yii::$app->request->get('type');
+ $id = Yii::$app->request->get('goodsId');
+ $data['sku'] = GoodsManager::getCreatedSku($id, $type);
+ $data['attributes'] = GoodsManager::getAttrs($id, $type);
+ return $data;
+ }
+
+ /**
+ * @return false|string
+ * 根据商品分类获取商品属性
+ */
+ public function actionFilterAttribute()
+ {
+ $catId = Yii::$app->request->get('catId')??0;
+ $goodsId = Yii::$app->request->get('goodsId')??0;
+ $allAttr = Attribute::find()->where(['type' => Attribute::TYPE_ATTR])->andWhere(['cat_id' => [0,$catId]])->asArray()->all();
+ return json_encode($allAttr);
+ }
+}
diff --git a/antgoods/controllers/ShopCategoryController.php b/antgoods/controllers/ShopCategoryController.php
new file mode 100644
index 0000000..3a32b55
--- /dev/null
+++ b/antgoods/controllers/ShopCategoryController.php
@@ -0,0 +1,287 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ public function actions()
+ {
+ return [
+ 'upload' => [
+ 'class' => 'iron\actions\UploadAction',
+ 'path' => 'xls/',
+ 'maxSize' => 20480,
+ ]
+ ];
+ }
+
+ /**
+ * Lists all ShopCategory models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new ShopCategorySearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single ShopCategory model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new ShopCategory model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new ShopCategory();
+ $model->is_show = ShopCategory::IS_SHOW_HIDE;
+ $model->sort_order = 0;
+
+ if ($model->load(Yii::$app->request->post())) {
+ if ($model->filter_attr != null && is_array($model->filter_attr)) {
+ $model->filter_attr = implode(',', $model->filter_attr);
+ } else {
+ $model->filter_attr = '';
+ }
+
+ //类目图片上传保存处理
+ $icon_image_id_str = $model->iconImageId;
+ $model->save();
+ $save_icon_image_res = GoodsManager::saveFile(explode(',', $icon_image_id_str), $model, [], File::OWN_TYPE_CATEGORY_ICON);
+ if($save_icon_image_res['status']){
+ $model->icon = $save_icon_image_res['first_file_id'];
+ $model->save();
+ }
+
+ return $this->redirect('index');
+ }
+
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing ShopCategory model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+ if ($model->filter_attr != null) {
+ $model->filter_attr = explode(',', $model->filter_attr);
+ }
+ $model->iconImageId = $model->icon;
+ $icon_image_old_id_arr = $model->icon;//记录已保存的类目图片id,用于修改
+
+ if ($model->load(Yii::$app->request->post())) {
+ if ($model->filter_attr != null && is_array($model->filter_attr)) {
+ $model->filter_attr = implode(',', $model->filter_attr);
+ } else {
+ $model->filter_attr = '';
+ }
+
+ //类目图片上传保存处理
+ $icon_image_id_str = $model->iconImageId;
+ $model->save();
+ $save_icon_image_res = GoodsManager::saveFile(explode(',', $icon_image_id_str), $model, explode(',', $icon_image_old_id_arr), File::OWN_TYPE_CATEGORY_ICON);
+ if($save_icon_image_res['status'] && $save_icon_image_res['first_file_id'] !== 0){
+ $model->icon = $save_icon_image_res['first_file_id'];
+ $model->save();
+ }
+
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Deletes an existing ShopCategory model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+ $model->is_delete = ShopCategory::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the ShopCategory model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return ShopCategory the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = ShopCategory::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new ShopCategorySearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Shop Categories'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * 处理文件上传成功后回调保存到临时文件表中,并返回临时文件id
+ */
+ public function actionSaveFile()
+ {
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\backend\logic\file\FileManager')){
+ return '';
+ }
+
+ $data = Yii::$app->request->get('data');
+ $file_name = Yii::$app->request->get('fileName')[0];
+
+ if ($data['status'] == true) {
+ $model = new \common\models\ars\TemFile();
+ $model->user_id = Yii::$app->user->identity->id;
+ $model->name = $file_name;
+ $file_manager = new \backend\logic\file\FileManager();
+ $type_res = $file_manager->searchType(\backend\logic\file\FileManager::$extension, pathinfo($data['path'])['extension']);
+ if ($type_res['status']) {
+ $model->type = $type_res['type'];
+ }
+ $model->alias = $data['alias'];
+ $model->path = $data['path'];
+ $model->save();
+ return $model->id;
+ }
+ }
+
+ /**
+ * @return string
+ * 点击删除按钮时同时删除字符串中的id
+ */
+ public function actionImgIdDel()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\TemFile') || !class_exists('\common\models\ars\File')){
+ return '';
+ }
+
+ $img_id = Yii::$app->request->get('imgid');
+ $img_id_arr = explode(',', $img_id);
+ if(isset(Yii::$app->request->get('data')['alias'])) {
+ $alias = Yii::$app->request->get('data')['alias'];
+ $tem_file = \common\models\ars\TemFile::findOne(['alias' => $alias]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }else{
+ foreach (Yii::$app->request->get() as $key => $value) {
+ $tem_file = \common\models\ars\File::findOne(['alias' => $value]);
+ if ($tem_file) {
+ $img_id_arr = array_diff($img_id_arr, [$tem_file->id]);
+ }
+ }
+ }
+ $img_id_str = implode(',', $img_id_arr);
+ return $img_id_str;
+ }
+
+ /**
+ * @return bool|false|string
+ * 加载已有的文件
+ */
+ public function actionImageFile()
+ {
+ //判断该类是否存在
+ if(!class_exists('\common\models\ars\File')){
+ return false;
+ }
+
+ $file_id_str = Yii::$app->request->get('fileidstr');
+ $file_id_arr = explode(',', $file_id_str);
+ $data = \common\models\ars\File::find()->where(['id' => $file_id_arr])->all();
+ $res = array();
+ if($data) {
+ $i = 0;
+ foreach ($data as $key => $value) {
+ $res[$i]['name'] = $value->alias;
+ $res[$i]['path'] = Yii::$app->request->hostInfo . '/' . $value->path;
+ $res[$i]['size'] = filesize($value->path);
+ $i++;
+ }
+ }
+ return json_encode($res);
+ }
+}
diff --git a/antgoods/controllers/SiteController.php b/antgoods/controllers/SiteController.php
new file mode 100755
index 0000000..155c9f8
--- /dev/null
+++ b/antgoods/controllers/SiteController.php
@@ -0,0 +1,112 @@
+ [
+ 'class' => AccessControl::className(),
+ 'rules' => [
+ [
+ 'actions' => ['login', 'error', 'test'],
+ 'allow' => true,
+ ],
+ [
+ 'actions' => ['logout', 'index'],
+ 'allow' => true,
+ 'roles' => ['@'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+// 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function actions() {
+ return [
+ 'error' => [
+ 'class' => 'yii\web\ErrorAction',
+ ],
+ 'upload'=>[
+ 'class'=>'iron\actions\UploadAction',
+ ]
+ ];
+ }
+
+ /**
+ * Displays homepage.
+ *
+ * @return string
+ */
+ public function actionIndex() {
+ return $this->render('index');
+ }
+
+ /**
+ * Login action.
+ *
+ * @return string
+ */
+ public function actionLogin() {
+
+ $this->layout = 'base';
+
+ if (!Yii::$app->user->isGuest) {
+ return $this->goHome();
+ }
+
+ $model = new LoginForm();
+ if ($model->load(Yii::$app->request->post()) && $model->login()) {
+ return $this->goBack();
+ } else {
+ $model->password = '';
+
+ return $this->render('login', [
+ 'model' => $model,
+ ]);
+ }
+ }
+
+ /**
+ * Logout action.
+ *
+ * @return string
+ */
+ public function actionLogout() {
+ Yii::$app->user->logout();
+
+ return $this->goHome();
+ }
+
+ public function actionTest() {
+ $searchModel = new CategorySearch();
+ return $this->render('test', [
+ 'name' => 'blobt',
+ 'model' => $searchModel
+ ]);
+ }
+
+}
diff --git a/antgoods/controllers/SupplierController.php b/antgoods/controllers/SupplierController.php
new file mode 100644
index 0000000..67c067b
--- /dev/null
+++ b/antgoods/controllers/SupplierController.php
@@ -0,0 +1,151 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['POST'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Supplier models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new SupplierSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+
+ /**
+ * Displays a single Supplier model.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Supplier model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Supplier();
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect('index');
+ }
+
+ return $this->render('create', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Updates an existing Supplier model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect('index');
+ }
+
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+
+ /**
+ * Deletes an existing Supplier model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ public function actionDelete($id)
+ {
+ $model = $this->findModel($id);
+ $model->is_delete = Supplier::IS_DELETE_YES;
+ $model->save();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Supplier model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Supplier the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Supplier::findOne($id)) !== null) {
+ return $model;
+ }
+
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ /**
+ * @author iron
+ * 文件导出
+ */
+ public function actionExport()
+ {
+ $searchModel = new SupplierSearch();
+ $params = Yii::$app->request->queryParams;
+ if ($params['page-type'] == 'all') {
+ $dataProvider = $searchModel->allData($params);
+ } else {
+ $dataProvider = $searchModel->search($params);
+ }
+ \iron\widget\Excel::export([
+ 'models' => $dataProvider->getModels(),
+ 'format' => 'Xlsx',
+ 'asAttachment' => true,
+ 'fileName' =>'Suppliers'. "-" .date('Y-m-d H/i/s', time()),
+ 'columns' => $searchModel->columns()
+ ]);
+ }
+}
diff --git a/antgoods/logic/goods/GoodsManager.php b/antgoods/logic/goods/GoodsManager.php
new file mode 100644
index 0000000..c9d134d
--- /dev/null
+++ b/antgoods/logic/goods/GoodsManager.php
@@ -0,0 +1,578 @@
+ false, 'info' => '操作失败'];
+ }
+
+ //需要新建的文件id
+ $createFileIdArr = array_diff($newFileIdArr, $oldFileIdArr);
+
+ //创建文件
+ $class = new \backend\logic\file\FileManager();
+ $createFileRes = $class->saveTemFileToFile($createFileIdArr, $goodsModel->id, $fileType);
+
+ //需要删除的文件id
+ $delFileIdArr = array_diff($oldFileIdArr, $newFileIdArr);
+
+ //删除文件
+ $class->deleteFile($delFileIdArr);
+
+ //记录第一张图片id
+ $firstFileId = 0;
+
+ //查看修改数组是否为空
+ if (!$newFileIdArr[0]) {
+ $firstFileId = null;
+ }else {
+ if ($createFileRes['status']) {
+ $firstFileId = $createFileRes['first_file_id'];
+ }
+ }
+
+ return ['status' => true, 'info' => '操作成功', 'first_file_id' => $firstFileId];
+ }
+
+ /**
+ * @param $data
+ * @param $model
+ * @param null $coverImageOldIdStr
+ * @param null $detailImageOldIdStr
+ * @return array
+ * @throws \Throwable
+ * 创建修改商品操作
+ */
+ public static function updateGoods($data, $model, $coverImageOldIdStr = null, $detailImageOldIdStr = null)
+ {
+ $attribute = $data['attribute'];
+ $filterAttribute = $data['filterattribute'];
+ $tra = Yii::$app->db->beginTransaction();
+ try {
+ if (!$model->save()) {
+ throw new Exception('');
+ }
+ $saveCoverImageRes = self::saveFile(explode(',', $model->coverImageId), $model, explode(',', $coverImageOldIdStr));
+ $saveDetailImageRes = self::saveFile(explode(',', $model->detailImageId), $model, explode(',', $detailImageOldIdStr), File::OWN_TYPE_GOODS_DETAILS);
+ if ($saveCoverImageRes['status'] && $saveDetailImageRes['status']) {
+ if($saveCoverImageRes['first_file_id'] !== 0) {
+ $model->image = $saveCoverImageRes['first_file_id'];
+ if (!$model->save()) {
+ throw new Exception('图片保存失败');
+ }
+ }
+ } else {
+ throw new Exception('图片保存失败');
+ }
+ self::addAttributeOperating(['id' => $model->id, 'attribute' => $attribute]);
+ self::addFilterAttributeOperating(['id' => $model->id, 'filterAttribute' => $filterAttribute]);
+ $tra->commit();
+ return ['status' => true];
+ } catch (\yii\base\Exception $e) {
+ $tra->rollBack();
+ return ['status' => false, 'info' => $e->getMessage()];
+ }
+ }
+
+ /**
+ * @param $data
+ * @return bool
+ * @throws Exception
+ * 创建修改商品属性操作
+ */
+ public static function addAttributeOperating($data)
+ {
+ if (!$data['attribute']) {
+ return true;
+ }
+ $data['attribute'] = json_decode($data['attribute'], true);
+ $oldAttr = [];
+ $goodsAttr = GoodsAttr::find()->where(['goods_id' => $data['id'], 'is_delete' => GoodsAttr::IS_DELETE_NO])->all();
+ if ($goodsAttr) { //如果商品有旧的属性
+ if(count($data['attribute']) == 0 && is_array($data['attribute'])) { //如果传上来的是空数组,删除该商品下的全部属性
+ self::delAttribute($goodsAttr);
+ return true;
+ }
+ foreach ($goodsAttr as $key => $value) { //把旧的商品属性保存到一个数组
+ $oldAttr[$value->id] = $value->attr_value;
+ }
+ }
+ $newAttr = self::addAttribute($data['attribute'], $data['id']); //添加新的商品属性
+ $delAttr = array_diff(array_keys($oldAttr), array_keys($newAttr)); //找出需要删除的goodsAttrId
+ if (!$delAttr) {
+ return true;
+ }
+ foreach ($delAttr as $value) {
+ $model = GoodsAttr::find()->where(['id' => $value, 'is_delete' => GoodsAttr::IS_DELETE_NO])->One();
+ if ($model) {
+ $model->is_delete = GoodsAttr::IS_DELETE_YES;
+ if (!$model->save()) {
+ throw new Exception('goodsAttribute delete false');
+ }
+ }
+ }
+ }
+
+ /**
+ * @param $goodsAttr
+ * @throws Exception
+ * 删除商品属性
+ */
+ public static function delAttribute($goodsAttr)
+ {
+ foreach ($goodsAttr as $key => $value) {
+ $value->is_delete = GoodsAttr::IS_DELETE_YES;
+ if (!$value->save()) {
+ throw new Exception('goods attribute delete false');
+ }
+ }
+ }
+
+ /**
+ * @param $attribute
+ * @param $goodsId
+ * @return array
+ * @throws Exception
+ * 保存商品属性
+ */
+ public static function addAttribute($attribute, $goodsId)
+ {
+ $newAttr = [];
+ if (!$attribute) {
+ return [];
+ }
+ foreach ($attribute as $value) {
+ foreach ($value['value'] as $k => $v) {
+ $goodsAttrModel = new GoodsAttr();
+ $goodsAttrModel->attr_id = $value['id'];
+ $attr = GoodsAttr::find()->where(['goods_id' => $goodsId, 'attr_id' => $value['id'], 'attr_value' => $v, 'is_delete' => GoodsAttr::IS_DELETE_NO])->one();
+ if ($attr) {
+ $newAttr[$attr->id] = $attr->attr_value; //原有的数据
+ } else {
+ $goodsAttrModel->goods_id = $goodsId;
+ $goodsAttrModel->attr_value = $v;
+ if (!$goodsAttrModel->save()) {
+ throw new Exception('goodsAttribute save false');
+ }
+ $newAttr[$goodsAttrModel->id] = $goodsAttrModel->attr_value; //新增的数据
+ }
+ }
+ }
+ return $newAttr;
+ }
+
+ /**
+ * @param $id
+ * @return Attribute|array|null
+ * 获取属性信息
+ */
+ public static function getAttribute($id)
+ {
+ $goodsAttributes = GoodsAttr::find()->where(['goods_id' => $id, 'is_delete' => GoodsAttr::IS_DELETE_NO])->andWhere(['!=', 'attr_id', 0])->all();
+ $filter = [];
+ $goodsAttributeModel = [];
+ if (!$goodsAttributes) {
+ return $goodsAttributeModel;
+ }
+ foreach ($goodsAttributes as $key => $value) {
+ $attribute = Attribute::findOne($value->attr_id);
+ if (!in_array($attribute->name, $filter)) {
+ $filter[] = $attribute->name;
+ $attribute = ['name' => $attribute->name, 'id' => $attribute->id, 'value' => [$value->attr_value]];
+ $goodsAttributeModel[] = $attribute;
+ } else {
+ foreach ($goodsAttributeModel as $k => $v) {
+ if ($v['name'] == $attribute->name) {
+ $goodsAttributeModel[$k]['value'][] = $value->attr_value;
+ }
+ }
+ }
+ }
+ return $goodsAttributeModel;
+ }
+
+ /**
+ * @param $id
+ * @return array
+ * 获取sku信息
+ */
+ public static function getSkuInfo($id)
+ {
+ $skus = GoodsSku::find()->where(['goods_id' => $id, 'is_delete' => GoodsSku::IS_DELETE_NO])->all();
+ $attrId = [];
+ foreach ($skus as $sku) {
+ $attrId = array_merge(explode(',', $sku->goods_attr), $attrId);
+ }
+ $attrs = GoodsAttr::find()->where(['id' => $attrId, 'is_delete' => GoodsAttr::IS_DELETE_NO])->andWhere(['!=', 'attr_id', 0])->all();
+ $checkAttr = [];
+ $filterAttr = [];
+ foreach ($attrs as $value) {
+ $attr = Attribute::findOne(['id' => $value->attr_id, 'is_delete' => Attribute::IS_DELETE_NO]);
+ if (!in_array($attr->name, $filterAttr)) {
+ $filterAttr[] = $attr->name;
+ $newAttr = ['id' => $attr->id, 'name' => $attr->name, 'value' => [$value->attr_value]];
+ $checkAttr[] = $newAttr;
+ } else {
+ foreach ($checkAttr as $key => $item) {
+ if ($item['name'] == $attr->name) { //如果attr_id与$filter的attr_id相符,入栈
+ $checkAttr[$key]['value'][] = $value->attr_value;
+ }
+ }
+ }
+ }
+ return $checkAttr;
+ }
+
+ /**
+ * @param $id
+ * @return mixed
+ * 已创建sku信息
+ */
+ public static function getCreatedSku($id, $type = 0)
+ {
+ $goods = Goods::findOne($id);
+ $data['type'] = $type ?: $goods->sku_mode;
+ $data['data'] = [];
+ if ($data['type'] == Goods::SKU_MODE_ATTR) {
+ $sku = GoodsSku::find()
+ ->where(['goods_id' => $id, 'is_manaul' => 0])
+ ->all();
+ } else {
+ $sku = GoodsSku::find()
+ ->where(['goods_id' => $id, 'is_manaul' => 1])
+ ->all();
+ }
+ foreach ($sku as $value) {
+ $data['data'][] = self::getAttrInfo($data['type'], $value);
+ }
+ return $data;
+ }
+
+ /**
+ * @param $type
+ * @param $sku
+ * @return array
+ * 获取商品详情
+ */
+ public static function getAttrInfo($type, $sku)
+ {
+ $data = [];
+ if ($type == Goods::SKU_MODE_ATTR) {
+ $data['value'] = array_filter(explode(',', $sku->goods_attr));
+ } else {
+ $attr = explode(',', $sku->goods_attr);
+ $goodsAttr = GoodsAttr::findOne($attr[0]);
+ $data['value'] = $goodsAttr->attr_value;
+ }
+ $data['id'] = $sku->id;
+ $data['price'] = $sku->price;
+ $data['stock'] = $sku->stock;
+ $data['weight'] = $sku->weight;
+ return $data;
+ }
+
+ /**
+ * @param $id
+ * @return array
+ * 获取商品属性
+ */
+ public static function getAttrs($id)
+ {
+ $attrId = GoodsAttr::find()->where(['goods_id' => $id, 'is_delete' => GoodsAttr::IS_DELETE_NO])
+ ->andWhere(['>', 'attr_id', 0])
+ ->select('attr_id')
+ ->distinct()
+ ->all();
+ $attributes = [];
+ foreach ($attrId as $v) {
+ $attribute = Attribute::findOne($v);
+ if ($attribute && $attribute->type == Attribute::TYPE_ATTR) {
+ $ret['name'] = $attribute->name;
+ $ret['id'] = $attribute->id;
+ $ret['attrValue'] = self::getAttrValue($attribute->id, $id);
+ $attributes[] = $ret;
+ }
+ }
+ return $attributes;
+ }
+
+ /**
+ * @param $attrId
+ * @param $goodsId
+ * @return GoodsAttr[]|GoodsSku[]|array|File[]|\common\models\ars\TemFile[]|\yii\db\ActiveRecord[]
+ * 获取属性值
+ */
+ public static function getAttrValue($attrId, $goodsId)
+ {
+ return GoodsAttr::find()
+ ->select(['id', 'attr_value'])
+ ->where(['goods_id' => $goodsId])
+ ->andWhere(['attr_id' => $attrId])
+ ->asArray()
+ ->all();
+ }
+
+ /**
+ * @param $type
+ * @param $goodsId
+ * @return array
+ * 获取已存储的商品sku的id
+ */
+ public static function getOriginalIds($type, $goodsId)
+ {
+ $ids = [];
+ if ($type == Goods::SKU_MODE_MANUAL) {
+ $query = GoodsSku::find()
+ ->where(['is_manaul' => 1]);
+ } else {
+ $query = GoodsSku::find()
+ ->where(['is_manaul' => 0]);
+ }
+ $sku = $query
+ ->andWhere(['goods_id' => $goodsId])
+ ->all();
+ foreach ($sku as $value) {
+ $ids[] = $value->id;
+ }
+ return $ids;
+ }
+
+ /**
+ * @param $sku
+ * @throws \yii\db\Exception
+ * 添加或更新sku数据
+ */
+ public static function AddOrUpdateData($sku, $type, $goodsId)
+ {
+ $goodsModel = Goods::findOne($goodsId);
+ if ($sku['id'] > 0) {
+ $goodsSku = GoodsSku::findOne($sku['id']);
+ $attrId = array_filter(explode(',', $goodsSku->goods_attr));
+ $attr = GoodsAttr::findOne($attrId[0]);
+ } else {
+ $goodsSku = new GoodsSku();
+ $attr = new GoodsAttr();
+ }
+ if (!$attr || !$goodsSku || !$goodsModel) {
+ throw new \yii\db\Exception('系统异常');
+ }
+ if ($type == Goods::SKU_MODE_MANUAL) {
+ $attr->attr_value = $sku['value'];
+ if (!$attr->save()) {
+ throw new \yii\db\Exception('手动属性修改失败');
+ }
+ $goodsSku->goods_attr = (string)$attr->id;
+ $goodsSku->is_manaul = 1;
+ } else {
+ $goodsSku->goods_attr = implode(',', array_filter($sku['value']));
+ }
+ $goodsSku->goods_id = $goodsId;
+ $goodsSku->price = $sku['price'];
+ $goodsSku->stock = $sku['stock'];
+ $goodsSku->weight = $sku['weight'];
+ $goodsSku->goods_sn = $goodsModel->sn;
+ if (!$goodsSku->save()) {
+ throw new \yii\db\Exception('保存失败,请检查是否有重复规格');
+ }
+ $goods = Goods::findOne($goodsId);
+ $goods->sku_mode = $type;
+ if (!$goods->save()) {
+ throw new \yii\db\Exception('商品sku类型修改失败');
+ }
+ }
+
+ /**
+ * @param $type
+ * @param $data
+ * @param $goodsId
+ * @return bool
+ * @throws \Throwable
+ * @throws \yii\db\StaleObjectException
+ * 删除sku
+ */
+ public static function deleteSku($type, $data, $goodsId)
+ {
+ if (!$data['originalIds']) {
+ return true;
+ }
+ if ($type == Goods::SKU_MODE_MANUAL) {
+ $query = GoodsSku::find()
+ ->where(['is_manaul' => 1]);
+ } else {
+ $query = GoodsSku::find()
+ ->where(['is_manaul' => 0]);
+ }
+ $sku = $query
+ ->andWhere(['goods_id' => $goodsId])
+ ->andWhere(['in', 'id', $data['originalIds']])
+ ->andWhere(['not in', 'id', $data['acceptIds']])
+ ->all();
+ foreach ($sku as $value) {
+ $value->delete();
+ }
+ }
+
+ /**
+ * @param $data
+ * @return bool
+ * @throws Exception
+ * 创建修改商品筛选属性操作
+ */
+ public static function addFilterAttributeOperating($data)
+ {
+ if (!$data['filterAttribute']) {
+ return true;
+ }
+ $data['filterAttribute'] = json_decode($data['filterAttribute'], true);
+ $oldFilterAttr = [];
+ $goodsFilterAttr = FilterAttr::find()->where(['goods_id' => $data['id'], 'is_delete' => FilterAttr::IS_DELETE_NO])->all();
+ if ($goodsFilterAttr) { //如果商品有旧的属性
+ if(count($data['filterAttribute']) == 0 && is_array($data['filterAttribute'])) { //如果传上来的是空数组,删除该商品下的全部属性
+ self::delFilterAttribute($goodsFilterAttr);
+ return true;
+ }
+ foreach ($goodsFilterAttr as $key => $value) { //把旧的商品属性保存到一个数组
+ $oldFilterAttr[$value->id] = $value->attr_value;
+ }
+ }
+ $newAttr = self::addFilterAttribute($data['filterAttribute'], $data['id']); //添加新的商品属性
+ $delAttr = array_diff(array_keys($oldFilterAttr), array_keys($newAttr)); //找出需要删除的goodsAttrId
+ if (!$delAttr) {
+ return true;
+ }
+ foreach ($delAttr as $value) {
+ $model = FilterAttr::find()->where(['id' => $value, 'is_delete' => FilterAttr::IS_DELETE_NO])->One();
+ if ($model) {
+ $model->is_delete = FilterAttr::IS_DELETE_YES;
+ if (!$model->save()) {
+ throw new Exception('goodsAttribute delete false');
+ }
+ }
+ }
+ }
+
+ /**
+ * @param $goodsFilterAttr
+ * @throws Exception
+ * 删除商品筛选属性
+ */
+ public static function delFilterAttribute($goodsFilterAttr)
+ {
+ foreach ($goodsFilterAttr as $key => $value) {
+ $value->is_delete = FilterAttr::IS_DELETE_YES;
+ if (!$value->save()) {
+ throw new Exception('goods attribute delete false');
+ }
+ }
+ }
+
+ /**
+ * @param $attribute
+ * @param $goodsId
+ * @return array
+ * @throws Exception
+ * 保存商品筛选属性
+ */
+ public static function addFilterAttribute($attribute, $goodsId)
+ {
+ $newAttr = [];
+ if (!$attribute) {
+ return [];
+ }
+ foreach ($attribute as $value) {
+ foreach ($value['value'] as $k => $v) {
+ $goodsFilterAttrModel = new FilterAttr();
+ $goodsFilterAttrModel->attr_id = $value['id'];
+ $attr = FilterAttr::find()->where(['goods_id' => $goodsId, 'attr_id' => $value['id'], 'attr_value' => $v, 'is_delete' => FilterAttr::IS_DELETE_NO])->one();
+ if ($attr) {
+ $newAttr[$attr->id] = $attr->attr_value; //原有的数据
+ } else {
+ $goodsFilterAttrModel->goods_id = $goodsId;
+ $goodsFilterAttrModel->attr_value = $v;
+ if (!$goodsFilterAttrModel->save()) {
+ throw new Exception('goodsAttribute save false');
+ }
+ $newAttr[$goodsFilterAttrModel->id] = $goodsFilterAttrModel->attr_value; //新增的数据
+ }
+ }
+ }
+ return $newAttr;
+ }
+
+ /**
+ * @param $id
+ * @return Attribute|array|null
+ * 获取筛选属性信息
+ */
+ public static function getFilterAttribute($id)
+ {
+ $goodsFilterAttributes = FilterAttr::find()->where(['goods_id' => $id, 'is_delete' => FilterAttr::IS_DELETE_NO])->andWhere(['!=', 'attr_id', 0])->all();
+ $filter = [];
+ $goodsFilterAttributeModel = [];
+ if (!$goodsFilterAttributes) {
+ return $goodsFilterAttributeModel;
+ }
+ foreach ($goodsFilterAttributes as $key => $value) {
+ $attribute = Attribute::findOne($value->attr_id);
+ if (!in_array($attribute->name, $filter)) {
+ $filter[] = $attribute->name;
+ $attribute = ['name' => $attribute->name, 'id' => $attribute->id, 'value' => [$value->attr_value]];
+ $goodsFilterAttributeModel[] = $attribute;
+ } else {
+ foreach ($goodsFilterAttributeModel as $k => $v) {
+ if ($v['name'] == $attribute->name) {
+ $goodsFilterAttributeModel[$k]['value'][] = $value->attr_value;
+ }
+ }
+ }
+ }
+ return $goodsFilterAttributeModel;
+ }
+
+ /**
+ * @param $goodsModel
+ * @return bool
+ *
+ */
+ public static function judgeGoodsCategory($goodsModel)
+ {
+ $skus = GoodsSku::find()->where(['goods_id' => $goodsModel->id, 'is_delete' => GoodsSku::IS_DELETE_NO])->all();
+ $attrId = [];
+ foreach ($skus as $sku) {
+ $attrId = array_merge(explode(',', $sku->goods_attr), $attrId);
+ }
+ $goodsAttr = array_unique(GoodsAttr::find()->select(['attr_id'])->where(['id' => $attrId, 'is_delete' => GoodsAttr::IS_DELETE_NO])->andWhere(['!=', 'attr_id', 0])->column());
+ $attrArr = array_unique(Attribute::find()->select(['cat_id'])->where(['is_delete' => Attribute::IS_DELETE_NO, 'id' => $goodsAttr])->column());
+ if (in_array($goodsModel->cat_id, $attrArr)) {
+ return true; //存在,则返回true,表示后台分类不得修改
+ }
+ return false; //否则返回false,表示后台分类可以修改
+ }
+
+ public static function categoryBtreeList()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/antgoods/models/.gitkeep b/antgoods/models/.gitkeep
new file mode 100755
index 0000000..72e8ffc
--- /dev/null
+++ b/antgoods/models/.gitkeep
@@ -0,0 +1 @@
+*
diff --git a/antgoods/models/ars/Attribute.php b/antgoods/models/ars/Attribute.php
new file mode 100644
index 0000000..0b077d7
--- /dev/null
+++ b/antgoods/models/ars/Attribute.php
@@ -0,0 +1,111 @@
+ 50],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'name' => '规格名称',
+ 'value' => '规格内容(每项以逗号隔开)',
+ 'type' => '类型',
+ 'sort_order' => '排序',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ 'cat_id' => '后台商品分类',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * 数据键值对
+ */
+ public static function modelColumn()
+ {
+ return $column = self::find()->select(['name'])->where(['is_delete' => self::IS_DELETE_NO])->indexBy('id')->column();
+ }
+
+ public function beforeSave($insert)
+ {
+ if(!$this->type){
+ $this->type = self::TYPE_ATTR;
+ }
+ return parent::beforeSave($insert); // TODO: Change the autogenerated stub
+ }
+
+ public function getCategory()
+ {
+ return $this->hasOne(Category::className(), ['id' => 'cat_id']);
+ }
+}
diff --git a/antgoods/models/ars/Brand.php b/antgoods/models/ars/Brand.php
new file mode 100644
index 0000000..09ef7c3
--- /dev/null
+++ b/antgoods/models/ars/Brand.php
@@ -0,0 +1,82 @@
+ 50],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'name' => '品牌名',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ public static function modelColumn()
+ {
+ return $column = self::find()->select(['name'])->where(['is_delete' => self::IS_DELETE_NO])->indexBy('id')->column();
+ }
+}
diff --git a/antgoods/models/ars/Category.php b/antgoods/models/ars/Category.php
new file mode 100644
index 0000000..181da3e
--- /dev/null
+++ b/antgoods/models/ars/Category.php
@@ -0,0 +1,114 @@
+ '显示',
+ self::IS_SHOW_HIDE => '隐藏'
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'antgoods_category';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['name'], 'required'],
+ [['pid', 'goods_count', 'sort_order', 'is_show', 'is_delete', 'icon'], 'integer'],
+ [['name'], 'string', 'max' => 60],
+ [['iconImageId'], 'string'],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'name' => '类别名称',
+ 'pid' => '父级',
+ 'goods_count' => '商品数量',
+ 'sort_order' => '排序',
+ 'icon' => '图标',
+ 'is_show' => '是否显示',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * 数据键值对
+ */
+ public static function modelColumn()
+ {
+ return $column = self::find()->select(['name'])->where(['is_delete' => self::IS_DELETE_NO])->indexBy('id')->column();
+ }
+
+ public function getIconFile()
+ {
+ return $this->hasOne(File::className(), ['id' => 'icon']);
+ }
+}
diff --git a/antgoods/models/ars/FilterAttr.php b/antgoods/models/ars/FilterAttr.php
new file mode 100644
index 0000000..c6b8aa2
--- /dev/null
+++ b/antgoods/models/ars/FilterAttr.php
@@ -0,0 +1,81 @@
+ 50],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'goods_id' => '商品id',
+ 'attr_id' => '属性id',
+ 'attr_value' => '属性值',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+}
diff --git a/antgoods/models/ars/Goods.php b/antgoods/models/ars/Goods.php
new file mode 100644
index 0000000..ebc748e
--- /dev/null
+++ b/antgoods/models/ars/Goods.php
@@ -0,0 +1,232 @@
+ '不在售',
+ self::IS_SALE_YES => '在售'
+ ];
+ public $ruleVerify = 0;//规则验证是否通过
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'antgoods_goods';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['pid', 'cat_id', 'brand_id', 'shop_cat_id', 'supplier_id', 'weight', 'length', 'width', 'height', 'diameter', 'sold_count', 'limit_count', 'stock', 'stock_warn', 'market_price', 'price', 'image', 'model_id', 'is_sale', 'sort_order', 'bouns_points', 'experience_points', 'is_delete', 'express_template', 'sku_mode'], 'integer'],
+ [['cat_id', 'brand_id', 'shop_cat_id', 'name'], 'required'],
+ [['sn'], 'checkExist'],
+ [['description', 'coverImageId', 'detailImageId'], 'string'],
+ [['name'], 'string', 'max' => 120],
+ [['sn'], 'string', 'max' => 60],
+ [['code'], 'string', 'max' => 50],
+ [['unit'], 'string', 'max' => 16],
+ [['brief'], 'string', 'max' => 255],
+ [['weight', 'length', 'width', 'height', 'diameter', 'sold_count', 'market_price', 'price'], 'checkNegative'],
+ ];
+ }
+
+ /**
+ * @param $attribute
+ * @param $params
+ * 验证是否为负数
+ */
+ public function checkNegative($attribute, $params)
+ {
+ if ($this->$attribute < 0) {
+ $this->addError($attribute, "不得为负数");
+ }
+ }
+
+ /**
+ * @param $attribute
+ * @param $params
+ * 验证商品编号唯一
+ */
+ public function checkExist($attribute, $params)
+ {
+ $goods = self::find()->where([$attribute => $this->$attribute, 'is_delete' => 0])->one();
+ if ($this->isNewRecord) {
+ if ($goods) {
+ $this->addError($attribute, "该商品编号已经存在");
+ }
+ } else {
+ if ($goods && $goods->id != $this->id) {
+ $this->addError($attribute, "该商品编号已经存在");
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'pid' => '父级id',
+ 'cat_id' => '后台商品类别',
+ 'brand_id' => '品牌',
+ 'shop_cat_id' => '前端商品类别',
+ 'name' => '商品名称',
+ 'sn' => '商品唯一货号',
+ 'code' => '商品货码',
+ 'supplier_id' => '供应商',
+ 'weight' => '重量',
+ 'length' => '长度',
+ 'width' => '宽度',
+ 'height' => '高度',
+ 'diameter' => '直径',
+ 'unit' => '单位',
+ 'sold_count' => '已售数量',
+ 'limit_count' => '限购数量',
+ 'stock' => '库存',
+ 'stock_warn' => '库存警告',
+ 'market_price' => '市场价',
+ 'price' => '销售价',
+ 'brief' => '简介',
+ 'description' => '详细介绍',
+ 'image' => '首页图片',
+ 'model_id' => '模型id',
+ 'is_sale' => '销售状态',
+ 'sort_order' => '排序',
+ 'bouns_points' => '奖励积分',
+ 'experience_points' => '经验值',
+ 'is_delete' => '是否删除,1为已删除',
+ 'express_template' => '配送详情id',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @param bool $insert
+ * @return bool
+ * 自动填入参数
+ */
+ public function beforeSave($insert)
+ {
+ if (!$this->sn) {
+ $this->sn = time() . rand(1111, 9999);
+ }
+ return parent::beforeSave($insert); // TODO: Change the autogenerated stub
+ }
+
+ public function getCategory()
+ {
+ return $this->hasOne(Category::className(), ['id' => 'cat_id']);
+ }
+
+ public function getShopCategory()
+ {
+ return $this->hasOne(ShopCategory::className(), ['id' => 'shop_cat_id']);
+ }
+
+ public function getImageFile()
+ {
+ return $this->hasOne(File::className(), ['id' => 'image']);
+ }
+
+ public function getBrand()
+ {
+ return $this->hasOne(Brand::className(), ['id' => 'brand_id']);
+ }
+
+ public function getSupplier()
+ {
+ return $this->hasOne(Supplier::className(), ['id' => 'supplier_id']);
+ }
+}
diff --git a/antgoods/models/ars/GoodsAttr.php b/antgoods/models/ars/GoodsAttr.php
new file mode 100644
index 0000000..4cb2495
--- /dev/null
+++ b/antgoods/models/ars/GoodsAttr.php
@@ -0,0 +1,81 @@
+ 50],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'goods_id' => '商品id',
+ 'attr_id' => '属性id',
+ 'attr_value' => '属性名',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+}
diff --git a/antgoods/models/ars/GoodsSku.php b/antgoods/models/ars/GoodsSku.php
new file mode 100644
index 0000000..45e729a
--- /dev/null
+++ b/antgoods/models/ars/GoodsSku.php
@@ -0,0 +1,102 @@
+ 50],
+ [['goods_sn', 'goods_attr'], 'string', 'max' => 60],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'goods_id' => '商品id',
+ 'goods_code' => '商品条码',
+ 'goods_sn' => '商品唯一货号',
+ 'goods_attr' => '属性匹配',
+ 'sold_count' => '已售数量',
+ 'stock' => '库存',
+ 'market_price' => '市场价',
+ 'price' => '销售价',
+ 'model_id' => '模型id',
+ 'is_sale' => '该商品是否开放销售,1为是,0为否',
+ 'sort_order' => '排序',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+}
diff --git a/antgoods/models/ars/ShopCategory.php b/antgoods/models/ars/ShopCategory.php
new file mode 100644
index 0000000..1212ec2
--- /dev/null
+++ b/antgoods/models/ars/ShopCategory.php
@@ -0,0 +1,122 @@
+ '显示',
+ self::IS_SHOW_HIDE => '隐藏'
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'antgoods_shop_category';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['name'], 'required'],
+ [['pid', 'goods_count', 'sort_order', 'icon', 'is_show', 'is_delete', 'iconImageId'], 'integer'],
+ [['filter_attr'], 'safe'],
+ [['name'], 'string', 'max' => 60],
+ [['keywords'], 'string', 'max' => 100],
+ [['desc'], 'string', 'max' => 255],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'name' => '类别名称',
+ 'pid' => '父级',
+ 'goods_count' => '商品数量',
+ 'keywords' => '关键字',
+ 'desc' => '描述',
+ 'sort_order' => '排序',
+ 'icon' => '图标',
+ 'filter_attr' => '筛选属性',
+ 'is_show' => '是否显示',
+ 'is_delete' => '是否删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * 数据键值对
+ */
+ public static function modelColumn()
+ {
+ return $column = self::find()->select(['name'])->where(['is_delete' => self::IS_DELETE_NO])->indexBy('id')->column();
+ }
+
+ public function getIconFile()
+ {
+ return $this->hasOne(File::className(), ['id' => 'icon']);
+ }
+}
diff --git a/antgoods/models/ars/Supplier.php b/antgoods/models/ars/Supplier.php
new file mode 100644
index 0000000..31bc64d
--- /dev/null
+++ b/antgoods/models/ars/Supplier.php
@@ -0,0 +1,96 @@
+ 50],
+ [['phone'], 'string', 'max' => 20],
+ ['phone', 'filter', 'filter' => 'trim'],
+ ['phone','match','pattern'=>'/^[1][34578][0-9]{9}$/'],
+ ['phone', 'unique', 'targetClass' => '\antgoods\models\ars\Supplier', 'message' => '手机号已被使用'],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'id',
+ 'name' => '供应商名称',
+ 'full_name' => '供应商全称',
+ 'phone' => '手机号码',
+ 'address' => '地址',
+ 'is_delete' => '是否删除,1为已删除',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ];
+ }
+
+
+ /**
+ * @author linyao
+ * @email 602604991@qq.com
+ * @created Nov 8, 2019
+ *
+ * 行为存储创建时间和更新时间
+ */
+ public function behaviors()
+ {
+ return [
+ [
+ 'class' => TimestampBehavior::className(),
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => function() {
+ return time();
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * 数据键值对
+ */
+ public static function modelColumn()
+ {
+ return $column = self::find()->select(['name'])->where(['is_delete' => self::IS_DELETE_NO])->indexBy('id')->column();
+ }
+}
diff --git a/antgoods/models/searchs/AttributeSearch.php b/antgoods/models/searchs/AttributeSearch.php
new file mode 100644
index 0000000..dc97a43
--- /dev/null
+++ b/antgoods/models/searchs/AttributeSearch.php
@@ -0,0 +1,162 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ 'name',
+ 'value',
+ 'sort_order',
+ ['attribute' => 'cat_id',
+ 'value' => function ($model){
+ return $model->cat_id ? $model->category->name : '无限制';
+ },
+ ],
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ 'config' => [
+ [
+ 'name' => 'update',
+ 'icon' => 'pencil',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ],
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = Attribute::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = Attribute::find()->where(['is_delete' => Attribute::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ $query->andFilterWhere(['is_delete' => Attribute::IS_DELETE_NO]);
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'type' => $this->type,
+ 'sort_order' => $this->sort_order,
+ 'is_delete' => $this->is_delete,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name])
+ ->andFilterWhere(['like', 'value', $this->value]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/models/searchs/BrandSearch.php b/antgoods/models/searchs/BrandSearch.php
new file mode 100644
index 0000000..a91ad40
--- /dev/null
+++ b/antgoods/models/searchs/BrandSearch.php
@@ -0,0 +1,152 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ 'name',
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ 'config' => [
+ [
+ 'name' => 'update',
+ 'icon' => 'pencil',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ],
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = Brand::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = Brand::find()->where(['is_delete' => Brand::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ $query->andFilterWhere(['is_delete' => Brand::IS_DELETE_NO]);
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'is_delete' => $this->is_delete,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/models/searchs/CategorySearch.php b/antgoods/models/searchs/CategorySearch.php
new file mode 100644
index 0000000..1a0f1a1
--- /dev/null
+++ b/antgoods/models/searchs/CategorySearch.php
@@ -0,0 +1,172 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ 'name',
+ ['attribute' => 'icon',
+ 'contentOptions' => [
+ 'align' => 'center',
+ ],
+ 'width'=>'10%',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return $model->iconFile ?
+ Html::img(['/'.$model->iconFile->path], ['style' => 'width:80px'])
+ : '
未设置
';
+
+ }
+ ],
+ 'sort_order',
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ 'config' => [
+ [
+ 'name' => 'update',
+ 'icon' => 'pencil',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ],
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = Category::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = Category::find()->where(['is_delete' => Category::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ $query->andFilterWhere(['is_delete' => Category::IS_DELETE_NO]);
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'pid' => $this->pid,
+ 'goods_count' => $this->goods_count,
+ 'sort_order' => $this->sort_order,
+ 'is_show' => $this->is_show,
+ 'is_delete' => $this->is_delete,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ 'icon' => $this->icon,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/models/searchs/GoodsSearch.php b/antgoods/models/searchs/GoodsSearch.php
new file mode 100644
index 0000000..4e9797a
--- /dev/null
+++ b/antgoods/models/searchs/GoodsSearch.php
@@ -0,0 +1,241 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ ['attribute' => 'image',
+ 'contentOptions' => [
+ 'align' => 'center',
+ ],
+ 'width'=>'10%',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return $model->image ?
+ Html::img(['/'.$model->imageFile->path], ['style' => 'width:80px'])
+ : '未设置
';
+
+ }
+ ],
+ 'name',
+ [
+ 'attribute' => 'cat_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->category ? $model->category->name : '';
+ },
+ ],
+ [
+ 'attribute' => 'shop_cat_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->shopCategory ? $model->shopCategory->name : '';
+ },
+ ],
+ [
+ 'attribute' => 'stock',
+ 'width' => '5%',
+ 'value' => function ($model) {
+ if ($model->stock == -1) {
+ return '未开启';
+ } else {
+ return $model->stock;
+ }
+ },
+ ],
+ 'price',
+ ['attribute' => 'is_sale',
+ 'width' => '5%',
+ 'value' =>
+ function ($model) {
+ return $model->is_sale==Goods::IS_SALE_YES ? '在售' : '不在售';
+
+ },
+ ],
+ 'updated_at:datetime',
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ 'config' => [
+ [
+ 'name' => 'view',
+ 'icon' => 'list',
+ 'title' => '详情',
+ ],
+ [
+ 'name' => 'update',
+ 'icon' => 'pencil',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'edit-sku',
+ 'icon' => 'hard-drive',
+ 'title' => '商品sku'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ],
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = Goods::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = Goods::find()->where(['is_delete' => Goods::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ $query->andFilterWhere(['is_delete' => Goods::IS_DELETE_NO]);
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'pid' => $this->pid,
+ 'cat_id' => $this->cat_id,
+ 'brand_id' => $this->brand_id,
+ 'shop_cat_id' => $this->shop_cat_id,
+ 'supplier_id' => $this->supplier_id,
+ 'weight' => $this->weight,
+ 'length' => $this->length,
+ 'width' => $this->width,
+ 'height' => $this->height,
+ 'diameter' => $this->diameter,
+ 'sold_count' => $this->sold_count,
+ 'limit_count' => $this->limit_count,
+ 'stock' => $this->stock,
+ 'stock_warn' => $this->stock_warn,
+ 'market_price' => $this->market_price,
+ 'price' => $this->price,
+ 'image' => $this->image,
+ 'model_id' => $this->model_id,
+ 'is_sale' => $this->is_sale,
+ 'sort_order' => $this->sort_order,
+ 'bouns_points' => $this->bouns_points,
+ 'experience_points' => $this->experience_points,
+ 'is_delete' => $this->is_delete,
+ 'express_template' => $this->express_template,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name])
+ ->andFilterWhere(['like', 'sn', $this->sn])
+ ->andFilterWhere(['like', 'code', $this->code])
+ ->andFilterWhere(['like', 'unit', $this->unit])
+ ->andFilterWhere(['like', 'brief', $this->brief])
+ ->andFilterWhere(['like', 'description', $this->description]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/models/searchs/ShopCategorySearch.php b/antgoods/models/searchs/ShopCategorySearch.php
new file mode 100644
index 0000000..6cbd842
--- /dev/null
+++ b/antgoods/models/searchs/ShopCategorySearch.php
@@ -0,0 +1,162 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ 'name',
+ ['attribute' => 'icon',
+ 'contentOptions' => [
+ 'align' => 'center',
+ ],
+ 'width'=>'10%',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return $model->iconFile ?
+ Html::img(['/'.$model->iconFile->path], ['style' => 'width:80px'])
+ : '未设置
';
+
+ }
+ ],
+ 'sort_order',
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = ShopCategory::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = ShopCategory::find()
+ ->where(['is_delete' => ShopCategory::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'pid' => $this->pid,
+ 'goods_count' => $this->goods_count,
+ 'sort_order' => $this->sort_order,
+ 'icon' => $this->icon,
+ 'is_show' => $this->is_show,
+ 'is_delete' => $this->is_delete,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name])
+ ->andFilterWhere(['like', 'keywords', $this->keywords])
+ ->andFilterWhere(['like', 'desc', $this->desc])
+ ->andFilterWhere(['like', 'filter_attr', $this->filter_attr]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/models/searchs/SupplierSearch.php b/antgoods/models/searchs/SupplierSearch.php
new file mode 100644
index 0000000..1d70164
--- /dev/null
+++ b/antgoods/models/searchs/SupplierSearch.php
@@ -0,0 +1,161 @@
+ 'blobt\grid\CheckboxColumn',
+ 'width' => '2%',
+ 'align' => 'center'
+ ],
+ 'id',
+ 'name',
+ 'full_name',
+ 'phone',
+ 'address',
+ //'is_delete',
+ //'created_at',
+ //'updated_at',
+ [
+ 'class' => 'iron\grid\ActionColumn',
+ 'align' => 'center',
+ 'config' => [
+ [
+ 'name' => 'update',
+ 'icon' => 'pencil',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ],
+ ],
+ ];
+ }
+ /**
+ * @param $params
+ * @return ActiveDataProvider
+ * 不分页的所有数据
+ */
+ public function allData($params)
+ {
+ $query = Supplier::find();
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => false,
+ 'sort' => false
+ ]);
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+
+ /**
+ * Creates data provider instance with search query applied
+ *
+ * @param array $params
+ *
+ * @return ActiveDataProvider
+ */
+ public function search($params)
+ {
+ $query = Supplier::find()->where(['is_delete' => Supplier::IS_DELETE_NO]);
+
+ // add conditions that should always apply here
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => $query,
+ 'pagination' => [
+ 'pageSizeLimit' => [1, 200]
+ ],
+ 'sort' => [
+ 'defaultOrder' => [
+ 'id' => SORT_DESC,
+ ]
+ ],
+ ]);
+
+ $this->load($params);
+ return $this->filter($query, $dataProvider);
+ }
+ /**
+ * @param $query
+ * @param $dataProvider
+ * @return ActiveDataProvider
+ * 条件筛选
+ */
+ private function filter($query, $dataProvider){
+ $query->andFilterWhere(['is_delete' => Supplier::IS_DELETE_NO]);
+ if (!$this->validate()) {
+ // uncomment the following line if you do not want to return any records when validation fails
+ // $query->where('0=1');
+ return $dataProvider;
+ }
+
+ // grid filtering conditions
+ $query->andFilterWhere([
+ 'id' => $this->id,
+ 'is_delete' => $this->is_delete,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'name', $this->name])
+ ->andFilterWhere(['like', 'full_name', $this->full_name])
+ ->andFilterWhere(['like', 'phone', $this->phone])
+ ->andFilterWhere(['like', 'address', $this->address]);
+ if ($this->created_at_range) {
+ $arr = explode(' ~ ', $this->created_at_range);
+ $start = strtotime($arr[0]);
+ $end = strtotime($arr[1]) + 3600 * 24;
+ $query->andFilterWhere(['between', 'created_at', $start, $end]);
+ }
+ return $dataProvider;
+ }
+}
diff --git a/antgoods/views/attribute/_form.php b/antgoods/views/attribute/_form.php
new file mode 100644
index 0000000..da40e0e
--- /dev/null
+++ b/antgoods/views/attribute/_form.php
@@ -0,0 +1,32 @@
+
+
+
diff --git a/antgoods/views/attribute/_search.php b/antgoods/views/attribute/_search.php
new file mode 100644
index 0000000..0a9d3be
--- /dev/null
+++ b/antgoods/views/attribute/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/attribute/create.php b/antgoods/views/attribute/create.php
new file mode 100644
index 0000000..2192559
--- /dev/null
+++ b/antgoods/views/attribute/create.php
@@ -0,0 +1,18 @@
+title = '创建规格';
+$this->params['breadcrumbs'][] = ['label' => '规格管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/attribute/index.php b/antgoods/views/attribute/index.php
new file mode 100644
index 0000000..b147a9f
--- /dev/null
+++ b/antgoods/views/attribute/index.php
@@ -0,0 +1,28 @@
+title = '规格管理';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "attribute/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/attribute/update.php b/antgoods/views/attribute/update.php
new file mode 100644
index 0000000..d21423f
--- /dev/null
+++ b/antgoods/views/attribute/update.php
@@ -0,0 +1,19 @@
+title = '编辑规格: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '规格管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = 'Update ';
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/attribute/view.php b/antgoods/views/attribute/view.php
new file mode 100644
index 0000000..9475eb3
--- /dev/null
+++ b/antgoods/views/attribute/view.php
@@ -0,0 +1,33 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '规格管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'value:ntext',
+ 'type',
+ 'sort_order',
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/views/brand/_form.php b/antgoods/views/brand/_form.php
new file mode 100644
index 0000000..fe87664
--- /dev/null
+++ b/antgoods/views/brand/_form.php
@@ -0,0 +1,24 @@
+
+
+
diff --git a/antgoods/views/brand/_search.php b/antgoods/views/brand/_search.php
new file mode 100644
index 0000000..ed21354
--- /dev/null
+++ b/antgoods/views/brand/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/brand/create.php b/antgoods/views/brand/create.php
new file mode 100644
index 0000000..ab0e683
--- /dev/null
+++ b/antgoods/views/brand/create.php
@@ -0,0 +1,18 @@
+title = '创建品牌';
+$this->params['breadcrumbs'][] = ['label' => '品牌管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/brand/index.php b/antgoods/views/brand/index.php
new file mode 100644
index 0000000..7f2b6ba
--- /dev/null
+++ b/antgoods/views/brand/index.php
@@ -0,0 +1,28 @@
+title = '品牌管理';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "brand/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/brand/update.php b/antgoods/views/brand/update.php
new file mode 100644
index 0000000..c8453dc
--- /dev/null
+++ b/antgoods/views/brand/update.php
@@ -0,0 +1,19 @@
+title = '编辑品牌: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '品牌管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = '编辑 ';
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/brand/view.php b/antgoods/views/brand/view.php
new file mode 100644
index 0000000..f5cb312
--- /dev/null
+++ b/antgoods/views/brand/view.php
@@ -0,0 +1,30 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '品牌管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/views/category/_form.php b/antgoods/views/category/_form.php
new file mode 100644
index 0000000..482e25b
--- /dev/null
+++ b/antgoods/views/category/_form.php
@@ -0,0 +1,47 @@
+
+
+
diff --git a/antgoods/views/category/_search.php b/antgoods/views/category/_search.php
new file mode 100644
index 0000000..d43cb1d
--- /dev/null
+++ b/antgoods/views/category/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/category/create.php b/antgoods/views/category/create.php
new file mode 100644
index 0000000..a88ba47
--- /dev/null
+++ b/antgoods/views/category/create.php
@@ -0,0 +1,18 @@
+title = '创建后台商品分类';
+$this->params['breadcrumbs'][] = ['label' => '后台商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/category/index.php b/antgoods/views/category/index.php
new file mode 100644
index 0000000..0f5127f
--- /dev/null
+++ b/antgoods/views/category/index.php
@@ -0,0 +1,28 @@
+title = '后台商品分类';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "category/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/category/update.php b/antgoods/views/category/update.php
new file mode 100644
index 0000000..cb213ab
--- /dev/null
+++ b/antgoods/views/category/update.php
@@ -0,0 +1,19 @@
+title = '编辑后台商品分类: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '后台商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = '编辑 ';
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/category/view.php b/antgoods/views/category/view.php
new file mode 100644
index 0000000..37a7243
--- /dev/null
+++ b/antgoods/views/category/view.php
@@ -0,0 +1,41 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '后台商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'pid',
+ 'goods_count',
+ 'sort_order',
+ 'icon_type',
+ 'icon',
+ [
+ 'attribute' => 'is_show',
+ 'value' => function ($model) {
+ return $model->is_show == \antgoods\models\ars\Category::IS_SHOW_DISPLAY ? '显示':'隐藏';
+ }
+ ],
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/views/config/index.php b/antgoods/views/config/index.php
new file mode 100755
index 0000000..3bbeb28
--- /dev/null
+++ b/antgoods/views/config/index.php
@@ -0,0 +1,27 @@
+
+
+配置页
diff --git a/antgoods/views/goods/_form.php b/antgoods/views/goods/_form.php
new file mode 100644
index 0000000..6ee45ba
--- /dev/null
+++ b/antgoods/views/goods/_form.php
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ = $form->field($model, 'cat_id')->dropDownList(Category::modelColumn(), ['prompt' => '请选择']) ?>
+
+ = $form->field($model, 'brand_id')->dropDownList(Brand::modelColumn(), ['prompt' => '请选择']) ?>
+
+ = $form->field($model, 'shop_cat_id')->dropDownList(ShopCategory::modelColumn(), ['prompt' => '请选择']) ?>
+
+ = $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
+
+ = $form->field($model, 'sn')->textInput(['maxlength' => true]) ?>
+
+ = $form->field($model, 'code')->textInput(['maxlength' => true]) ?>
+
+ = $form->field($model, 'supplier_id')->dropDownList(Supplier::modelColumn(), ['prompt' => '请选择']) ?>
+
+ = $form->field($model, 'weight')->textInput() ?>
+
+ = $form->field($model, 'length')->textInput() ?>
+
+ = $form->field($model, 'width')->textInput() ?>
+
+ = $form->field($model, 'height')->textInput() ?>
+
+ = $form->field($model, 'diameter')->textInput() ?>
+
+ = $form->field($model, 'unit')->textInput(['maxlength' => true]) ?>
+
+ = $form->field($model, 'limit_count')->textInput() ?>
+
+ = $form->field($model, 'stock')->textInput() ?>
+
+ = $form->field($model, 'stock_warn')->textInput() ?>
+
+ = $form->field($model, 'market_price')->textInput() ?>
+
+ = $form->field($model, 'price')->textInput() ?>
+
+ = $form->field($model, 'brief')->textInput(['maxlength' => true]) ?>
+
+ = $form->field($model, 'description')->textarea(['rows' => 6]) ?>
+
+ = $form->field($model, 'model_id')->textInput() ?>
+
+ = $form->field($model, 'is_sale')->radioList($model::$isSale) ?>
+
+ = $form->field($model, 'sort_order')->textInput() ?>
+
+ = $form->field($model, 'bouns_points')->textInput() ?>
+
+ = $form->field($model, 'experience_points')->textInput() ?>
+
+ = $form->field($model, 'express_template')->textInput() ?>
+
+ = $form->field($model, 'coverImageId')->hiddenInput()->label('') ?>
+ = $form->field($model, 'coverImagePath')->widget(\iron\widgets\Upload::className(), [
+ 'url' => 'upload',
+ 'deleteUrl' => 'img-id-del',
+ 'dragdropWidth'=> 800,
+ 'afterSave' => 'save-file',
+ 'maxCount' => 1,
+ 'fillInAttribute' => 'coverImageId',
+ 'model' => $model,
+ 'previewConfig' => [
+ 'url' => Url::to(['image-file', 'fileidstr' => $model->coverImageId]),
+ ],
+ ])->label('商品封面图') ?>
+
+ = $form->field($model, 'detailImageId')->hiddenInput()->label('') ?>
+ = $form->field($model, 'detailImagePath')->widget(\iron\widgets\Upload::className(), [
+ 'url' => 'upload',
+ 'deleteUrl' => 'img-id-del',
+ 'dragdropWidth'=> 800,
+ 'afterSave' => 'save-file',
+ 'maxCount' => 5,
+ 'fillInAttribute' => 'detailImageId',
+ 'model' => $model,
+ 'previewConfig' => [
+ 'url' => Url::to(['image-file', 'fileidstr' => $model->detailImageId]),
+ ],
+ ])->label('商品详情图') ?>
+
+
+ = Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
+ = Html::a('返回', ['index'], ['class' => 'btn btn-info']) ?>
+
+
+
+
+
diff --git a/antgoods/views/goods/_search.php b/antgoods/views/goods/_search.php
new file mode 100644
index 0000000..9a86777
--- /dev/null
+++ b/antgoods/views/goods/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/goods/attribute.php b/antgoods/views/goods/attribute.php
new file mode 100755
index 0000000..cf3b70c
--- /dev/null
+++ b/antgoods/views/goods/attribute.php
@@ -0,0 +1,22 @@
+where(['type' => Attribute::TYPE_ATTR])->asArray()->all();
+GoodsAttributeAsset::register($this);
+?>
+
+
+
diff --git a/antgoods/views/goods/create.php b/antgoods/views/goods/create.php
new file mode 100644
index 0000000..5003ce5
--- /dev/null
+++ b/antgoods/views/goods/create.php
@@ -0,0 +1,72 @@
+title = '创建商品';
+$this->params['breadcrumbs'][] = ['label' => '商品列表', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+Yii::$app->params['bsVersion'] = '4.x';
+?>
+
+
+
+ ['class' => 'container-fluid']]);
+
+ echo TabsX::widget([
+ 'bordered' => true,
+ 'items' => [
+ [
+ 'label' => '
基本信息',
+ 'content' => $this->render('goods', ['model' => $model,
+ 'form' => $form,
+ 'judgeGoodsCategory' => false, //表示后台分类可以修改
+ ]),
+ ],
+ [
+ 'label' => '
筛选规格',
+ 'content' => $this->render('filter_attribute', [
+ 'filterModel' => [],
+ 'filterAttrValue' => [],
+ ]),
+ ],
+ [
+ 'label' => '
商品规格',
+ 'content' => $this->render('attribute', [
+ 'model' => [],
+ 'attrValue' => [],
+ ]),
+ ],
+ [
+ 'label' => '
详情上传',
+ 'content' => $this->render('new_editor', ['model' => $model,
+ 'form' => $form,
+ ]),
+ ],
+ [
+ 'label' => '
图片上传',
+ 'content' => $this->render('picture', [
+ 'model' => $model,
+ 'form' => $form
+ ]),
+ ],
+ ],
+ 'position' => TabsX::POS_ABOVE,
+ 'encodeLabels' => false
+ ]);
+ ?>
+
+
+ = Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
+ = Html::a('返回', ['index'], ['class' => 'btn btn-info']) ?>
+
+
+
+
+
+
diff --git a/antgoods/views/goods/filter_attribute.php b/antgoods/views/goods/filter_attribute.php
new file mode 100755
index 0000000..9980068
--- /dev/null
+++ b/antgoods/views/goods/filter_attribute.php
@@ -0,0 +1,22 @@
+where(['type' => Attribute::TYPE_ATTR])->asArray()->all();
+GoodsFilterAttributeAsset::register($this);
+?>
+
+
+
diff --git a/antgoods/views/goods/goods.php b/antgoods/views/goods/goods.php
new file mode 100644
index 0000000..0d2e11d
--- /dev/null
+++ b/antgoods/views/goods/goods.php
@@ -0,0 +1,63 @@
+
+= $form->field($model, 'cat_id')->dropDownList(Category::modelColumn(), ['prompt' => '请选择', 'disabled' => $judgeGoodsCategory]) ?>
+
+= $form->field($model, 'brand_id')->dropDownList(Brand::modelColumn(), ['prompt' => '请选择']) ?>
+
+= $form->field($model, 'shop_cat_id')->dropDownList(ShopCategory::modelColumn(), ['prompt' => '请选择']) ?>
+
+= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
+
+= $form->field($model, 'sn')->textInput(['maxlength' => true]) ?>
+
+= $form->field($model, 'code')->textInput(['maxlength' => true]) ?>
+
+= $form->field($model, 'supplier_id')->dropDownList(Supplier::modelColumn(), ['prompt' => '请选择']) ?>
+
+= $form->field($model, 'weight')->textInput() ?>
+
+= $form->field($model, 'length')->textInput() ?>
+
+= $form->field($model, 'width')->textInput() ?>
+
+= $form->field($model, 'height')->textInput() ?>
+
+= $form->field($model, 'diameter')->textInput() ?>
+
+= $form->field($model, 'unit')->textInput(['maxlength' => true]) ?>
+
+= $form->field($model, 'limit_count')->textInput() ?>
+
+= $form->field($model, 'stock')->textInput() ?>
+
+= $form->field($model, 'stock_warn')->textInput() ?>
+
+= $form->field($model, 'market_price')->textInput() ?>
+
+= $form->field($model, 'price')->textInput() ?>
+
+= $form->field($model, 'brief')->textInput(['maxlength' => true]) ?>
+
+= $form->field($model, 'is_sale')->radioList($model::$isSale) ?>
+
+= $form->field($model, 'sort_order')->textInput() ?>
+
+= $form->field($model, 'bouns_points')->textInput() ?>
+
+= $form->field($model, 'experience_points')->textInput() ?>
+
+
+ = Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
+ = Html::a('返回', ['index'], ['class' => 'btn btn-info']) ?>
+
\ No newline at end of file
diff --git a/antgoods/views/goods/index.php b/antgoods/views/goods/index.php
new file mode 100644
index 0000000..40421e3
--- /dev/null
+++ b/antgoods/views/goods/index.php
@@ -0,0 +1,28 @@
+title = '商品列表';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "goods/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/goods/new_editor.php b/antgoods/views/goods/new_editor.php
new file mode 100644
index 0000000..a35c049
--- /dev/null
+++ b/antgoods/views/goods/new_editor.php
@@ -0,0 +1,31 @@
+
+
+
+
+ = $form->field($model, 'description')->widget('common\widgets\ueditor\Ueditor',[
+ 'options'=>[
+ 'initialFrameWidth' => 760,//宽度
+ 'initialFrameHeight' => 500,//高度
+
+ ]
+
+ ]) ?>
+
+
+
+
+
+
+ = Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
+
+
+
diff --git a/antgoods/views/goods/picture.php b/antgoods/views/goods/picture.php
new file mode 100644
index 0000000..0b77d7c
--- /dev/null
+++ b/antgoods/views/goods/picture.php
@@ -0,0 +1,37 @@
+
+= $form->field($model, 'coverImageId')->hiddenInput()->label('') ?>
+= $form->field($model, 'coverImagePath')->widget(\iron\widgets\Upload::className(), [
+ 'url' => 'upload',
+ 'deleteUrl' => 'img-id-del',
+ 'dragdropWidth'=> 800,
+ 'afterSave' => 'save-file',
+ 'maxCount' => 1,
+ 'fillInAttribute' => 'coverImageId',
+ 'model' => $model,
+ 'ruleVerify' => $model->ruleVerify,
+ 'previewConfig' => [
+ 'url' => Url::to(['image-file', 'fileidstr' => $model->coverImageId]),
+ ],
+])->label('商品封面图') ?>
+
+= $form->field($model, 'detailImageId')->hiddenInput()->label('') ?>
+= $form->field($model, 'detailImagePath')->widget(\iron\widgets\Upload::className(), [
+ 'url' => 'upload',
+ 'deleteUrl' => 'img-id-del',
+ 'dragdropWidth'=> 800,
+ 'afterSave' => 'save-file',
+ 'maxCount' => 5,
+ 'fillInAttribute' => 'detailImageId',
+ 'model' => $model,
+ 'ruleVerify' => $model->ruleVerify,
+ 'previewConfig' => [
+ 'url' => Url::to(['image-file', 'fileidstr' => $model->detailImageId]),
+ ],
+])->label('商品详情图') ?>
diff --git a/antgoods/views/goods/sku_edit.php b/antgoods/views/goods/sku_edit.php
new file mode 100644
index 0000000..af194a9
--- /dev/null
+++ b/antgoods/views/goods/sku_edit.php
@@ -0,0 +1,15 @@
+title = '添加SKU';
+$this->params['breadcrumbs'][] = ['label' => '商品列表', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+GoodsSkuEditAsset::register($this);
+?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/goods/update.php b/antgoods/views/goods/update.php
new file mode 100644
index 0000000..221e40a
--- /dev/null
+++ b/antgoods/views/goods/update.php
@@ -0,0 +1,74 @@
+title = '编辑商品: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '商品管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = '编辑 ';
+Yii::$app->params['bsVersion'] = '4.x';
+?>
+
+
+ ['class' => 'container-fluid']]);
+
+ echo TabsX::widget([
+ 'bordered' => true,
+ 'items' => [
+ [
+ 'label' => '
基本信息',
+ 'content' => $this->render('goods', [
+ 'model' => $model,
+ 'form' => $form,
+ 'judgeGoodsCategory' => $judgeGoodsCategory
+ ]),
+ ],
+ [
+ 'label' => '
筛选规格',
+ 'content' => $this->render('filter_attribute', [
+ 'filterModel' => $filterAttributeModel,
+ 'filterAttrValue' => [],
+ ]),
+ ],
+ [
+ 'label' => '
商品规格',
+ 'content' => $this->render('attribute', [
+ 'model' => $attributeModel,
+ 'attrValue' => $attrValue,
+ 'goodsModel' => $model,
+ ]),
+ ],
+ [
+ 'label' => '
图片上传',
+ 'content' => $this->render('picture', [
+ 'model' => $model,
+ 'form' => $form,
+ ]),
+ ],
+ ],
+ 'position' => TabsX::POS_ABOVE,
+ 'encodeLabels' => false
+ ]);
+ ?>
+
+
+ = Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
+ = Html::a('返回', ['index'], ['class' => 'btn btn-info']) ?>
+
+
+
+
+
+ render('_form', [
+// 'model' => $model,
+// ])
+ ?>
+
+
diff --git a/antgoods/views/goods/view.php b/antgoods/views/goods/view.php
new file mode 100644
index 0000000..8c61b50
--- /dev/null
+++ b/antgoods/views/goods/view.php
@@ -0,0 +1,113 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '商品管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'sn',
+ [
+ 'attribute' => 'cat_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->category ? $model->category->name : '';
+ },
+ ],
+ [
+ 'attribute' => 'shop_cat_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->shopCategory ? $model->shopCategory->name : '';
+ },
+ ],
+ [
+ 'attribute' => 'brand_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->brand ? $model->brand->name : '';
+ },
+ ],
+ 'code',
+ [
+ 'attribute' => 'supplier_id',
+ 'width' => '10%',
+ 'value' => function ($model) {
+ return $model->supplier ? $model->supplier->name : '';
+ },
+ ],
+ 'weight',
+ 'length',
+ 'width',
+ 'height',
+ 'diameter',
+ 'unit',
+ [
+ 'attribute' => 'stock',
+ 'width' => '5%',
+ 'value' => function ($model) {
+ if ($model->stock == -1) {
+ return '未开启';
+ } else {
+ return $model->stock;
+ }
+ },
+ ],
+ 'market_price',
+ 'price',
+ 'brief',
+ ['attribute' => 'image',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return $model->image ?
+ Html::img(['/'.$model->imageFile->path], ['style' => 'width:80px'])
+ : '
未设置
';
+
+ }
+ ],
+ [
+ 'label' => '详情图',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ $image = '';
+ $imgs = File::findAll(['own_id' => $model->id, 'own_type' => File::OWN_TYPE_GOODS_DETAILS, 'is_delete' => File::IS_DELETE_NO]);
+ foreach ($imgs as $img) {
+ $image .= Html::img(['/'.$img->path], ['style' => 'width:150px']);
+ }
+ return $image;
+
+ }
+ ],
+ ['attribute' => 'is_sale',
+ 'width' => '5%',
+ 'value' =>
+ function ($model) {
+ return $model->is_sale ? Goods::$isSale[$model->is_sale] : '未设置';
+
+ },
+ ],
+ 'sort_order',
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/views/layouts/base.php b/antgoods/views/layouts/base.php
new file mode 100755
index 0000000..987f0b3
--- /dev/null
+++ b/antgoods/views/layouts/base.php
@@ -0,0 +1,33 @@
+
+beginPage() ?>
+
+
+
+
+
+
+ registerCsrfMetaTags() ?>
+ = Html::encode($this->title) ?>
+ head() ?>
+
+
+ beginBody() ?>
+
+ = $content ?>
+
+ endBody() ?>
+
+
+endPage() ?>
diff --git a/antgoods/views/layouts/breadcrumb.php b/antgoods/views/layouts/breadcrumb.php
new file mode 100755
index 0000000..57806ab
--- /dev/null
+++ b/antgoods/views/layouts/breadcrumb.php
@@ -0,0 +1,25 @@
+
+
+
+
+ title)): ?>
+
= $this->title ?>params['subtitle'])): ?>
+ = $this->params['subtitle'] ?>
+
+
+
+ 'ol',
+ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
+ 'itemTemplate' => "
{link} \n",
+ 'activeItemTemplate' => "{link} \n",
+ 'options' => ['class' => 'breadcrumb float-sm-right']
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/layouts/footer.php b/antgoods/views/layouts/footer.php
new file mode 100755
index 0000000..a0a801d
--- /dev/null
+++ b/antgoods/views/layouts/footer.php
@@ -0,0 +1,7 @@
+
+
+ Version 0.1.0
+
+ Copyright © 2014-2019 KcAdmin . All rights
+ reserved.
+
\ No newline at end of file
diff --git a/antgoods/views/layouts/header.php b/antgoods/views/layouts/header.php
new file mode 100755
index 0000000..0fd795d
--- /dev/null
+++ b/antgoods/views/layouts/header.php
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/layouts/main.php b/antgoods/views/layouts/main.php
new file mode 100755
index 0000000..b938779
--- /dev/null
+++ b/antgoods/views/layouts/main.php
@@ -0,0 +1,57 @@
+
+
+beginPage() ?>
+
+
+
+
+
+
+ registerCsrfMetaTags() ?>
+
= Html::encode($this->title) ?>
+
+
+
+
+
+
+
+ head() ?>
+
+
+ beginBody() ?>
+
+ = $this->render('header') ?>
+
+ = $this->render('sidebar') ?>
+
+
+ session->hasFlash('error') || Yii::$app->session->hasFlash('success')) {
+ echo Alert::widget();
+ }
+ ?>
+
+
+
+
+ = $this->render('footer') ?>
+
+ endBody() ?>
+
+
+endPage() ?>
diff --git a/antgoods/views/layouts/sidebar.php b/antgoods/views/layouts/sidebar.php
new file mode 100755
index 0000000..f296711
--- /dev/null
+++ b/antgoods/views/layouts/sidebar.php
@@ -0,0 +1,33 @@
+
+
\ No newline at end of file
diff --git a/antgoods/views/shop-category/_form.php b/antgoods/views/shop-category/_form.php
new file mode 100644
index 0000000..ecc4a20
--- /dev/null
+++ b/antgoods/views/shop-category/_form.php
@@ -0,0 +1,55 @@
+
+
+
diff --git a/antgoods/views/shop-category/_search.php b/antgoods/views/shop-category/_search.php
new file mode 100644
index 0000000..1e839e6
--- /dev/null
+++ b/antgoods/views/shop-category/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/shop-category/create.php b/antgoods/views/shop-category/create.php
new file mode 100644
index 0000000..73f3eae
--- /dev/null
+++ b/antgoods/views/shop-category/create.php
@@ -0,0 +1,18 @@
+title = '创建前端商品分类';
+$this->params['breadcrumbs'][] = ['label' => '前端商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/shop-category/index.php b/antgoods/views/shop-category/index.php
new file mode 100644
index 0000000..af3692d
--- /dev/null
+++ b/antgoods/views/shop-category/index.php
@@ -0,0 +1,28 @@
+title = '前端商品分类';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "shopcategory/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/shop-category/update.php b/antgoods/views/shop-category/update.php
new file mode 100644
index 0000000..5c97d16
--- /dev/null
+++ b/antgoods/views/shop-category/update.php
@@ -0,0 +1,19 @@
+title = '编辑前端商品分类: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '前端商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = '编辑 ';
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/shop-category/view.php b/antgoods/views/shop-category/view.php
new file mode 100644
index 0000000..c6ef07e
--- /dev/null
+++ b/antgoods/views/shop-category/view.php
@@ -0,0 +1,64 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '前端商品分类', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+$filter_attr_arr = explode(',', $model->filter_attr);
+$attr_str = '';
+foreach ($filter_attr_arr as $filter_attr_id) {
+ $attr = Attribute::findOne($filter_attr_id);
+ if ($attr) {
+ $attr_str = $attr_str . ',' . $attr->name;
+ }
+}
+$attr_str = substr($attr_str, 1);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'keywords',
+ 'desc',
+ 'sort_order',
+ ['attribute' => 'icon',
+ 'width'=>'10%',
+ 'format' => 'raw',
+ 'value' => function ($model) {
+ return $model->iconFile ?
+ \yii\bootstrap4\Html::img(['/'.$model->iconFile->path], ['style' => 'width:80px'])
+ : '未设置';
+
+ }
+ ],
+ ['attribute' => 'filter_attr',
+ 'value' => $attr_str
+ ],
+ ['attribute' => 'is_show',
+ 'width' => '5%',
+ 'value' =>
+ function ($model) {
+ return $model->is_show == ShopCategory::IS_SHOW_HIDE ? '隐藏' : '显示';
+ },
+ ],
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/views/site/error.php b/antgoods/views/site/error.php
new file mode 100755
index 0000000..0ba2574
--- /dev/null
+++ b/antgoods/views/site/error.php
@@ -0,0 +1,27 @@
+title = $name;
+?>
+
+
+
= Html::encode($this->title) ?>
+
+
+ = nl2br(Html::encode($message)) ?>
+
+
+
+ The above error occurred while the Web server was processing your request.
+
+
+ Please contact us if you think this is a server error. Thank you.
+
+
+
diff --git a/antgoods/views/site/index.php b/antgoods/views/site/index.php
new file mode 100755
index 0000000..21cb7e4
--- /dev/null
+++ b/antgoods/views/site/index.php
@@ -0,0 +1,6 @@
+title = 'Dashboard';
+$this->params['subtitle'] = 'Control panel';
+$this->params['breadcrumbs'][] = $this->title;
+?>
\ No newline at end of file
diff --git a/antgoods/views/site/login.php b/antgoods/views/site/login.php
new file mode 100755
index 0000000..461327c
--- /dev/null
+++ b/antgoods/views/site/login.php
@@ -0,0 +1,34 @@
+title = '系统登录';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
\ No newline at end of file
diff --git a/antgoods/views/site/test.php b/antgoods/views/site/test.php
new file mode 100755
index 0000000..f9eebef
--- /dev/null
+++ b/antgoods/views/site/test.php
@@ -0,0 +1,68 @@
+title = '测试';
+$this->params['subtitle'] = '这是一个小小的测试';
+$this->params['breadcrumbs'][] = $this->title;
+
+/* @var $this yii\web\View */
+/* @var $model common\models\CategorySearch */
+/* @var $form yii\widgets\ActiveForm */
+?>
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+
+ =
+ $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索的id",
+ "class" => "form-control"
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+ =
+ $form->field($model, 'cat_name', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索类名",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+ =
+ $form->field($model, "created_at", [
+ "template" => "{input}{error}",
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
diff --git a/antgoods/views/supplier/_form.php b/antgoods/views/supplier/_form.php
new file mode 100644
index 0000000..93942e2
--- /dev/null
+++ b/antgoods/views/supplier/_form.php
@@ -0,0 +1,30 @@
+
+
+
diff --git a/antgoods/views/supplier/_search.php b/antgoods/views/supplier/_search.php
new file mode 100644
index 0000000..1f00e41
--- /dev/null
+++ b/antgoods/views/supplier/_search.php
@@ -0,0 +1,49 @@
+
+
+ ['index'],
+ 'method' => 'get',
+ 'validateOnType' => true,
+ ]);
+?>
+
+
+ = $form->field($model, 'id', [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "检索ID",
+ "class" => "form-control",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])
+ ?>
+
+
+ = $form->field($model, "created_at_range", [
+ "template" => "{input}{error}",
+ "inputOptions" => [
+ "placeholder" => "创建时间",
+ ],
+ "errorOptions" => [
+ "class" => "error-tips"
+ ]
+ ])->widget(DateRangePicker::className());
+ ?>
+
+
+ = Html::submitButton(' ', ['class' => 'btn btn-default']) ?>
+ = Html::resetButton(' ', ['class' => 'btn btn-default']) ?>
+
+
+
\ No newline at end of file
diff --git a/antgoods/views/supplier/create.php b/antgoods/views/supplier/create.php
new file mode 100644
index 0000000..57e0b0e
--- /dev/null
+++ b/antgoods/views/supplier/create.php
@@ -0,0 +1,18 @@
+title = '创建供应商';
+$this->params['breadcrumbs'][] = ['label' => '供应商管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/supplier/index.php b/antgoods/views/supplier/index.php
new file mode 100644
index 0000000..bad1e50
--- /dev/null
+++ b/antgoods/views/supplier/index.php
@@ -0,0 +1,28 @@
+title = '供应商管理';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filter' => $this->render("_search", ['model' => $searchModel]),
+ 'batch' => [
+ [
+ "label" => "删除",
+ "url" => "supplier/deletes"
+ ],
+ ],
+ 'columns' => $columns
+ ]);
+ ?>
+
+
\ No newline at end of file
diff --git a/antgoods/views/supplier/update.php b/antgoods/views/supplier/update.php
new file mode 100644
index 0000000..a6aca3d
--- /dev/null
+++ b/antgoods/views/supplier/update.php
@@ -0,0 +1,19 @@
+title = '编辑供应商: ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => '供应商管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = '编辑 ';
+?>
+
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/antgoods/views/supplier/view.php b/antgoods/views/supplier/view.php
new file mode 100644
index 0000000..6619f91
--- /dev/null
+++ b/antgoods/views/supplier/view.php
@@ -0,0 +1,33 @@
+title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => '供应商管理', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+
+
+
+ = Html::a('返回列表', ['index'], ['class' => 'btn btn-success']) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id',
+ 'name',
+ 'full_name',
+ 'phone',
+ 'address',
+ 'created_at:datetime',
+ 'updated_at:datetime',
+ ],
+ ]) ?>
+
+
diff --git a/antgoods/web/.gitignore b/antgoods/web/.gitignore
new file mode 100755
index 0000000..cb7f43e
--- /dev/null
+++ b/antgoods/web/.gitignore
@@ -0,0 +1,11 @@
+/index.php
+/index-test.php
+/robots.txt
+uploads
+css/umeditor/php/upload/
+
+node_modules/
+yarn-error.log
+yarn.lock
+package-lock.json
+ueditor
diff --git a/antgoods/web/assets/.gitignore b/antgoods/web/assets/.gitignore
new file mode 100755
index 0000000..d6b7ef3
--- /dev/null
+++ b/antgoods/web/assets/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/antgoods/web/css/reset.css b/antgoods/web/css/reset.css
new file mode 100755
index 0000000..9ff51eb
--- /dev/null
+++ b/antgoods/web/css/reset.css
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
\ No newline at end of file
diff --git a/antgoods/web/css/site.css b/antgoods/web/css/site.css
new file mode 100755
index 0000000..23fa9ae
--- /dev/null
+++ b/antgoods/web/css/site.css
@@ -0,0 +1,52 @@
+/*公共样式*/
+
+/*登录页*/
+.login-body{
+ display: flex;
+ align-items: center;
+ height: 100vh;
+}
+
+.login-body .line {
+ border-bottom: 1px solid #dadada;
+ line-height: 0.1em;
+ margin: 10px 0 20px;
+}
+
+.login-body .line span {
+ background: #fff;
+ padding: 0 10px;
+}
+
+.login-form {
+ box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+ margin: 0 auto;
+}
+
+.login-form h2{
+ text-align: center;
+ margin-bottom: 20px;
+}
+
+.login-form h6 {
+ text-align: center;
+}
+
+/*修复select2插件 from表框颜色不生效*/
+.form-group.has-error .select2-selection, .form-group.has-error .select2-selection {
+ border-color: #dd4b39;
+ box-shadow: none;
+}
+
+.form-group.has-success .select2-selection, .form-group.has-success .select2-selection {
+ border-color: #00a65a;
+ box-shadow: none;
+}
+
+.icheck-label-group {
+ padding-top: 2px;
+}
+
+.icheck-label-group label{
+ margin-right: 20px;
+}
\ No newline at end of file
diff --git a/antgoods/web/custom/sku.49a56a9198d9c3ec233c.js b/antgoods/web/custom/sku.49a56a9198d9c3ec233c.js
new file mode 100644
index 0000000..efefa7e
--- /dev/null
+++ b/antgoods/web/custom/sku.49a56a9198d9c3ec233c.js
@@ -0,0 +1,58 @@
+!function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/custom/",n(n.s=315)}([function(e,t,n){"use strict";e.exports=n(233)},function(e,t,n){e.exports=n(245)()},function(e,t,n){(function(e){e.exports=function(){"use strict";var t,r;function a(){return t.apply(null,arguments)}function i(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function o(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function c(e){return void 0===e}function s(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function l(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function u(e,t){var n,r=[];for(n=0;n
>>0,r=0;r0)for(n=0;n<_.length;n++)c(a=t[r=_[n]])||(e[r]=a);return e}var M=!1;function b(e){y(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===M&&(M=!0,a.updateOffset(this),M=!1)}function g(e){return e instanceof b||null!=e&&null!=e._isAMomentObject}function w(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function L(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=w(t)),n}function z(e,t,n){var r,a=Math.min(e.length,t.length),i=Math.abs(e.length-t.length),o=0;for(r=0;r=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+r}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,I=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,R={},W={};function U(e,t,n,r){var a=r;"string"==typeof r&&(a=function(){return this[r]()}),e&&(W[e]=a),t&&(W[t[0]]=function(){return F(a.apply(this,arguments),t[1],t[2])}),n&&(W[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),e)})}function B(e,t){return e.isValid()?(t=K(t,e.localeData()),R[t]=R[t]||function(e){var t,n,r,a=e.match(N);for(t=0,n=a.length;t=0&&I.test(e);)e=e.replace(I,r),I.lastIndex=0,n-=1;return e}var q=/\d/,J=/\d\d/,G=/\d{3}/,$=/\d{4}/,X=/[+-]?\d{6}/,Z=/\d\d?/,Q=/\d\d\d\d?/,ee=/\d\d\d\d\d\d?/,te=/\d{1,3}/,ne=/\d{1,4}/,re=/[+-]?\d{1,6}/,ae=/\d+/,ie=/[+-]?\d+/,oe=/Z|[+-]\d\d:?\d\d/gi,ce=/Z|[+-]\d\d(?::?\d\d)?/gi,se=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,le={};function ue(e,t,n){le[e]=D(t)?t:function(e,r){return e&&n?n:t}}function de(e,t){return d(le,e)?le[e](t._strict,t._locale):new RegExp(me(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(e,t,n,r,a){return t||n||r||a}))))}function me(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var he={};function fe(e,t){var n,r=t;for("string"==typeof e&&(e=[e]),s(t)&&(r=function(e,n){n[t]=L(e)}),n=0;n68?1900:2e3)};var Se,Ye=De("FullYear",!0);function De(e,t){return function(n){return null!=n?(xe(this,e,n),a.updateOffset(this,t),this):Oe(this,e)}}function Oe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&Te(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Ce(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Ce(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,r=(t%(n=12)+n)%n;return e+=(t-r)/12,1===r?Te(e)?29:28:31-r%7%2}Se=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t=0?(c=new Date(e+400,t,n,r,a,i,o),isFinite(c.getFullYear())&&c.setFullYear(e)):c=new Date(e,t,n,r,a,i,o),c}function Ue(e){var t;if(e<100&&e>=0){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Be(e,t,n){var r=7+t-n;return-(7+Ue(e,0,r).getUTCDay()-t)%7+r-1}function Ke(e,t,n,r,a){var i,o,c=1+7*(t-1)+(7+n-r)%7+Be(e,r,a);return c<=0?o=He(i=e-1)+c:c>He(e)?(i=e+1,o=c-He(e)):(i=e,o=c),{year:i,dayOfYear:o}}function qe(e,t,n){var r,a,i=Be(e.year(),t,n),o=Math.floor((e.dayOfYear()-i-1)/7)+1;return o<1?r=o+Je(a=e.year()-1,t,n):o>Je(e.year(),t,n)?(r=o-Je(e.year(),t,n),a=e.year()+1):(a=e.year(),r=o),{week:r,year:a}}function Je(e,t,n){var r=Be(e,t,n),a=Be(e+1,t,n);return(He(e)-r+a)/7}function Ge(e,t){return e.slice(t,7).concat(e.slice(0,t))}U("w",["ww",2],"wo","week"),U("W",["WW",2],"Wo","isoWeek"),V("week","w"),V("isoWeek","W"),A("week",5),A("isoWeek",5),ue("w",Z),ue("ww",Z,J),ue("W",Z),ue("WW",Z,J),pe(["w","ww","W","WW"],(function(e,t,n,r){t[r.substr(0,1)]=L(e)})),U("d",0,"do","day"),U("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),U("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),U("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),U("e",0,0,"weekday"),U("E",0,0,"isoWeekday"),V("day","d"),V("weekday","e"),V("isoWeekday","E"),A("day",11),A("weekday",11),A("isoWeekday",11),ue("d",Z),ue("e",Z),ue("E",Z),ue("dd",(function(e,t){return t.weekdaysMinRegex(e)})),ue("ddd",(function(e,t){return t.weekdaysShortRegex(e)})),ue("dddd",(function(e,t){return t.weekdaysRegex(e)})),pe(["dd","ddd","dddd"],(function(e,t,n,r){var a=n._locale.weekdaysParse(e,r,n._strict);null!=a?t.d=a:f(n).invalidWeekday=e})),pe(["d","e","E"],(function(e,t,n,r){t[r]=L(e)}));var $e="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Xe="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");function Qe(e,t,n){var r,a,i,o=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],r=0;r<7;++r)i=h([2e3,1]).day(r),this._minWeekdaysParse[r]=this.weekdaysMin(i,"").toLocaleLowerCase(),this._shortWeekdaysParse[r]=this.weekdaysShort(i,"").toLocaleLowerCase(),this._weekdaysParse[r]=this.weekdays(i,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(a=Se.call(this._weekdaysParse,o))?a:null:"ddd"===t?-1!==(a=Se.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=Se.call(this._minWeekdaysParse,o))?a:null:"dddd"===t?-1!==(a=Se.call(this._weekdaysParse,o))?a:-1!==(a=Se.call(this._shortWeekdaysParse,o))?a:-1!==(a=Se.call(this._minWeekdaysParse,o))?a:null:"ddd"===t?-1!==(a=Se.call(this._shortWeekdaysParse,o))?a:-1!==(a=Se.call(this._weekdaysParse,o))?a:-1!==(a=Se.call(this._minWeekdaysParse,o))?a:null:-1!==(a=Se.call(this._minWeekdaysParse,o))?a:-1!==(a=Se.call(this._weekdaysParse,o))?a:-1!==(a=Se.call(this._shortWeekdaysParse,o))?a:null}var et=se,tt=se,nt=se;function rt(){function e(e,t){return t.length-e.length}var t,n,r,a,i,o=[],c=[],s=[],l=[];for(t=0;t<7;t++)n=h([2e3,1]).day(t),r=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),i=this.weekdays(n,""),o.push(r),c.push(a),s.push(i),l.push(r),l.push(a),l.push(i);for(o.sort(e),c.sort(e),s.sort(e),l.sort(e),t=0;t<7;t++)c[t]=me(c[t]),s[t]=me(s[t]),l[t]=me(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+c.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function at(){return this.hours()%12||12}function it(e,t){U(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)}))}function ot(e,t){return t._meridiemParse}U("H",["HH",2],0,"hour"),U("h",["hh",2],0,at),U("k",["kk",2],0,(function(){return this.hours()||24})),U("hmm",0,0,(function(){return""+at.apply(this)+F(this.minutes(),2)})),U("hmmss",0,0,(function(){return""+at.apply(this)+F(this.minutes(),2)+F(this.seconds(),2)})),U("Hmm",0,0,(function(){return""+this.hours()+F(this.minutes(),2)})),U("Hmmss",0,0,(function(){return""+this.hours()+F(this.minutes(),2)+F(this.seconds(),2)})),it("a",!0),it("A",!1),V("hour","h"),A("hour",13),ue("a",ot),ue("A",ot),ue("H",Z),ue("h",Z),ue("k",Z),ue("HH",Z,J),ue("hh",Z,J),ue("kk",Z,J),ue("hmm",Q),ue("hmmss",ee),ue("Hmm",Q),ue("Hmmss",ee),fe(["H","HH"],be),fe(["k","kk"],(function(e,t,n){var r=L(e);t[be]=24===r?0:r})),fe(["a","A"],(function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e})),fe(["h","hh"],(function(e,t,n){t[be]=L(e),f(n).bigHour=!0})),fe("hmm",(function(e,t,n){var r=e.length-2;t[be]=L(e.substr(0,r)),t[ge]=L(e.substr(r)),f(n).bigHour=!0})),fe("hmmss",(function(e,t,n){var r=e.length-4,a=e.length-2;t[be]=L(e.substr(0,r)),t[ge]=L(e.substr(r,2)),t[we]=L(e.substr(a)),f(n).bigHour=!0})),fe("Hmm",(function(e,t,n){var r=e.length-2;t[be]=L(e.substr(0,r)),t[ge]=L(e.substr(r))})),fe("Hmmss",(function(e,t,n){var r=e.length-4,a=e.length-2;t[be]=L(e.substr(0,r)),t[ge]=L(e.substr(r,2)),t[we]=L(e.substr(a))}));var ct,st=De("Hours",!0),lt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ee,monthsShort:Pe,week:{dow:0,doy:6},weekdays:$e,weekdaysMin:Ze,weekdaysShort:Xe,meridiemParse:/[ap]\.?m?\.?/i},ut={},dt={};function mt(e){return e?e.toLowerCase().replace("_","-"):e}function ht(t){var r=null;if(!ut[t]&&void 0!==e&&e&&e.exports)try{r=ct._abbr,n(310)("./"+t),ft(r)}catch(e){}return ut[t]}function ft(e,t){var n;return e&&((n=c(t)?vt(e):pt(e,t))?ct=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),ct._abbr}function pt(e,t){if(null!==t){var n,r=lt;if(t.abbr=e,null!=ut[e])Y("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),r=ut[e]._config;else if(null!=t.parentLocale)if(null!=ut[t.parentLocale])r=ut[t.parentLocale]._config;else{if(null==(n=ht(t.parentLocale)))return dt[t.parentLocale]||(dt[t.parentLocale]=[]),dt[t.parentLocale].push({name:e,config:t}),null;r=n._config}return ut[e]=new x(O(r,t)),dt[e]&&dt[e].forEach((function(e){pt(e.name,e.config)})),ft(e),ut[e]}return delete ut[e],null}function vt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return ct;if(!i(e)){if(t=ht(e))return t;e=[e]}return function(e){for(var t,n,r,a,i=0;i0;){if(r=ht(a.slice(0,t).join("-")))return r;if(n&&n.length>=t&&z(a,n,!0)>=t-1)break;t--}i++}return ct}(e)}function _t(e){var t,n=e._a;return n&&-2===f(e).overflow&&(t=n[ye]<0||n[ye]>11?ye:n[Me]<1||n[Me]>Ce(n[_e],n[ye])?Me:n[be]<0||n[be]>24||24===n[be]&&(0!==n[ge]||0!==n[we]||0!==n[Le])?be:n[ge]<0||n[ge]>59?ge:n[we]<0||n[we]>59?we:n[Le]<0||n[Le]>999?Le:-1,f(e)._overflowDayOfYear&&(t<_e||t>Me)&&(t=Me),f(e)._overflowWeeks&&-1===t&&(t=ze),f(e)._overflowWeekday&&-1===t&&(t=ke),f(e).overflow=t),e}function yt(e,t,n){return null!=e?e:null!=t?t:n}function Mt(e){var t,n,r,i,o,c=[];if(!e._d){for(r=function(e){var t=new Date(a.now());return e._useUTC?[t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()]:[t.getFullYear(),t.getMonth(),t.getDate()]}(e),e._w&&null==e._a[Me]&&null==e._a[ye]&&function(e){var t,n,r,a,i,o,c,s;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)i=1,o=4,n=yt(t.GG,e._a[_e],qe(Vt(),1,4).year),r=yt(t.W,1),((a=yt(t.E,1))<1||a>7)&&(s=!0);else{i=e._locale._week.dow,o=e._locale._week.doy;var l=qe(Vt(),i,o);n=yt(t.gg,e._a[_e],l.year),r=yt(t.w,l.week),null!=t.d?((a=t.d)<0||a>6)&&(s=!0):null!=t.e?(a=t.e+i,(t.e<0||t.e>6)&&(s=!0)):a=i}r<1||r>Je(n,i,o)?f(e)._overflowWeeks=!0:null!=s?f(e)._overflowWeekday=!0:(c=Ke(n,r,a,i,o),e._a[_e]=c.year,e._dayOfYear=c.dayOfYear)}(e),null!=e._dayOfYear&&(o=yt(e._a[_e],r[_e]),(e._dayOfYear>He(o)||0===e._dayOfYear)&&(f(e)._overflowDayOfYear=!0),n=Ue(o,0,e._dayOfYear),e._a[ye]=n.getUTCMonth(),e._a[Me]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=c[t]=r[t];for(;t<7;t++)e._a[t]=c[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[be]&&0===e._a[ge]&&0===e._a[we]&&0===e._a[Le]&&(e._nextDay=!0,e._a[be]=0),e._d=(e._useUTC?Ue:We).apply(null,c),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[be]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(f(e).weekdayMismatch=!0)}}var bt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,gt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,wt=/Z|[+-]\d\d(?::?\d\d)?/,Lt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],zt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],kt=/^\/?Date\((\-?\d+)/i;function Ht(e){var t,n,r,a,i,o,c=e._i,s=bt.exec(c)||gt.exec(c);if(s){for(f(e).iso=!0,t=0,n=Lt.length;t0&&f(e).unusedInput.push(o),c=c.slice(c.indexOf(n)+n.length),l+=n.length),W[i]?(n?f(e).empty=!1:f(e).unusedTokens.push(i),ve(i,n,e)):e._strict&&!n&&f(e).unusedTokens.push(i);f(e).charsLeftOver=s-l,c.length>0&&f(e).unusedInput.push(c),e._a[be]<=12&&!0===f(e).bigHour&&e._a[be]>0&&(f(e).bigHour=void 0),f(e).parsedDateParts=e._a.slice(0),f(e).meridiem=e._meridiem,e._a[be]=function(e,t,n){var r;return null==n?t:null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((r=e.isPM(n))&&t<12&&(t+=12),r||12!==t||(t=0),t):t}(e._locale,e._a[be],e._meridiem),Mt(e),_t(e)}else Dt(e);else Ht(e)}function xt(e){var t=e._i,n=e._f;return e._locale=e._locale||vt(e._l),null===t||void 0===n&&""===t?v({nullInput:!0}):("string"==typeof t&&(e._i=t=e._locale.preparse(t)),g(t)?new b(_t(t)):(l(t)?e._d=t:i(n)?function(e){var t,n,r,a,i;if(0===e._f.length)return f(e).invalidFormat=!0,void(e._d=new Date(NaN));for(a=0;athis?this:e:v()}));function jt(e,t){var n,r;if(1===t.length&&i(t[0])&&(t=t[0]),!t.length)return Vt();for(n=t[0],r=1;r=0?new Date(e+400,t,n)-dn:new Date(e,t,n).valueOf()}function fn(e,t,n){return e<100&&e>=0?Date.UTC(e+400,t,n)-dn:Date.UTC(e,t,n)}function pn(e,t){U(0,[e,e.length],0,t)}function vn(e,t,n,r,a){var i;return null==e?qe(this,r,a).year:(t>(i=Je(e,r,a))&&(t=i),_n.call(this,e,t,n,r,a))}function _n(e,t,n,r,a){var i=Ke(e,t,n,r,a),o=Ue(i.year,0,i.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}U(0,["gg",2],0,(function(){return this.weekYear()%100})),U(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),pn("gggg","weekYear"),pn("ggggg","weekYear"),pn("GGGG","isoWeekYear"),pn("GGGGG","isoWeekYear"),V("weekYear","gg"),V("isoWeekYear","GG"),A("weekYear",1),A("isoWeekYear",1),ue("G",ie),ue("g",ie),ue("GG",Z,J),ue("gg",Z,J),ue("GGGG",ne,$),ue("gggg",ne,$),ue("GGGGG",re,X),ue("ggggg",re,X),pe(["gggg","ggggg","GGGG","GGGGG"],(function(e,t,n,r){t[r.substr(0,2)]=L(e)})),pe(["gg","GG"],(function(e,t,n,r){t[r]=a.parseTwoDigitYear(e)})),U("Q",0,"Qo","quarter"),V("quarter","Q"),A("quarter",7),ue("Q",q),fe("Q",(function(e,t){t[ye]=3*(L(e)-1)})),U("D",["DD",2],"Do","date"),V("date","D"),A("date",9),ue("D",Z),ue("DD",Z,J),ue("Do",(function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient})),fe(["D","DD"],Me),fe("Do",(function(e,t){t[Me]=L(e.match(Z)[0])}));var yn=De("Date",!0);U("DDD",["DDDD",3],"DDDo","dayOfYear"),V("dayOfYear","DDD"),A("dayOfYear",4),ue("DDD",te),ue("DDDD",G),fe(["DDD","DDDD"],(function(e,t,n){n._dayOfYear=L(e)})),U("m",["mm",2],0,"minute"),V("minute","m"),A("minute",14),ue("m",Z),ue("mm",Z,J),fe(["m","mm"],ge);var Mn=De("Minutes",!1);U("s",["ss",2],0,"second"),V("second","s"),A("second",15),ue("s",Z),ue("ss",Z,J),fe(["s","ss"],we);var bn,gn=De("Seconds",!1);for(U("S",0,0,(function(){return~~(this.millisecond()/100)})),U(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),U(0,["SSS",3],0,"millisecond"),U(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),U(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),U(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),U(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),U(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),U(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),V("millisecond","ms"),A("millisecond",16),ue("S",te,q),ue("SS",te,J),ue("SSS",te,G),bn="SSSS";bn.length<=9;bn+="S")ue(bn,ae);function wn(e,t){t[Le]=L(1e3*("0."+e))}for(bn="S";bn.length<=9;bn+="S")fe(bn,wn);var Ln=De("Milliseconds",!1);U("z",0,0,"zoneAbbr"),U("zz",0,0,"zoneName");var zn=b.prototype;function kn(e){return e}zn.add=tn,zn.calendar=function(e,t){var n=e||Vt(),r=Bt(n,this).startOf("day"),i=a.calendarFormat(this,r)||"sameElse",o=t&&(D(t[i])?t[i].call(this,n):t[i]);return this.format(o||this.localeData().calendar(i,this,Vt(n)))},zn.clone=function(){return new b(this)},zn.diff=function(e,t,n){var r,a,i;if(!this.isValid())return NaN;if(!(r=Bt(e,this)).isValid())return NaN;switch(a=6e4*(r.utcOffset()-this.utcOffset()),t=E(t)){case"year":i=rn(this,r)/12;break;case"month":i=rn(this,r);break;case"quarter":i=rn(this,r)/3;break;case"second":i=(this-r)/1e3;break;case"minute":i=(this-r)/6e4;break;case"hour":i=(this-r)/36e5;break;case"day":i=(this-r-a)/864e5;break;case"week":i=(this-r-a)/6048e5;break;default:i=this-r}return n?i:w(i)},zn.endOf=function(e){var t;if(void 0===(e=E(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?fn:hn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=un-mn(t+(this._isUTC?0:this.utcOffset()*ln),un)-1;break;case"minute":t=this._d.valueOf(),t+=ln-mn(t,ln)-1;break;case"second":t=this._d.valueOf(),t+=sn-mn(t,sn)-1}return this._d.setTime(t),a.updateOffset(this,!0),this},zn.format=function(e){e||(e=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var t=B(this,e);return this.localeData().postformat(t)},zn.from=function(e,t){return this.isValid()&&(g(e)&&e.isValid()||Vt(e).isValid())?$t({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},zn.fromNow=function(e){return this.from(Vt(),e)},zn.to=function(e,t){return this.isValid()&&(g(e)&&e.isValid()||Vt(e).isValid())?$t({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},zn.toNow=function(e){return this.to(Vt(),e)},zn.get=function(e){return D(this[e=E(e)])?this[e]():this},zn.invalidAt=function(){return f(this).overflow},zn.isAfter=function(e,t){var n=g(e)?e:Vt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=E(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()9999?B(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):D(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",B(n,"Z")):B(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},zn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',r=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=t+'[")]';return this.format(n+r+"-MM-DD[T]HH:mm:ss.SSS"+a)},zn.toJSON=function(){return this.isValid()?this.toISOString():null},zn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},zn.unix=function(){return Math.floor(this.valueOf()/1e3)},zn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},zn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},zn.year=Ye,zn.isLeapYear=function(){return Te(this.year())},zn.weekYear=function(e){return vn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},zn.isoWeekYear=function(e){return vn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},zn.quarter=zn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},zn.month=Fe,zn.daysInMonth=function(){return Ce(this.year(),this.month())},zn.week=zn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},zn.isoWeek=zn.isoWeeks=function(e){var t=qe(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},zn.weeksInYear=function(){var e=this.localeData()._week;return Je(this.year(),e.dow,e.doy)},zn.isoWeeksInYear=function(){return Je(this.year(),1,4)},zn.date=yn,zn.day=zn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=function(e,t){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=t.weekdaysParse(e))?e:null:parseInt(e,10)}(e,this.localeData()),this.add(e-t,"d")):t},zn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},zn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=function(e,t){return"string"==typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7},zn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},zn.hour=zn.hours=st,zn.minute=zn.minutes=Mn,zn.second=zn.seconds=gn,zn.millisecond=zn.milliseconds=Ln,zn.utcOffset=function(e,t,n){var r,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null!=e){if("string"==typeof e){if(null===(e=Ut(ce,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(r=Kt(this)),this._offset=e,this._isUTC=!0,null!=r&&this.add(r,"m"),i!==e&&(!t||this._changeInProgress?en(this,$t(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?i:Kt(this)},zn.utc=function(e){return this.utcOffset(0,e)},zn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Kt(this),"m")),this},zn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Ut(oe,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},zn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?Vt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},zn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},zn.isLocal=function(){return!!this.isValid()&&!this._isUTC},zn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},zn.isUtc=qt,zn.isUTC=qt,zn.zoneAbbr=function(){return this._isUTC?"UTC":""},zn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},zn.dates=H("dates accessor is deprecated. Use date instead.",yn),zn.months=H("months accessor is deprecated. Use month instead",Fe),zn.years=H("years accessor is deprecated. Use year instead",Ye),zn.zone=H("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",(function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()})),zn.isDSTShifted=H("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",(function(){if(!c(this._isDSTShifted))return this._isDSTShifted;var e={};if(y(e,this),(e=xt(e))._a){var t=e._isUTC?h(e._a):Vt(e._a);this._isDSTShifted=this.isValid()&&z(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}));var Hn=x.prototype;function Tn(e,t,n,r){var a=vt(),i=h().set(r,t);return a[n](i,e)}function Sn(e,t,n){if(s(e)&&(t=e,e=void 0),e=e||"",null!=t)return Tn(e,t,n,"month");var r,a=[];for(r=0;r<12;r++)a[r]=Tn(e,r,n,"month");return a}function Yn(e,t,n,r){"boolean"==typeof e?(s(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,s(t)&&(n=t,t=void 0),t=t||"");var a,i=vt(),o=e?i._week.dow:0;if(null!=n)return Tn(t,(n+o)%7,r,"day");var c=[];for(a=0;a<7;a++)c[a]=Tn(t,(a+o)%7,r,"day");return c}Hn.calendar=function(e,t,n){var r=this._calendar[e]||this._calendar.sameElse;return D(r)?r.call(t,n):r},Hn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,(function(e){return e.slice(1)})),this._longDateFormat[e])},Hn.invalidDate=function(){return this._invalidDate},Hn.ordinal=function(e){return this._ordinal.replace("%d",e)},Hn.preparse=kn,Hn.postformat=kn,Hn.relativeTime=function(e,t,n,r){var a=this._relativeTime[n];return D(a)?a(e,t,n,r):a.replace(/%d/i,e)},Hn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return D(n)?n(t):n.replace(/%s/i,t)},Hn.set=function(e){var t,n;for(n in e)D(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},Hn.months=function(e,t){return e?i(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||Ve).test(t)?"format":"standalone"][e.month()]:i(this._months)?this._months:this._months.standalone},Hn.monthsShort=function(e,t){return e?i(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[Ve.test(t)?"format":"standalone"][e.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Hn.monthsParse=function(e,t,n){var r,a,i;if(this._monthsParseExact)return je.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),r=0;r<12;r++){if(a=h([2e3,r]),n&&!this._longMonthsParse[r]&&(this._longMonthsParse[r]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[r]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[r]||(i="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[r]=new RegExp(i.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[r].test(e))return r;if(n&&"MMM"===t&&this._shortMonthsParse[r].test(e))return r;if(!n&&this._monthsParse[r].test(e))return r}},Hn.monthsRegex=function(e){return this._monthsParseExact?(d(this,"_monthsRegex")||Re.call(this),e?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=Ie),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},Hn.monthsShortRegex=function(e){return this._monthsParseExact?(d(this,"_monthsRegex")||Re.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=Ne),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},Hn.week=function(e){return qe(e,this._week.dow,this._week.doy).week},Hn.firstDayOfYear=function(){return this._week.doy},Hn.firstDayOfWeek=function(){return this._week.dow},Hn.weekdays=function(e,t){var n=i(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?Ge(n,this._week.dow):e?n[e.day()]:n},Hn.weekdaysMin=function(e){return!0===e?Ge(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},Hn.weekdaysShort=function(e){return!0===e?Ge(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},Hn.weekdaysParse=function(e,t,n){var r,a,i;if(this._weekdaysParseExact)return Qe.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),r=0;r<7;r++){if(a=h([2e3,1]).day(r),n&&!this._fullWeekdaysParse[r]&&(this._fullWeekdaysParse[r]=new RegExp("^"+this.weekdays(a,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[r]=new RegExp("^"+this.weekdaysShort(a,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[r]=new RegExp("^"+this.weekdaysMin(a,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[r]||(i="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[r]=new RegExp(i.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[r].test(e))return r;if(n&&"ddd"===t&&this._shortWeekdaysParse[r].test(e))return r;if(n&&"dd"===t&&this._minWeekdaysParse[r].test(e))return r;if(!n&&this._weekdaysParse[r].test(e))return r}},Hn.weekdaysRegex=function(e){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||rt.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=et),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},Hn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||rt.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=tt),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Hn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||rt.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=nt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Hn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},Hn.meridiem=function(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"},ft("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===L(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),a.lang=H("moment.lang is deprecated. Use moment.locale instead.",ft),a.langData=H("moment.langData is deprecated. Use moment.localeData instead.",vt);var Dn=Math.abs;function On(e,t,n,r){var a=$t(t,n);return e._milliseconds+=r*a._milliseconds,e._days+=r*a._days,e._months+=r*a._months,e._bubble()}function xn(e){return e<0?Math.floor(e):Math.ceil(e)}function Cn(e){return 4800*e/146097}function Vn(e){return 146097*e/4800}function En(e){return function(){return this.as(e)}}var Pn=En("ms"),jn=En("s"),An=En("m"),Fn=En("h"),Nn=En("d"),In=En("w"),Rn=En("M"),Wn=En("Q"),Un=En("y");function Bn(e){return function(){return this.isValid()?this._data[e]:NaN}}var Kn=Bn("milliseconds"),qn=Bn("seconds"),Jn=Bn("minutes"),Gn=Bn("hours"),$n=Bn("days"),Xn=Bn("months"),Zn=Bn("years"),Qn=Math.round,er={ss:44,s:45,m:45,h:22,d:26,M:11};function tr(e,t,n,r,a){return a.relativeTime(t||1,!!n,e,r)}var nr=Math.abs;function rr(e){return(e>0)-(e<0)||+e}function ar(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=nr(this._milliseconds)/1e3,r=nr(this._days),a=nr(this._months);e=w(n/60),t=w(e/60),n%=60,e%=60;var i=w(a/12),o=a%=12,c=r,s=t,l=e,u=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var m=d<0?"-":"",h=rr(this._months)!==rr(d)?"-":"",f=rr(this._days)!==rr(d)?"-":"",p=rr(this._milliseconds)!==rr(d)?"-":"";return m+"P"+(i?h+i+"Y":"")+(o?h+o+"M":"")+(c?f+c+"D":"")+(s||l||u?"T":"")+(s?p+s+"H":"")+(l?p+l+"M":"")+(u?p+u+"S":"")}var ir=Ft.prototype;return ir.isValid=function(){return this._isValid},ir.abs=function(){var e=this._data;return this._milliseconds=Dn(this._milliseconds),this._days=Dn(this._days),this._months=Dn(this._months),e.milliseconds=Dn(e.milliseconds),e.seconds=Dn(e.seconds),e.minutes=Dn(e.minutes),e.hours=Dn(e.hours),e.months=Dn(e.months),e.years=Dn(e.years),this},ir.add=function(e,t){return On(this,e,t,1)},ir.subtract=function(e,t){return On(this,e,t,-1)},ir.as=function(e){if(!this.isValid())return NaN;var t,n,r=this._milliseconds;if("month"===(e=E(e))||"quarter"===e||"year"===e)switch(t=this._days+r/864e5,n=this._months+Cn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Vn(this._months)),e){case"week":return t/7+r/6048e5;case"day":return t+r/864e5;case"hour":return 24*t+r/36e5;case"minute":return 1440*t+r/6e4;case"second":return 86400*t+r/1e3;case"millisecond":return Math.floor(864e5*t)+r;default:throw new Error("Unknown unit "+e)}},ir.asMilliseconds=Pn,ir.asSeconds=jn,ir.asMinutes=An,ir.asHours=Fn,ir.asDays=Nn,ir.asWeeks=In,ir.asMonths=Rn,ir.asQuarters=Wn,ir.asYears=Un,ir.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*L(this._months/12):NaN},ir._bubble=function(){var e,t,n,r,a,i=this._milliseconds,o=this._days,c=this._months,s=this._data;return i>=0&&o>=0&&c>=0||i<=0&&o<=0&&c<=0||(i+=864e5*xn(Vn(c)+o),o=0,c=0),s.milliseconds=i%1e3,e=w(i/1e3),s.seconds=e%60,t=w(e/60),s.minutes=t%60,n=w(t/60),s.hours=n%24,o+=w(n/24),a=w(Cn(o)),c+=a,o-=xn(Vn(a)),r=w(c/12),c%=12,s.days=o,s.months=c,s.years=r,this},ir.clone=function(){return $t(this)},ir.get=function(e){return e=E(e),this.isValid()?this[e+"s"]():NaN},ir.milliseconds=Kn,ir.seconds=qn,ir.minutes=Jn,ir.hours=Gn,ir.days=$n,ir.weeks=function(){return w(this.days()/7)},ir.months=Xn,ir.years=Zn,ir.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=function(e,t,n){var r=$t(e).abs(),a=Qn(r.as("s")),i=Qn(r.as("m")),o=Qn(r.as("h")),c=Qn(r.as("d")),s=Qn(r.as("M")),l=Qn(r.as("y")),u=a<=er.ss&&["s",a]||a0,u[4]=n,tr.apply(null,u)}(this,!e,t);return e&&(n=t.pastFuture(+this,n)),t.postformat(n)},ir.toISOString=ar,ir.toString=ar,ir.toJSON=ar,ir.locale=an,ir.localeData=cn,ir.toIsoString=H("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ar),ir.lang=on,U("X",0,0,"unix"),U("x",0,0,"valueOf"),ue("x",ie),ue("X",/[+-]?\d+(\.\d{1,3})?/),fe("X",(function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))})),fe("x",(function(e,t,n){n._d=new Date(L(e))})),a.version="2.24.0",t=Vt,a.fn=zn,a.min=function(){return jt("isBefore",[].slice.call(arguments,0))},a.max=function(){return jt("isAfter",[].slice.call(arguments,0))},a.now=function(){return Date.now?Date.now():+new Date},a.utc=h,a.unix=function(e){return Vt(1e3*e)},a.months=function(e,t){return Sn(e,t,"months")},a.isDate=l,a.locale=ft,a.invalid=v,a.duration=$t,a.isMoment=g,a.weekdays=function(e,t,n){return Yn(e,t,n,"weekdays")},a.parseZone=function(){return Vt.apply(null,arguments).parseZone()},a.localeData=vt,a.isDuration=Nt,a.monthsShort=function(e,t){return Sn(e,t,"monthsShort")},a.weekdaysMin=function(e,t,n){return Yn(e,t,n,"weekdaysMin")},a.defineLocale=pt,a.updateLocale=function(e,t){if(null!=t){var n,r,a=lt;null!=(r=ht(e))&&(a=r._config),t=O(a,t),(n=new x(t)).parentLocale=ut[e],ut[e]=n,ft(e)}else null!=ut[e]&&(null!=ut[e].parentLocale?ut[e]=ut[e].parentLocale:null!=ut[e]&&delete ut[e]);return ut[e]},a.locales=function(){return T(ut)},a.weekdaysShort=function(e,t,n){return Yn(e,t,n,"weekdaysShort")},a.normalizeUnits=E,a.relativeTimeRounding=function(e){return void 0===e?Qn:"function"==typeof e&&(Qn=e,!0)},a.relativeTimeThreshold=function(e,t){return void 0!==er[e]&&(void 0===t?er[e]:(er[e]=t,"s"===e&&(er.ss=t-1),!0))},a.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},a.prototype=zn,a.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},a}()}).call(this,n(309)(e))},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(234)},function(e,t,n){var r;
+/*!
+ Copyright (c) 2017 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/!function(){"use strict";var n={}.hasOwnProperty;function a(){for(var e=[],t=0;t0&&void 0!==arguments[0]?arguments[0]:{};return Object.keys(e).reduce((function(t,n){var r=e[n];switch(n){case"class":t.className=r,delete t.class;break;default:t[n]=r}return t}),{})}var f=function(){function e(){o()(this,e),this.collection={}}return s()(e,[{key:"clear",value:function(){this.collection={}}},{key:"delete",value:function(e){return delete this.collection[e]}},{key:"get",value:function(e){return this.collection[e]}},{key:"has",value:function(e){return Boolean(this.collection[e])}},{key:"set",value:function(e,t){return this.collection[e]=t,this}},{key:"size",get:function(){return Object.keys(this.collection).length}}]),e}();function p(e,t,n){return n?u.createElement(e.tag,a()({key:t},h(e.attrs),n),(e.children||[]).map((function(n,r){return p(n,t+"-"+e.tag+"-"+r)}))):u.createElement(e.tag,a()({key:t},h(e.attrs)),(e.children||[]).map((function(n,r){return p(n,t+"-"+e.tag+"-"+r)})))}function v(e){return Object(l.generate)(e)[0]}function _(e,t){switch(t){case"fill":return e+"-fill";case"outline":return e+"-o";case"twotone":return e+"-twotone";default:throw new TypeError("Unknown theme type: "+t+", name: "+e)}}}).call(this,n(62))},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var a=(o=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */"),i=r.sources.map((function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"}));return[n].concat(i).concat([a]).join("\n")}var o;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},a=0;a=0&&d.splice(t,1)}function _(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var r=function(){0;return n.nc}();r&&(e.attrs.nonce=r)}return y(t,e.attrs),p(e,t),t}function y(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function M(e,t){var n,r,a,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var o=u++;n=l||(l=_(t)),r=w.bind(null,n,o,!1),a=w.bind(null,n,o,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),p(e,t),t}(t),r=z.bind(null,n,t),a=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=_(t),r=L.bind(null,n),a=function(){v(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else a()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=o()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=f(e,t);return h(n,t),function(e){for(var r=[],a=0;a=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},g=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},w=function(e){return"object"===(void 0===e?"undefined":p(e))&&e.constructor===Object},L=Object.freeze([]),z=Object.freeze({});function k(e){return"function"==typeof e}function H(e){return e.displayName||e.name||"Component"}function T(e){return e&&"string"==typeof e.styledComponentId}var S=void 0!==e&&(e.env.REACT_APP_SC_ATTR||e.env.SC_ATTR)||"data-styled",Y="undefined"!=typeof window&&"HTMLElement"in window,D="boolean"==typeof SC_DISABLE_SPEEDY&&SC_DISABLE_SPEEDY||void 0!==e&&(e.env.REACT_APP_SC_DISABLE_SPEEDY||e.env.SC_DISABLE_SPEEDY)||!1;var O=function(e){function t(n){v(this,t);for(var r=arguments.length,a=Array(r>1?r-1:0),i=1;i0?" Additional arguments: "+a.join(", "):"")));return g(o)}return M(t,e),t}(Error),x=/^[^\S\n]*?\/\* sc-component-id:\s*(\S+)\s+\*\//gm,C=function(e){var t=""+(e||""),n=[];return t.replace(x,(function(e,t,r){return n.push({componentId:t,matchIndex:r}),e})),n.map((function(e,r){var a=e.componentId,i=e.matchIndex,o=n[r+1];return{componentId:a,cssFromDOM:o?t.slice(i,o.matchIndex):t.slice(i)}}))},V=/^\s*\/\/.*$/gm,E=new a.a({global:!1,cascade:!0,keyframe:!1,prefix:!1,compress:!1,semicolon:!0}),P=new a.a({global:!1,cascade:!0,keyframe:!1,prefix:!0,compress:!1,semicolon:!1}),j=[],A=function(e){if(-2===e){var t=j;return j=[],t}},F=o()((function(e){j.push(e)})),N=void 0,I=void 0,R=void 0,W=function(e,t,n){return t>0&&-1!==n.slice(0,t).indexOf(I)&&n.slice(t-I.length,t)!==I?"."+N:e};P.use([function(e,t,n){2===e&&n.length&&n[0].lastIndexOf(I)>0&&(n[0]=n[0].replace(R,W))},F,A]),E.use([F,A]);var U=function(e){return E("",e)};function B(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"&",a=e.join("").replace(V,""),i=t&&n?n+" "+t+" { "+a+" }":a;return N=r,I=t,R=new RegExp("\\"+I+"\\b","g"),P(n||!t?"":t,i)}var K=function(){return n.nc},q=function(e,t,n){n&&((e[t]||(e[t]=Object.create(null)))[n]=!0)},J=function(e,t){e[t]=Object.create(null)},G=function(e){return function(t,n){return void 0!==e[t]&&e[t][n]}},$=function(e){var t="";for(var n in e)t+=Object.keys(e[n]).join(" ")+" ";return t.trim()},X=function(e){if(e.sheet)return e.sheet;for(var t=e.ownerDocument.styleSheets.length,n=0;n"+e()+""}},ne=function(e,t){return function(){var n,r=((n={})[S]=$(t),n["data-styled-version"]="4.4.1",n),a=K();return a&&(r.nonce=a),s.a.createElement("style",y({},r,{dangerouslySetInnerHTML:{__html:e()}}))}},re=function(e){return function(){return Object.keys(e)}},ae=function(e,t){return e.createTextNode(Q(t))},ie=function e(t,n){var r=void 0===t?Object.create(null):t,a=void 0===n?Object.create(null):n,i=function(e){var t=a[e];return void 0!==t?t:a[e]=[""]},o=function(){var e="";for(var t in a){var n=a[t][0];n&&(e+=Q(t)+n)}return e};return{clone:function(){var t=function(e){var t=Object.create(null);for(var n in e)t[n]=y({},e[n]);return t}(r),n=Object.create(null);for(var i in a)n[i]=[a[i][0]];return e(t,n)},css:o,getIds:re(a),hasNameForId:G(r),insertMarker:i,insertRules:function(e,t,n){i(e)[0]+=t.join(" "),q(r,e,n)},removeRules:function(e){var t=a[e];void 0!==t&&(t[0]="",J(r,e))},sealed:!1,styleTag:null,toElement:ne(o,r),toHTML:te(o,r)}},oe=function(e,t,n,r,a){if(Y&&!n){var i=function(e,t,n){var r=document;e?r=e.ownerDocument:t&&(r=t.ownerDocument);var a=r.createElement("style");a.setAttribute(S,""),a.setAttribute("data-styled-version","4.4.1");var i=K();if(i&&a.setAttribute("nonce",i),a.appendChild(r.createTextNode("")),e&&!t)e.appendChild(a);else{if(!t||!e||!t.parentNode)throw new O(6);t.parentNode.insertBefore(a,n?t:t.nextSibling)}return a}(e,t,r);return D?function(e,t){var n=Object.create(null),r=Object.create(null),a=void 0!==t,i=!1,o=function(t){var a=r[t];return void 0!==a?a:(r[t]=ae(e.ownerDocument,t),e.appendChild(r[t]),n[t]=Object.create(null),r[t])},c=function(){var e="";for(var t in r)e+=r[t].data;return e};return{clone:function(){throw new O(5)},css:c,getIds:re(r),hasNameForId:G(n),insertMarker:o,insertRules:function(e,r,c){for(var s=o(e),l=[],u=r.length,d=0;d0&&(i=!0,t().insertRules(e+"-import",l))},removeRules:function(o){var c=r[o];if(void 0!==c){var s=ae(e.ownerDocument,o);e.replaceChild(s,c),r[o]=s,J(n,o),a&&i&&t().removeRules(o+"-import")}},sealed:!1,styleTag:e,toElement:ne(c,n),toHTML:te(c,n)}}(i,a):function(e,t){var n=Object.create(null),r=Object.create(null),a=[],i=void 0!==t,o=!1,c=function(e){var t=r[e];return void 0!==t?t:(r[e]=a.length,a.push(0),J(n,e),r[e])},s=function(){var t=X(e).cssRules,n="";for(var i in r){n+=Q(i);for(var o=r[i],c=ee(a,o),s=c-a[o];s0&&(o=!0,t().insertRules(r+"-import",f)),a[u]+=h,q(n,r,l)},removeRules:function(c){var s=r[c];if(void 0!==s&&!1!==e.isConnected){var l=a[s];!function(e,t,n){for(var r=t-n,a=t;a>r;a-=1)e.deleteRule(a)}(X(e),ee(a,s)-1,l),a[s]=0,J(n,c),i&&o&&t().removeRules(c+"-import")}},sealed:!1,styleTag:e,toElement:ne(s,n),toHTML:te(s,n)}}(i,a)}return ie()},ce=/\s+/,se=void 0;se=Y?D?40:1e3:-1;var le=0,ue=void 0,de=function(){function e(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Y?document.head:null,r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];v(this,e),this.getImportRuleTag=function(){var e=t.importRuleTag;if(void 0!==e)return e;var n=t.tags[0];return t.importRuleTag=oe(t.target,n?n.styleTag:null,t.forceServer,!0)},le+=1,this.id=le,this.forceServer=r,this.target=r?null:n,this.tagMap={},this.deferred={},this.rehydratedNames={},this.ignoreRehydratedNames={},this.tags=[],this.capacity=1,this.clones=[]}return e.prototype.rehydrate=function(){if(!Y||this.forceServer)return this;var e=[],t=[],n=!1,r=document.querySelectorAll("style["+S+'][data-styled-version="4.4.1"]'),a=r.length;if(!a)return this;for(var i=0;i0&&void 0!==arguments[0]&&arguments[0];ue=new e(void 0,t).rehydrate()},e.prototype.clone=function(){var t=new e(this.target,this.forceServer);return this.clones.push(t),t.tags=this.tags.map((function(e){for(var n=e.getIds(),r=e.clone(),a=0;a1?t-1:0),r=1;r=4;)t=1540483477*(65535&(t=255&e.charCodeAt(a)|(255&e.charCodeAt(++a))<<8|(255&e.charCodeAt(++a))<<16|(255&e.charCodeAt(++a))<<24))+((1540483477*(t>>>16)&65535)<<16),r=1540483477*(65535&r)+((1540483477*(r>>>16)&65535)<<16)^(t=1540483477*(65535&(t^=t>>>24))+((1540483477*(t>>>16)&65535)<<16)),n-=4,++a;switch(n){case 3:r^=(255&e.charCodeAt(a+2))<<16;case 2:r^=(255&e.charCodeAt(a+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(a)))+((1540483477*(r>>>16)&65535)<<16)}return((r=1540483477*(65535&(r^=r>>>13))+((1540483477*(r>>>16)&65535)<<16))^r>>>15)>>>0}var ge=52,we=function(e){return String.fromCharCode(e+(e>25?39:97))};function Le(e){var t="",n=void 0;for(n=e;n>ge;n=Math.floor(n/ge))t=we(n%ge)+t;return we(n%ge)+t}function ze(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:z,r=!!n&&e.theme===n.theme,a=e.theme&&!r?e.theme:t||n.theme;return a},Ye=/[[\].#*$><+~=|^:(),"'`-]+/g,De=/(^-|-$)/g;function Oe(e){return e.replace(Ye,"-").replace(De,"")}function xe(e){return"string"==typeof e&&!0}var Ce={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDerivedStateFromProps:!0,propTypes:!0,type:!0},Ve={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},Ee=((ke={})[u.ForwardRef]={$$typeof:!0,render:!0},ke),Pe=Object.defineProperty,je=Object.getOwnPropertyNames,Ae=Object.getOwnPropertySymbols,Fe=void 0===Ae?function(){return[]}:Ae,Ne=Object.getOwnPropertyDescriptor,Ie=Object.getPrototypeOf,Re=Object.prototype,We=Array.prototype;function Ue(e,t,n){if("string"!=typeof t){var r=Ie(t);r&&r!==Re&&Ue(e,r,n);for(var a=We.concat(je(t),Fe(t)),i=Ee[e.$$typeof]||Ce,o=Ee[t.$$typeof]||Ce,c=a.length,s=void 0,l=void 0;c--;)if(l=a[c],!(Ve[l]||n&&n[l]||o&&o[l]||i&&i[l])&&(s=Ne(t,l)))try{Pe(e,l,s)}catch(e){}return e}return e}var Be=Object(c.createContext)(),Ke=Be.Consumer,qe=(function(e){function t(n){v(this,t);var r=g(this,e.call(this,n));return r.getContext=Object(d.a)(r.getContext.bind(r)),r.renderInner=r.renderInner.bind(r),r}M(t,e),t.prototype.render=function(){return this.props.children?s.a.createElement(Be.Consumer,null,this.renderInner):null},t.prototype.renderInner=function(e){var t=this.getContext(this.props.theme,e);return s.a.createElement(Be.Provider,{value:t},this.props.children)},t.prototype.getTheme=function(e,t){if(k(e))return e(t);if(null===e||Array.isArray(e)||"object"!==(void 0===e?"undefined":p(e)))throw new O(8);return y({},t,e)},t.prototype.getContext=function(e,t){return this.getTheme(e,t)}}(c.Component),function(){function e(){v(this,e),this.masterSheet=de.master,this.instance=this.masterSheet.clone(),this.sealed=!1}e.prototype.seal=function(){if(!this.sealed){var e=this.masterSheet.clones.indexOf(this.instance);this.masterSheet.clones.splice(e,1),this.sealed=!0}},e.prototype.collectStyles=function(e){if(this.sealed)throw new O(2);return s.a.createElement(Ge,{sheet:this.instance},e)},e.prototype.getStyleTags=function(){return this.seal(),this.instance.toHTML()},e.prototype.getStyleElement=function(){return this.seal(),this.instance.toReactElements()},e.prototype.interleaveWithNodeStream=function(e){throw new O(3)}}(),Object(c.createContext)()),Je=qe.Consumer,Ge=function(e){function t(n){v(this,t);var r=g(this,e.call(this,n));return r.getContext=Object(d.a)(r.getContext),r}return M(t,e),t.prototype.getContext=function(e,t){if(e)return e;if(t)return new de(t);throw new O(4)},t.prototype.render=function(){var e=this.props,t=e.children,n=e.sheet,r=e.target;return s.a.createElement(qe.Provider,{value:this.getContext(n,r)},t)},t}(c.Component),$e={};var Xe=function(e){function t(){v(this,t);var n=g(this,e.call(this));return n.attrs={},n.renderOuter=n.renderOuter.bind(n),n.renderInner=n.renderInner.bind(n),n}return M(t,e),t.prototype.render=function(){return s.a.createElement(Je,null,this.renderOuter)},t.prototype.renderOuter=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:de.master;return this.styleSheet=e,this.props.forwardedComponent.componentStyle.isStatic?this.renderInner():s.a.createElement(Ke,null,this.renderInner)},t.prototype.renderInner=function(e){var t=this.props.forwardedComponent,n=t.componentStyle,r=t.defaultProps,a=(t.displayName,t.foldedComponentIds),i=t.styledComponentId,o=t.target,s=void 0;s=n.isStatic?this.generateAndInjectStyles(z,this.props):this.generateAndInjectStyles(Se(this.props,e,r)||z,this.props);var l=this.props.as||this.attrs.as||o,u=xe(l),d={},h=y({},this.props,this.attrs),f=void 0;for(f in h)"forwardedComponent"!==f&&"as"!==f&&("forwardedRef"===f?d.ref=h[f]:"forwardedAs"===f?d.as=h[f]:u&&!Object(m.a)(f)||(d[f]=h[f]));return this.props.style&&this.attrs.style&&(d.style=y({},this.attrs.style,this.props.style)),d.className=Array.prototype.concat(a,i,s!==i?s:null,this.props.className,this.attrs.className).filter(Boolean).join(" "),Object(c.createElement)(l,d)},t.prototype.buildExecutionContext=function(e,t,n){var r=this,a=y({},t,{theme:e});return n.length?(this.attrs={},n.forEach((function(e){var t,n=e,i=!1,o=void 0,c=void 0;for(c in k(n)&&(n=n(a),i=!0),n)o=n[c],i||!k(o)||(t=o)&&t.prototype&&t.prototype.isReactComponent||T(o)||(o=o(a)),r.attrs[c]=o,a[c]=o})),a):a},t.prototype.generateAndInjectStyles=function(e,t){var n=t.forwardedComponent,r=n.attrs,a=n.componentStyle;n.warnTooManyClasses;return a.isStatic&&!r.length?a.generateAndInjectStyles(z,this.styleSheet):a.generateAndInjectStyles(this.buildExecutionContext(e,t,r),this.styleSheet)},t}(c.Component);function Ze(e,t,n){var r=T(e),a=!xe(e),i=t.displayName,o=void 0===i?function(e){return xe(e)?"styled."+e:"Styled("+H(e)+")"}(e):i,c=t.componentId,l=void 0===c?function(e,t,n){var r="string"!=typeof t?"sc":Oe(t),a=($e[r]||0)+1;$e[r]=a;var i=r+"-"+e.generateName(r+a);return n?n+"-"+i:i}(Te,t.displayName,t.parentComponentId):c,u=t.ParentComponent,d=void 0===u?Xe:u,m=t.attrs,f=void 0===m?L:m,p=t.displayName&&t.componentId?Oe(t.displayName)+"-"+t.componentId:t.componentId||l,v=r&&e.attrs?Array.prototype.concat(e.attrs,f).filter(Boolean):f,_=new Te(r?e.componentStyle.rules.concat(n):n,v,p),M=void 0,g=function(e,t){return s.a.createElement(d,y({},e,{forwardedComponent:M,forwardedRef:t}))};return g.displayName=o,(M=s.a.forwardRef(g)).displayName=o,M.attrs=v,M.componentStyle=_,M.foldedComponentIds=r?Array.prototype.concat(e.foldedComponentIds,e.styledComponentId):L,M.styledComponentId=p,M.target=r?e.target:e,M.withComponent=function(e){var r=t.componentId,a=b(t,["componentId"]),i=r&&r+"-"+(xe(e)?e:Oe(H(e)));return Ze(e,y({},a,{attrs:v,componentId:i,ParentComponent:d}),n)},Object.defineProperty(M,"defaultProps",{get:function(){return this._foldedDefaultProps},set:function(t){this._foldedDefaultProps=r?Object(h.a)(e.defaultProps,t):t}}),M.toString=function(){return"."+M.styledComponentId},a&&Ue(M,e,{attrs:!0,componentStyle:!0,displayName:!0,foldedComponentIds:!0,styledComponentId:!0,target:!0,withComponent:!0}),M}var Qe=function(e){return function e(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:z;if(!Object(u.isValidElementType)(n))throw new O(1,String(n));var a=function(){return t(n,r,Me.apply(void 0,arguments))};return a.withConfig=function(a){return e(t,n,y({},r,a))},a.attrs=function(a){return e(t,n,y({},r,{attrs:Array.prototype.concat(r.attrs,a).filter(Boolean)}))},a}(Ze,e)};["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr","circle","clipPath","defs","ellipse","foreignObject","g","image","line","linearGradient","marker","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","svg","text","tspan"].forEach((function(e){Qe[e]=Qe(e)}));!function(){function e(t,n){v(this,e),this.rules=t,this.componentId=n,this.isStatic=ze(t,L),de.master.hasId(n)||de.master.deferredInject(n,[])}e.prototype.createStyles=function(e,t){var n=B(ye(this.rules,e,t),"");t.inject(this.componentId,n)},e.prototype.removeStyles=function(e){var t=this.componentId;e.hasId(t)&&e.remove(t)},e.prototype.renderStyles=function(e,t){this.removeStyles(t),this.createStyles(e,t)}}();Y&&(window.scCGSHMRCache={});t.a=Qe}).call(this,n(62))},function(e,t,n){var r=n(13),a=n(14),i=n(69),o=n(24),c=n(20),s=function(e,t,n){var l,u,d,m=e&s.F,h=e&s.G,f=e&s.S,p=e&s.P,v=e&s.B,_=e&s.W,y=h?a:a[t]||(a[t]={}),M=y.prototype,b=h?r:f?r[t]:(r[t]||{}).prototype;for(l in h&&(n=t),n)(u=!m&&b&&void 0!==b[l])&&c(y,l)||(d=u?b[l]:n[l],y[l]=h&&"function"!=typeof b[l]?n[l]:v&&u?i(d,r):_&&b[l]==d?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(d):p&&"function"==typeof d?i(Function.call,d):d,p&&((y.virtual||(y.virtual={}))[l]=d,e&s.R&&M&&!M[l]&&o(M,l,d)))};s.F=1,s.G=2,s.S=4,s.P=8,s.B=16,s.W=32,s.U=64,s.R=128,e.exports=s},function(e,t,n){var r=n(19),a=n(33);e.exports=n(15)?function(e,t,n){return r.f(e,t,a(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){var r=n(73),a=n(50);e.exports=function(e){return r(a(e))}},function(e,t,n){var r=n(53)("wks"),a=n(36),i=n(13).Symbol,o="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=o&&i[e]||(o?i:a)("Symbol."+e))}).store=r},function(e,t,n){var r=n(227);"string"==typeof r&&(r=[[e.i,r,""]]);var a={hmr:!0,transform:void 0,insertInto:void 0};n(18)(r,a);r.locals&&(e.exports=r.locals)},function(e,t,n){var r=n(25);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){try{var r=n(68)}catch(e){r=n(68)}var a=/\s+/,i=Object.prototype.toString;function o(e){if(!e||!e.nodeType)throw new Error("A DOM element reference is required");this.el=e,this.list=e.classList}e.exports=function(e){return new o(e)},o.prototype.add=function(e){if(this.list)return this.list.add(e),this;var t=this.array();return~r(t,e)||t.push(e),this.el.className=t.join(" "),this},o.prototype.remove=function(e){if("[object RegExp]"==i.call(e))return this.removeMatching(e);if(this.list)return this.list.remove(e),this;var t=this.array(),n=r(t,e);return~n&&t.splice(n,1),this.el.className=t.join(" "),this},o.prototype.removeMatching=function(e){for(var t=this.array(),n=0;n=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}},function(e,t,n){"use strict";e.exports=n(294)},function(e,t,n){"use strict";var r=function(){};e.exports=r},function(e,t,n){"use strict";
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/var r=Object.getOwnPropertySymbols,a=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function o(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,c,s=o(e),l=1;l0?r:n)(e)}},function(e,t,n){var r=n(53)("keys"),a=n(36);e.exports=function(e){return r[e]||(r[e]=a(e))}},function(e,t,n){var r=n(14),a=n(13),i=a["__core-js_shared__"]||(a["__core-js_shared__"]={});(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})("versions",[]).push({version:r.version,mode:n(35)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,n){var r=n(50);e.exports=function(e){return Object(r(e))}},function(e,t){e.exports={}},function(e,t,n){var r=n(29),a=n(262),i=n(54),o=n(52)("IE_PROTO"),c=function(){},s=function(){var e,t=n(71)("iframe"),r=i.length;for(t.style.display="none",n(263).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("