commit cc434cf89f1a4a39d395387c73e114b955831acf Author: liangjiami <2249412933@qq.com> Date: Wed Oct 14 14:00:29 2026 +0800 init: 项目初始代码 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b13344 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +/.idea +/.vscode +/vendor +*.log +.env +/runtime +public/storage/* +public/gitea_webhook.php +public/.user.ini +public/ueditor +*.rar +*.zip +.DS_Store +*.sh +/public/attachmenet/resources/ +.DS_Store +public/.DS_Store +public/GeoLite2-City.mmdb +public/GeoLite2-Country.mmdb +public/admin +public/.well-known +pd.sh +pm.sh \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/.htaccess @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36f7b6f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +sudo: false + +language: php + +branches: + only: + - stable + +cache: + directories: + - $HOME/.composer/cache + +before_install: + - composer self-update + +install: + - composer install --no-dev --no-interaction --ignore-platform-reqs + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . + - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" + - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . + +script: + - php think unit + +deploy: + provider: releases + api_key: + secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= + file: + - ThinkPHP_Core.zip + - ThinkPHP_Full.zip + skip_cleanup: true + on: + tags: true diff --git a/404.html b/404.html new file mode 100644 index 0000000..6f17eaf --- /dev/null +++ b/404.html @@ -0,0 +1,7 @@ + +404 Not Found + +

404 Not Found

+
nginx
+ + \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..574a39c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,32 @@ + +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 +版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) +All rights reserved。 +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 + +Apache Licence是著名的非盈利开源组织Apache采用的协议。 +该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, +允许代码修改,再作为开源或商业软件发布。需要满足 +的条件: +1. 需要给代码的用户一份Apache Licence ; +2. 如果你修改了代码,需要在被修改的文件中说明; +3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 +带有原来代码中的协议,商标,专利声明和其他原来作者规 +定需要包含的说明; +4. 如果再发布的产品中包含一个Notice文件,则在Notice文 +件中需要带有本协议内容。你可以在Notice中增加自己的 +许可,但不可以表现为对Apache Licence构成更改。 +具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a5d4a5 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# setmspace Idsonix官网 + +> 此项目为内容管理系统的接口,包括前台与后台管理系统的接口,主要用于各子品牌官网 + +### 后台接口开发进度 +- [x] 登录模块 +- [x] 管理员模块 - 待梳理 +- [x] 商品模块 +- [x] 商品分类模块 +- [x] 优惠券模块 +- [x] 驱动文档模块 +- [x] 驱动文档类型模块 +- [x] 用户评论模块 +- [x] ask a question模块 +- [x] FAQ 分类模块 +- [x] FAQ模块 +- [x] 广告模块 +- [x] 广告位模块 +- [x] 广告页模块 +- [x] 角色模块 - 待梳理 +- [x] 组织模块 - 待梳理 +- [x] 部门模块 - 待梳理 +- [x] 站点模块 - 待梳理 +- [x] 语言包模块 - 待梳理 +- [x] 品牌(平台)模块 - 待梳理 +- [x] 导航栏模块 - 待梳理 +- [x] 全球国家模块 - 待梳理 +- [x] 文章模块 - 待梳理 +- [x] 日志模块 - 待梳理 +- [x] 大批量采购模块 - 待梳理 +- [x] 菜单模块 - 待梳理 +- [x] 币种模块 - 待梳理 + +### 执行下面命令可以部署到一台新环境里面 +```shell +git clone http://git.f2b211.com/orico_f2b211/setmspace.git +cd setmspace +cp .example.env .env + +``` +### 修复 `.env` 文件,配置好对应数据库参数,并且在数据库里面添加好数据库 +```shell +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +DATABASE = test +USERNAME = username +PASSWORD = password +HOSTPORT = 3306 +CHARSET = utf8 +DEBUG = true +PREFIX = t_ +``` + + +### 在项目根目录里面运行下面命令 +``` +composer install +php think migrate:run +# 下面命令只适合初次使用,后面重复使用会报错,并且会有各种小问题 +php think seed:run +``` \ No newline at end of file diff --git a/app/AppService.php b/app/AppService.php new file mode 100644 index 0000000..96556e8 --- /dev/null +++ b/app/AppService.php @@ -0,0 +1,22 @@ +app = $app; + $this->request = $this->app->request; + + // 控制器初始化 + $this->initialize(); + } + + // 初始化 + protected function initialize() + {} + + /** + * 验证数据 + * @access protected + * @param array $data 数据 + * @param string|array $validate 验证器名或者验证规则数组 + * @param array $message 提示信息 + * @param bool $batch 是否批量验证 + * @return array|string|true + * @throws ValidateException + */ + protected function validate(array $data, $validate, array $message = [], bool $batch = false) + { + if (is_array($validate)) { + $v = new Validate(); + $v->rule($validate); + } else { + if (strpos($validate, '.')) { + // 支持场景 + [$validate, $scene] = explode('.', $validate); + } + $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate); + $v = new $class(); + if (!empty($scene)) { + $v->scene($scene); + } + } + + $v->message($message); + + // 是否批量验证 + if ($batch || $this->batchValidate) { + $v->batch(true); + } + + return $v->failException(true)->check($data); + } + +} diff --git a/app/ExceptionHandle.php b/app/ExceptionHandle.php new file mode 100644 index 0000000..453d126 --- /dev/null +++ b/app/ExceptionHandle.php @@ -0,0 +1,58 @@ + [ + /* 上传图片配置项 */ + "imageActionName" => "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName" => "upfile", /* 提交的图片表单名称 */ + "imageMaxSize" => 204800000, /* 上传大小限制,单位B */ + "imageAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable"=> true, /* 是否压缩图片,默认是true */ + "imageCompressBorder"=> 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign" => "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix" => "", /* 图片访问路径前缀 */ + "imagePathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + ], + 'upload_scrawl' => [ + /* 涂鸦图片上传配置项 */ + "scrawlActionName" => "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName" => "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize" => 204800000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix" => "", /* 图片访问路径前缀 */ + "scrawlInsertAlign" => "none", + ], + 'upload_snap_image' => [ + /* 截图工具上传 */ + "snapscreenActionName" => "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix" => "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign" => "none", /* 插入的图片浮动方式 */ + ], + 'upload_catcher' => [ + /* 抓取远程图片配置 */ + "catcherLocalDomain" => ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName" => "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName" => "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix" => "", /* 图片访问路径前缀 */ + "catcherMaxSize" => 204800000, /* 上传大小限制,单位B */ + "catcherAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + ], + 'upload_video' => [ + /* 上传视频配置 */ + "videoActionName" => "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName" => "upfile", /* 提交的视频表单名称 */ + "videoPathFormat" => "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix" => "", /* 视频访问路径前缀 */ + "videoMaxSize" => 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles" => [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid" + ], /* 上传视频格式显示 */ + ], + 'upload_file' => [ + /* 上传文件配置 */ + "fileActionName" => "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName" => "upfile", /* 提交的文件表单名称 */ + "filePathFormat" => "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix" => "", /* 文件访问路径前缀 */ + "fileMaxSize" => 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles" => [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + ], + 'upload_list_image' => [ + /* 列出指定目录下的图片 */ + "imageManagerActionName" => "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath" => "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize" => 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix" => "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign" => "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + ], + 'upload_file_list' => [ + /* 列出指定目录下的文件 */ + "fileManagerActionName" => "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath" => "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix" => "", /* 文件访问路径前缀 */ + "fileManagerListSize" => 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles" => [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + ] +]; diff --git a/app/api/config/whitelist.php b/app/api/config/whitelist.php new file mode 100644 index 0000000..88aa931 --- /dev/null +++ b/app/api/config/whitelist.php @@ -0,0 +1,35 @@ + [ + 'v1/auth/login', + 'goods/ue_upload', + 'cdn/get_cdn_url', + + 'v1/auth/login_sso', + 'v1/goods/ue_upload', + 'v1/investment/export', + 'v1/cdn/get_cdn_url', + 'v1/nav/upload', + 'v1/comment/upload', + 'v1/ad/upload', + 'v1/soft_manual/upload', +// 'v1/soft_manual/check_file', + 'v1/goods/upload', + 'v1/plat/upload', + 'v1/lang/upload', + 'v1/video/upload', + 'v1/ad/uploadImg' + ], + + /*域名白名单*/ + 'domain' => [ +// 'yc.test', + ] + + +]; diff --git a/app/api/controller/v1/Admin.php b/app/api/controller/v1/Admin.php new file mode 100644 index 0000000..56ac838 --- /dev/null +++ b/app/api/controller/v1/Admin.php @@ -0,0 +1,90 @@ + '添加管理员失败', + self::ERR_EDIT => '编辑管理员失败', + self::ERR_FORBIDDEN => '禁用管理员失败', + self::EMPTY_ADMINID => 'id不能为空', + self::EMPTY_ADMIN => '没有找到该管理员' + ]; + + public function initialize() + { + parent::initialize(); + $this->validate = new AdminValidate(); + $this->model = new AdminModel(); + } + + protected $errorMsg = [ + self::EMPTY_ADMINID + ]; + + /** + * 显示指定的资源 + * + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function read() + { + $inputData = $this->request->param(['admin_id']); + + if ($inputData['admin_id'] <= 0) { + return $this->msg(self::EMPTY_ADMINID, self::ERROR[self::EMPTY_ADMINID]); + } + + $info = $this->model->getInfo($inputData['admin_id']); + if (empty($info)) { + return $this->msg(self::EMPTY_ADMIN, self::ERROR[self::EMPTY_ADMIN]); + } + return $this->msg(200, '获取管理员信息成功', $info); + } + + /** + * 保存更新的资源 + * + * @return \think\Response + */ + public function update() + { + $inputData = $this->request->param(['admin_id', 'password', 'role_id', 'mobile']); + $inputData['password'] = md5($inputData['password']); + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if ($inputData['password'] == '') { + unset($inputData['password']); + } + + $result = $this->model->edit($inputData); + + if ($result) { + return $this->msg(200, '编辑管理员成功'); + } else { + return $this->msg(504, '编辑管理员失败'); + } + + } +} diff --git a/app/api/controller/v1/AdvertisePage.php b/app/api/controller/v1/AdvertisePage.php new file mode 100644 index 0000000..9419e11 --- /dev/null +++ b/app/api/controller/v1/AdvertisePage.php @@ -0,0 +1,98 @@ +validate = new AdvertisePageValidate(); + $this->model = new AdvertisePageModel(); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + $item['site_id'] = $item['language_id']; + unset($item['language_id']); + if (isset($item['id']) && $item['id'] != '') { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['site_id'], + 'name' => htmlspecialchars($item['name']), + 'platform_id'=>$this->platformId + ]; + } else { + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => htmlspecialchars($item['name']), + 'site_id' => $item['site_id'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getAdSpace($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该广告页下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/AdvertiseSpace.php b/app/api/controller/v1/AdvertiseSpace.php new file mode 100644 index 0000000..258f3ae --- /dev/null +++ b/app/api/controller/v1/AdvertiseSpace.php @@ -0,0 +1,126 @@ +validate = new AdvertiseSpaceValidate(); + $this->model = new AdvertiseSpaceModel(); + } + + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (isset($inputData['advertise_page_id']) && $inputData['advertise_page_id'] != '' && $inputData['advertise_page_id'] != 0) { + $this->focus['advertise_page_id'] = $inputData['advertise_page_id']; + } + $this->orderby['create_time'] = 'desc'; + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + + return $this->msg(200,'获取列表成功',$result); + } + + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //修改前,先判断广告位数量 上限,如果已经使用的位置比当前修改提交过来的 数量大,则不让修改 + $useNum = $this->model->getUseSpaceNum($inputData); + if ($useNum > $inputData['max_num']) { + return $this->msg(504,'此广告位已经使用了'.$useNum.',不能修改比使用数量小的数值!'); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + + /** + * 获取可用的列表 + */ + public function invalidList():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + $result = $this->model->getList($inputData); +// $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + if ($result) { + foreach ($result as $key => $item) { + if ($result[$key]['max_num'] - $result[$key]['use_num'] <= 0) { + $result[$key]['is_show'] = 0; //不显示列表项 + } else { + $result[$key]['is_show'] = 1; //显示列表项 + } + } + } + //查询出当前广告位已经存在多少广告, + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getAd($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该广告位已经被使用,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Advertisement.php b/app/api/controller/v1/Advertisement.php new file mode 100644 index 0000000..09826ce --- /dev/null +++ b/app/api/controller/v1/Advertisement.php @@ -0,0 +1,124 @@ +validate = new AdvertisementValidate(); + $this->model = new AdvertisementModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + + if (isset($inputData['advertise_space_id']) && $inputData['advertise_space_id'] != '' && $inputData['advertise_space_id'] != 0) { + $this->focus['advertise_space_id'] = $inputData['advertise_space_id']; + } + + if (isset($inputData['name']) && $inputData['name'] != '') { + $this->simple['name'] = $inputData['name']; + } + + $this->order['create_time'] = 'desc'; + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //动态检测数据是否完整 + $isExitsSpace = $this->model->dynamicCheck(\app\api\model\AdvertiseSpace::class,['id'=>$inputData['advertise_space_id']]); + if (!$isExitsSpace) { + return $this->msg(504,'广告位数据有变动,请重新填写再提交!'); + } + //查询是否满足广告位数量上限 + $isFull = $this->model->getAdvertiseSpaceMaxNum($inputData['advertise_space_id']); + $useNum = $this->model->getAdvertiseUseSpaceNum($inputData); + if ($useNum+1 > $isFull) { + return $this->msg(504,'广告位已经数量达到上限!'); + } + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //动态检测数据是否完整 + $isExitsSpace = $this->model->dynamicCheck(\app\api\model\AdvertiseSpace::class,['id'=>$inputData['advertise_space_id']]); + if (!$isExitsSpace) { + return $this->msg(504,'广告位数据有变动,请重新填写再提交!'); + } + //查询是否满足广告位数量上限 + $isFull = $this->model->getAdvertiseSpaceMaxNum($inputData['advertise_space_id']); + $useNum = $this->model->getAdvertiseUseSpaceNum($inputData); + //判断是自己修改,还是其他条目修改过来 + $ret = $this->model->getBeforeUpdate($inputData); + $useNum = $ret ? $useNum : $useNum + 1; + if ($useNum > $isFull) { + return $this->msg(504,'广告位已经数量达到上限!'); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } +} diff --git a/app/api/controller/v1/Article.php b/app/api/controller/v1/Article.php new file mode 100644 index 0000000..fe514d9 --- /dev/null +++ b/app/api/controller/v1/Article.php @@ -0,0 +1,135 @@ +validate = new ArticleValidate(); + $this->model = new ArticleModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['article_type_id']) && $inputData['article_type_id'] != '' && $inputData['article_type_id'] != 0) { + $this->focus['article_type_id'] = $inputData['article_type_id']; + } + + if (isset($inputData['title']) && $inputData['title'] != '') { + $this->simple['title'] = $inputData['title']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time']) && !$inputData['create_time']) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time'])) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + +} diff --git a/app/api/controller/v1/ArticleType.php b/app/api/controller/v1/ArticleType.php new file mode 100644 index 0000000..bbdd881 --- /dev/null +++ b/app/api/controller/v1/ArticleType.php @@ -0,0 +1,131 @@ +validate = new ArticleTypeValidate(); + $this->model = new ArticleTypeModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //兼容新方式 + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->orderby['sort'] = $inputData['sort']; + } else { + $this->orderby['sort'] = 'asc'; + } + + $this->field = ['id','platform_id','site_id','icon','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($item['id']) && $item['id'] != '') { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['language_id'], + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } else { + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'site_id' => $item['language_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getArticleData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Attribute.php b/app/api/controller/v1/Attribute.php new file mode 100644 index 0000000..336791f --- /dev/null +++ b/app/api/controller/v1/Attribute.php @@ -0,0 +1,73 @@ +model = new AttributeModel(); + $this->validate = new AttributeValidate(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (isset($inputData['page']) && $inputData['page'] != '') { + $this->page = $inputData['page']; + } + + if (isset($inputData['size']) && $inputData['size'] != '') { + $this->page = $inputData['size']; + } + + $result = $this->model->getIndexList($this->page,$this->size,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $hasGoodsAttr = $this->model->getGoodsAttrById($inputData); + + if (!$hasGoodsAttr) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"此属性有商品引用,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Auth.php b/app/api/controller/v1/Auth.php new file mode 100644 index 0000000..6f1fcda --- /dev/null +++ b/app/api/controller/v1/Auth.php @@ -0,0 +1,157 @@ + '该用户不存在', + self::ERR_PASSWORD => '用户名或密码错误', + self::ERR_TOKEN => 'token解析失败', + self::EMPTY_ROLE => '当前用户没有分配角色', + self::ERR_CLOSED => '该用户被禁用', + self::ERR_PWD => '旧密码错误', + self::EMPTY_HEADIMG => '请选择头像', + self::ERR_MOBILE => '手机号格式错误', + self::ERR_SAMEPWD => '新密码不能与旧密码相同' + ]; + + //后台管理员控制器 + protected $validate = null; + //定义管理员模型 + protected $model = null; + //定义管理员模型 + protected $roleModel = null; + + public function initialize() + { + parent::initialize(); + $this->model = new model(); + $this->validate = new AdminValidate(); + $this->roleModel = new RoleModel(); + } + + + /** + * 后台登录接口 + */ + public function login() + { + //获取输入数据 + $inputData = $this->request->param(['username', 'password']); + //验证器验证 + $this->commonValidate(__FUNCTION__,$inputData); + + $adminInfo = $this->model->getInfoByUsername($inputData['username']); + + if (empty($adminInfo)) { + return $this->msg(self::EMPTY_ADMIN, self::ERROR[self::EMPTY_ADMIN]); + } + + if ($inputData['password'] != $adminInfo['password']) { + return $this->msg(self::ERR_PASSWORD, self::ERROR[self::ERR_PASSWORD]); + } + + if ($adminInfo['status'] == 1) { + return $this->msg(self::ERR_CLOSED, self::ERROR[self::ERR_CLOSED]); + } + unset($adminInfo['password']); + $login_token = $this->jwt->getToken($adminInfo); + Cache::set('api-info',$adminInfo,300); + $data = [ + 'login_token' => $login_token, + 'exp' => Env::get('jwt_config.exp'), + 'need_update_pwd' => $inputData['password'] == md5('Aa-1221') ? 1 : 0 + ]; + return $this->msg(200, '登录成功', $data); + } + + /** + * 获取管理员基本信息 + */ + public function info() + { + $role = $this->roleModel->getInfo($this->adminInfo); + if (empty($role)) { + return $this->msg(self::EMPTY_ROLE, self::ERROR[self::EMPTY_ROLE]); + } + + $data = [ + 'roles' => [$role['role_name'] ?? $role['name']], + 'name' => $this->adminInfo['username'], + 'avatar' => $this->adminInfo['avatar'] + ]; + + return $this->msg(200, '获取用户信息成功', $data); + } + + /** + * 获取用户所有权限 + */ + public function getAuth() + { + $data = [ + 'auth_list' => $this->adminInfo['auth_id_list'] + ]; + return $this->msg(200, '获取权限成功', $data); + } + + /** + * 退出登录 + */ + public function logout() + { + if (!Session::has('signed_in') || !Session::get('signed_in')) { + return success('操作成功'); + } + $sso = new SSOClient(); + $access_token = Session::get('access_token'); + if (empty($access_token)) { + return error('请选登录'); + } + $result = $sso->notifySSOServerSigninOut($access_token, Session::get('uc_sessid')); + if (empty($result)) { + return error('操作失败'); + } + if (0 != $result['errno']) { + return error($result['errmsg']); + } + Session::clear(); + return success('操作成功'); + } + + /** + * 管理员列表 + */ + public function list(){ + + } + + +} diff --git a/app/api/controller/v1/Base.php b/app/api/controller/v1/Base.php new file mode 100644 index 0000000..18d6d41 --- /dev/null +++ b/app/api/controller/v1/Base.php @@ -0,0 +1,1138 @@ +'test'] + * @var null + */ + protected $simple = []; + + /** + * 精准查询,精确字段,格式['language_id'=> 1] + * @var null + */ + protected $focus = []; + + /** + * 排序字段。格式 ['sort'=>'desc'] + * @var null + */ + protected $order = []; + + /** + * 筛选字段,用于提交给前端需要显示哪些数据库字段数据, + * @var null + */ + protected $field = []; + + /** + * 模型 + * @var null + */ + protected $model = null; + + /** + * 验证器 + * @var null + */ + protected $validate = null; + + /** + * 七牛云 + * @var null + */ + protected $qn = null; + + /** + * 分页页码 + * @var integer + */ + protected $page = 0; + + /** + * 分页数量 + * @var integer + */ + protected $size = 0; + + /** + * 接口监控数据 + * @var string[] + */ + protected $apiLog = [ + 'items' => '', + 'forum' => '',/*模块-中文*/ + 'forum_code'=> '',/*模块日志编码*/ + 'refer' => '',/*引用接口页*/ + 'source' => '',/*数据来源标识*/ + 'source_code'=> '',/*接口地址*/ + 'source_name'=> '',/*接口调用地址*/ + 'state' => '',/*结果状态*/ + 'date_time' => '',/*生成时间*/ + 'start_time'=> '',/*开始时间*/ + 'end_time' => '',/*结束时间*/ + 'elapsed_time'=>'',/*耗时*/ + 'ip' => '',/*访客IP*/ + 'country' => '',/*国家*/ + 'city' => '',/*城市*/ + 'area' => '',/*地区*/ + 'system' => '',/*设备系统*/ + 'version' => '',/*系统版本*/ + 'brower' => '',/*浏览器*/ + 'models' => '',/*设备型号*/ + 'beginCode' => '',/*传值参数*/ + 'reurnCode' => '',/*返回结果*/ + ]; + + /** + * 初始化方法 + */ + public function initialize() + { + //初始化用户信息 + $this->adminInfo = $this->request->admin_user_info; + $config = [ + 'iss' => Env::get('jwt_config.iss'), + 'exp' => Env::get('jwt_config.exp') + ]; + $this->jwt = new Jwt($config); + $this->platformId = 1; + $this->qn = new QiniuUploader(); + // + if ($this->request->param('page') != '') { + $this->page = $this->request->param('page/d',1); + } + if ($this->request->param('size') != '') { + $this->size = $this->request->param('size/d',10); + } + //请求来源页 + $this->apiLog['items'] = Env::get('platform_name','官网'); + $this->apiLog['refer'] = $this->request->server('HTTP_REFERER'); + $this->apiLog['source'] = $this->request->server('HTTP_REFERER'); + $this->apiLog['source_code'] = $this->request->domain().$this->request->server('REQUEST_URI'); + $this->apiLog['source_name'] = $this->request->server('REQUEST_URI'); + //获取应用启动时间 + $this->apiLog['start_time'] = $this->app->getBeginTime(); + //获取访问设备,系统版本,浏览器,设备型号 + $userAgent = $this->request->server('HTTP_USER_AGENT'); + AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE); + $dd = new DeviceDetector($userAgent); + $dd->parse(); + + if ($dd->isBot()) { + $this->apiLog['brower'] = '未知'; + $this->apiLog['system'] = '未知'; + $this->apiLog['version'] = '未知'; + $this->apiLog['models'] = '爬虫'; + } else { + $clientInfo = $dd->getClient(); + $osInfo = $dd->getOs(); + $device = $dd->getDeviceName(); + $brand = $dd->getBrandName(); + $model = $dd->getModel(); + $this->apiLog['brower'] = !empty($clientInfo) ? $clientInfo['name'].' '.$clientInfo['version'] : '未知'; + $this->apiLog['system'] = !empty($osInfo) ? $osInfo['name'].' '.$osInfo['version'] : '未知'; + $this->apiLog['version'] = $osInfo['version']??''; + $this->apiLog['models'] = $device . " " . $brand . " ". $model; + } + //解析IP地址,得到国家,城市,地址, + $visitIp = get_client_ip(); + $this->apiLog['ip'] = $visitIp; + + if (!filter_var($visitIp,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_NULL_ON_FAILURE)) { + $this->apiLog['country'] = '本地'; + $this->apiLog['city'] = '本地'; + $this->apiLog['area'] = '本地'; + } else { + $reader = new Reader(public_path() . '/GeoLite2-City.mmdb'); + $record = $reader->city($visitIp); + $this->apiLog['country'] = $record->country->names['zh-CN']; + $this->apiLog['city'] = $record->city->name; + $this->apiLog['area'] = $record->city->name; + } + } + + /** + * 全局接口返回 + * @param int $status 状态码 + * @param string $message 消息提示 + * @param array $data 返回的数据内容 + */ + public function msg(int $status,string $message,array $data = []):\think\response\Json + { + $route = strtolower($this->request->pathinfo()); + $pathInfo = explode('/',$route); + $this->apiLog['state'] = $status; + $this->apiLog['forum'] = $pathInfo[1]??''; + $this->apiLog['forum_code'] = $status == 200 ? 0 : 1; + $this->apiLog['date_time'] = date('Y-m-d H:i:s',time()); + $this->apiLog['end_time'] = microtime(true); + $this->apiLog['elapsed_time'] = round((float)($this->apiLog['end_time'] - $this->apiLog['start_time']),6); + $this->apiLog['end_time'] = date('Y-m-d H:i:s',time()); + $this->apiLog['start_time'] = date('Y-m-d H:i:s',(int)$this->app->getBeginTime()); + $this->apiLog['beginCode'] = json_encode($this->request->param()); + $this->apiLog['reurnCode'] = $status == 200 ? 'SUCCESS' : 'ERROR'; + //返回信息前,写入kafka log日志 + if (!Env::get('APP_DEBUG')) { +// $this->sendLogsToKafkaProduce($this->apiLog,'api_logs',Env::get('database.database'),'api'); + $this->asyncApiLog($this->apiLog,'api_logs','api'); + } + header("Content-Type: application/json; charset=UTF-8"); + $result = [ + 'status' => $status, + 'message' => $message, + 'data' => $data + ]; + return json($result); + } + + /** + * PHP发送Json对象数据 + * + * @param string $url 请求url + * @param string $jsonStr 发送的json字符串 + * @param string $Bearer + * @return array + */ + public function curlJson(string $url, string $jsonStr,string $Bearer = ''):array + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json; charset=utf-8', + 'Content-Length: ' . strlen($jsonStr), + 'Bearer:' . $Bearer + ) + ); + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + return array('status' => $httpCode, 'data' => $response); + } + + /** + * 全局验证器验证方法 + * + * @param string $functionName 当前控制器需要验证的方法名 + * @param array $inputData 当前控制器需要验证的数据 + */ + public function commonValidate(string $functionName,array $inputData):bool + { + //验证器验证 + return $this->validate->scene($functionName)->check($inputData); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getIndexList($this->page,$this->size,$this->field, $this->simple, $this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 详情 + */ + public function read():\think\Response\Json + { + $inputData = $this->request->param(['id']); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getInfo($inputData); + if ($result) { + $result['language_id'] = $result['site_id']; + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(200,'获取列表成功',[]); + } + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + //语言包 + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['site_id']) || !empty($inputData['site_id']) || $inputData['site_id'] != 0) { + $this->focus['site_id'] = $inputData['site_id']; + } else { + return $this->msg(504,'语言包/所属站点参数,不正确,请检查!'); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 图片,ICON上传 + */ + public function upload():\think\Response\Json + { + $files = $this->request->file(); + if (!$files) { + return $this->msg(-1, "请选择上传的文件"); + } + $field = array_keys($files)[0]; + $data = []; + //兼容多图上传 + if (is_array($files) && count($files) > 1 ) { + //不同字段文件名上传 image img ico + //上传到七牛 + foreach ($files as $key => $fileSimple) { + if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { + return $this->msg(-1, $this->validate->getError()); + } + $result[$key] = $this->qn->uploadFile($key); + } + + foreach ($result as $key => $item) { + $data[] = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$key]->getOriginalName(), + 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], + 'md5' => md5_file($files[$key]->getPathname()), + 'url' => $item['remote_url'], + 'relative_path' => $item['filename'] + ]; + } + } elseif (is_array($files[$field]) && count($files[$field]) > 1) { + //同一名称的数组文件上传.image[0] image[1] + foreach ($files as $key => $fileSimple) { + if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { + return $this->msg(-1, $this->validate->getError()); + } + } + //上传到七牛 + $result = $this->qn->uploadFile($field, true, count($files[$field])); + + foreach ($result as $key => $item) { + $data[] = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$field][$key]->getOriginalName(), + 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], + 'md5' => md5_file($files[$field][$key]->getPathname()), + 'url' => $item['remote_url'], + 'relative_path' => $item['filename'] + ]; + } + } else { + if (!$this->commonValidate(__FUNCTION__,[$field=>$files])) { + return $this->msg(-1,$this->validate->getError()); + } + //上传到七牛 + $result = $this->qn->uploadFile($field); + $data = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$field]->getOriginalName(), + 'filename' => explode('/',$result['filename'])[count(explode('/',$result['filename']))-1], + 'md5' => md5_file($files[$field]->getPathname()), + 'url' => $result['remote_url'], + 'relative_path' => $result['filename'] + ]; + } + + return $this->msg(200, '上传成功', $data); + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } + + /** + * 列表树 + */ + public function tree():\think\Response\Json + { + $inputData = $this->request->param(); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $list = $this->model->getAllList($inputData); + $tree = list_to_tree($list); + return $this->msg(200, '获取列表成功', $tree); + } + + /** + * 排序 + */ + public function sort():\think\Response\Json + { + $inputData = $this->request->param(['id','sort']); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,"排序成功"); + } else { + return $this->msg(504,"排序失败"); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(['id','status']); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } + + /** + * 批量新增 + */ + public function batchCreate():\think\Response\Json + { + $inputData = $this->request->param(); + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $item['platform_id'] = $this->platformId; + } + } + $result = $this->model->saveAll($inputData['data']); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 批量更新 + */ + public function batchUpdate():\think\Response\Json + { + $inputData = $this->request->param(); + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $item['platform_id'] = $this->platformId; + } + } + + $result = $this->model->batchEditData($inputData['data']); + + if ($result) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + /** + * 百度富文本上传 + * @throws \Exception + */ + public function ueditorUpload():\think\Response\Json + { + header("Access-Control-Allow-Origin:*"); + header("Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE,OPTIONS"); + header("Access-Control-Allow-Headers:Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With,x_requested_with,x-token"); + + $action = $this->request->param(); + $config = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents(root_path()."extend/utils/ueditor_config.json")), true); + //替换前台图片后缀 + $config['imageUrlPrefix'] = Env::get('QINIU.cdn'); + $config['scrawlUrlPrefix'] = Env::get('QINIU.cdn'); + $config['snapscreenUrlPrefix'] = Env::get('QINIU.cdn'); + $config['catcherUrlPrefix'] = Env::get('QINIU.cdn'); + $config['videoUrlPrefix'] = Env::get('QINIU.cdn'); + $config['fileUrlPrefix'] = Env::get('QINIU.cdn'); + $config['imageManagerUrlPrefix'] = Env::get('QINIU.cdn'); + $config['fileManagerUrlPrefix'] = Env::get('QINIU.cdn'); + + $action['action'] ?? $action['action'] = 'config'; + switch ($action['action']) { + case 'uploadimage': + $fieldName = $config['imageFieldName']; + $config = [ + "pathFormat" => $config['imagePathFormat'], + "maxSize" => $config['imageMaxSize'], + "allowFiles" => $config['imageAllowFiles'] + ]; + break; + case 'uploadscrawl': + $fieldName = $config['scrawlFieldName']; + $config = [ + "pathFormat" => $config['scrawlPathFormat'], + "maxSize" => $config['scrawlMaxSize'], + "allowFiles" => $config['scrawlAllowFiles'], + "oriName" => "scrawl.png" + ]; + break; + case 'uploadvideo': + $fieldName = $config['videoFieldName']; + $config = [ + "pathFormat" => $config['videoPathFormat'], + "maxSize" => $config['videoMaxSize'], + "allowFiles" => $config['videoAllowFiles'] + ]; + break; + case 'uploadfile': + + $fieldName = $config['fileFieldName']; + $config = [ + "pathFormat" => $config['filePathFormat'], + "maxSize" => $config['fileMaxSize'], + "allowFiles" => $config['fileAllowFiles'] + ]; + break; + case 'config': + default: + echo isset($action['callback']) ? $action['callback'].'('.json_encode($config).')': '('.json_encode($config).')';die; + } + + $up = new UEUploader($fieldName, $config); + $resultData = $up->getFileInfo(); + if ($resultData['state'] == 'SUCCESS') { + //本地文件上传七牛云 + $qn = new QiniuUploader(); + $res = $qn->uploadLocalFile(public_path().$resultData['url'],$resultData['url']); + $data = [ + "state" => "SUCCESS", + "title" => $resultData["title"], + "original" => $resultData["original"], + "type" => $resultData["type"], + "size" => $resultData["size"], + 'cdn' => Env::get('QINIU.cdn'), + 'filename' => explode('/',$res['filename'])[count(explode('/',$res['filename']))-1], +// 'url' => $res['remote_url'], + 'url' => $res['filename'], + 'relative_path' => $res['filename'] + ]; + echo json_encode($data);die; + } else { + echo "上传失败";die; + } + } + + /** + * 静态cdn域名 + */ + public function getCDNUrl():\think\Response\Json + { + $data = [ + 'domain' => Env::get('QINIU.cdn','') + ]; + return $this->msg(200,'获取成功',$data); + } + + + /** + * Excel导入 + */ + public function import():\think\Response\Json + { + $file = $this->request->file('file'); + if (!$file) { + return $this->msg(-1,'没有上传文件'); + } +// if ($this->commonValidate(__FUNCTION__,['file'=>$file])) { +// return json($this->message(true)); +// } + $filename = Filesystem::disk('public')->putFile('', $file, 'unique_id'); + $filePath = public_path().'storage/' . $filename; + if (!is_file($filePath)) { + return $this->msg(-1,'没找到数据'); + } + //实例化reader + $ext = pathinfo($filePath, PATHINFO_EXTENSION); + if (!in_array($ext, ['csv', 'xls', 'xlsx'])) { + return $this->msg(-1,'文件格式不对'); + } + if ($ext === 'csv') { + $file = fopen($filePath, 'r'); + $filePath = tempnam(sys_get_temp_dir(), 'import_csv'); + $fp = fopen($filePath, "w"); + $n = 0; + while ($line = fgets($file)) { + $line = rtrim($line, "\n\r\0"); + $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']); + if ($encoding != 'utf-8') { + $line = mb_convert_encoding($line, 'utf-8', $encoding); + } + if ($n == 0 || preg_match('/^".*"$/', $line)) { + fwrite($fp, $line . "\n"); + } else { + fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n"); + } + $n++; + } + fclose($file) || fclose($fp); + + $reader = new Csv(); + } elseif ($ext === 'xls') { + $reader = new Xls(); + } else { + $reader = new Xlsx(); + } + //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name + $table = $this->model->getTable(); + $database = Env::get('database.database'); + $fieldArr = []; + $list = Db::query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); + foreach ($list as $v) { + if ($this->importHeadType == 'comment') { + $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; + } else { + $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_NAME']; + } + } + //加载文件 + $insert = []; + try { + if (!$PHPExcel = $reader->load($filePath)) { + return $this->msg(-1,'没找到数据'); + } + $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表 + $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号 + $allRow = $currentSheet->getHighestRow(); //取得一共有多少行 + $maxColumnNumber = Coordinate::columnIndexFromString($allColumn); + $fields = []; + for ($currentRow = 1; $currentRow <= 1; $currentRow++) { + for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { + $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); + $fields[] = $val; + } + } + for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) { + $values = []; + for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { + $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); + $values[] = is_null($val) ? '' : $val; + } + $row = []; + $temp = array_combine($fields, $values); + foreach ($temp as $k => $v) { + if (isset($fieldArr[$k]) && $k !== '') { + $row[$fieldArr[$k]] = $v; + } + } + if ($row) { + $insert[] = $row; + } + } + //需要关联查询的字段,进行关联相询翻译 + } catch (\Exception $exception) { + return $this->msg(-1,$exception->getMessage()); + } + + //批量新增 + try { + $count = 0; + $failCount = 0; +// foreach ($insert as $item) { +// if ($this->commonValidate(__FUNCTION__,$item)) { +// $failCount++; +// continue; +// } + $res = $this->model->save($insert[0]); +// $count++; +// } + + if (count($insert) > $count) { + return $this->msg(-1,'总共【'.count($insert).'】,成功导入【'.$count.'】条记录,还有【'.(count($insert) - $count).'】条记录未导入成功'); + } else { + return $this->msg(200,'总共【'.count($insert).'】,成功导入【'.$count.'】条记录,有【'.(count($insert) - $count).'】条记录未导入成功'); + } + + } catch (PDOException $exception) { + $this->msg = $exception->getMessage(); + if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $this->msg, $matches)) { + $this->msg = "导入失败,包含【{$matches[1]}】的记录已存在"; + return $this->msg(-1,"导入失败,包含【{$matches[1]}】的记录已存在"); + } + return $this->msg(-1,$exception->getMessage()); + } catch (\Exception $e) { + return $this->msg(-1,$e->getMessage()); + } + } + + /** + * Excel导出, + * @param array $data + * @param int $count + * @param string $fileName + * @param array $options + * @return \think\Response\Json + */ + protected function excelExport(array $data = [], int $count = 10 ,string $fileName = '', array $options = []):\think\Response\Json + { + try { + if (empty($data)) { + return $this->msg(-1,'没有选择需要导出的数据'); + } + set_time_limit(0); + $objSpreadsheet = new Spreadsheet(); + //设置全局字体,大小 + $styleArray = [ + 'font' => [ + 'bold' => false, + 'color' => ['rgb'=>'000000'], + 'size' => 14, + 'name' => 'Verdana' + ] + ]; + $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray); + /* 设置默认文字居左,上下居中 */ + $styleArray = [ + 'alignment' => [ + 'horizontal' => Alignment::HORIZONTAL_LEFT, + 'vertical' => Alignment::VERTICAL_CENTER, + ], + ]; + $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray); + /* 设置Excel Sheet */ + $activeSheet = $objSpreadsheet->setActiveSheetIndex(0); + + /* 打印设置 */ + if (isset($options['print']) && $options['print']) { + /* 设置打印为A4效果 */ + $activeSheet->getPageSetup()->setPaperSize(PageSetup:: PAPERSIZE_A4); + + /* 设置打印时边距 */ + $pValue = 1 / 2.54; + $activeSheet->getPageMargins()->setTop($pValue / 2); + $activeSheet->getPageMargins()->setBottom($pValue * 2); + $activeSheet->getPageMargins()->setLeft($pValue / 2); + $activeSheet->getPageMargins()->setRight($pValue / 2); + } + + $row = 2; + $col = 0; + /* 行数据处理 */ + foreach ($data as $sKey => $sItem) { + /* 默认文本格式 */ + $pDataType = DataType::TYPE_STRING; + /* 设置单元格格式 */ + if (isset($options['format']) && !empty($options['format'])) { + $colRow = Coordinate::coordinateFromString($sKey); + + /* 存在该列格式并且有特殊格式 */ + if (isset($options['format'][$colRow[0]]) && + NumberFormat::FORMAT_GENERAL != $options['format'][$colRow[0]]) { + $activeSheet->getStyle($sKey)->getNumberFormat() + ->setFormatCode($options['format'][$colRow[0]]); + + if (false !== strpos($options['format'][$colRow[0]], '0.00') && + is_numeric(str_replace(['¥', ','], '', $sItem))) { + /* 数字格式转换为数字单元格 */ + $pDataType = DataType::TYPE_NUMERIC; + $sItem = str_replace(['¥', ','], '', $sItem); + } + } elseif (is_int($sItem)) { + $pDataType = DataType::TYPE_NUMERIC; + } + } + + if ($col < count($options['alignCenter'])) { + if (strlen($sItem) <= 255) { + $activeSheet->getColumnDimension($options['alignCenter'][$col])->setWidth(100); + } else { + $activeSheet->getColumnDimension($options['alignCenter'][$col])->setAutoSize(true); + } + } + $activeSheet->getRowDimension($row)->setRowHeight(30); + $activeSheet->setCellValueExplicit($sKey, $sItem, $pDataType); + $row++; + $col++; + /* 存在:形式的合并行列,列入A1:B2,则对应合并 */ + if (false !== strstr($sKey, ":")) { + $options['mergeCells'][$sKey] = $sKey; + } + if (is_image(public_path().$sItem) && file_exists(public_path().$sItem)) { + $activeSheet->setCellValueExplicit($sKey, '', $pDataType); + $drawing = new Drawing(); + $drawing->setName('Logo'); + $drawing->setDescription('Logo'); + $drawing->setPath(Env::get('root_path').'public'.$sItem); + $drawing->setResizeProportional(false); + $drawing->setHeight(60); + $drawing->setCoordinates($sKey); + $drawing->setOffsetX(12); + $drawing->setOffsetY(12); + $drawing->getShadow()->setVisible(true); +// $drawing->getShadow()->setDirection(45); + $drawing->setWorksheet($objSpreadsheet->getActiveSheet()); + } + } + unset($data); + /* 设置锁定行 */ + if (isset($options['freezePane']) && !empty($options['freezePane'])) { + $activeSheet->freezePane($options['freezePane']); + unset($options['freezePane']); + } + /* 设置宽度 */ + if (isset($options['setWidth']) && !empty($options['setWidth'])) { + foreach ($options['setWidth'] as $swKey => $swItem) { + $activeSheet->getColumnDimension($swKey)->setWidth($swItem); + } + unset($options['setWidth']); + } else { + $end = $count + 64 > 80 ? 80 : $count + 64; + foreach(range(chr(65),chr($end)) as $columnID) { + $activeSheet->getColumnDimension($columnID)->setAutoSize(true); + } + } + /* 设置背景色 */ + if (isset($options['setARGB']) && !empty($options['setARGB'])) { + foreach ($options['setARGB'] as $sItem) { + $activeSheet->getStyle($sItem) + ->getFill()->setFillType(Fill::FILL_SOLID) + ->getStartColor()->setARGB(Color::COLOR_YELLOW); + } + + unset($options['setARGB']); + } + /* 设置公式 */ + if (isset($options['formula']) && !empty($options['formula'])) { + foreach ($options['formula'] as $fKey => $fItem) { + $activeSheet->setCellValue($fKey, $fItem); + } + + unset($options['formula']); + } + /* 合并行列处理 */ + if (isset($options['mergeCells']) && !empty($options['mergeCells'])) { + $activeSheet->setMergeCells($options['mergeCells']); + unset($options['mergeCells']); + } + /* 设置居中 */ + if (isset($options['alignCenter']) && !empty($options['alignCenter'])) { + $styleArray = [ + 'alignment' => [ + 'horizontal' => Alignment::HORIZONTAL_LEFT, + 'vertical' => Alignment::VERTICAL_CENTER, + ], + ]; + + foreach ($options['alignCenter'] as $acItem) { + $activeSheet->getStyle($acItem)->applyFromArray($styleArray); + } + + unset($options['alignCenter']); + } + /* 设置加粗 */ + if (isset($options['bold']) && !empty($options['bold'])) { + foreach ($options['bold'] as $bItem) { + $activeSheet->getStyle($bItem)->getFont()->setBold(true); + } + + unset($options['bold']); + } + /* 设置单元格边框,整个表格设置即可,必须在数据填充后才可以获取到最大行列 */ + if (isset($options['setBorder']) && $options['setBorder']) { + $border = [ + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => Border::BORDER_THIN, // 设置border样式 + 'color' => ['argb' => 'FF000000'], // 设置border颜色 + ], + ], + ]; + $setBorder = 'A1:' . $activeSheet->getHighestColumn() . $activeSheet->getHighestRow(); + $activeSheet->getStyle($setBorder)->applyFromArray($border); + unset($options['setBorder']); + } + + $fileName = !empty($fileName) ? $fileName : (date('YmdHis') . '.xlsx'); + + if (!isset($options['savePath'])) { + /* 直接导出Excel,无需保存到本地,输出07Excel文件 */ + header('Content-Type: application/vnd.ms-excel,application/x-rar-compressed,application/vnd.openxmlformats-officedocument.wordprocessingml.document; Charset=UTF-8'); + header('Access-Control-Expose-Headers: Content-Disposition'); +// header( +// "Content-Disposition:attachment;filename=" . iconv( +// "utf-8", "GB2312//TRANSLIT", $fileName +// ) +// ); + header("Content-Disposition:attachment;filename=" . $fileName); + header('Cache-Control: max-age=0');//禁止缓存 + header("Content-Transfer-Encoding:binary"); + $savePath = 'php://output'; + } else { + $savePath = $options['savePath']; + } + ob_clean(); + ob_start(); + $objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx'); + $objWriter->save($savePath); + /* 释放内存 */ + $objSpreadsheet->disconnectWorksheets(); + unset($objSpreadsheet); + ob_end_flush(); + exit; + } catch (\Exception $e) { + return $this->msg(-1,$e->getMessage()); + } + } + + /** + * 表格导出数据前置方法 + */ + public function export():\think\Response\Json + { + $ids = $this->request->param(); + if ($this->commonValidate(__FUNCTION__,$ids)) { + return $this->msg(-1,''); + } + $data = $this->model->getExportData($ids); + //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name + $this->importHeadType = 'name'; + $table = $this->model->getTable(); + $database = Env::get('database.database'); + //字段名与注释的数组, + $fieldArr = []; + $list = Db::query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); + foreach ($list as $v) { + if ($this->importHeadType == 'comment') { + $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; + } else { + $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_COMMENT']; + } + } + + $newData = [];/*表格数据*/ + $newHeader = [];/*表格表头*/ + $cols = []; /*分别占用表格哪几列*/ + if (array_key_exists(0,$data)) { + $header = array_keys($data[0]); + foreach ($header as $k => $v) { + if ($k <= 25) { + $newHeader[chr($k+65).'1'] = $fieldArr[$v]?:$v; + $cols[$k] = chr($k+65); + } else { + $newHeader[chr(65).chr($k-26+65).'1'] = $fieldArr[$v]?:$v; + $cols[$k] = chr(65).chr($k-26+65); + } + + } + } + + foreach ($data as $k => $v) { + $index = 0; + foreach ($v as $v1) { + if ($index <= 25) { + $header = chr($index+65); + $header .= $k+2; + $newData[$header] = $v1;/*获取表头*/ + } else { + $header = chr(65).chr($index-26+65); + $header .= $k+2; + $newData[$header] = $v1;/*获取表头*/ + } + $index++; + } + } + $newData = array_merge($newHeader,$newData); + $options = [ + 'print' =>false, + 'freezePane'=>'A2', +// 'setWidth'=>['A'=>40,'B'=>30,'C'=>20,'D'=>25,'E'=>20,'F'=>15,'G'=>10,'H'=>10], + 'setBorder'=>true, + 'alignCenter'=>$cols, + 'bold'=>array_keys($newHeader), + ]; + return $this->excelExport($newData,count($newHeader),'export-excel-'.time().'.xlsx',$options); + } + + /** + * 异步提交 + * @param array $apiLog 日志提交的数据 + * @param string $logType 日志类型 api_logs + * @param string $type 请求类型 api add queue + * @return string + */ + public function asyncApiLog(array $apiLog, string $logType, string $type):string + { + // 异步执行 +// Async::exec(LogToKafka::class, 'sendLogsToKafkaProduce', $apiLog,$logType,'user',$type); +// Async::execUseCustomQueue(self::class, 'test','async_exec_method_custom', 'exec'); + // 异步延迟执行 延迟20秒 + Async::delay(20, LogToKafka::class, 'sendLogsToKafkaProduce', $apiLog,$logType,Env::get('database.database'),$type); +// Async::delayUseCustomQueue(20, LogToKafka::class, 'sendLogsToKafkaProduce','async_exec_method_custom', $apiLog,$logType,Env::get('database.database'),$type); + return ''; + } + + /** + * 写入日志调试信息 + * @param array $data + * @param string $string + * @return void + */ + public function dLog(array $data,string $string = 'debug') : void + { + \think\facade\Log::record($string . " = ".json_encode($data)); + } +} diff --git a/app/api/controller/v1/Brand.php b/app/api/controller/v1/Brand.php new file mode 100644 index 0000000..ac82f42 --- /dev/null +++ b/app/api/controller/v1/Brand.php @@ -0,0 +1,135 @@ +validate = new BrandValidate(); + $this->model = new BrandModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['Brand_type_id']) && $inputData['Brand_type_id'] != '' && $inputData['Brand_type_id'] != 0) { + $this->focus['Brand_type_id'] = $inputData['Brand_type_id']; + } + + if (isset($inputData['title']) && $inputData['title'] != '') { + $this->simple['title'] = $inputData['title']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time']) && !$inputData['create_time']) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time'])) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + +} diff --git a/app/api/controller/v1/BrandType.php b/app/api/controller/v1/BrandType.php new file mode 100644 index 0000000..4202efc --- /dev/null +++ b/app/api/controller/v1/BrandType.php @@ -0,0 +1,131 @@ +validate = new BrandTypeValidate(); + $this->model = new BrandTypeModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //兼容新方式 + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->orderby['sort'] = $inputData['sort']; + } else { + $this->orderby['sort'] = 'asc'; + } + + $this->field = ['id','platform_id','site_id','icon','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($item['id']) && $item['id'] != '') { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['language_id'], + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } else { + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'site_id' => $item['language_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getArticleData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/BulkBuy.php b/app/api/controller/v1/BulkBuy.php new file mode 100644 index 0000000..35bca0c --- /dev/null +++ b/app/api/controller/v1/BulkBuy.php @@ -0,0 +1,44 @@ +model = new BulkBuyModel(); + $this->validate = new BulkBuyValidate(); + } + + /** + * 列表 + * @return \think\response\Json + */ + public function index() + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $this->orderby['create_time'] = 'desc'; + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + foreach ($result['page'] as $key => $item) { + $result['page'][$key]['area_name'] = $this->model->getAreaNameById(substr($item['area_id'],0,2)).$this->model->getAreaNameById($item['area_id']); + $result['page'][$key]['delivery_time'] = date('Y-m-d',$item['delivery_time']); + } + return $this->msg(200,'获取列表成功',$result); + } +} diff --git a/app/api/controller/v1/Comment.php b/app/api/controller/v1/Comment.php new file mode 100644 index 0000000..3ecc4b3 --- /dev/null +++ b/app/api/controller/v1/Comment.php @@ -0,0 +1,59 @@ +model = new CommentModel(); + $this->validate = new CommentValidate(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['nickname']) && $inputData['nickname'] != '') { + $this->simple['nickname'] = $inputData['nickname']; + } + + if (isset($inputData['comment']) && $inputData['comment'] != '') { + $this->simple['comment'] = $inputData['comment']; + } + + //正常数据验证器验证 + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (!empty($this->focus)) { + if (!$this->commonValidate(__FUNCTION__,$this->focus)) { + return $this->msg(-1,$this->validate->getError()); + } + } + $this->order['create_time'] = 'desc'; + //过滤字段 + $this->field = ['id','platform_id','language_id','site_id','avatar','name','nickname','comment','url','sort','create_time']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } +} diff --git a/app/api/controller/v1/Country.php b/app/api/controller/v1/Country.php new file mode 100644 index 0000000..de9ee63 --- /dev/null +++ b/app/api/controller/v1/Country.php @@ -0,0 +1,18 @@ +model = new CountryModel(); + } + +} diff --git a/app/api/controller/v1/CouponSubscribe.php b/app/api/controller/v1/CouponSubscribe.php new file mode 100644 index 0000000..e8e3c7e --- /dev/null +++ b/app/api/controller/v1/CouponSubscribe.php @@ -0,0 +1,41 @@ +model = new CouponSubscribeModel(); + $this->validate = new CouponSubscribeValidate(); + } + + /** + * 列表 + * @return \think\response\Json + */ + public function index() + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $this->orderby = ['create_time'=>'desc']; + $this->field = ['id','platform_id','site_id','email','phone','create_time']; + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + return $this->msg(200,'获取列表成功',$result); + } +} diff --git a/app/api/controller/v1/Currency.php b/app/api/controller/v1/Currency.php new file mode 100644 index 0000000..df52f51 --- /dev/null +++ b/app/api/controller/v1/Currency.php @@ -0,0 +1,129 @@ +model = new CurrencyModel(); + $this->validate = new CurrencyValidate(); + } + + /** + * 列表 + */ + public function index(): \think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['status']) && $inputData['status'] != '') { + $this->focus['status'] = $inputData['status']; + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 修改 + */ + public function update():\think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + + /** + * 新增 + */ + public function create():\think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\response\Json + { + $inputData = $this->request->param(['id','status']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有平台使用此币种。 + $data = $this->model->find($inputData['id']); + $hasPlatformUse = $this->model->getPlatformCoin($inputData['id']); + if (!$hasPlatformUse || $data['status'] == 1) { + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } else { + return $this->msg(504,"有平台使用了此币种,不能进行禁用/启用操作"); + } + + } + + /** + * 删除 + */ + public function del():\think\response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有平台使用此币种。 + $hasPlatformUse = $this->model->getPlatformCoin($inputData['id']); + if (!$hasPlatformUse) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"有平台使用此币种,不能进行删除操作"); + } + + } + +} diff --git a/app/api/controller/v1/Faq.php b/app/api/controller/v1/Faq.php new file mode 100644 index 0000000..7385e3d --- /dev/null +++ b/app/api/controller/v1/Faq.php @@ -0,0 +1,60 @@ +model = new FaqModel(); + $this->validate = new FaqValidate(); + } + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['faq_type_id']) && $inputData['faq_type_id'] != '' && $inputData['faq_type_id'] != 0) { + $this->focus['faq_type_id'] = $inputData['faq_type_id']; + } + + + if (isset($inputData['answer']) && $inputData['answer'] != '') { + $this->simple['answer'] = $inputData['answer']; + $this->simple['question'] = $inputData['answer']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (!empty($this->focus)) { + if (!$this->commonValidate(__FUNCTION__,$this->focus)) { + return $this->msg(-1,$this->validate->getError()); + } + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + +} diff --git a/app/api/controller/v1/FaqType.php b/app/api/controller/v1/FaqType.php new file mode 100644 index 0000000..b8a3299 --- /dev/null +++ b/app/api/controller/v1/FaqType.php @@ -0,0 +1,129 @@ +model = new FaqTypeModel(); + $this->validate = new FaqTypeValidate(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->order['sort'] = $inputData['sort']; + } + //过滤字段 + $this->field = ['id','platform_id','language_id','icon','site_id','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as $key => $item) { + if (isset($item['id'])) { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'name' => $item['name'], + 'site_id' => $item['language_id'], + 'icon' => $item['icon']??0, + 'sort' => $item['sort'], + 'platform_id' =>$this->platformId + ]; + unset($item['language_id']); + } else { + $item['site_id'] = $item['language_id']; + unset($item['language_id']); + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??0, + 'site_id' => $item['site_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + unset($item['language_id']); + } + } + } + + $result = $result1 = false; + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + $result1 = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + $result = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getFaqData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/FileType.php b/app/api/controller/v1/FileType.php new file mode 100644 index 0000000..45dc7ad --- /dev/null +++ b/app/api/controller/v1/FileType.php @@ -0,0 +1,135 @@ +validate = new FileTypeValidate(); + $this->model = new FileTypeModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //兼容新方式 + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->order['sort'] = $inputData['sort']; + } else { + $this->order['sort'] = 'asc'; + } + + $this->field = ['id','platform_id','language_id','icon','site_id','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($item['id'])) { + //欺骗验证器 + $item['site_id'] = $item['language_id']; + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['language_id'], + 'icon' => $item['icon']??0, + 'name' => $item['name'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } else { + //欺骗验证器 + $item['site_id'] = $item['language_id']; + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??0, + 'site_id' => $item['language_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getSoftManualData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Goods.php b/app/api/controller/v1/Goods.php new file mode 100644 index 0000000..0e1a9ac --- /dev/null +++ b/app/api/controller/v1/Goods.php @@ -0,0 +1,487 @@ +model = new GoodsModel(); + $this->validate = new GoodsValidate(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['goods_category_id']) && $inputData['goods_category_id'] != '' && $inputData['goods_category_id'] != 0 ) { + //批量获取当前类与子类ID + $inputData['goods_category_id'] = $this->model->getAllSonCategory(['id'=>$inputData['goods_category_id']]); + } + + if (isset($inputData['status']) && $inputData['status'] != '' ) { + $this->focus['status'] = $inputData['status']; + } + + //组建查询条件 + if (isset($inputData['keyword']) && $inputData['keyword'] != '') { + $this->simple['model_number'] = $inputData['keyword']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if (!empty($this->focus)) { + if (!$this->commonValidate(__FUNCTION__,$this->focus)) { + return $this->msg(-1,$this->validate->getError()); + } + } + + //强制商品列表按添加时间倒序 + $this->order['create_time'] = 'desc'; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + if (!empty($result['page'])) { + foreach ($result['page'] as &$value) { + $value['language_id'] = $value['site_id']; + $value['language_name'] = $this->model->getLanguageName($value['site_id']); + $value['platform_name'] = $this->model->getPlatformName($value['platform_id']); + } + return $this->msg(200,'获取列表成功',$result); + } else { + if (isset($inputData['keyword']) && $inputData['keyword'] != '') { + if (isset($this->simple['model_number'])) { + unset($this->simple['model_number']); + } + $this->simple['name'] = $inputData['keyword']; + } + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + if (!empty($result['page'])) { + foreach ($result['page'] as &$value) { + $value['language_name'] = $this->model->getLanguageName($value['site_id']); + $value['platform_name'] = $this->model->getPlatformName($value['platform_id']); + } + return $this->msg(200,'获取列表成功',$result); + } +// if (isset($result['count']) && $result['count'] == 0) { + return $this->msg(200,'获取列表成功',$result); +// } else { +// return $this->msg(504,'获取列表失败'); +// } + } + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $details = $this->request->param('details','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['details'] = $details; + $inputData['platform_id'] = $this->platformId; + // 过滤ID + if (isset($inputData['id']) && $inputData['id'] == '') { + unset($inputData['id']); + } + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + //主要参数不能为空 + if ((isset($inputData['attr'][0]['attribute_id']) && $inputData['attr'][0]['attribute_id'] == '') || (isset($inputData['attr'][0]['value']) && $inputData['attr'][0]['value'] == "")) { + return $this->msg(504,'主要参数必填,请检查!'); + } + + //主要参数不能为空 + if (isset($inputData['goods_images']) && empty($inputData['goods_images'])) { + return $this->msg(504,'必须上传商品主图,请检查!'); + } + + //主要参数不能为空 + if (!isset($inputData['details']) || empty($inputData['details'])) { + return $this->msg(504,'图文介绍必填,请检查!'); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //动态检测数据是否完整 +// $isExitsLang = $this->model->dynamicCheck(\app\api\model\Site::class,['status'=>0,'id'=>$inputData['site_id']]); +// if (!$isExitsLang) { +// return $this->msg(504,'语言数据有变动,请重新填写再提交!'); +// } +// $isExitsGoodsCategory = $this->model->dynamicCheck(\app\api\model\GoodsCategory::class,['status'=>0,'id'=>$inputData['goods_category_id']]); +// if (!$isExitsGoodsCategory) { +// return $this->msg(504,'商品分类数据有变动,请重新填写再提交!'); +// } +// $flag = true; +// foreach ($inputData['attr'] as $datum) { +// $isExitsAttr = $this->model->dynamicCheck(\app\api\model\Attribute::class,['id'=>$datum['attribute_id']]); +// $flag = $isExitsAttr && $flag; +// if (!$flag) { +// return $this->msg(504,'商品参数有变动,请重新填写再提交!'); +// } +// } +// +// foreach ($inputData['connect_goods'] as $item) { +// $isExitsGoodsCategory = $this->model->dynamicCheck(\app\api\model\GoodsCategory::class,['status'=>0,'id'=>$item['goods_category_id']]); +// $flag = $isExitsGoodsCategory && $flag; +// if (!$flag) { +// return $this->msg(504,'商品分类数据有变动,请重新填写再提交!'); +// } +// $isExitsGoods = $this->model->dynamicCheck(\app\api\model\Goods::class,['status'=>0,'id'=>$item['connect_good_id']]); +// $flag = $isExitsGoods && $flag; +// if (!$flag) { +// return $this->msg(504,'关联商品数据有变动,请重新填写再提交!'); +// } +// } +// +// foreach ($inputData['soft_manual'] as $item) { +// $isExitsSoft = $this->model->dynamicCheck(\app\api\model\Download::class,['status'=>0,'id'=>$item['soft_manual_id']]); +// $flag = $isExitsSoft && $flag; +// if (!$flag) { +// return $this->msg(504,'下载文件数据有变动,请重新填写再提交!'); +// } +// $isExitsFileType = $this->model->dynamicCheck(\app\api\model\FileType::class,['status'=>0,'id'=>$item['file_type_id']]); +// $flag = $isExitsFileType && $flag; +// if (!$flag) { +// return $this->msg(504,'文件分类数据有变动,请重新填写再提交!'); +// } +// } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $details = $this->request->param('details','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['details'] = $details; + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + //主要参数不能为空 + if ((isset($inputData['attr'][0]['attribute_id']) && $inputData['attr'][0]['attribute_id'] == '') || (isset($inputData['attr'][0]['value']) && $inputData['attr'][0]['value'] == "")) { + return $this->msg(504,'主要参数必填,请检查!'); + } + + //主要参数不能为空 + if (isset($inputData['goods_images']) && empty($inputData['goods_images'])) { + return $this->msg(504,'必须上传商品主图,请检查!'); + } + + //主要参数不能为空 + if (!isset($inputData['details']) || empty($inputData['details'])) { + return $this->msg(504,'图文介绍必填,请检查!'); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + +// //动态检测数据是否完整 +// $isExitsLang = $this->model->dynamicCheck(\app\api\model\Site::class,['status'=>0,'id'=>$inputData['site_id']]); +// if (!$isExitsLang) { +// return $this->msg(504,'语言数据有变动,请重新填写再提交!'); +// } +// $isExitsGoodsCategory = $this->model->dynamicCheck(\app\api\model\GoodsCategory::class,['status'=>0,'id'=>$inputData['goods_category_id']]); +// if (!$isExitsGoodsCategory) { +// return $this->msg(504,'商品分类数据有变动,请重新填写再提交!'); +// } +// $flag = true; +// foreach ($inputData['attr'] as $datum) { +// $isExitsAttr = $this->model->dynamicCheck(\app\api\model\Attribute::class,['id'=>$datum['attribute_id']]); +// $flag = $isExitsAttr && $flag; +// if (!$flag) { +// return $this->msg(504,'商品参数有变动,请重新填写再提交!'); +// } +// } +// +// foreach ($inputData['connect_goods'] as $item) { +// $isExitsGoodsCategory = $this->model->dynamicCheck(\app\api\model\GoodsCategory::class,['status'=>0,'id'=>$item['goods_category_id']]); +// $flag = $isExitsGoodsCategory && $flag; +// if (!$flag) { +// return $this->msg(504,'关联商品,商品分类数据有变动,请重新填写再提交!'); +// } +// $isExitsGoods = $this->model->dynamicCheck(\app\api\model\Goods::class,['status'=>0,'id'=>$item['connect_good_id']]); +// $flag = $isExitsGoods && $flag; +// if (!$flag) { +// return $this->msg(504,'关联商品数据有变动,请重新填写再提交!'); +// } +// } +// +// foreach ($inputData['soft_manual'] as $item) { +// $isExitsSoft = $this->model->dynamicCheck(\app\api\model\Download::class,['status'=>0,'id'=>$item['soft_manual_id']]); +// $flag = $isExitsSoft && $flag; +// if (!$flag) { +// return $this->msg(504,'下载文件数据有变动,请重新填写再提交!'); +// } +// $isExitsFileType = $this->model->dynamicCheck(\app\api\model\FileType::class,['status'=>0,'id'=>$item['file_type_id']]); +// $flag = $isExitsFileType && $flag; +// if (!$flag) { +// return $this->msg(504,'文件分类数据有变动,请重新填写再提交!'); +// } +// } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 详情 + */ + public function read():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getInfo($inputData); + $result['details'] = htmlspecialchars_decode($result['details']); + + if ($result) { + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(504,'获取列表失败'); + } + } + + /** + * 获取当前品牌语言列表 + * @return mixed + */ + public function languageList():\think\Response\Json + { + $result = $this->model->getPlatformLanguage($this->platformId); + return $this->msg(200,'获取成功',$result); + } + + /** + * 批量修改分类 + */ + public function batchCategoryModify():\think\Response\Json + { + $inputData = $this->request->param(); + + if (count($inputData['id']) > 0) { + //构建分类数据 + $newCateData = []; + foreach ($inputData['id'] as $item) { + //分类不能超过3个, + $newCateData[] = [ + 'id' => $item, + 'goods_category_id' => $inputData['goods_category_id'] + ]; + } + + $result = $this->model->goodsBatchEditCategory($newCateData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } else { + return $this->msg(504,'提交的数据有问题,请检查后再提交'); + } + } + + /** + * 批量删除 + */ + public function batchGoodsDel():\think\Response\Json + { + $inputData = $this->request->param(); + if (count($inputData['id']) > 0) { + $newData = []; + //构建数据 + foreach ($inputData['id'] as $item) { + $newData[] = [ + 'id' => $item, + ]; + } + + $result = $this->model->batchDelData($newData); + + if ($result) { + return $this->msg(200,'删除成功'); + } else { + return $this->msg(504,'删除失败'); + } + } else { + return $this->msg(504,'提交的数据有问题,请检查后再提交'); + } + } + + /** + * 批量启用 + */ + public function batchGoodsEnable():\think\Response\Json + { + $inputData = $this->request->param(); + if (count($inputData['id']) > 0) { + //验证分类ID + $newData = []; + if (count($inputData['id']) > 0) { + foreach ($inputData['id'] as $item) { + $newData[] = [ + 'id' => $item, + 'status' => 0 + ]; + } + } + + $result = $this->model->batchEditData($newData); + + if ($result) { + return $this->msg(200,'启用成功'); + } else { + return $this->msg(504,'启用失败'); + } + + } else { + return $this->msg(504,'提交的数据有问题,请检查后再提交'); + } + } + + /** + * 排序 + */ + public function changeSort():\think\Response\Json + { + $inputData = $this->request->param(['id','sort']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeSort($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(['id','status']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } + + /** + * 分类商品 + * @return \think\response\Json + */ + public function categoryGoodsInfo():\think\Response\Json + { + $inputData = $this->request->param(['goods_category_id','type']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + // + if (isset($inputData['goods_category_id'])) { + $list = $this->model->getGoodsInfoByGoodsCategoryId($inputData); + if ($list) { + $list['type'] = $inputData['type']; + return $this->msg(200, '获取列表成功', $list); + } else { + return $this->msg(504, '获取列表失败'); + } + } else { +// $list['type'] = $inputData['type']; + $list = [ + ['connect_good_id'=>'','category'=>''], + ['connect_good_id'=>'','category'=>''], + ['connect_good_id'=>'','category'=>''], + ['connect_good_id'=>'','category'=>''], + ]; + return $this->msg(200, '获取列表成功', $list); + } + } + + /** + * 批量禁用 + */ + public function batchGoodsDisable():\think\Response\Json + { + $inputData = $this->request->param(); + if (count($inputData['id']) > 0) { + //验证分类ID + $newData = []; + if (count($inputData['id']) > 0) { + foreach ($inputData['id'] as $item) { + $newData[] = [ + 'id' => $item, + 'status' => 1 + ]; + } + } + + $result = $this->model->batchEditData($newData); + + if ($result) { + return $this->msg(200,'禁用成功'); + } else { + return $this->msg(504,'禁用失败'); + } + } else { + return $this->msg(504,'提交的数据有问题,请检查后再提交'); + } + } +} diff --git a/app/api/controller/v1/GoodsBuyNow.php b/app/api/controller/v1/GoodsBuyNow.php new file mode 100644 index 0000000..f74c512 --- /dev/null +++ b/app/api/controller/v1/GoodsBuyNow.php @@ -0,0 +1,20 @@ +model = new GoodsBuyNowModel(); + $this->validate = new GoodsBuyNowValidate(); + } +} diff --git a/app/api/controller/v1/GoodsCategory.php b/app/api/controller/v1/GoodsCategory.php new file mode 100644 index 0000000..91bdfd1 --- /dev/null +++ b/app/api/controller/v1/GoodsCategory.php @@ -0,0 +1,316 @@ +model = new GoodsCategoryModel(); + $this->validate = new GoodsCategoryValidate(); + } + + /** + * 列表树 + */ + public function tree():\think\Response\Json + { + $inputData['type'] = 0; + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $this->order['sort'] = 'desc'; + //默认接口列表为全部输出 + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + //前台勾选显示正常启用列表,用status字段来进行筛选 + if (isset($inputData['status'])) { + switch ($inputData['status']) { + case 0: + unset($inputData['status']); + break; + default: + $this->focus['status'] = 0; + unset($inputData['status']); + break; + } + } + + $list = $this->model->getIndexList($this->page,$this->size,$this->field,$this->simple,$this->focus,$this->order); + //策划规定,尤达品牌只做2级分类,不允许添加3级或者4级 +// if ($inputData['type'] == 1) { + $indexTree = list_to_tree($list); + $addEditList = list_to_tree($list,3);//表示遇到第三级就跳出 + $tree = ['add'=>$addEditList,'index'=>$indexTree]; +// } else { +// $tree = list_to_tree($list); +// $tree = ['add'=>$tree,'index'=>$tree]; +// } + return $this->msg(200, '获取列表成功', $tree); + } + + /** + * 新增 + * @return \think\response\Json + */ + public function create():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; +// //策划规定,尤达品牌只做2级分类,不允许添加3级或者4级 +// if ($inputData['platform_id'] == 1) { +// $inputData['pid'] = [$inputData['pid']]; +// } + //语言包 + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + //处理PID结构 +// if (count($inputData['pid']) >= 1) { +// $inputData['pid'] = array_pop($inputData['pid']); +// } else { +// return $this->msg(-1,'pid必填'); +// } + if (isset($inputData['pid']) && $inputData['pid'] == '') { + $inputData['pid'] = 0; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 详情 + * @return \think\response\Json + */ + public function read():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + $result = $this->model->getInfo($inputData); + //获取当前分类的所有子类 + $sonCategory = $this->model->getChildCategory($inputData['id']); + //获取所有分类数据 + $cates = $this->model->where(['status'=>0,'site_id'=>$result['site_id'],'platform_id'=>$this->platformId])->select()->toArray(); + //取出编辑时上级分类列表。 + $list = []; + foreach ($cates as $cate) { + if (!in_array($cate['id'],$sonCategory)) { + $list[] = $cate; + } + } + $addEditList = list_to_tree($list,3);//表示遇到第三级就跳出 + $result['list'] = $addEditList; + //获取当前分类下是否有子分类。 + $hasChild = $this->model->where('pid',$inputData['id'])->find(); + $result['has_child'] = (bool) $hasChild; + if ($result) { + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(504,'获取列表失败'); + } + } + + /** + * 修改 + * @return \think\response\Json + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } +// //策划规定,尤达品牌只做2级分类,不允许添加3级或者4级 +// if ($inputData['platform_id'] == 1) { +// $inputData['pid'] = [$inputData['pid']]; +// } +// dd($inputData); + //处理PID结构 +// $inputData['pid'] = $inputData['pid'][0]; + if (isset($inputData['pid']) && $inputData['pid'] == '') { + $inputData['pid'] = 0; + } + + if ($inputData['pid'] == $inputData['id']) { + return $this->msg(-1,'不能选择当前分类为自己的父分类'); + } + //状态修改判断 + if (isset($inputData['status']) && $inputData['status'] != '' && $inputData['status'] == 1) { + //判断当前修改的分类是否有子分类。如果有,将所有子分类全部禁用 + $sonCategory = $this->model->getChildCategory($inputData['id']); + $newData = []; + foreach ($sonCategory as $item) { + $newData[] = [ + 'id' => $item, + 'status'=> 1 + ]; + } + $this->model->changeStatus($newData,true); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 分类商品 + * @return \think\response\Json + */ + public function categoryGoodsList():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + if ($inputData['goods_category_id'] == '') { + return $this->msg(200, '获取列表成功', []); + } + + $list = $this->model->getGategoryListData($inputData); + //商品编辑的时候。去除当前分类当前商品ID + if (isset($inputData['goods_id']) && $inputData['goods_id'] > 0) { + foreach ($list as $key => $item) { + if ($item['id'] == $inputData['goods_id']) { + unset($list[$key]); + } + } + } + if (!empty($list)) { + $newList = []; + $newList['page'] = array_merge($list,[]); + $newList['type'] = $inputData['type']??0; + return $this->msg(200, '获取列表成功', $newList); + } else { + return $this->msg(504, '此分类下没有商品,请重新选择'); + } + } + + /** + * 分类商品 + * @return \think\response\Json + */ + public function categoryGoodsInfo():\think\Response\Json + { + $inputData = $this->request->param(['id','type']); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['language_id']; + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } +// dd($inputData); + // + if (isset($inputData['id'])) { + $list = $this->model->getGategoryListDataInfo($inputData); + dd($list); +// if ($list) { + $list['type'] = $inputData['type']??0; + return $this->msg(200, '获取列表成功', $list); +// } else { +// return $this->msg(504, '获取列表失败'); +// } + } else { +// $list['type'] = $inputData['type']; + $list = [ + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ]; + return $this->msg(200, '获取列表成功', $list); + } + } + + /** + * 删除 + * @return \think\response\Json + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasChild = $this->model->where('pid',$inputData['id'])->find(); + //查找是否有商品。 + $hasGoods = $this->model->hasGoodsOnCategory($inputData); + if (empty($hasChild) && empty($hasGoods)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"有子分类或者分类下有商品,不能删除"); + } + + } + +} diff --git a/app/api/controller/v1/GoodsConnect.php b/app/api/controller/v1/GoodsConnect.php new file mode 100644 index 0000000..bf31522 --- /dev/null +++ b/app/api/controller/v1/GoodsConnect.php @@ -0,0 +1,21 @@ +model = new GoodsConnectModel(); + $this->validate = new GoodsConnectValidate(); + } + +} diff --git a/app/api/controller/v1/GoodsCoupon.php b/app/api/controller/v1/GoodsCoupon.php new file mode 100644 index 0000000..0d98c67 --- /dev/null +++ b/app/api/controller/v1/GoodsCoupon.php @@ -0,0 +1,66 @@ +model = new GoodsCouponModel(); + $this->validate = new GoodsCouponValidate(); + } + + /** + * 列表 + * @return \think\response\Json + */ + public function index() + { + $inputData = $this->request->param(); +// //语言包 +// if (isset($inputData['language_id']) && $inputData['language_id'] != '' && $inputData['language_id'] != 0) { +// $this->focus['language_id'] = $inputData['language_id']; +// } else { +// return $this->msg(504,'语言包ID不正确,请检查!'); +// } + + $data = [ +// 'language_id'=>$inputData['language_id'], + 'platform_id'=>$this->platformId + ]; + + $result = $this->model->getLatest($data); + $result = ['old_code'=>$result['new_code']]; + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + * @return \think\response\Json + */ + public function create() + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + $inputData['new_code'] = htmlspecialchars_decode($inputData['new_code']); + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $inputData['new_code'] = htmlspecialchars($inputData['new_code']); + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } +} diff --git a/app/api/controller/v1/GoodsImages.php b/app/api/controller/v1/GoodsImages.php new file mode 100644 index 0000000..87c05e2 --- /dev/null +++ b/app/api/controller/v1/GoodsImages.php @@ -0,0 +1,20 @@ +model = new GoodsImagesModel(); + $this->validate = new GoodsImagesValidate(); + } + +} diff --git a/app/api/controller/v1/GoodsSoftManual.php b/app/api/controller/v1/GoodsSoftManual.php new file mode 100644 index 0000000..c23eb79 --- /dev/null +++ b/app/api/controller/v1/GoodsSoftManual.php @@ -0,0 +1,20 @@ +model = new GoodsSoftManualModel(); + $this->validate = new GoodsSoftManualValidate(); + } +} diff --git a/app/api/controller/v1/ImagesFile.php b/app/api/controller/v1/ImagesFile.php new file mode 100644 index 0000000..da3b60f --- /dev/null +++ b/app/api/controller/v1/ImagesFile.php @@ -0,0 +1,213 @@ + "", + 'md5' => "", + 'chunks' => "", + 'chunk' => 0, + 'is_test' => 1, + 'file_name' => '', + ]; + $newData = $this->request->post($field); + $file = $this->request->file('file'); + if (empty($file)) { + return $this->msg(504,'文件不能为空'); + } + if (!$newData['hash']) { + return $this->msg(504,'hash值不能为空'); + } + //分片数据为第一片时 校验文件是否已经上传 如果上传直接返回地址 + if ($newData['chunk'] == 0) { + $file_data = Attachment::where('hash', $newData['hash']) + ->find(); + if (!empty($file_data)) { + $file_data['id'] = (int)$file_data['id']; + if ($file_data['id'] > 0 ) { + return $this->msg(200, $file_data); + } + } + } + $uploader = new LocalUploader(); + $result = $uploader->uploadFile($newData, $file); + //异常 + if ($result['code'] == -1) { + return $this->msg(504,$uploader->getError()); + } + if ($result['code'] == 1) { +// $data = [ +// 'path' => $result['data']['save_path'], +// 'url' => $result['data']['file_path'], +// ]; + + //上传到七牛 + $res = $this->qn->uploadLocalFile(public_path().ltrim($result['data']['save_path'],'/'),$result['data']['file_path']); + $ret = [ + 'code' => 1, + 'data' => [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $file->getOriginalName(), + 'filename' => explode('/',$res['filename'])[count(explode('/',$res['filename']))-1], + 'md5' => $newData['hash'], + 'url' => $res['remote_url'], + 'relative_path' => $res['filename'] + ] + ]; + //构建数据 + $attach = [ + 'platform_id' => $this->platformId, + 'site_id' => '', + 'name' => $file->getOriginalName(), + 'type' => $file->getMime(), + 'local' => $result['data']['save_path'], + 'path' => $res['filename'], + 'md5' => $newData['hash'], + 'hash' => $newData['hash'] + ]; + Attachment::create($attach); + return $this->msg(200, '上传成功', $ret); + } else { + $data = [ + 'code' => 0, + 'data' => $result['data'], + ]; + return $this->msg(200, '文件包不完整', $data); + } + + } catch (\Exception $e) { + return $this->msg(504,$e->getMessage()); + } + } + + + /** + * 分片上传文件检测 + */ + public function checkFile() + { + header("Access-Control-Allow-Origin:*"); + header("Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE,OPTIONS"); + header("Access-Control-Allow-Credentials:true"); + header("Access-Control-Allow-Headers:Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With,x_requested_with,x-token"); + + $hash = $this->request->param('hash'); + $chunks = $this->request->param('chunks'); + if (!$hash) { + return $this->msg(504,'hash值异常'); + } + if ($chunks <= 0) { + return $this->msg(504,'分片总数错误'); + } +// $file_data = ImagesFileModel::where('file_hash', '=', $hash) +// ->with('uploader') +// ->find(); + //查询该上传的文件是否存在 + $file_data = Attachment::where('hash',$hash)->findOrEmpty(); + + if (!empty($file_data)) { + $file_data['id'] = (int)$file_data['id']; + if ($file_data['id'] > 0) { + $arr = explode('/',$file_data['path']); + $data = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $file_data['name'], + 'filename' => array_pop($arr), + 'md5' => $file_data['md5'], + 'url' => Env::get('QINIU.cdn').$file_data['path'], + 'relative_path' => $file_data['path'] + ]; + return $this->msg(200,'成功', ['code' => 1, 'data' => $data]); + } + } + //如果为需要上传的文件 则检测文件的分片情况 + $uploader = new LocalUploader(); + $result = $uploader->checkFile($hash, $chunks); + return $this->msg(200,'成功', ['code' => 0, 'data' => $result]); + } + + /** + * 上传图片 + */ + public function uploadImg() + { + try { + $uploader = new QiniuUploader(); + $file = $this->request->file('file'); + $result = $uploader->uploadFile('file'); + $data = [ + 'up_id' => isset($this->user['id']) ? $this->user['id'] : 0, + 'path' => $result['filename'], + 'url' => $result['remote_url'], + 'file_hash' => $result['hash'], + 'file_md5' => $file->md5(), + 'created_at' => date("Y-m-d H:i:s"), + 'file_name' => $file->getOriginalName(), + 'file_type' => $file->getOriginalMime(), + 'storage_type' => 'qiniu', + ]; + $file_id = ImagesFileModel::insert($data, true); + $data['id'] = (int)$file_id; + return $this->msg(200,'成功', $data); + + } catch (\Exception $e) { + return $this->msg(504,$e->getMessage()); + } + } + + + /** + * 删除文件 + * @return \think\response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function deleteFile() + { + $file_id = $this->request->get('file_id/d'); + if ($file_id <= 0) { + return $this->msg(504,'请求参数异常'); + } + $file_info = ImagesFileModel::where('id', '=', $file_id)->find(); + + switch ($file_info['storage_type']) { + case 'qiniu': + $uploader = new QiniuUploader(); + $uploader->deleteFile($file_info['path']); + break; + case 'local': + $uploader = new LocalUploader(); + $uploader->deleteFile($file_info['path']); + break; + } + ImagesFileModel::where('id', '=', $file_id)->delete(); + return $this->msg(504,'操作成功'); + + } + +} diff --git a/app/api/controller/v1/Investment.php b/app/api/controller/v1/Investment.php new file mode 100644 index 0000000..cb7ba37 --- /dev/null +++ b/app/api/controller/v1/Investment.php @@ -0,0 +1,153 @@ +model = new InvestmentModel(); + $this->validate = new InvestmentValidate(); + } + + /** + * 显示资源列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $this->focus['platform_id'] = $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + //判断是否需要分页 + if (isset($inputData['page']) && $inputData['page'] != 0) { + $this->page = (int)$inputData['page']; + } + if (isset($inputData['size']) && $inputData['size'] != 0) { + $this->size = (int)$inputData['size']; + } + + if (isset($inputData['create_time']) && $inputData['create_time'] != '') { + $this->order['create_time'] = $inputData['create_time']; + } + + if (isset($inputData['keyword']) && $inputData['keyword'] != '') { + $this->simple['keyword'] = $inputData['keyword']; + } + + $result = $this->model->getIndexList($this->page,$this->size,$this->field,$this->simple,$this->focus,$this->order); + + if (isset($result['data']) && !empty($result['data'])) { + foreach ($result['data'] as $key => $item) { + $result['data'][$key]['province_id'] = $this->model->getAreaNameById($item['province_id']); + $result['data'][$key]['city_id'] = $this->model->getAreaNameById($item['city_id']); + } + } + //构建返回数据结构 + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 表格导出数据前置方法 + */ + public function export():\think\Response\Json + { + $ids = $this->request->param(); + if ($this->commonValidate(__FUNCTION__,$ids)) { + return $this->msg(-1,'获取列表成功'); + } + $data = $this->model->getExportData($ids); + $fields = [ + 'id','platform_id','language_id','site_id','country_id', + 'province_id','city_id','area','from','phone','name','email', + 'wechat','qq','desc','sort','is_open','create_time','update_time' + ]; + //处理数据 +// foreach ($data as &$datum) { +// $datum['admin_id'] = $datum['admin_name']; +// $datum['country_timezone_id'] = $datum['country_name']; +// $datum['is_cooperation'] = $datum['is_cooperation'] == 0 ? "无" : "有"; +// $datum['follow_up_stage_id'] = !empty($datum['follow_up_stage_name']) ?$datum['follow_up_stage_name']: '无'; +// $datum['customer_from_id'] = !empty($datum['customer_from_name']) ?$datum['customer_from_name'] : '无'; +// $datum['customer_level_id'] = !empty($datum['customer_level_name']) ? $datum['customer_level_name']: '无'; +// foreach ($datum as $key => $value) { +// if (!in_array($key,$fields)) { +// unset($datum[$key]); +// } +// } +// } + //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name + $this->importHeadType = 'name'; + $table = $this->model->getTable(); + $database = Env::get('database.database'); + //字段名与注释的数组, + $fieldArr = []; + $list = Db::query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); + foreach ($list as $v) { + if (in_array($v['COLUMN_NAME'],$fields)) { + if ($this->importHeadType == 'comment') { + $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; + } else { + $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_COMMENT']; + } + } + } + $newData = [];/*表格数据*/ + $newHeader = [];/*表格表头*/ + $cols = []; /*分别占用表格哪几列*/ + if (array_key_exists(0,$data)) { + $header = array_keys($data[0]); + foreach ($header as $k => $v) { + if ($k <= 25) { + $newHeader[chr($k+65).'1'] = $fieldArr[$v]?:$v; + $cols[$k] = chr($k+65); + } else { + $newHeader[chr(65).chr($k-26+65).'1'] = $fieldArr[$v]?:$v; + $cols[$k] = chr(65).chr($k-26+65); + } + + } + } + + foreach ($data as $k => $v) { + $index = 0; + foreach ($v as $v1) { + if ($index <= 25) { + $header = chr($index+65); + $header .= $k+2; + $newData[$header] = $v1;/*获取表头*/ + } else { + $header = chr(65).chr($index-26+65); + $header .= $k+2; + $newData[$header] = $v1;/*获取表头*/ + } + $index++; + } + } + $newData = array_merge($newHeader,$newData); + $options = [ + 'print' =>false, + 'freezePane'=>'A2', +// 'setWidth'=>['A'=>40,'B'=>30,'C'=>20,'D'=>25,'E'=>20,'F'=>15,'G'=>10,'H'=>10], + 'setBorder'=>true, + 'alignCenter'=>$cols, + 'bold'=>array_keys($newHeader), + ]; + return $this->excelExport($newData,count($fields),'招商信息导出-'.date('YmdHis',time()).'.xlsx',$options); + } +} diff --git a/app/api/controller/v1/Join.php b/app/api/controller/v1/Join.php new file mode 100644 index 0000000..f816ce3 --- /dev/null +++ b/app/api/controller/v1/Join.php @@ -0,0 +1,135 @@ +validate = new JoinValidate(); + $this->model = new JoinModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['join_type_id']) && $inputData['join_type_id'] != '' && $inputData['join_type_id'] != 0) { + $this->focus['join_type_id'] = $inputData['join_type_id']; + } + + if (isset($inputData['title']) && $inputData['title'] != '') { + $this->simple['title'] = $inputData['title']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time']) && !$inputData['create_time']) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time'])) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + +} diff --git a/app/api/controller/v1/JoinType.php b/app/api/controller/v1/JoinType.php new file mode 100644 index 0000000..deae853 --- /dev/null +++ b/app/api/controller/v1/JoinType.php @@ -0,0 +1,131 @@ +validate = new JoinTypeValidate(); + $this->model = new JoinTypeModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //兼容新方式 + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->orderby['sort'] = $inputData['sort']; + } else { + $this->orderby['sort'] = 'asc'; + } + + $this->field = ['id','platform_id','site_id','icon','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($item['id']) && $item['id'] != '') { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['language_id'], + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } else { + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'site_id' => $item['language_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getArticleData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Language.php b/app/api/controller/v1/Language.php new file mode 100644 index 0000000..c94a86b --- /dev/null +++ b/app/api/controller/v1/Language.php @@ -0,0 +1,128 @@ +validate = new LanguageValidate(); + $this->model = new LanguageModel(); + } + + /** + * 列表 + */ + public function index():\think\response\Json + { + $inputData = $this->request->param(); + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + if (isset($inputData['status']) && $inputData['status'] != '') { + $this->focus['status'] = $inputData['status']; + } + $this->field = ['id','name','code','icon','status']; + $result = $this->model->getIndexList($this->page,$this->size,$this->field,$this->simple,$this->focus,$this->order); + return $result ? $this->msg(200,'获取列表成功',$result) : $this->msg(504,'获取列表失败'); + } + + /** + * 新增 + */ + public function create():\think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\response\Json + { + $inputData = $this->request->param(['id','status']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //判断是否是否使用 + $hasUsed = $this->model->getLanguageUse($inputData['id']); + if (!$hasUsed) { + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } else { + return $this->msg(504,"此语言包已经被使用,不能启用/禁用"); + } + + } + + /** + * 删除 + */ + public function del():\think\response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //判断是否是否使用 + $hasUsed = $this->model->getLanguageUse($inputData['id']); + if (!$hasUsed) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"此语言包已经被使用,不能删除"); + } + + } + + + +} diff --git a/app/api/controller/v1/LogVisit.php b/app/api/controller/v1/LogVisit.php new file mode 100644 index 0000000..9b4d8d9 --- /dev/null +++ b/app/api/controller/v1/LogVisit.php @@ -0,0 +1,18 @@ +model = new LogVisitModel(); + } +} diff --git a/app/api/controller/v1/Navigator.php b/app/api/controller/v1/Navigator.php new file mode 100644 index 0000000..0513b53 --- /dev/null +++ b/app/api/controller/v1/Navigator.php @@ -0,0 +1,196 @@ +validate = new NavigatorValidate(); + $this->model = new NavigatorModel(); + } + + /** + * 详情 + */ + public function read():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $inputData['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getInfo($inputData); + if ($result['pid'] != 0) { + $pidName = $this->model->where('id',$result['pid'])->find()->toArray(); + $result['pid_name'] = $pidName['name']; + } else { + $result['pid_name'] = ''; + } + $result['language_id'] = $result['site_id']; + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 列表树 + */ + public function tree():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + if (isset($inputData['language_id']) && $inputData['language_id'] != '' && $inputData['language_id'] != 0) { + $this->focus['site_id'] = $inputData['language_id']; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + $this->order['sort'] = 'desc'; + + $list = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + $tree = list_to_tree($list); + return $this->msg(200, '获取列表成功', $tree); + } + + /** + * 顶级列表树 + */ + public function topTree():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + if (isset($inputData['language_id']) && $inputData['language_id'] != '' && $inputData['language_id'] != 0) { + $this->focus['site_id'] = $inputData['language_id']; + //$this->focus['pid'] = 0; + } + if (isset($inputData['language_id'])) { + unset($inputData['language_id']); + } + $list = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + //echo "
=="; print_r($list);
+        //去除自己的顶级
+        if (isset($inputData['id']) && $inputData['id'] != '') {
+            //查找当前分类是否有子类。
+            $nav = $this->model->find($inputData['id']);
+            $hasSon = $this->model->where('pid',$inputData['id'])->find();
+            
+            if($hasSon) {
+                $tree = [];
+            }
+            else{
+                foreach ($list as $key => $item) {
+                    if ($inputData['id'] == $item['id']){
+                        unset($list[$key]);
+                        break;
+                    }
+                }   
+                $tree = list_to_tree($list);
+            }
+            
+            /*if ($nav) {
+                if (!empty($son)) {
+                    $tree = [];
+                } else {
+                    foreach ($list as $key => $item) {
+                        if ($inputData['id'] == $item['id']){
+                            unset($list[$key]);
+                        }
+                    }
+                    $tree = list_to_tree($list);
+                }
+            }*/
+        } else {
+            /*foreach ($list as $key => $item) {
+                if ($inputData['id'] == $item['id']){
+                    unset($list[$key]);
+                }
+            }*/
+            
+            $tree = list_to_tree($list);
+            
+        }
+        //echo "
---"; print_r($tree);
+        return $this->msg(200, '获取列表成功', $tree);
+    }
+
+    /**
+     * 修改是否是顶部状态
+     */
+    public function changeStatus():\think\Response\Json
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $inputData['site_id'] = $inputData['language_id'];
+        }
+        if (isset($inputData['language_id'])) {
+            unset($inputData['language_id']);
+        }
+        if (isset($inputData['is_foot']) && $inputData['is_foot'] == '') {
+            unset($inputData['is_foot']);
+        }
+
+        if (isset($inputData['is_top']) && $inputData['is_top'] == '') {
+            unset($inputData['is_top']);
+        }
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        //不能都提交为空
+        if (count($inputData) < 3) {
+            return $this->msg(504,"参数错误");
+        }
+
+        $result = $this->model->changeStatus($inputData);
+        if ($result) {
+            return $this->msg(200,"操作成功");
+        } else {
+            return $this->msg(504,"操作失败");
+        }
+    }
+
+    /**
+     * 删除
+     */
+    public function del():\think\Response\Json
+    {
+        $inputData = $this->request->param(['id']);
+        $inputData['platform_id'] = $this->platformId;
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        //查找是否有子类。
+        $hasData = $this->model->getNavigatorIsInUse($inputData);
+        if (!$hasData) {
+            $result = $this->model->delData($inputData);
+            if ($result) {
+                return $this->msg(200,"删除成功");
+            } else {
+                return $this->msg(504,"删除失败");
+            }
+        } else {
+            return $this->msg(504,"该导航下有子分类,不能删除");
+        }
+    }
+}
diff --git a/app/api/controller/v1/News.php b/app/api/controller/v1/News.php
new file mode 100644
index 0000000..af2102c
--- /dev/null
+++ b/app/api/controller/v1/News.php
@@ -0,0 +1,135 @@
+validate = new NewsValidate();
+        $this->model = new NewsModel();
+    }
+
+    /**
+     * 列表
+     */
+    public function index():\think\Response\Json
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+            unset($inputData['language_id']);
+        }
+
+        if (isset($inputData['News_type_id']) && $inputData['News_type_id'] != '' && $inputData['News_type_id'] != 0) {
+            $this->focus['News_type_id'] = $inputData['News_type_id'];
+        }
+
+        if (isset($inputData['title']) && $inputData['title'] != '') {
+            $this->simple['title'] = $inputData['title'];
+        }
+
+        $this->order['create_time'] = 'desc';
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+
+        $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order);
+        return $this->msg(200,'获取列表成功',$result);
+    }
+
+    /**
+     * 新增
+     */
+    public function create():\think\Response\Json
+    {
+        $detail = $this->request->param('detail','','htmlspecialchars');
+        $inputData = $this->request->param();
+        $inputData['detail'] = $detail;
+        $inputData['platform_id'] = $this->platformId;
+        if (isset($inputData['create_time']) && $inputData['create_time'] != '') {
+            $inputData['create_time'] = intval($inputData['create_time']) / 1000;
+        } else {
+            unset($inputData['create_time']);
+        }
+        unset($inputData['update_time']);
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+        }
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+
+        $result = $this->model->addData($inputData);
+
+        if ($result) {
+            return $this->msg(200,'新增成功');
+        } else {
+            return $this->msg(504,'新增失败');
+        }
+    }
+
+    /**
+     * 修改
+     */
+    public function update():\think\Response\Json
+    {
+        $detail = $this->request->param('detail','','htmlspecialchars');
+        $inputData = $this->request->param();
+        $inputData['detail'] = $detail;
+        $inputData['platform_id'] = $this->platformId;
+        if (isset($inputData['create_time']) && $inputData['create_time'] != '') {
+            $inputData['create_time'] = intval($inputData['create_time']) / 1000;
+        } else {
+            unset($inputData['create_time']);
+        }
+        unset($inputData['update_time']);
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+        }
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->editData($inputData);
+        if ($result) {
+            return $this->msg(200,'更改成功');
+        } else {
+            return $this->msg(504,'更改失败');
+        }
+    }
+
+    /**
+     * 启用禁用
+     */
+    public function changeStatus():\think\Response\Json
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->changeStatus($inputData);
+        if ($result) {
+            return $this->msg(200,'更改成功');
+        } else {
+            return $this->msg(504,'更改失败');
+        }
+    }
+
+}
diff --git a/app/api/controller/v1/NewsType.php b/app/api/controller/v1/NewsType.php
new file mode 100644
index 0000000..e88a41a
--- /dev/null
+++ b/app/api/controller/v1/NewsType.php
@@ -0,0 +1,131 @@
+validate = new NewsTypeValidate();
+        $this->model = new NewsTypeModel();
+    }
+
+    /**
+     * 列表
+     */
+    public function index():\think\Response\Json
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+            unset($inputData['language_id']);
+        }
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+
+        //兼容新方式
+        if (isset($inputData['sort']) && $inputData['sort'] != '') {
+            $this->orderby['sort'] = $inputData['sort'];
+        } else {
+            $this->orderby['sort'] = 'asc';
+        }
+
+        $this->field = ['id','platform_id','site_id','icon','name','sort'];
+
+        $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field);
+        return $this->msg(200,'获取列表成功',$result);
+    }
+
+    /**
+     * 更新
+     */
+    public function update():\think\Response\Json
+    {
+        $inputData = $this->request->param();
+        $updateData = $insertData = [];
+        if (count($inputData['data']) > 0) {
+            foreach ($inputData['data'] as &$item) {
+                if (isset($item['id']) && $item['id'] != '') {
+                    if (!$this->commonValidate(__FUNCTION__,$item)) {
+                        return $this->msg(-1,$this->validate->getError());
+                    }
+                    $updateData[] =[
+                        'id'      =>   $item['id'],
+                        'site_id' =>  $item['language_id'],
+                        'name'    =>   $item['name'],
+                        'icon'    =>   $item['icon']??'',
+                        'sort'    =>   $item['sort'],
+                        'platform_id'=>$this->platformId
+                    ];
+                } else {
+                    if (!$this->commonValidate('create',$item)) {
+                        return $this->msg(-1,$this->validate->getError());
+                    }
+                    $insertData[] = [
+                        'id'      =>   null,
+                        'name'    =>   $item['name'],
+                        'icon'    =>   $item['icon']??'',
+                        'site_id' =>   $item['language_id'],
+                        'sort'    =>   $item['sort'],
+                        'platform_id'=>$this->platformId
+                    ];
+                }
+            }
+        }
+
+        if (!empty($updateData)) {
+            $result = $this->model->batchEditData($updateData);
+        } else {
+            $result = true;
+        }
+        if (!empty($insertData)) {
+            $result1 = $this->model->saveAll($insertData);
+        } else {
+            $result1 = true;
+        }
+
+        if ($result && $result1) {
+            return $this->msg(200,'更新成功');
+        } else {
+            return $this->msg(504,'更新失败');
+        }
+    }
+
+
+    /**
+     * 删除
+     */
+    public function del():\think\Response\Json
+    {
+        $inputData = $this->request->param(['id']);
+        $inputData['platform_id'] = $this->platformId;
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        //查找是否有子类。
+        $hasData = $this->model->getArticleData($inputData);
+        if (empty($hasData)) {
+            $result = $this->model->delData($inputData);
+            if ($result) {
+                return $this->msg(200,"删除成功");
+            } else {
+                return $this->msg(504,"删除失败");
+            }
+        } else {
+            return $this->msg(504,"该类型下有内容,不能删除");
+        }
+    }
+}
diff --git a/app/api/controller/v1/Platform.php b/app/api/controller/v1/Platform.php
new file mode 100644
index 0000000..c0f0c29
--- /dev/null
+++ b/app/api/controller/v1/Platform.php
@@ -0,0 +1,133 @@
+validate = new PlatformValidate();
+        $this->model = new PlatformModel();
+    }
+
+    /**
+     * 列表
+     */
+    public function index():\think\response\Json
+    {
+        $inputData = $this->request->param();
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+
+        $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order);
+        return $this->msg(200,'获取列表成功',$result);
+    }
+
+    /**
+     * 语言列表
+     */
+    public function languageList():\think\response\Json
+    {
+        $inputData = $this->request->param();
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $this->field = ['id','name','code','icon','status'];
+        $result = $this->model->getLanguageList($this->field,['status'=>0]);
+        return $this->msg(200,'获取列表成功',$result);
+    }
+
+
+    /**
+     * 新增
+     */
+    public function create():\think\response\Json
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->addData($inputData);
+        if ($result) {
+            return $this->msg(200,'新增成功');
+        } else {
+            return $this->msg(504,'新增失败');
+        }
+    }
+
+    /**
+     * 修改
+     */
+    public function update():\think\response\Json
+    {
+        $inputData = $this->request->param();
+        // 已经注册的平台,如果被使用,则不允许修改品牌名
+        //TODO::暂时限制不能更改品牌名称
+        $isExist = $this->model->hasUserPlatform($inputData);
+        if (count($isExist) >= 1) {
+            unset($inputData['name']);
+        }
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->editData($inputData);
+        if ($result) {
+            return $this->msg(200,'更改成功');
+        } else {
+            return $this->msg(504,'更改失败');
+        }
+    }
+
+    /**
+     * 详情
+     */
+    public function read():\think\response\Json
+    {
+        $inputData = $this->request->param(['id']);
+        $inputData['platform_id'] = $this->platformId;
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->getInfo($inputData);
+        if ($result) {
+            return $this->msg(200,'获取列表成功',$result);
+        } else {
+            return $this->msg(504,'获取列表失败');
+        }
+    }
+
+
+    /**
+     * 删除
+     */
+    public function del():\think\response\Json
+    {
+        $inputData = $this->request->param(['id']);
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        //删除前检测
+        $isExist = $this->model->hasUserPlatform($inputData);
+        if (count($isExist) >= 1) {
+            return $this->msg(504,"平台被使用,不能删除");
+        }
+        $result = $this->model->delData($inputData);
+        if ($result) {
+            return $this->msg(200,"删除成功");
+        } else {
+            return $this->msg(504,"删除失败");
+        }
+    }
+
+}
diff --git a/app/api/controller/v1/Question.php b/app/api/controller/v1/Question.php
new file mode 100644
index 0000000..d29d10f
--- /dev/null
+++ b/app/api/controller/v1/Question.php
@@ -0,0 +1,549 @@
+validate = new QuestionValidate();
+        $this->model = new QuestionModel();
+    }
+
+    /**
+     * 列表
+     * @return \think\response\Json
+     */
+    public function index()
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+            unset($inputData['language_id']);
+        }
+        if (isset($inputData['is_done']) && $inputData['is_done'] != '') {
+            $this->focus['is_done'] = $inputData['is_done'];
+        }
+
+        if (isset($inputData['product_model']) && $inputData['product_model'] != '') {
+            $this->simple['product_model'] = $inputData['product_model'];
+        }
+
+        if (isset($inputData['create_time']) && $inputData['create_time'] != '') {
+            $this->orderby['create_time'] = $inputData['create_time'];
+        }
+
+
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        if (!empty($this->focus)) {
+            if (!$this->commonValidate(__FUNCTION__,$this->focus)) {
+                return $this->msg(-1,$this->validate->getError());
+            }
+        }
+
+        if (!empty($this->simple)) {
+            if (!$this->commonValidate(__FUNCTION__,$this->simple)) {
+                return $this->msg(-1,$this->validate->getError());
+            }
+        }
+
+        if (!empty($this->orderby)) {
+            if (!$this->commonValidate(__FUNCTION__,$this->orderby)) {
+                return $this->msg(-1,$this->validate->getError());
+            }
+        }
+        //字段过滤
+        $this->field = ['id','platform_id','language_id','site_id','country_id','name','phone','email','order_sn','product_model','os','sort','is_done','create_time'];
+        $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field);
+        return $this->msg(200,'获取列表成功',$result);
+    }
+
+    /**
+     * 已解决
+     */
+    public function isDone()
+    {
+        $inputData = $this->request->param();
+        $inputData['platform_id'] = $this->platformId;
+
+        if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') {
+            $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id'];
+            unset($inputData['language_id']);
+        }
+        if (!$this->commonValidate(__FUNCTION__,$inputData)) {
+            return $this->msg(-1,$this->validate->getError());
+        }
+        $result = $this->model->isDone($inputData);
+        if ($result) {
+            return $this->msg(200,'更改成功');
+        } else {
+            return $this->msg(504,'更改失败');
+        }
+    }
+
+    /**
+     * Excel导出,
+     * @param array $data
+     * @param string $fileName
+     * @param array $options
+     * @return bool
+     */
+    public function export($data = [], $fileName = '', $options = [])
+    {
+        try {
+            if (empty($data)) {
+                return false;
+            }
+
+            set_time_limit(0);
+            $objSpreadsheet = new Spreadsheet();
+            /* 设置默认文字居左,上下居中 */
+            $styleArray = [
+                'alignment' => [
+                    'horizontal' => Alignment::HORIZONTAL_LEFT,
+                    'vertical'   => Alignment::VERTICAL_CENTER,
+                ],
+            ];
+            $objSpreadsheet->getDefaultStyle()->applyFromArray($styleArray);
+            /* 设置Excel Sheet */
+            $activeSheet = $objSpreadsheet->setActiveSheetIndex(0);
+
+            /* 打印设置 */
+            if (isset($options['print']) && $options['print']) {
+                /* 设置打印为A4效果 */
+                $activeSheet->getPageSetup()->setPaperSize(PageSetup:: PAPERSIZE_A4);
+                /* 设置打印时边距 */
+                $pValue = 1 / 2.54;
+                $activeSheet->getPageMargins()->setTop($pValue / 2);
+                $activeSheet->getPageMargins()->setBottom($pValue * 2);
+                $activeSheet->getPageMargins()->setLeft($pValue / 2);
+                $activeSheet->getPageMargins()->setRight($pValue / 2);
+            }
+
+            $row = 2;
+            $col = 0;
+            /* 行数据处理 */
+            foreach ($data as $sKey => $sItem) {
+                /* 默认文本格式 */
+                $pDataType = DataType::TYPE_STRING;
+
+                /* 设置单元格格式 */
+                if (isset($options['format']) && !empty($options['format'])) {
+                    $colRow = Coordinate::coordinateFromString($sKey);
+
+                    /* 存在该列格式并且有特殊格式 */
+                    if (isset($options['format'][$colRow[0]]) &&
+                        NumberFormat::FORMAT_GENERAL != $options['format'][$colRow[0]]) {
+                        $activeSheet->getStyle($sKey)->getNumberFormat()
+                            ->setFormatCode($options['format'][$colRow[0]]);
+
+                        if (false !== strpos($options['format'][$colRow[0]], '0.00') &&
+                            is_numeric(str_replace(['¥', ','], '', $sItem))) {
+                            /* 数字格式转换为数字单元格 */
+                            $pDataType = DataType::TYPE_NUMERIC;
+                            $sItem     = str_replace(['¥', ','], '', $sItem);
+                        }
+                    } elseif (is_int($sItem)) {
+                        $pDataType = DataType::TYPE_NUMERIC;
+                    }
+                }
+
+                if ($col < count($options['alignCenter'])) {
+                    $activeSheet->getColumnDimension($options['alignCenter'][$col])->setAutoSize(true);
+                }
+                $activeSheet->getRowDimension($row)->setRowHeight(65);
+                $activeSheet->setCellValueExplicit($sKey, $sItem, $pDataType);
+                $row++;
+                $col++;
+                /* 存在:形式的合并行列,列入A1:B2,则对应合并 */
+                if (false !== strstr($sKey, ":")) {
+                    $options['mergeCells'][$sKey] = $sKey;
+                }
+
+                if (is_image(Env::get('root_path').'public'.$sItem) && file_exists(Env::get('root_path').'public'.$sItem)) {
+                    $activeSheet->setCellValueExplicit($sKey, '', $pDataType);
+                    $drawing = new Drawing();
+                    $drawing->setName('Logo');
+                    $drawing->setDescription('Logo');
+                    $drawing->setPath(Env::get('root_path').'public'.$sItem);
+                    $drawing->setResizeProportional(false);
+                    $drawing->setHeight(50);
+                    $drawing->setCoordinates($sKey);
+                    $drawing->setOffsetX(12);
+                    $drawing->setOffsetY(12);
+                    $drawing->getShadow()->setVisible(true);
+//                    $drawing->getShadow()->setDirection(45);
+                    $drawing->setWorksheet($objSpreadsheet->getActiveSheet());
+                }
+            }
+
+            unset($data);
+
+            /* 设置锁定行 */
+            if (isset($options['freezePane']) && !empty($options['freezePane'])) {
+                $activeSheet->freezePane($options['freezePane']);
+                unset($options['freezePane']);
+            }
+
+            /* 设置宽度 */
+            if (isset($options['setWidth']) && !empty($options['setWidth'])) {
+                foreach ($options['setWidth'] as $swKey => $swItem) {
+                    $activeSheet->getColumnDimension($swKey)->setWidth($swItem);
+                }
+
+                unset($options['setWidth']);
+            }
+
+            /* 设置背景色 */
+            if (isset($options['setARGB']) && !empty($options['setARGB'])) {
+                foreach ($options['setARGB'] as $sItem) {
+                    $activeSheet->getStyle($sItem)
+                        ->getFill()->setFillType(Fill::FILL_SOLID)
+                        ->getStartColor()->setARGB(Color::COLOR_YELLOW);
+                }
+
+                unset($options['setARGB']);
+            }
+
+            /* 设置公式 */
+            if (isset($options['formula']) && !empty($options['formula'])) {
+                foreach ($options['formula'] as $fKey => $fItem) {
+                    $activeSheet->setCellValue($fKey, $fItem);
+                }
+
+                unset($options['formula']);
+            }
+
+            /* 合并行列处理 */
+            if (isset($options['mergeCells']) && !empty($options['mergeCells'])) {
+                $activeSheet->setMergeCells($options['mergeCells']);
+                unset($options['mergeCells']);
+            }
+
+            /* 设置居中 */
+            if (isset($options['alignCenter']) && !empty($options['alignCenter'])) {
+                $styleArray = [
+                    'alignment' => [
+                        'horizontal' => Alignment::HORIZONTAL_CENTER,
+                        'vertical'   => Alignment::VERTICAL_CENTER,
+                    ],
+                ];
+
+                foreach ($options['alignCenter'] as $acItem) {
+                    $activeSheet->getStyle($acItem)->applyFromArray($styleArray);
+                }
+
+                unset($options['alignCenter']);
+            }
+
+            /* 设置加粗 */
+            if (isset($options['bold']) && !empty($options['bold'])) {
+                foreach ($options['bold'] as $bItem) {
+                    $activeSheet->getStyle($bItem)->getFont()->setBold(true);
+                }
+
+                unset($options['bold']);
+            }
+
+            /* 设置单元格边框,整个表格设置即可,必须在数据填充后才可以获取到最大行列 */
+            if (isset($options['setBorder']) && $options['setBorder']) {
+                $border    = [
+                    'borders' => [
+                        'allBorders' => [
+                            'borderStyle' => Border::BORDER_THIN, // 设置border样式
+                            'color'       => ['argb' => 'FF000000'], // 设置border颜色
+                        ],
+                    ],
+                ];
+                $setBorder = 'A1:' . $activeSheet->getHighestColumn() . $activeSheet->getHighestRow();
+                $activeSheet->getStyle($setBorder)->applyFromArray($border);
+                unset($options['setBorder']);
+            }
+
+            $fileName = !empty($fileName) ? $fileName : (date('YmdHis') . '.xlsx');
+
+            if (!isset($options['savePath'])) {
+                /* 直接导出Excel,无需保存到本地,输出07Excel文件 */
+                header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
+                header(
+                    "Content-Disposition:attachment;filename=" . iconv(
+                        "utf-8", "GB2312//TRANSLIT", $fileName
+                    )
+                );
+                header('Cache-Control: max-age=0');//禁止缓存
+                $savePath = 'php://output';
+            } else {
+                $savePath = $options['savePath'];
+            }
+
+            ob_clean();
+            ob_start();
+            $objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx');
+            $objWriter->save($savePath);
+            /* 释放内存 */
+            $objSpreadsheet->disconnectWorksheets();
+            unset($objSpreadsheet);
+            ob_end_flush();
+
+            return true;
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+    /**
+     * 导入
+     */
+    public function import()
+    {
+        $file = $this->request->request('file');
+        if (!$file) {
+            return $this->msg(504,'Parameter %s can not be empty');
+        }
+        $filePath = Env::get('root_path') . '/public/'  . $file;
+        if (!is_file($filePath)) {
+            return $this->msg(504,'No results were found');
+        }
+        //实例化reader
+        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
+        if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
+            return $this->msg(504,'Unknown data format');
+        }
+        if ($ext === 'csv') {
+            $file = fopen($filePath, 'r');
+            $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
+            $fp = fopen($filePath, "w");
+            $n = 0;
+            while ($line = fgets($file)) {
+                $line = rtrim($line, "\n\r\0");
+                $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
+                if ($encoding != 'utf-8') {
+                    $line = mb_convert_encoding($line, 'utf-8', $encoding);
+                }
+                if ($n == 0 || preg_match('/^".*"$/', $line)) {
+                    fwrite($fp, $line . "\n");
+                } else {
+                    fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
+                }
+                $n++;
+            }
+            fclose($file) || fclose($fp);
+
+            $reader = new Csv();
+        } elseif ($ext === 'xls') {
+            $reader = new Xls();
+        } else {
+            $reader = new Xlsx();
+        }
+
+        //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name
+        $importHeadType = isset($this->importHeadType) ? $this->importHeadType : 'comment';
+
+        $table = $this->model->getQuery()->getTable();
+        $database = Config::get('database.database');
+        $fieldArr = [];
+        $list = db()->query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]);
+        foreach ($list as $k => $v) {
+            if ($importHeadType == 'comment') {
+                $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME'];
+            } else {
+                $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_NAME'];
+            }
+        }
+
+        //加载文件
+        $insert = [];
+        try {
+            if (!$PHPExcel = $reader->load($filePath)) {
+                return $this->msg(504,'Unknown data format');
+            }
+            $currentSheet = $PHPExcel->getSheet(0);  //读取文件中的第一个工作表
+            $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
+            $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
+            $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
+            $fields = [];
+            for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
+                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
+                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
+                    $fields[] = $val;
+                }
+            }
+
+            for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
+                $values = [];
+                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
+                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
+                    $values[] = is_null($val) ? '' : $val;
+                }
+                $row = [];
+                $temp = array_combine($fields, $values);
+                foreach ($temp as $k => $v) {
+                    if (isset($fieldArr[$k]) && $k !== '') {
+                        $row[$fieldArr[$k]] = $v;
+                    }
+                }
+                if ($row) {
+                    $insert[] = $row;
+                }
+            }
+        } catch (Exception $exception) {
+            return $this->msg(504,$exception->getMessage());
+        }
+        if (!$insert) {
+            return $this->msg(504,'No rows were updated');
+        }
+
+        try {
+            //是否包含admin_id字段
+            $has_admin_id = false;
+            foreach ($fieldArr as $name => $key) {
+                if ($key == 'admin_id') {
+                    $has_admin_id = true;
+                    break;
+                }
+            }
+            if ($has_admin_id) {
+                $auth = Auth::instance();
+                foreach ($insert as &$val) {
+                    if (!isset($val['admin_id']) || empty($val['admin_id'])) {
+                        $val['admin_id'] = $auth->isLogin() ? $auth->id : 0;
+                    }
+                }
+            }
+            $this->model->saveAll($insert);
+        } catch (PDOException $exception) {
+            $msg = $exception->getMessage();
+            if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $msg, $matches)) {
+                $msg = "导入失败,包含【{$matches[1]}】的记录已存在";
+            };
+            return $this->msg(504,$msg);
+        } catch (\Exception $e) {
+            return $this->msg(504,$e->getMessage());
+        }
+
+        return $this->msg(200,'导入成功!!');
+    }
+
+//    /**
+//     * 发送邮件
+//     */
+//    public function sendEmail()
+//    {
+//        $translate = [
+//            'language_id'   => '所属站点',
+//            'country_id'    => '国家/地区',
+//            'name'          => '客户名称',
+//            'email'         => '客户邮箱',
+//            'order_sn'      => '订单号',
+//            'product_model' => '产品型号',
+//            'os'            => '操作系统',
+//            'desc'          => '问题详情',
+//            'question_attachment' => '反馈附件',
+//            'create_time'   => '反馈时间'
+//        ];
+//
+//        $data = $this->request->param();
+//        $data['create_time'] = date('Y-m-d H:i:s',time());
+//        $mail = new PHPMailer();
+//        $mail->CharSet = "UTF8";
+//        $mail->SMTPDebug = 0;                      //Enable verbose debug output
+//        $mail->isSMTP();                                            //Send using SMTP
+//        $mail->Host       = Env::get('EMAIL.MAIL_HOST');     //Set the SMTP server to send through
+//        $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
+//        $mail->Username   = Env::get('EMAIL.MAIL_USERNAME'); //SMTP username
+//        $mail->Password   = Env::get('EMAIL.MAIL_PASSWORD'); //SMTP password
+//        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         //Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
+//        $mail->Port       = Env::get('EMAIL.MAIL_PORT');     //TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
+//
+//        //Recipients
+//        $mail->setFrom(Env::get('EMAIL.MAIL_FROM_ADDRESS'), Env::get('EMAIL.MAIL_FROM_ADDRESS'));
+//        $mail->addAddress('yulinzhihou@163.com', 'yulinzhihou');     //Add a recipient
+//
+//        //Content
+//        $mail->isHTML(true);                                  //Set email format to HTML
+//        $mail->Subject = '尤达官网用户问题反馈'.$data['name'].date('Y-m-d H:i:s');
+//        $body = '';
+//        $body .= <<
+//  table,tr,td,th {
+//    border: 1px solid #ccc;
+//    border-collapse: collapse;
+//    text-align: justify;
+//  }
+//  .item1 {
+//    width: 20%;
+//  }
+//
+//
+//EOF;
+//        foreach ($data as $key => $value) {
+//            if (is_array($value)) {
+//                foreach ($value as $item) {
+//                    $body .= ''.'';
+//                }
+//            } else {
+//                $body .= ''.'';
+//            }
+//        }
+//        $body .= '
'.$translate[$key].'点击查看附件
'.$translate[$key].''.$value.'
'; +// $mail->Body = $body; +// $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; +// $result = $mail->send(); +// dd($result); +// +// } +// +// +// public function validateEmail() +// { +// $inputData = $this->request->param(); +// $validator = new EmailValidator(); +// $multipleValidations = new MultipleValidationWithAnd([ +// new RFCValidation(), +// new DNSCheckValidation() +// ]); +// //ietf.org has MX records signaling a server with email capabilites +// $result = $validator->isValid($inputData['email'], $multipleValidations); //true +// if ($result) { +// return $this->msg(200,'邮箱有效'); +// } else { +// return $this->msg(504,'邮箱无效'); +// } +// } +} diff --git a/app/api/controller/v1/Resource.php b/app/api/controller/v1/Resource.php new file mode 100644 index 0000000..12f764a --- /dev/null +++ b/app/api/controller/v1/Resource.php @@ -0,0 +1,135 @@ +validate = new ResourceValidate(); + $this->model = new ResourceModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['resource_type_id']) && $inputData['resource_type_id'] != '' && $inputData['resource_type_id'] != 0) { + $this->focus['resource_type_id'] = $inputData['resource_type_id']; + } + + if (isset($inputData['title']) && $inputData['title'] != '') { + $this->simple['title'] = $inputData['title']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time']) && !$inputData['create_time']) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $detail = $this->request->param('detail','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['detail'] = $detail; + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['create_time'])) { + $inputData['create_time'] = intval($inputData['create_time']) / 1000; + } else { + unset($inputData['create_time']); + } + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + +} diff --git a/app/api/controller/v1/ResourceType.php b/app/api/controller/v1/ResourceType.php new file mode 100644 index 0000000..b1a261c --- /dev/null +++ b/app/api/controller/v1/ResourceType.php @@ -0,0 +1,131 @@ +validate = new ResourceTypeValidate(); + $this->model = new ResourceTypeModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + //兼容新方式 + if (isset($inputData['sort']) && $inputData['sort'] != '') { + $this->orderby['sort'] = $inputData['sort']; + } else { + $this->orderby['sort'] = 'asc'; + } + + $this->field = ['id','platform_id','site_id','icon','name','sort']; + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->orderby,$this->field); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 更新 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + $updateData = $insertData = []; + if (count($inputData['data']) > 0) { + foreach ($inputData['data'] as &$item) { + if (isset($item['id']) && $item['id'] != '') { + if (!$this->commonValidate(__FUNCTION__,$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $updateData[] =[ + 'id' => $item['id'], + 'site_id' => $item['language_id'], + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } else { + if (!$this->commonValidate('create',$item)) { + return $this->msg(-1,$this->validate->getError()); + } + $insertData[] = [ + 'id' => null, + 'name' => $item['name'], + 'icon' => $item['icon']??'', + 'site_id' => $item['language_id'], + 'sort' => $item['sort'], + 'platform_id'=>$this->platformId + ]; + } + } + } + + if (!empty($updateData)) { + $result = $this->model->batchEditData($updateData); + } else { + $result = true; + } + if (!empty($insertData)) { + $result1 = $this->model->saveAll($insertData); + } else { + $result1 = true; + } + + if ($result && $result1) { + return $this->msg(200,'更新成功'); + } else { + return $this->msg(504,'更新失败'); + } + } + + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查找是否有子类。 + $hasData = $this->model->getArticleData($inputData); + if (empty($hasData)) { + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } else { + return $this->msg(504,"该类型下有内容,不能删除"); + } + } +} diff --git a/app/api/controller/v1/Role.php b/app/api/controller/v1/Role.php new file mode 100644 index 0000000..b47f59a --- /dev/null +++ b/app/api/controller/v1/Role.php @@ -0,0 +1,21 @@ +model = new RoleModel(); + $this->validate = new RoleValidate(); + } +} diff --git a/app/api/controller/v1/Site.php b/app/api/controller/v1/Site.php new file mode 100644 index 0000000..cbd6c02 --- /dev/null +++ b/app/api/controller/v1/Site.php @@ -0,0 +1,175 @@ +validate = new SiteValidate(); + $this->model = new SiteModel(); + } + + /** + * 列表 + */ + public function index():\think\response\Json + { + $inputData = $this->request->param(); + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + + /** + * 列表接口 + */ + public function siteIndex():\think\response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $this->focus['status'] = 0; + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + $data = []; + foreach ($result as $item) { + $data[] = [ + 'id' => $item['id'], + 'name' => $item['language_name'], + 'currency_name' => $this->model->getCoinName($item['currency_id']) + ]; + } + return $this->msg(200,'获取列表成功',$data); + } + + /** + * 详情 + */ + public function read():\think\response\Json + { + $inputData = $this->request->param(['id']); + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getInfo($inputData); + + if ($result) { + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(504,'获取列表失败'); + } + } + + /** + * 新增 + */ + public function create():\think\response\Json + { + $inputData = $this->request->param(); + //语言包 + if (isset($inputData['language_id']) || !empty($inputData['language_id']) || $inputData['language_id'] != 0) { + $this->focus['language_id'] = $inputData['language_id']; + } else { + return $this->msg(504,'语言包ID不正确,请检查!'); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //验证站点是否已经添加过 + $isExits = $this->model->getSiteData($inputData); + if (count($isExits) >= 1) { + return $this->msg(504,'一个品牌只能添加一个相同语言的站点。'); + } + //增加站点加密算法 语言ID+站点域名, + $inputData['app_id'] = md5($inputData['language_id'].$inputData['domain']); + $inputData['app_key'] = md5($inputData['app_id']); + + $result = $this->model->addData($inputData); + + if ($result) { + Cache::set($inputData['app_id'],$inputData['app_key']); + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\response\Json + { + $inputData = $this->request->param(); + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //验证站点是否已经添加过 + $isExits = $this->model->getSiteData($inputData); + + if (count($isExits) >= 1 && !in_array($inputData['id'],$isExits)) { + return $this->msg(504,'一个品牌只能添加一个相同语言的站点。'); + } + //增加站点加密算法 语言ID+站点域名, + $inputData['app_id'] = md5($inputData['language_id'].$inputData['domain']); + $inputData['app_key'] = md5($inputData['app_id']); + $result = $this->model->editData($inputData); + if ($result) { + Cache::set($inputData['app_id'],$inputData['app_key']); + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 获取导航数据 + */ + public function getNavigatorList():\think\response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + $this->commonValidate(__FUNCTION__,$inputData); + $result = $this->model->getNav($inputData); + + if ($result) { + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(504,'获取列表失败'); + } + } + + /** + * 删除 + */ + public function del():\think\response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } + +} diff --git a/app/api/controller/v1/SoftManual.php b/app/api/controller/v1/SoftManual.php new file mode 100644 index 0000000..98a3428 --- /dev/null +++ b/app/api/controller/v1/SoftManual.php @@ -0,0 +1,236 @@ +validate = new SoftManualValidate(); + $this->model = new SoftManualModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['file_type_id']) && $inputData['file_type_id'] != '' && $inputData['file_type_id'] != 0) { + $this->focus['file_type_id'] = $inputData['file_type_id']; + } + + if (isset($inputData['name']) && $inputData['name'] != '') { + $this->simple['name'] = $inputData['name']; + } + + $this->order['create_time'] = 'desc'; + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->getAllList($inputData,$this->simple,$this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $introduce = $this->request->param('introduce','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['introduce'] = $introduce; + $inputData['platform_id'] = $this->platformId; + unset($inputData['create_time']); + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + //验证是否提交按钮参数与链接 + if (isset($inputData['softBtn']) && empty($inputData['softBtn'])) { + $this->msg(504,'还没有填写按钮信息,请检查!'); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $introduce = $this->request->param('introduce','','htmlspecialchars'); + $inputData = $this->request->param(); + $inputData['introduce'] = $introduce; + $inputData['platform_id'] = $this->platformId; + unset($inputData['create_time']); + unset($inputData['update_time']); + + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //验证是否提交按钮参数与链接 + if (empty($inputData['softBtn'])) { + return $this->msg(504,'还没有填写按钮信息,请检查!'); + } + + $result = $this->model->editData($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + /** + * 更改排序 + */ + public function changeSort():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeSort($inputData); + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + + /** + * 图片,ICON上传 + */ + public function upload():\think\Response\Json + { + $files = $this->request->file(); + if (!$files) { + return $this->msg(-1, "请选择上传的文件"); + } + $field = array_keys($files)[0]; + $data = []; + //兼容多图上传 + if (is_array($files) && count($files) > 1 ) { + //不同字段文件名上传 image img ico + //上传到七牛 + foreach ($files as $key => $fileSimple) { +// if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { +// return $this->msg(200, $this->validate->getError()); +// } + $result[$key] = $this->qn->uploadFile($key); + } + + foreach ($result as $key => $item) { + $data[] = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$key]->getOriginalName(), + 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], + 'md5' => md5_file($files[$key]->getPathname()), + 'url' => $item['remote_url'], + 'relative_path' => $item['filename'] + ]; + } + } elseif (is_array($files[$field]) && count($files[$field]) > 1) { + //同一名称的数组文件上传.image[0] image[1] +// foreach ($files as $key => $fileSimple) { +// if (!$this->commonValidate(__FUNCTION__, [$key => $fileSimple])) { +// return $this->msg(200, $this->validate->getError()); +// } +// } + //上传到七牛 + $result = $this->qn->uploadFile($field, true, count($files[$field])); + + foreach ($result as $key => $item) { + $data[] = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$field][$key]->getOriginalName(), + 'filename' => explode('/', $item['filename'])[count(explode('/', $item['filename'])) - 1], + 'md5' => md5_file($files[$field][$key]->getPathname()), + 'url' => $item['remote_url'], + 'relative_path' => $item['filename'] + ]; + } + } else { +// if (!$this->commonValidate(__FUNCTION__,[$field=>$files])) { +// return $this->msg(200,$this->validate->getError()); +// } + //上传到七牛 + $result = $this->qn->uploadFile($field); + $data = [ + 'cdn' => Env::get('QINIU.cdn'), + 'origin_name' => $files[$field]->getOriginalName(), + 'filename' => explode('/',$result['filename'])[count(explode('/',$result['filename']))-1], + 'md5' => md5_file($files[$field]->getPathname()), + 'url' => $result['remote_url'], + 'relative_path' => $result['filename'] + ]; + } + + return $this->msg(200, '上传成功', $data); + } + + /** + * 删除 + */ + public function del():\think\Response\Json + { + $inputData = $this->request->param(['id']); + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + //查询是否有被使用 + $hasUsed = $this->model->getSoftManualUsed($inputData); + if ($hasUsed) { + return $this->msg(504,'已被使用,不能删除!'); + } + $result = $this->model->delData($inputData); + if ($result) { + return $this->msg(200,"删除成功"); + } else { + return $this->msg(504,"删除失败"); + } + } + + + +} diff --git a/app/api/controller/v1/SystemConfig.php b/app/api/controller/v1/SystemConfig.php new file mode 100644 index 0000000..5908f62 --- /dev/null +++ b/app/api/controller/v1/SystemConfig.php @@ -0,0 +1,145 @@ +model = new SystemConfigModel(); + $this->validate = new SystemConfigValidate(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getIndexList($this->page,$this->size,$this->field, $this->simple, $this->focus,$this->order); + if (isset($result['data']) && !empty($result['data'])) { + foreach ($result['data'] as $key => $item) { + if (!empty($item['image'])) { + $result['data'][$key]['image'] = json_decode($item['image'],true); + } + } + } + return $this->msg(200,'获取列表成功',$result); + } + + /** + * 详情 + */ + public function read():\think\Response\Json + { + $inputData = $this->request->param(['id']); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->getInfo($inputData); + if ($result['type'] == 2 || $result['type'] == 4) { + // 处理图片 + if (isset($result['image']) && !empty($result['image'])) { + $result['image'] = json_decode($result['image'],true); + } else { + $result['image'] = []; + } + } + + if ($result) { + $result['language_id'] = $result['site_id']; + return $this->msg(200,'获取列表成功',$result); + } else { + return $this->msg(200,'获取列表成功',[]); + } + } + + /** + * 新增 + */ + public function create():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + //语言包 + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + if (isset($inputData['site_id']) || !empty($inputData['site_id']) || $inputData['site_id'] != 0) { + $this->focus['site_id'] = $inputData['site_id']; + } else { + return $this->msg(504,'语言包/所属站点参数,不正确,请检查!'); + } + + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + // 处理图片 + if (isset($inputData['image']) && !empty($inputData['image'])) { + $inputData['image'] = json_encode($inputData['image']); + } + + $result = $this->model->addData($inputData); + + if ($result) { + return $this->msg(200,'新增成功'); + } else { + return $this->msg(504,'新增失败'); + } + } + + /** + * 修改 + */ + public function update():\think\Response\Json + { + $inputData = $this->request->param(); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + + $inputData['platform_id'] = $this->platformId; + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + + // 处理图片 + if (isset($inputData['image']) && !empty($inputData['image'])) { + $inputData['image'] = json_encode($inputData['image']); + } + + $result = $this->model->editData($inputData); + + if ($result) { + return $this->msg(200,'更改成功'); + } else { + return $this->msg(504,'更改失败'); + } + } + + + +} diff --git a/app/api/controller/v1/Video.php b/app/api/controller/v1/Video.php new file mode 100644 index 0000000..c9e6283 --- /dev/null +++ b/app/api/controller/v1/Video.php @@ -0,0 +1,66 @@ +validate = new VideoValidate(); + $this->model = new VideoModel(); + } + + /** + * 列表 + */ + public function index():\think\Response\Json + { + $inputData = $this->request->param(); + $inputData['platform_id'] = $this->platformId; + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $this->simple['name'] = $inputData['name'] ?? ''; + $result = $this->model->getIndexList($this->page,$this->size,$this->field, $this->simple, $this->focus,$this->order); + return $this->msg(200,'获取列表成功',$result); + } + + + /** + * 启用禁用 + */ + public function changeStatus():\think\Response\Json + { + $inputData = $this->request->param(); + if (isset($inputData['language_id']) && $inputData['language_id'] != 0 && $inputData['language_id'] != '') { + $this->focus['site_id'] = $inputData['site_id'] = $inputData['language_id']; + unset($inputData['language_id']); + } + if (!$this->commonValidate(__FUNCTION__,$inputData)) { + return $this->msg(-1,$this->validate->getError()); + } + $result = $this->model->changeStatus($inputData); + if ($result) { + return $this->msg(200,"操作成功"); + } else { + return $this->msg(504,"操作失败"); + } + } +} diff --git a/app/api/middleware/Auth.php b/app/api/middleware/Auth.php new file mode 100644 index 0000000..924a9ae --- /dev/null +++ b/app/api/middleware/Auth.php @@ -0,0 +1,79 @@ + Env::get('jwt_config.iss'), + 'exp' => Env::get('jwt_config.exp') + ]; + $jwt = new Jwt($config); + $route = strtolower($request->pathinfo()); + $domain = strtolower($request->host()); + + if (in_array($route,Config::get('whitelist.route')) or in_array($domain,Config::get('whitelist.domain'))) { + //表示此系列请求不需要鉴权,直接通行 + return $next($request); + } else { + //此系列请求需要鉴权。 + $loginToken = $request->header('x-token'); + $result = $jwt->checkToken($loginToken); + if ($result < 0) { + switch ($result) { + case -1: + show(-1,"token异常"); + break; + case -2: + show(-2,"token被篡改"); + break; + case -3: + show(-3,"token验签异常"); + break; + case -4: + show(-4,"token已过期"); + break; + } + } elseif ($result === 200 || $result === 201) { + // token通过 + $adminInfo = $jwt->getUserInfo($loginToken); + if (!isset($adminInfo['id'])) { + show(-1001, '登录异常'); + } + + if (empty($adminInfo) || $adminInfo['status'] == 1) { + show(-1002, '登录异常'); + } + + if ($result === 201) { + $new_login_token = $jwt->getToken($adminInfo); + $data = [ + 'login_token' => $new_login_token, + 'exp' => Env::get('jwt_config.exp') + ]; + + header("Access-Control-Expose-Headers: X-Token-info"); + header("X-Token-info: " . base64_encode(json_encode($data))); + } + $adminInfo['auth_id_list'] = [];//权限菜单下发 + $request->admin_user_info = $adminInfo; + return $next($request); + } + } + } +} \ No newline at end of file diff --git a/app/api/middleware/LogVisit.php b/app/api/middleware/LogVisit.php new file mode 100644 index 0000000..1812965 --- /dev/null +++ b/app/api/middleware/LogVisit.php @@ -0,0 +1,32 @@ +domain() . $request->url(); + $params = json_encode($request->param(), JSON_UNESCAPED_UNICODE); + $route = strtolower($request->pathinfo()); + $pathInfo = explode('/',$route); + $action = array_pop($pathInfo); + $controller = array_pop($pathInfo); + $admin_id = 0; + $admin_name = ''; + $platformId = 0; + if (isset($request->admin_user_info)) { + $admin_id = $request->admin_user_info['id']; + $admin_name = $request->admin_user_info['nickname']; + $platformId = $request->admin_user_info['platform_id']; + } + $log = new LogVisitModel(); + $log->log($url, $params, $controller, $action,$admin_id, $admin_name,$platformId); + return $next($request); + } + +} diff --git a/app/api/model/Admin.php b/app/api/model/Admin.php new file mode 100644 index 0000000..9ef0358 --- /dev/null +++ b/app/api/model/Admin.php @@ -0,0 +1,92 @@ + 'int', + 'code' => 'string', + 'username' => 'string', + 'nickname' => 'string', + 'password' => 'string', + 'avatar' => 'string', + 'role_id' => 'int', + 'org_id' => 'int', + 'dept_group_id' => 'int', + 'dept_id' => 'int', + 'mobile' => 'string', + 'create_time' => 'int', + 'create_ip' => 'string', + 'last_time' => 'int', + 'last_ip' => 'string', + 'status' => 'int', + 'update_time' => 'int', + ]; + + /** + * 获取管理员列表 + * @param array $where + * @param int $page + * @param int $size + * @param string $order + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList($where, $page=1, $size=12, $order='id asc') + { + $w = []; + if (isset($where['username']) && $where['username'] != '') { + $w[] = ['username', 'like', $where['username'] . '%']; + } + + if (isset($where['role_id']) && $where['role_id'] != 0) { + $w[] = ['role_id', '=', $where['role_id']]; + } + + if ($page < 0) $page = 1; + if ($size > 100) $size = 100; + + $result = $this->where($w)->limit(($page-1)*$size, intval($size))->order($order)->withoutField(['password'])->select()->toArray(); + return $result; + } + + /** + * 通过用户名获取信息 + * @param string $username + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfoByUserName($username) + { + $result = $this->where(['username' => $username])->find(); + return $result ? $result->toArray() : []; + } + + /** + * 获取用户信息 + * @param int $id 管理员表主键 + * @param bool $type + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getUserInfo(int $id,bool $type=false):array + { + if ($type) { + $result = $this->find($id); + } else { + $result = $this->withoutField('password')->find($id); + } + return $result ? $result->toArray() : []; + } +} diff --git a/app/api/model/AdvertisePage.php b/app/api/model/AdvertisePage.php new file mode 100644 index 0000000..af2eab6 --- /dev/null +++ b/app/api/model/AdvertisePage.php @@ -0,0 +1,100 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 广告页关系广告位模型 + */ + public function PageSpace() + { + return $this->hasMany(AdvertiseSpace::class); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + } + } + + + /** + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdSpace($data) + { + $result = $this->where('id',$data['id'])->with('PageSpace')->find()->toArray(); + return $result['PageSpace']; + } + +} diff --git a/app/api/model/AdvertiseSpace.php b/app/api/model/AdvertiseSpace.php new file mode 100644 index 0000000..83a72a4 --- /dev/null +++ b/app/api/model/AdvertiseSpace.php @@ -0,0 +1,140 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'advertise_page_id'=>'int', + 'max_num' =>'int', + 'width' =>'int', + 'height' =>'int', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 一个广告位对应一个多多个广告 + */ + public function pageAd():\think\model\relation\HasMany + { + return $this->hasMany(Advertisement::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + $page[$key]['advertise_page_name'] = $this->getAdvertisePageName($item['advertise_page_id']); + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + $page[$key]['advertise_page_name'] = $this->getAdvertisePageName($item['advertise_page_id']); + } + } + return $page; + } + } + + /** + * 广告位-广告的关联模型 + */ + public function spaceToAD():\think\model\relation\HasMany + { + return $this->hasMany(Advertisement::class); + } + + /** + * 获取列表 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList($data):array + { + $result = $this->where('site_id',$data['site_id'])->select(); + if ($result) { + foreach ($result as &$item) { + $item['use_num'] = $item->spaceToAD()->count(); + } + } + return $result->toArray(); + } + + + /** + * 获取此广告位已经使用了的数量 + * @param $data + * @return int + */ + public function getUseSpaceNum($data):int + { + return Advertisement::where('advertise_space_id',$data['id'])->where('site_id',$data['site_id'])->count(); + } + + + /** + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAd($data):array + { + return $this->where('id',$data['id'])->with('pageAd')->find()->toArray()['pageAd']; + } +} diff --git a/app/api/model/Advertisement.php b/app/api/model/Advertisement.php new file mode 100644 index 0000000..a9d3e48 --- /dev/null +++ b/app/api/model/Advertisement.php @@ -0,0 +1,154 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'advertise_space_id' =>'int', + 'command' =>'string', + 'name' =>'string', + 'image' =>'string', + 'url' =>'string', + 'start_time' =>'int', + 'stop_time' =>'int', + 'play_order' =>'int', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + $page[$key]['advertise_space_name'] = $this->getAdertiseSpaceName($item['advertise_space_id']); + $page[$key]['spec'] = $this->getAdvertiseSpaceSpec($item['advertise_space_id']); + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + $page[$key]['advertise_space_name'] = $this->getAdertiseSpaceName($item['advertise_space_id']); + $page[$key]['spec'] = $this->getAdvertiseSpaceSpec($item['advertise_space_id']); + } + return $page; + } + } + + /** + * 广告对应广告位,一对一 + * @return \think\model\relation\BelongsTo + */ + public function getAdToSpace() + { + return $this->belongsTo(AdvertiseSpace::class); + } + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + $advertisement = $this->find($data['id']); + if ($advertisement) { + $advertisement['ad_space_max_num'] = $advertisement->getAdToSpace()->value('max_num'); + $advertisement['size'] = $advertisement->getAdToSpace()->value('width')."x".$advertisement->getAdToSpace()->value('height'); + } + return $advertisement->toArray() ? : []; + } + + /** + * 通过id获取当前广告位最大的广告数量 + * @param $data + * @return int|mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdvertiseSpaceMaxNum($data):int + { + $result = AdvertiseSpace::find($data); + return $result ? $result['max_num'] : 1; + } + + /** + * 通过id获取当前广告位已经有多少条广告 + * @param $data + * @return int + */ + public function getAdvertiseUseSpaceNum($data):int + { + return $this->where('advertise_space_id',$data['advertise_space_id'])->where('site_id',$data['site_id'])->count(); + } + + + /** + * 查询当前数据是否是修改自己,还是别的项目修改成其他的 + * @param $data + * @return bool + */ + public function getBeforeUpdate($data):bool + { + $result = $this->findOrEmpty($data['id']); + if (!empty($result)) { + if ($result['advertise_space_id'] == $data['advertise_space_id']) { + return true; + } + } + return false; + } +} diff --git a/app/api/model/Area.php b/app/api/model/Area.php new file mode 100644 index 0000000..c7016ba --- /dev/null +++ b/app/api/model/Area.php @@ -0,0 +1,16 @@ + 'int', + 'pid' => 'int', + 'name' => 'string', + 'level' => 'int', + ]; +} diff --git a/app/api/model/Article.php b/app/api/model/Article.php new file mode 100644 index 0000000..968d7ec --- /dev/null +++ b/app/api/model/Article.php @@ -0,0 +1,96 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'article_type_id' => 'int', + 'title' => 'string', + 'brief' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'meta_title' => 'string', + 'keywords' => 'string', + 'detail' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_outer_chain' => 'int', + 'click_num' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * + */ + public function articleType():\think\model\relation\HasOne + { + return $this->hasOne(ArticleType::class,'id','article_type_id')->bind(['article_type_name'=>'name']); + } + + /** + */ + public function languageName():\think\model\relation\HasOne + { + return $this->hasOne(Language::class,'id','site_id')->bind(['language_name'=>'name']); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int) $data['size'])->page((int)$data['page'])->order($sort)->with(['articleType','languageName'])->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->with(['articleType','languageName'])->select()->toArray(); + } + } +} diff --git a/app/api/model/ArticleType.php b/app/api/model/ArticleType.php new file mode 100644 index 0000000..513bd6f --- /dev/null +++ b/app/api/model/ArticleType.php @@ -0,0 +1,105 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * article分类与article表模型 + * @return \think\model\relation\HasMany + */ + public function getArticle() + { + return $this->hasMany(Article::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getArticleData($data):array + { + $article = $this->find($data['id']); + if (!empty($article)) { + return $article->getArticle()->select()->toArray(); + } + return []; + } +} diff --git a/app/api/model/Attachment.php b/app/api/model/Attachment.php new file mode 100644 index 0000000..8ec1bd5 --- /dev/null +++ b/app/api/model/Attachment.php @@ -0,0 +1,24 @@ + 'int', + 'platform_id' => 'int', + 'site_id' => 'int', + 'name' => 'string', + 'type' => 'string', + 'local' => 'string', + 'path' => 'string', + 'hash' => 'string', + 'md5' => 'string', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + +} diff --git a/app/api/model/Attribute.php b/app/api/model/Attribute.php new file mode 100644 index 0000000..1891e78 --- /dev/null +++ b/app/api/model/Attribute.php @@ -0,0 +1,34 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'name' => 'string', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + + /** + * 通过属性ID,查找是否有商品引用属性 + * @param $data + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodsAttrById($data) + { + return GoodsAttribute::where('attribute_id',$data['id'])->find(); + } +} diff --git a/app/api/model/BaseModel.php b/app/api/model/BaseModel.php new file mode 100644 index 0000000..78d9e7e --- /dev/null +++ b/app/api/model/BaseModel.php @@ -0,0 +1,417 @@ +'desc','sort'=>'desc'] + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getIndexList(int $page,int $pageSize,array $field = [], array $vague = [],array $focus = [],array $order = []):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($fields,$focus) { + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + })->where(function($query) use ($fields,$vague) { + //模糊查询 + if (!empty($vague)) { + foreach ($vague as $key => $item) { + if (in_array($key,$fields)) { + $query->whereOr($key,'like',"%".$item."%"); + } + } + } + })->order($order); + //判断是否需要分页 + if (0 == $page || 0 == $pageSize) { + //不需要分页 + return $collection->select()->toArray(); + } else { + //需要分布 + $totalNum = $collection->count(); + $data = $collection->page($page)->limit($pageSize)->select()->toArray();; + return ['count'=>$totalNum,'data'=>$data]; + } + } + + /** + * 新增数据 + * @param array $data + * @return bool + */ + public function addData(array $data) : bool + { + $result = $this->create($data); + return (bool)$result; + } + + /** + * 编辑数据 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editData(array $data) : bool + { + if (isset($data['id']) && $data['id'] > 0) { + $result = $this->find($data['id']); + return $result && $result->save($data); + } + return false; + } + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data) : array + { + if (isset($data['id'])) { + $result = $this->find($data['id']); + return $result ? $result->toArray() : []; + } + return []; + } + + /** + * 删除 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData(array $data) : bool + { + if (isset($data['id'])) { + $result = $this->find($data['id']); + return $result && $result->delete(); + } + return false; + } + + /** + * 通过ID获取数据 + * @param $ids + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getExportData($ids): array + { + $result = $this->whereIn($this->pk,$ids['ids'])->order('create_time','desc')->select(); + return $result ? $result->toArray() : []; + } + + + /** + * 批量修改 + * @param $data + * @return bool + * @throws \Exception + */ + public function batchEditData($data):bool + { + $result = $this->saveAll($data); + return (bool)$result; + } + + + /** + * 批量删除 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function batchDelData(array $data) : bool + { + $res = true; + foreach ($data as $item) { + if (isset($item['id']) && $item['id'] > 0) { + $result = $this->find($item['id']); + $result = $result->delete(); + $res = $res && $result; + } + } + return $res; + } + + /** + * 获取地区名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAreaNameById($id):string + { + $data = Area::find($id); + return $data ? $data['name'] : ''; + } + + /** + * 获取币种名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getCoinName($id):string + { + $result = Currency::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 获取站点语言名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSiteLanguageName($id):string + { + $lang = Site::find($id); + $result = Language::find($lang['language_id']); + return $result ? $result['name'] : ''; + } + + + /** + * 获取语言名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLanguageName($id):string + { + $result = Language::find($id); + return $result ? $result['name'] : ''; + } + + + /** + * 获取语言名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getCountryName($id):string + { + $result = Country::find($id); + return $result ? $result['zh'] : '其他'; + } + + /** + * 获取币种名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPlatformName($id):string + { + $result = Platform::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过id获取名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFileTypeName($id):string + { + $result = FileType::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过id获取名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFaqTypeName($id):string + { + $result = FaqType::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过id获取名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdvertisePageName($id):string + { + $result = AdvertisePage::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过id获取名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdertiseSpaceName($id):string + { + $result = AdvertiseSpace::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过id获取尺寸 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdvertiseSpaceSpec($id):string + { + $result = AdvertiseSpace::find($id); + if ($result) { + $width = $result['width']; + $height = $result['height']; + return $width. 'x' . $height; + + } + return ''; + } + + /** + * 通过id获取名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodsName($id):string + { + $result = Goods::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 启用禁用 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function changeStatus($data):bool + { + $result = $this->find($data['id']); + return $result && $result->save($data); + } + + /** + * 排序 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function changeSort($data):bool + { + $result = $this->find($data['id']); + return $result && $result->save($data); + } + + /** + * 获取子类ID + * @param $id + * @return array + */ + public function getChildCategory($id):array + { + $res = $this->where('pid',$id)->column('id'); + array_push($res,intval($id)); + return $res ?: []; + } + + /** + * 获取父类ID + * @param $id + * @return array + */ + public function getPCategory($id):array + { + $res = $this->where('id',$id)->column('id'); + array_push($res,intval($id)); + return $res ?: []; + } + + /** + * 动态数据检测,检测提交过来的数据中ID是否合法 + * @param $model + * @param $condition + * @return bool + */ + public function dynamicCheck($model,$condition):bool + { + return (bool) $model::where($condition)->find(); + } + + +} diff --git a/app/api/model/Brand.php b/app/api/model/Brand.php new file mode 100644 index 0000000..a830ce6 --- /dev/null +++ b/app/api/model/Brand.php @@ -0,0 +1,106 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'brand_type_id' => 'int', + 'title' => 'string', + 'brief' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'meta_title' => 'string', + 'keywords' => 'string', + 'detail' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_outer_chain' => 'int', + 'is_on_index' => 'int', + 'click_num' => 'int', + 'create_time' => 'int', + 'update_time' => 'int', + 'website' => 'string', + 'cname' => 'string', +// 'en_name' => 'string', + 'belong' => 'string', +// 'turnover' => 'string', + 'brand_cate' => 'string', + 'work_address' => 'string', + 'founded' => 'string', + 'founder' => 'string' + ]; + + /** + * + */ + public function BrandType():\think\model\relation\HasOne + { + return $this->hasOne(BrandType::class,'id','brand_type_id')->bind(['brand_type_name'=>'name']); + } + + /** + */ + public function languageName():\think\model\relation\HasOne + { + return $this->hasOne(Language::class,'id','site_id')->bind(['language_name'=>'name']); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int) $data['size'])->page((int)$data['page'])->order($sort)->with(['BrandType','languageName'])->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->with(['BrandType','languageName'])->select()->toArray(); + } + } +} diff --git a/app/api/model/BrandType.php b/app/api/model/BrandType.php new file mode 100644 index 0000000..74e5871 --- /dev/null +++ b/app/api/model/BrandType.php @@ -0,0 +1,122 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * Brand分类与Brand表模型 + * @return \think\model\relation\HasMany + */ + public function getBrand() + { + return $this->hasMany(Brand::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getBrandData($data):array + { + $Brand = $this->find($data['id']); + if (!empty($Brand)) { + return $Brand->getBrand()->select()->toArray(); + } + return []; + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getArticleData($data):array + { + $article = $this->find($data['id']); + if (!empty($article)) { + return $article->getBrand()->select()->toArray(); + } + return []; + } +} diff --git a/app/api/model/BulkBuy.php b/app/api/model/BulkBuy.php new file mode 100644 index 0000000..b215ebc --- /dev/null +++ b/app/api/model/BulkBuy.php @@ -0,0 +1,25 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'area_id' =>'int', + 'name' =>'string', + 'phone' =>'string', + 'mode_number' =>'string', + 'email' =>'string', + 'arrival_country'=>'string', + 'delivery_time' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/api/model/Comment.php b/app/api/model/Comment.php new file mode 100644 index 0000000..fbfb637 --- /dev/null +++ b/app/api/model/Comment.php @@ -0,0 +1,222 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'avatar' =>'string', + 'name' =>'string', + 'nickname' =>'string', + 'comment' =>'string', + 'url' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + protected $disuse = ['name']; + /** + * 反馈附件关联 + * @return \think\model\relation\HasMany + */ + public function CommentImage() + { + return $this->hasMany(CommentImage::class); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + $newCommentImage = []; + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->with('CommentImage')->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $value) { + $resData[$key]['language_id'] = $value['site_id']; + if (isset($value['CommentImage']) && !empty($value['CommentImage'])) { + foreach ($value['CommentImage'] as $key1 => $value1) { + $newCommentImage[$key1]['name'] = basename($value1['image']); +// $newCommentImage[$key1]['url'] = Env::get('QINIU.cdn') . $value1['image']; + $newCommentImage[$key1]['url'] = $value1['image']; + } + $page[$key]['CommentImage'] = $newCommentImage; + } + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->order($sort)->with('CommentImage')->select()->toArray(); + + if (!empty($resData)) { + if ($resData['CommentImage']) { + foreach ($resData as $key => $value) { + $resData[$key]['language_id'] = $value['site_id']; + foreach ($value['CommentImage'] as $key1 => $value1) { + $newCommentImage[$key1]['name'] = basename($value1['image']); +// $newCommentImage[$key1]['url'] = Env::get('QINIU.cdn') . $value1['image']; + $newCommentImage[$key1]['url'] = $value1['image']; + } + $resData[$key]['CommentImage'] = $newCommentImage; + } + } + } + return $resData; + } + } + + /** + * 新增数据 + * @param $data + * @return bool + */ + public function addData($data):bool + { + $this->startTrans(); + try { + $data['avatar'] = doImageURLtoRelativePath($data['avatar']); + $comment = $this->create($data); + //处理数据结构 + if (!empty($data['CommentImage'])) { + foreach ($data['CommentImage'] as &$value) { + $value['comment_id'] = $comment->id; + $value['image'] = doImageURLtoRelativePath($value['url']); + } + //模型关联新增 + $comment->CommentImage()->saveAll($data['CommentImage']); + } + $this->commit(); + return true; + } catch (\Exception $e) { + $this->rollback(); + return false; + } + } + + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + $comment = $this->find($data['id']); + $comment['CommentImage'] = $this->CommentImage()->where('comment_id',$data['id'])->select(); + if ($comment['CommentImage']) { + $newImage = []; + foreach ($comment['CommentImage'] as $key1 => $value1) { + $newImage[$key1]['name'] = basename($value1['image']); + $newImage[$key1]['url'] = $value1['image']; + } + $comment['CommentImage'] = $newImage; + } + return $comment->toArray(); + } + + /** + * 编辑数据 + * @param array $data + * @return bool + */ + public function editData(array $data):bool + { + $this->startTrans(); + try { + $data['comment_image'] = $data['CommentImage']; + unset($data['CommentImage']); + $comment = $this->find($data['id']); + $data['avatar'] = doImageURLtoRelativePath($data['avatar']); + $result1 = $comment->save($data); + //先将原先的全部删除 + if (!empty($data['comment_image'])) { + $result2 = $comment->CommentImage->delete(); + if ($result1 && $result2) { + //处理数据结构 + $newCommentImage = []; + foreach ($data['comment_image'] as $key => $value) { + $newCommentImage[] = [ + 'comment_id' => $data['id'], + 'image' => doImageURLtoRelativePath($value['url']), + ]; + } + $data['comment_image'] = $newCommentImage; + //新增 + $comment->CommentImage()->saveAll($data['comment_image']); + } + } + $this->commit(); + return true; + } catch (\Exception $e) { + $this->rollback(); + return false; + } + } + + + /** + * 删除数据 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData(array $data):bool + { + $comment = $this->find($data['id']); + $result1 = $comment->delete(); + //先将原先的全部删除 + $result2 = $comment->CommentImage->delete();; + return $result1 && $result2; + } + +} diff --git a/app/api/model/CommentImage.php b/app/api/model/CommentImage.php new file mode 100644 index 0000000..d5660de --- /dev/null +++ b/app/api/model/CommentImage.php @@ -0,0 +1,16 @@ +'int', + 'comment_id' =>'int', + 'image' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/api/model/Country.php b/app/api/model/Country.php new file mode 100644 index 0000000..f07d24f --- /dev/null +++ b/app/api/model/Country.php @@ -0,0 +1,23 @@ + 'int', + 'en' => 'string', + 'code' => 'string', + 'tw' => 'string', + 'zh' => 'string', + 'icon' => 'string', + 'locale' => 'string', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + +} diff --git a/app/api/model/CouponSubscribe.php b/app/api/model/CouponSubscribe.php new file mode 100644 index 0000000..31c9767 --- /dev/null +++ b/app/api/model/CouponSubscribe.php @@ -0,0 +1,78 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'goods_coupon_id' =>'int', + 'email' =>'string', + 'phone' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList($data,$simple = null,$focus = null,$sort = null,$field = null) + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['site_id']); + } + } + return $page; + } + } + +} diff --git a/app/api/model/Currency.php b/app/api/model/Currency.php new file mode 100644 index 0000000..eab2b32 --- /dev/null +++ b/app/api/model/Currency.php @@ -0,0 +1,84 @@ +'int', + 'name' =>'string', + 'code' =>'string', + 'signal' =>'string', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * 通过币种ID获取平台是否已经使用 + * @param $data + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPlatformCoin($data) + { + return Platform::where('currency_id',$data)->find(); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->order($sort)->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->select()->toArray(); + } + } + +} diff --git a/app/api/model/Faq.php b/app/api/model/Faq.php new file mode 100644 index 0000000..cfea278 --- /dev/null +++ b/app/api/model/Faq.php @@ -0,0 +1,94 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'faq_type_id' =>'int', + 'question' =>'string', + 'answer' =>'string', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 +// if (!empty($simple)) { +// foreach ($simple as $key => $item) { +// if (in_array($key,$fields)) { +// $query->where($key,'like',"%".$item."%"); +// } +// } +// } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + })->where(function ($query) use ($data,$fields,$simple) { + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->whereOr($key,'like',"%".$item."%"); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + //获取列表名称 + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['faq_type_name'] = $this->getFaqTypeName($item['faq_type_id']); + $page[$key]['language_id'] = $this->getFaqTypeName($item['site_id']); + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + if (!empty($page)) { + //获取列表名称 + foreach ($page as $key => $item) { + $page[$key]['faq_type_name'] = $this->getFaqTypeName($item['faq_type_id']); + $page[$key]['language_id'] = $this->getFaqTypeName($item['site_id']); + } + } + return $page; + } + } +} diff --git a/app/api/model/FaqType.php b/app/api/model/FaqType.php new file mode 100644 index 0000000..c3f415d --- /dev/null +++ b/app/api/model/FaqType.php @@ -0,0 +1,106 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * faq分类关联faq表模型 + * @return \think\model\relation\HasMany + */ + public function getFaqContents() + { + return $this->hasMany(Faq::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的faq内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFaqData($data) + { + $faqType = $this->find($data['id']); + if (!empty($faqType)) { + return $faqType->getFaqContents()->select()->toArray(); + } + return false; + } +} diff --git a/app/api/model/FileType.php b/app/api/model/FileType.php new file mode 100644 index 0000000..520c4de --- /dev/null +++ b/app/api/model/FileType.php @@ -0,0 +1,130 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + public function fileTypeSoftManual() + { + return $this->hasMany(SoftManual::class); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->order($sort)->with('fileTypeSoftManual')->select()->toArray(); + if (!empty($resData)) { + foreach ($resData as $key => $item) + $resData[$key]['language_id'] = $item['site_id'];{ + if (count($item['fileTypeSoftManual']) > 0) { + $resData[$key]['is_gray'] = 1; + } else { + $resData[$key]['is_gray'] = 0; + } + } + } + return $resData; + } + } + + + /** + * 获取当前类型下驱动下载文件内容 + * @param $data + * @return false + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSoftManualData($data) + { + $softManual = $this->find($data['id']); + if (!empty($softManual)) { + return $softManual->fileTypeSoftManual()->select()->toArray(); + } + return false; + } + + + /** + * 批量编辑数据 + * @param $data + * @return \think\Collection + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function batchEditData($data):bool + { + return (bool)$this->saveAll($data); +// $result = $result1 = true; +// foreach ($data as $item) { +// $models = $this->find($item['id']); +// if ($models) { +// $result1 = $models->save($item); +// } +// $result = $result && $result1; +// } +// return $result; + } + +} diff --git a/app/api/model/Goods.php b/app/api/model/Goods.php new file mode 100644 index 0000000..feeb4a6 --- /dev/null +++ b/app/api/model/Goods.php @@ -0,0 +1,609 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'main_img' =>'string', + 'model_number' =>'string', + 'goods_category_id' =>'int', + 'price' =>'int', + 'is_new' =>'int', + 'is_discount' =>'int', + 'is_hot' =>'int', + 'is_recommend' =>'int', + 'details' =>'string', + 'title' =>'string', + 'keywords' =>'string', + 'description' =>'string', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 商品链接关联模型 + */ + public function GoodsBuyNow() + { + return $this->hasMany(GoodsBuyNow::class); + } + + /** + * 商品关联商品 + */ + public function GoodsConnect() + { + return $this->hasMany(GoodsConnect::class); + } + + /** + * 商品手册关联模型 + * @return \think\model\relation\HasMany + */ + public function GoodsSoftManual() + { + return $this->hasMany(GoodsSoftManual::class); + } + + /** + * 商品主图关联模型 + * @return \think\model\relation\HasMany + */ + public function GoodsImages() + { + return $this->hasMany(GoodsImages::class); + } + + /** + * 商品属性关联 + * @return \think\model\relation\HasMany + */ + public function goodsAttr() + { + return $this->hasMany(GoodsAttribute::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + //分类查询 + if (!empty($data['goods_category_id']) && is_array($data['goods_category_id'])) { + $query->whereIn('goods_category_id',implode(',',$data['goods_category_id'])); + } + }); + //先筛选再分 + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->order($sort)->select()->count(); + $page = $collection->order($sort)->limit((int)$data['size'])->page((int)$data['page'])->select()->toArray(); + return ['page'=>array_values($page),'count'=>$count]; + } else { + $resData = $collection->order($sort)->select()->toArray(); + return array_values($resData); + } + } + + /** + * 新增数据 + * @param array $data + * @return bool + */ + public function addData(array $data):bool + { + //开启事务 + $this->startTrans(); + //增加主图 + if (isset($data['goods_images'][0]['url'])) { + $data['main_img'] = doImageURLtoRelativePath($data['goods_images'][0]['url']); + } else { + //TODO::没有上传数据则使用空,后面可以替换为默认图片 + $data['main_img'] = ''; + } + $goods = $this->create($data); + //处理数据结构 + $newBuyNow = []; + foreach ($data['buy_now'] as $key => $value) { + if ($value['name'] != '' && $value['url'] != '') { + $newBuyNow[$key]['goods_id'] = $goods->id; + $newBuyNow[$key]['name'] = $value['name']; + $newBuyNow[$key]['url'] = $value['url']; + } + } + $data['buy_now'] = $newBuyNow; + if (!empty($data['buy_now'])) { + $result1 = $goods->GoodsBuyNow()->saveAll($data['buy_now']); + } else { + unset($data['buy_now']); + $result1 = true; + } + + $newGoodsImages = []; + foreach ($data['goods_images'] as $key => $value) { + if ($key < 8) { + $newGoodsImages[$key]['goods_id'] = $goods->id; + $newGoodsImages[$key]['image'] = doImageURLtoRelativePath($value['url']); + } + } + $data['goods_images'] = $newGoodsImages; + if (!empty($data['goods_images'])) { + $result2 = $goods->GoodsImages()->saveAll($data['goods_images']); + } else { + unset($data['goods_images']); + $result2 = true; + } + + $newConnectGoods = []; + foreach ($data['connect_goods'] as $key => $value) { + if ($value['connect_good_id'] != '' && $value['goods_category_id'] != '') { + $newConnectGoods[$key]['goods_id'] = $goods->id; + $newConnectGoods[$key]['connect_good_id'] = $value['connect_good_id']; + $newConnectGoods[$key]['goods_category_id'] = $value['goods_category_id']; + } + } + $data['connect_goods'] = $newConnectGoods; + if (!empty($data['connect_goods'])) { + $result3 = $goods->GoodsConnect()->saveAll($data['connect_goods']); + } else { + unset($data['connect_goods']); + $result3 = true; + } + //处理驱动文档数据 + $newSoft = []; + foreach ($data['soft_manual'] as $key => $value) { + if ($value['file_type_id'] != '' && $value['soft_manual_id'] != '') { + $newSoft[$key]['goods_id'] = $goods->id; + $newSoft[$key]['file_type_id'] = $value['file_type_id']; + $newSoft[$key]['soft_manual_id'] = $value['soft_manual_id']; + } + } + $data['soft_manual'] = $newSoft; + if (!empty($data['soft_manual'])) { + $result4 = $goods->GoodsSoftManual()->saveAll($data['soft_manual']); + } else { + unset($data['soft_manual']); + $result4 = true; + } + + //处理属性attr + $newAttr = []; + foreach ($data['attr'] as $key => $item) { + if ($item['attribute_id'] != '' && $item['value'] != '') { + $newAttr[$key]['goods_id'] = $goods->id; + $newAttr[$key]['attribute_id'] = $item['attribute_id']; + $newAttr[$key]['value'] = $item['value']; + } + } + $data['attr'] = $newAttr; + if (!empty($data['attr'])) { + $result5 = $goods->goodsAttr()->saveAll($data['attr']); + } else { + unset($data['attr']); + $result5 = true; + } + //模型关联新增 + if($result1 && $result2 && $result3 && $result4 && $result5) { + $this->commit(); + return true; + } else { + $this->rollback(); + return false; + } + } + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + //初始化默认结构 + $defaultBuyNow = [['name' => '','url' => '']]; + $defaultSoftManual = [['file_type_id'=>'','soft_manual_id'=>'']]; + $defaultAttr = [['id'=>'','value'=>'']]; + $defaultGoodsImages = [['name'=>'','url'=>'']]; + $defaultConnectGoods = [ + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ['connect_good_id'=>'','goods_category_id'=>''], + ]; + + $goods = $this->find($data['id']); + $goods['buy_now'] = $this->GoodsBuyNow()->where('goods_id',$data['id'])->select()->toArray(); + $goods['goods_images'] = $this->GoodsImages()->where('goods_id',$data['id'])->select()->toArray(); + $goods['connect_goods'] = $this->GoodsConnect()->where('goods_id',$data['id'])->select()->toArray(); + $goods['soft_manual'] = $this->GoodsSoftManual()->where('goods_id',$data['id'])->select()->toArray(); + $goods['attr'] = $this->goodsAttr()->where('goods_id',$data['id'])->select()->toArray(); + + //处理buynow + if (!empty($goods['buy_now'])) { + $newBuyNow = []; + foreach ($goods['buy_now'] as $key => $item) { + $newBuyNow[$key]['name'] = $item['name']; + $newBuyNow[$key]['url'] = $item['url']; + } + $goods['buy_now'] = $newBuyNow; + } else { + $goods['buy_now'] = $defaultBuyNow; + } + //处理属性attr + if (!empty($goods['attr'])) { + $newAttr = []; + foreach ($goods['attr'] as $key => $item) { + $newAttr[$key]['attribute_id'] = $item['attribute_id']; + $newAttr[$key]['value'] = $item['value']; + } + $goods['attr'] = $newAttr; + } else { + $goods['attr'] = $defaultAttr; + } + //处理图片 + if (!empty($goods['goods_images'])) { + $newGoodsImages = []; + foreach ($goods['goods_images'] as $key => $item) { + if ($key < 8) { + $newGoodsImages[$key]['id'] = $item['id']; + $newGoodsImages[$key]['name'] = basename($item['image']); + $newGoodsImages[$key]['url'] = $item['image']; + } + } + $goods['goods_images'] = $newGoodsImages; + } else { + $goods['goods_images'] = $defaultGoodsImages; + } + + //处理关联产品数据 + if (!empty($goods['connect_goods'])) { + $newConnectGoods = []; + foreach ($goods['connect_goods'] as $key => $item) { + $newConnectGoods[$key]['id'] = $item['id']; + $newConnectGoods[$key]['connect_good_id'] = $item['connect_good_id']; + $newConnectGoods[$key]['type'] = $key; + $newConnectGoods[$key]['goods_category_id'] = $item['goods_category_id']; + } + if (count($newConnectGoods) < 4 ) { + $arr = [['connect_good_id'=>'','goods_category_id'=>'']]; + switch (count($newConnectGoods)) { + case 1: + $newConnectGoods = array_merge(array_merge(array_merge($newConnectGoods,$arr),$arr),$arr); + break; + case 2: + $newConnectGoods = array_merge(array_merge($newConnectGoods,$arr),$arr); + break; + case 3: + $newConnectGoods = array_merge($newConnectGoods,$arr); + break; + } + } + $goods['connect_goods'] = $newConnectGoods; + } else { + $goods['connect_goods'] = $defaultConnectGoods; + } + + //处理下载驱动手册 + if (!empty($goods['soft_manual'])) { + $newSoft = []; + foreach ($goods['soft_manual'] as $key => $good) { + $newSoft[$key]['file_type_id'] = $good['file_type_id']; + $newSoft[$key]['soft_manual_id'] = $good['soft_manual_id']; + $newSoft[$key]['list'] = SoftManual::where('file_type_id',$good['file_type_id'])->select()->toArray(); + } + $goods['soft_manual'] = $newSoft; + } else { + $goods['soft_manual'] = $defaultSoftManual; + } + + return $goods->toArray(); + } + + /** + * 编辑数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editData(array $data):bool + { + $this->startTrans(); + $goods = $this->find($data['id']); + //如何编辑商品修改了分类数据,那么需要把相关产品对应的分类一同删除 + if ($goods['goods_category_id'] != $data['goods_category_id']) { + $connect = GoodsConnect::where(['goods_id'=>$data['id'],'goods_category_id'=>$goods['goods_category_id']])->column(['id']); + if (!empty($connect)) { + GoodsConnect::destroy($connect); + } + + } +// dd($goods['goods_category_id'] , $data['goods_category_id']); + //增加主图 + $data['main_img'] = doImageURLtoRelativePath($data['goods_images'][0]['url']); + $result1 = $goods->save($data); + //先将原先的全部删除 + $result2 = $goods->GoodsBuyNow->delete(); + $result3 = $goods->GoodsImages->delete(); + $result4 = $goods->GoodsConnect->delete(); + $result5 = $goods->GoodsSoftManual->delete(); + $result6 = $goods->goodsAttr->delete(); + + $result = false; + + if ($result1 && $result2 && $result3 && $result4 && $result5 && $result6) { + //处理数据结构 + $newBuyNow = []; + foreach ($data['buy_now'] as $key => $value) { + if ($value['name'] != '' && $value != '') { + $newBuyNow[$key]['goods_id'] = $data['id']; + $newBuyNow[$key]['name'] = $value['name']; + $newBuyNow[$key]['url'] = $value['url']; + } + } + $data['buy_now'] = $newBuyNow; + if (!empty($data['buy_now'])) { + $result11 = $goods->GoodsBuyNow()->saveAll($data['buy_now']); + } else { + $result11 = true; + } + + $newGoodsImages = []; + foreach ($data['goods_images'] as $key => $value) { + if ($key < 8) { + $newGoodsImages[$key]['goods_id'] = $data['id']; + $newGoodsImages[$key]['image'] = doImageURLtoRelativePath($value['url']); + } + } + $data['goods_images'] = $newGoodsImages; + if (!empty($data['goods_images'])) { + $result22 = $goods->GoodsImages()->saveAll($data['goods_images']); + } else { + $result22 = true; + } + + $newConnectGoods = []; + foreach ($data['connect_goods'] as $key => $value) { + if ($value['goods_category_id'] != '' && $value['connect_good_id'] != '') { + $newConnectGoods[$key]['goods_id'] = $data['id']; + $newConnectGoods[$key]['connect_good_id'] = $value['connect_good_id']; + $newConnectGoods[$key]['goods_category_id'] = $value['goods_category_id']; + } + } + $data['connect_goods'] = $newConnectGoods; + if (!empty($data['connect_goods'])) { + $result33 = $goods->GoodsConnect()->saveAll($data['connect_goods']); + } else { + $result33 = true; + } + + + //处理驱动文档数据 + $newSoft = []; + foreach ($data['soft_manual'] as $key => $value) { + if ($value['file_type_id'] != '' && $value['soft_manual_id'] != '') { + $newSoft[$key]['goods_id'] = $data['id']; + $newSoft[$key]['file_type_id'] = $value['file_type_id']; + $newSoft[$key]['soft_manual_id'] = $value['soft_manual_id']; + } + } + $data['soft_manual'] = $newSoft; + if (!empty($data['soft_manual'])) { + $result44 = $goods->GoodsSoftManual()->saveAll($data['soft_manual']); + } else { + $result44 = true; + } + //处理属性attr + $newAttr = []; + foreach ($data['attr'] as $key => $item) { + if ($item['attribute_id'] != '' && $item['value'] != '') { + $newAttr[$key]['goods_id'] = $goods->id; + $newAttr[$key]['attribute_id'] = $item['attribute_id']; + $newAttr[$key]['value'] = $item['value']; + } + } + $data['attr'] = $newAttr; + if (!empty($data['attr'])) { + $result55 = $goods->goodsAttr()->saveAll($data['attr']); + } else { + $result55 = true; + } + + $result = $result11 && $result22 && $result33 && $result44 && $result55; + } + + if ($result) { + $this->commit(); + return true; + } else { + $this->rollback(); + return false; + } + } + + /** + * 删除数据 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData(array $data):bool + { + $goods = $this->find($data['id']); + $result1 = $goods->delete(); + //先将原先的全部删除 + $result2 = $goods->GoodsBuyNow->delete(); + $result3 = $goods->GoodsImages->delete(); + $result4 = $goods->GoodsConnect->delete(); + $result5 = $goods->GoodsSoftManual->delete(); + $result6 = $goods->goodsAttr->delete(); + + return $result1 && $result2 && $result3 && $result4 && $result5 && $result6; + } + + /** + * 获取平台语言包列表 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPlatformLanguage($data) + { + $result = (new Platform())->getPlatformLanguage($data); + if ($result) { + foreach ($result as $key => $item) { + $result[$key]['language_name'] = $this->getLanguageName($item['site_id']); + $result[$key]['coin_name'] = $this->getCoinName($item['currency_id']); + foreach ($item['PlatformLanguage'] as $key1 => $item1) { + $result[$key]['PlatformLanguage'][$key1]['language_name'] = $this->getLanguageName($item1['site_id']); + } + foreach ($item['PlatformCoin'] as $key1 => $item1) { + $result[$key]['PlatformCoin'][$key1]['coin_name'] = $this->getCoinName($item1['currency_id']); + } + } + return $result->toArray(); + } + return []; + } + + /** + * 通过分类ID获取商品列表 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodsInfoByGoodsCategoryId($data) + { + return $this->where(['goods_category_id'=>$data['goods_category_id'],'status'=>0])->select()->toArray(); + } + + /** + * 批量删除数据 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function batchDelData(array $data):bool + { + $newResult = true; + foreach ($data as $item) { + $result = $this->delData($item); + $newResult = $newResult && $result; + } + return $newResult; + } + + /** + * 批量移除商品分类 + * @param $data + * @return bool + */ + public function batchRemoveOldCate($data) + { + return GoodsCate::whereIn('goods_id',implode(',',$data))->delete(); + } + + /** + * @param $data + * @return bool|\think\Collection + * @throws \Exception + */ + public function goodsBatchEditCategory($data) + { + $this->startTrans(); + try { + //修改分类时,先查询当前分类下的分类数据 + foreach ($data as $datum) { + $goods = $this->find($datum['id']); + if ($goods['goods_category_id'] != $datum['goods_category_id']) { + $connect = GoodsConnect::where(['goods_id'=>$datum['id'],'goods_category_id'=>$goods['goods_category_id']])->column('id'); + if (!empty($connect)) { + GoodsConnect::destroy($connect); + } + } + } + $result = $this->saveAll($data); + if ($result) { + $this->commit(); + return true; + } else { + $this->rollback(); + return false; + } + + }catch (\Exception $e) { + $this->rollback(); + return false; + } + + } + + /** + * 获取分类及其子分类 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllSonCategory($data) + { + $newData = (new GoodsCategory())->getAllSonCategory($data); + array_push($newData,$data['id']); + return $newData; + } +} diff --git a/app/api/model/GoodsAttribute.php b/app/api/model/GoodsAttribute.php new file mode 100644 index 0000000..e5eb4ec --- /dev/null +++ b/app/api/model/GoodsAttribute.php @@ -0,0 +1,18 @@ +'int', + 'goods_id' =>'int', + 'attribute_id' =>'int', + 'value' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + 'sort' =>'int', + ]; +} diff --git a/app/api/model/GoodsBuyNow.php b/app/api/model/GoodsBuyNow.php new file mode 100644 index 0000000..9c623ce --- /dev/null +++ b/app/api/model/GoodsBuyNow.php @@ -0,0 +1,21 @@ +'int', + 'goods_id' =>'int', + 'url' =>'string', + 'name' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/api/model/GoodsCate.php b/app/api/model/GoodsCate.php new file mode 100644 index 0000000..2e5dcdb --- /dev/null +++ b/app/api/model/GoodsCate.php @@ -0,0 +1,17 @@ +'int', + 'goods_id' =>'int', + 'goods_category_id' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/api/model/GoodsCategory.php b/app/api/model/GoodsCategory.php new file mode 100644 index 0000000..f2e0d03 --- /dev/null +++ b/app/api/model/GoodsCategory.php @@ -0,0 +1,133 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'int', + 'desc' =>'int', + 'pid' =>'int', + 'icon' =>'int', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 分类 商品数据 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGategoryListData($data) + { + return (new Goods())->where(['goods_category_id'=>$data['goods_category_id'],'status'=>0])->select()->toArray(); + } + + + /** + * 分类 商品明细数据 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGategoryListDataInfo($data) + { + if (isset($data['id']) && $data['id'] != 0) { + $result = GoodsConnect::where('goods_id',$data['id'])->find(); + return $result ? $result->toArray() : [] ; + } + return []; + } + + /** + * 启用禁用 + * @param $data + * @param bool $type + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function changeStatus($data,bool $type = false):bool + { + if (!$type) { + $result = $this->find($data['id']); + //正常更新 + if ($result) { + return $result->save($data); + } + } else { + $ret = $this->saveAll($data); + return (bool) $ret; + } + return false; + } + + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + $allCategory = $this->select()->toArray(); + $result = $this->find($data['id']); + $newPid = []; + if (!empty($allCategory)) { + if ($result['pid'] != 0) { + $newPid = category_to_all_pid($allCategory,$result['pid']); + } else { + $newPid = [0]; + } + } + $result['pid'] = $newPid; + return $result->toArray(); + } + + /** + * 查找所有子项 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllSonCategory($data):array + { + $newData = $this->select()->toArray(); + if (!empty($newData)) { + return category_to_all_children_id($newData,$data['id']); + } + return []; + } + + /** + * 查询当前分类下是否在商品 + * @param $data + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function hasGoodsOnCategory($data) + { + return Goods::where('goods_category_id',$data['id'])->find(); + } +} diff --git a/app/api/model/GoodsConnect.php b/app/api/model/GoodsConnect.php new file mode 100644 index 0000000..a5a91bc --- /dev/null +++ b/app/api/model/GoodsConnect.php @@ -0,0 +1,19 @@ +'int', + 'goods_id' =>'int', + 'goods_category_id' =>'int', + 'connect_good_id' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/api/model/GoodsCoupon.php b/app/api/model/GoodsCoupon.php new file mode 100644 index 0000000..2f8f46e --- /dev/null +++ b/app/api/model/GoodsCoupon.php @@ -0,0 +1,35 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'old_code' =>'string', + 'new_code' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * + * @param $data + * @return array|Model|void|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLatest($data) + { + return $this->order($this->pk,'desc')->where($data)->find(); + } +} diff --git a/app/api/model/GoodsImages.php b/app/api/model/GoodsImages.php new file mode 100644 index 0000000..e1e9e5f --- /dev/null +++ b/app/api/model/GoodsImages.php @@ -0,0 +1,19 @@ +'int', + 'goods_id' =>'int', + 'image' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + + ]; +} diff --git a/app/api/model/GoodsSoftManual.php b/app/api/model/GoodsSoftManual.php new file mode 100644 index 0000000..8a9e03c --- /dev/null +++ b/app/api/model/GoodsSoftManual.php @@ -0,0 +1,19 @@ +'int', + 'goods_id' =>'int', + 'file_type_id' =>'int', + 'soft_manual_id'=>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/api/model/ImagesFile.php b/app/api/model/ImagesFile.php new file mode 100644 index 0000000..d422096 --- /dev/null +++ b/app/api/model/ImagesFile.php @@ -0,0 +1,44 @@ +hasOne(User::class, 'id', 'up_id')->bind(['uploader_name'=>'nickname']); + } + + // 根据ID查询 + public function scopeId($query, $id) + { + if (is_array($id)) { + $query->where('id', 'in', $id); + } else { + $query->where('id', '=', $id); + } + } + + // 根据上传人查询 + public function scopeUpId($query, $up_id) + { + $query->where('up_id', '=', $up_id); + } + + // 根据文件MD5值查询 + public function scopeFileMd5($query, $md5) + { + $query->where('file_md5', '=', $md5); + } + + // 根据文件hash值查询 + public function scopeFileHash($query, $hash) + { + $query->where('file_hash', '=', $hash); + } +} diff --git a/app/api/model/Investment.php b/app/api/model/Investment.php new file mode 100644 index 0000000..a2c02cb --- /dev/null +++ b/app/api/model/Investment.php @@ -0,0 +1,107 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'country_id' => 'int', + 'province_id' => 'int', + 'city_id' => 'int', + 'from' => 'string', + 'area' => 'string', + 'phone' => 'string', + 'name' => 'string', + 'email' => 'string', + 'wechat' => 'string', + 'qq' => 'string', + 'desc' => 'string', + 'sort' => 'int', + 'is_open' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * 查看列表数据 + * @param int $page 分页页码 + * @param int $pageSize 分页类目数量 + * @param array $field 需要输入的字段,默认为全部输出,筛选表字段 + * @param array $vague 需要进行模糊查询的字段,如: a like %a% + * @param array $focus 精确搜索条件,如a=1,b=2这种精确等于某个值的 + * @param array $order 排序字段,如:['id'=>'desc','sort'=>'desc'] + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getIndexList(int $page,int $pageSize,array $field = [], array $vague = [],array $focus = [],array $order = []):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($fields,$focus) { + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + })->where(function($query) use ($fields,$vague) { + //模糊查询 + if (!empty($vague)) { + $query->whereOr('phone','like',"%".$vague['keyword']."%"); + $query->whereOr('name','like',"%".$vague['keyword']."%"); + $query->whereOr('wechat','like',"%".$vague['keyword']."%"); + $query->whereOr('qq','like',"%".$vague['keyword']."%"); + $query->whereOr('email','like',"%".$vague['keyword']."%"); + } + })->order($order); + //判断是否需要分页 + if (0 == $page || 0 == $pageSize) { + //不需要分页 + return $collection->select()->toArray(); + } else { + //需要分布 + $totalNum = $collection->count(); + $data = $collection->page($page)->limit($pageSize)->select()->toArray();; + return ['count'=>$totalNum,'data'=>$data]; + } + } + + + /** + * 通过ID获取数据 + * @param $ids + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getExportData($ids): array + { + $result = $this->whereIn($this->pk,$ids['ids'])->order('create_time','desc')->select()->toArray(); + foreach ($result as &$item){ + $item['platform_id'] = $this->getPlatformName($item['platform_id']); + $item['language_id'] = $item['site_id'] = $this->getLanguageName($item['site_id']); + $item['country_id'] = '中国'; + $item['province_id'] = $this->getAreaNameById($item['province_id']); + $item['city_id'] = $this->getAreaNameById($item['city_id']); + $item['is_open'] = $item['is_open'] == 0 ? '同意同类厂家查看,以便获得更多产品代理机会' : '同意意向厂家查看'; + unset($item['area']); + unset($item['qq']); + unset($item['sort']); + unset($item['update_time']); + unset($item['email']); + } + return $result; + } +} diff --git a/app/api/model/Join.php b/app/api/model/Join.php new file mode 100644 index 0000000..fbddbe4 --- /dev/null +++ b/app/api/model/Join.php @@ -0,0 +1,97 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'join_type_id' => 'int', + 'title' => 'string', + 'brief' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'meta_title' => 'string', + 'keywords' => 'string', + 'detail' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_outer_chain' => 'int', + 'is_on_index' => 'int', + 'click_num' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * + */ + public function JoinType():\think\model\relation\HasOne + { + return $this->hasOne(JoinType::class,'id','join_type_id')->bind(['join_type_name'=>'name']); + } + + /** + */ + public function languageName():\think\model\relation\HasOne + { + return $this->hasOne(Language::class,'id','site_id')->bind(['language_name'=>'name']); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int) $data['size'])->page((int)$data['page'])->order($sort)->with(['JoinType','languageName'])->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->with(['JoinType','languageName'])->select()->toArray(); + } + } +} diff --git a/app/api/model/JoinType.php b/app/api/model/JoinType.php new file mode 100644 index 0000000..328d8d8 --- /dev/null +++ b/app/api/model/JoinType.php @@ -0,0 +1,105 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * article分类与article表模型 + * @return \think\model\relation\HasMany + */ + public function getArticle() + { + return $this->hasMany(Join::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getArticleData($data):array + { + $article = $this->find($data['id']); + if (!empty($article)) { + return $article->getArticle()->select()->toArray(); + } + return []; + } +} diff --git a/app/api/model/Language.php b/app/api/model/Language.php new file mode 100644 index 0000000..cdac461 --- /dev/null +++ b/app/api/model/Language.php @@ -0,0 +1,37 @@ + 'int', + 'name' => 'string', + 'code' => 'string', + 'icon' => 'string', + 'locale' => 'string', + 'coin' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * 查找语言包是否被使用 + * @param $id + * @return array|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLanguageUse($id) + { + return Platform::where('language_id',$id)->find(); + } +} diff --git a/app/api/model/LogVisit.php b/app/api/model/LogVisit.php new file mode 100644 index 0000000..e742ed0 --- /dev/null +++ b/app/api/model/LogVisit.php @@ -0,0 +1,51 @@ + 'int', + 'platform_id' => 'int', + 'admin_id' => 'int', + 'admin_name' => 'string', + 'url' => 'string', + 'params' => 'string', + 'controller' => 'string', + 'action' => 'string', + 'ip' => 'string', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + + /** + * 写入日志 + * @param $url + * @param $params + * @param $controller + * @param $action + * @param $admin_id + * @param $admin_name + * @param $platformId + * @return bool + */ + public function log($url, $params, $controller, $action,$admin_id, $admin_name,$platformId) + { + $insert_data = [ + 'url' => $url, + 'params' => $params, + 'controller' => $controller, + 'action' => $action, + 'admin_id' => $admin_id?:0, + 'admin_name' => $admin_name?:'', + 'ip' => get_client_ip(), + 'platform_id' => $platformId?:0, + 'create_time' => time() + ]; + return $this->save($insert_data); + } +} diff --git a/app/api/model/Navigator.php b/app/api/model/Navigator.php new file mode 100644 index 0000000..94fa24a --- /dev/null +++ b/app/api/model/Navigator.php @@ -0,0 +1,119 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'pid' => 'int', + 'name' => 'string', + 'desc' => 'string', + 'icon' => 'string', + 'url' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_top' => 'int', + 'is_foot' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + + /** + * 查询子项 + * @param $id + * @return int + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + private function getPidData($id):int + { + $result = $this->where('pid',$id)->find(); + if ($result) { + return 1; + } else { + return 0; + } + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->order($sort)->select()->toArray(); + foreach ($resData as $key => $item) { + if (1 === $this->getPidData($item['id'])) { + $resData[$key]['is_gray'] = 1; + } else { + $resData[$key]['is_gray'] = 0; + } + } + return $resData; + } + } + + /** + * 判断导航栏是否有子类 + * @param $id + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getNavigatorIsInUse($id):bool + { + $result = $this->where('pid',$id['id'])->find(); + return (bool) $result; + } + + + +} diff --git a/app/api/model/News.php b/app/api/model/News.php new file mode 100644 index 0000000..671e4e6 --- /dev/null +++ b/app/api/model/News.php @@ -0,0 +1,97 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'news_type_id' => 'int', + 'title' => 'string', + 'brief' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'meta_title' => 'string', + 'keywords' => 'string', + 'detail' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_outer_chain' => 'int', + 'is_on_index' => 'int', + 'click_num' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * + */ + public function NewsType():\think\model\relation\HasOne + { + return $this->hasOne(NewsType::class,'id','news_type_id')->bind(['news_type_name'=>'name']); + } + + /** + */ + public function languageName():\think\model\relation\HasOne + { + return $this->hasOne(Language::class,'id','site_id')->bind(['language_name'=>'name']); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int) $data['size'])->page((int)$data['page'])->order($sort)->with(['NewsType','languageName'])->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->with(['NewsType','languageName'])->select()->toArray(); + } + } +} diff --git a/app/api/model/NewsType.php b/app/api/model/NewsType.php new file mode 100644 index 0000000..6511070 --- /dev/null +++ b/app/api/model/NewsType.php @@ -0,0 +1,105 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * article分类与article表模型 + * @return \think\model\relation\HasMany + */ + public function getArticle() + { + return $this->hasMany(News::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getArticleData($data):array + { + $article = $this->find($data['id']); + if (!empty($article)) { + return $article->getArticle()->select()->toArray(); + } + return []; + } +} diff --git a/app/api/model/Platform.php b/app/api/model/Platform.php new file mode 100644 index 0000000..f366b06 --- /dev/null +++ b/app/api/model/Platform.php @@ -0,0 +1,279 @@ + 'int', + 'vi_color1' => 'string', + 'vi_color2' => 'string', + 'vi_color3' => 'string', + 'language_id' => 'int', + 'currency_id' => 'int', + 'name' => 'string', + 'desc' => 'string', + 'icon' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + /** + * 平台语言包关联模型 + */ + public function PlatformLanguage():\think\model\relation\HasMany + { + return $this->hasMany(PlatformLanguage::class); + } + + /** + * 平台币种关联模型 + */ + public function PlatformCoin():\think\model\relation\HasMany + { + return $this->hasMany(PlatformCoin::class); + } + + /** + * 通过平台ID查询平台有没有被使用 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function hasUserPlatform($data):array + { + return Site::where('platform_id',$data['id'])->select()->toArray(); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->whereLike($key,'%'.$item.'%'); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->with(['PlatformLanguage'=>function($query) { + $query->with(['getLanguage'=>function ($query) { + $query->field(['id','name']); + }]); + },'PlatformCoin'=>function($query) { + $query->with(['getCoin'=>function ($query) { + $query->field(['id','name']); + }]); + }])->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_name'] = $this->getLanguageName($item['language_id']); + $page[$key]['currency_name'] = $this->getLanguageName($item['currency_id']); + } + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $this->where(function ($query) use ($data,$fields) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } else { + $query->where(1); + } + })->with(['PlatformLanguage'=>function($query) { + $query->with(['getLanguage'=>function ($query) { + $query->field(['id','name']); + }]); + },'PlatformCoin'=>function($query) { + $query->with(['getCoin'=>function ($query) { + $query->field(['id','name']); + }]); + }])->select()->toArray(); + + foreach ($resData as $key => $item) { + $resData[$key]['language_name'] = $this->getLanguageName($item['language_id']); + $resData[$key]['currency_name'] = $this->getCoinName($item['currency_id']); + } + + return $resData; + } + + + } + + /** + * 新增数据 + * @param array $data + * @return bool + */ + public function addData(array $data):bool + { + unset($data['id']); + $platform = $this->create($data); + if ($platform) { + //处理数据结构 + foreach ($data['platform_language'] as $k => $value) { + $data['platform_language'][$k]['platform_id'] = $platform->id; + } + + foreach ($data['platform_coin'] as $k => $value) { + $data['platform_coin'][$k]['platform_id'] = $platform->id; + } + //模型关联新增 + $result = $platform->PlatformLanguage()->saveAll($data['platform_language']); + $result1 = $platform->PlatformCoin()->saveAll($data['platform_coin']); + + return $result && $result1; + } + return false; + + } + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + $platform = $this->find($data['id'])->toArray(); + if ($platform) { + $platform['platform_language'] = $this->PlatformLanguage()->where('platform_id',$data['id'])->select()->toArray(); + $platform['platform_coin'] = $this->PlatformCoin()->where('platform_id',$data['id'])->select()->toArray(); + return $platform; + } + return []; + + } + + /** + * 编辑数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editData(array $data):bool + { + $this->startTrans(); + try { + $platform = $this->find($data['id']); + if ($platform) { + $result1 = $platform->save($data); + //先将原先的全部删除 + $result2 = $platform->PlatformLanguage->delete(); + $result3 = $platform->PlatformCoin->delete(); + $result = false; + if ($result1 && $result2 && $result3) { + //处理数据结构 + foreach ($data['platform_language'] as $k => $value) { + $data[$k]['platform_language'] = $data['id']; + } + + //处理数据结构 + foreach ($data['platform_coin'] as $k => $value) { + $data[$k]['platform_coin'] = $data['id']; + } + //新增 + $result4 = $platform->PlatformLanguage()->saveAll($data['platform_language']); + $result5 = $platform->PlatformCoin()->saveAll($data['platform_coin']); + $result = $result4 && $result5; + } +// return $result; + } + $this->commit(); + return true; + } catch (\Exception $e) { + $this->rollback(); + return false; + } + } + + /** + * 删除数据 + * @param array $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData(array $data):bool + { + $platform = $this->find($data['id']); + if ($platform) { + $result1 = $platform->delete(); + + //先将原先的全部删除 + $result2 = $platform->PlatformLanguage->delete();; + $result3 = $platform->PlatformCoin->delete();; + return $result1 && $result2 && $result3; + } + return false; + } + + /** + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPlatformLanguage($data):array + { + return $this->where('id',$data)->with(['PlatformLanguage','PlatformCoin'])->select()->toArray(); + } + + + /** + * @param $field + * @param $status + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLanguageList($field,$status):array + { + return Language::field($field)->where($status)->select()->toArray(); + } +} \ No newline at end of file diff --git a/app/api/model/PlatformCoin.php b/app/api/model/PlatformCoin.php new file mode 100644 index 0000000..237150f --- /dev/null +++ b/app/api/model/PlatformCoin.php @@ -0,0 +1,25 @@ +'int', + 'currency_id' =>'int', + 'platform_id' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 平台-币种关联模型 + * @return \think\model\relation\BelongsTo + */ + public function getCoin() + { + return $this->belongsTo(Currency::class,'currency_id','id'); + } +} diff --git a/app/api/model/PlatformLanguage.php b/app/api/model/PlatformLanguage.php new file mode 100644 index 0000000..4c58713 --- /dev/null +++ b/app/api/model/PlatformLanguage.php @@ -0,0 +1,27 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 平台-语言包关联模型 + * @return \think\model\relation\BelongsTo + */ + public function getLanguage() + { + return $this->belongsTo(Language::class); + } +} diff --git a/app/api/model/Question.php b/app/api/model/Question.php new file mode 100644 index 0000000..40c08ff --- /dev/null +++ b/app/api/model/Question.php @@ -0,0 +1,222 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'area_id' => 'int', + 'country_id' => 'int', + 'name' => 'string', + 'email' => 'string', + 'phone' => 'string', + 'order_sn' => 'string', + 'product_model' => 'string', + 'os' => 'string', + 'desc' => 'string', + 'is_done' => 'int', + 'is_send_email' => 'int', + 'is_send_status' => 'int', + 'send_time' => 'int', + 'send_details' => 'string', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * 反馈附件关联 + * @return \think\model\relation\HasMany + */ + public function QuestionAttachment() + { + return $this->hasMany(QuestionAttachment::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList($data,$simple = null,$focus = null,$sort = null,$field = null) + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $lang = Language::find($data['site_id']); + if (!empty($lang)) { + if (strtolower($lang['code']) == 'zh-cn' || strtolower($lang['code']) == 'zh_cn') { + $page[$key]['country_name'] = '中国'; + } else { + $page[$key]['country_name'] = $this->getCountryName($item['country_id']); + } + } + + $page[$key]['is_done_name'] = $item['is_done'] == 0 ? '未解决': '已解决'; + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['country_name'] = $this->getCountryName($item['country_id']); + $page[$key]['is_done_name'] = $item['is_done'] == 0 ? '未解决': '已解决'; + } + } + return $page; + } + } + + /** + * 新增数据 + * @param $data + * @return bool|void + */ + public function addData($data) + { + $this->startTrans(); + $question = $this->create($data); + //处理数据结构 + foreach ($data['question_attachment'] as $k => $value) { + $value['question_id'] = $question->id; + } + //模型关联新增 + $result = $question->QuestionAttachment()->saveAll($data['question_attachment']); + if ($result && $question) { + $this->commit(); + return true; + } else { + $this->rollback(); + return false; + } + } + + /** + * 获取详情 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($data) + { + $question = $this->find($data['id']); + $question['question_attachment'] = $this->QuestionAttachment()->where('question_id',$data['id'])->select()->toArray(); + if (!empty($question['question_attachment'])) { + $newAttach = []; + foreach ($question['question_attachment'] as $key1 => $value1) { + $newAttach[$key1]['name'] = basename($value1['attach']); +// $newAttach[$key1]['url'] = Env::get('QINIU.cdn').$value1['image']; + $newAttach[$key1]['url'] = $value1['attach']; + } + $question['question_attachment'] = $newAttach; + } + return $question; + } + +// /** +// * 编辑数据 +// * @param $data +// * @return bool +// * @throws \think\db\exception\DataNotFoundException +// * @throws \think\db\exception\DbException +// * @throws \think\db\exception\ModelNotFoundException +// */ +// public function editData($data) +// { +// $question = $this->find($data['id']); +// $result1 = $question->save($data); +// //先将原先的全部删除 +// $result2 = $question->QuestionAttachment->delete(); +// $result = false; +// if ($result1 && $result2) { +// //处理数据结构 +// $newData = []; +// foreach ($data['question_attachment'] as $key => $value) { +// $newData[$key]['question_id'] = $data['id']; +// $newData[$key]['attach'] = $value['url']; +// } +// $data['question_attachment'] = $newData; +// //新增 +// $result = $question->QuestionAttachment()->saveAll($data['question_attachment']); +// } +// return $result; +// } + + /** + * 删除数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData($data) + { + $this->startTrans(); + $question = $this->find($data['id']); + $result1 = $question->delete(); + //先将原先的全部删除 + $result2 = $question->QuestionAttachment->delete();; + if ($result1 && $result2) { + $this->commit(); + return true; + } else { + $this->rollback(); + return false; + } + } + + /** + * 解决-未解决 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function isDone($data) + { + $question = $this->find($data['id']); + return $question->save($data); + } +} diff --git a/app/api/model/QuestionAttachment.php b/app/api/model/QuestionAttachment.php new file mode 100644 index 0000000..fd02bf0 --- /dev/null +++ b/app/api/model/QuestionAttachment.php @@ -0,0 +1,27 @@ +'int', + 'question_id' =>'int', + 'attach' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * 附件-问题关联表 + * @return \think\model\relation\BelongsTo + */ + public function getQuestion() + { + return $this->belongsTo(Question::class); + } +} diff --git a/app/api/model/Resource.php b/app/api/model/Resource.php new file mode 100644 index 0000000..9736af3 --- /dev/null +++ b/app/api/model/Resource.php @@ -0,0 +1,98 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'resource_type_id' => 'int', + 'title' => 'string', + 's_title' => 'string', + 'brief' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'meta_title' => 'string', + 'keywords' => 'string', + 'detail' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_outer_chain' => 'int', + 'is_on_index' => 'int', + 'click_num' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * + */ + public function ResourceType():\think\model\relation\HasOne + { + return $this->hasOne(ResourceType::class,'id','resource_type_id')->bind(['resource_type_name'=>'name']); + } + + /** + */ + public function languageName():\think\model\relation\HasOne + { + return $this->hasOne(Language::class,'id','site_id')->bind(['language_name'=>'name']); + } + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int) $data['size'])->page((int)$data['page'])->order($sort)->with(['ResourceType','languageName'])->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->with(['ResourceType','languageName'])->select()->toArray(); + } + } +} diff --git a/app/api/model/ResourceType.php b/app/api/model/ResourceType.php new file mode 100644 index 0000000..8951030 --- /dev/null +++ b/app/api/model/ResourceType.php @@ -0,0 +1,105 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + + /** + * article分类与article表模型 + * @return \think\model\relation\HasMany + */ + public function getArticle() + { + return $this->hasMany(Resource::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field=null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return ['page'=>$page,'count'=>$count]; + } else { + $page = $collection->order($sort)->select()->toArray(); + foreach ($page as $key => $item) { + $page[$key]['language_id'] = $item['site_id']; + } + return $page; + + } + } + + /** + * 获取对应分类下的文章内容 + * @param $data + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getArticleData($data):array + { + $article = $this->find($data['id']); + if (!empty($article)) { + return $article->getArticle()->select()->toArray(); + } + return []; + } +} diff --git a/app/api/model/Role.php b/app/api/model/Role.php new file mode 100644 index 0000000..76da1c6 --- /dev/null +++ b/app/api/model/Role.php @@ -0,0 +1,49 @@ + 'int', + 'name' => 'string', + 'desc' => 'string', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + + protected $disuse = [ + 'desc' + ]; + + + /** + * 角色菜单关联 + * @return \think\model\relation\HasMany + */ + public function RoleToMenu() + { + return $this->hasMany(RoleToMenu::class); + } + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo(array $data):array + { + $result = $this->find($data['role_id']); + return $result ? $result->toArray() : []; + } + +} diff --git a/app/api/model/Site.php b/app/api/model/Site.php new file mode 100644 index 0000000..c448768 --- /dev/null +++ b/app/api/model/Site.php @@ -0,0 +1,141 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'currency_id' =>'int', + 'domain' =>'string', + 'app_id' =>'string', + 'app_key' =>'string', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (isset($data['platform_id'])) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->whereLike($key,'%'.$item.'%'); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $lang = Language::find($item['language_id']); + $page[$key]['language_name'] = $lang ? $lang->toArray()['name']: ""; + $page[$key]['currency_name'] = $this->getLanguageName($item['currency_id']); + $page[$key]['platform_name'] = $this->getPlatformName($item['platform_id']); + } + } + + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->field(['id','platform_id','language_id','currency_id','domain','status'])->select()->toArray(); + if (!empty($resData)) { + foreach ($resData as $key => $item) { + $lang = Language::find($item['language_id']); + $resData[$key]['language_name'] = $lang ? $lang->toArray()['name']: ""; + $resData[$key]['currency_name'] = $this->getCoinName($item['currency_id']); + $resData[$key]['platform_name'] = $this->getPlatformName($item['platform_id']); + } + } + + return $resData; + } + } + + /** + * 通过品牌ID与语言包ID获取是否存在相同的数据。 + * @param $data + * @return array + * @throws DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSiteData($data):array + { + return $this->where(['platform_id'=>$data['platform_id'],'language_id'=>$data['language_id']])->column('id'); + } + + + /** + * 通过品牌ID判断站点是否存在 + * @param $platformId + * @return bool + * @throws DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSiteInfoByPlatformId($platformId):bool + { + $result = $this->where(['platform_id'=>$platformId])->select()->toArray(); + if (!empty($result)) { + return true; + } + return false; + } + + /** + * 删除数据 + * @param array $data + * @return bool + * @throws DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData(array $data):bool + { + $result = $this->find($data['id']); + if ($result) { + Cache::set($result['app_id'],null); + return $result->delete(); + } + return false; + } +} diff --git a/app/api/model/SoftManual.php b/app/api/model/SoftManual.php new file mode 100644 index 0000000..5eefd7b --- /dev/null +++ b/app/api/model/SoftManual.php @@ -0,0 +1,230 @@ + 'int', + 'platform_id' => 'int', + 'language_id' => 'int', + 'site_id' => 'int', + 'file_type_id' => 'int', + 'name' => 'string', + 'image' => 'string', + 'introduce' => 'string', + 'file_name' => 'string', + 'btn_tips' => 'string', + 'url' => 'string', + 'support' => 'string', + 'os' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'download_count'=> 'int', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + /** + * 驱动手册分表 + * @return \think\model\relation\HasMany + */ + public function softBtn() + { + return $this->hasMany(SoftManualBtn::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @param null $sort + * @param null $field + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList(array $data,$simple = null,$focus = null,$sort = null,$field = null):array + { + $fields = array_keys($this->schema); + $collection = $this->field($field)->where(function ($query) use ($data,$fields,$simple,$focus) { + if (in_array('platform_id',$fields)) { + $query->where('platform_id',$data['platform_id']); + } + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit((int)$data['size'])->page((int)$data['page'])->with('softBtn')->order($sort)->select()->toArray(); + if (!empty($page)) { + foreach ($page as $key => $item) { + $page[$key]['file_type_name'] = $this->getFileTypeName($item['file_type_id']); + } + } + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->order($sort)->with('softBtn')->select()->toArray(); + if (!empty($resData)) { + foreach ($resData as $key => $item) { + $resData[$key]['file_type_name'] = $this->getFileTypeName($item['file_type_id']); + } + } + return $resData; + } + } + + /** + * 新增数据 + * @param $data + */ + public function addData($data):bool + { + $this->startTrans(); + try { + $soft = $this->create($data); + //处理数据结构 + foreach ($data['softBtn'] as $key => $value) { + $data['softBtn'][$key]['soft_manual_id'] = $soft->id; + $data['softBtn'][$key]['btn_tips'] = $value['btn_tips']; + $data['softBtn'][$key]['url'] = $value['url']; + $data['softBtn'][$key]['file_name'] = $value['file_name']; + $data['softBtn'][$key]['md5'] = $value['md5']; + } + //模型关联新增 + $soft->softBtn()->saveAll($data['softBtn']); + $this->commit(); + return true; + } catch (\Exception $e) { + $this->rollback(); + return false; + } + + } + + /** + * 获取详情 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($data):array + { + $soft = $this->find($data['id']); + $soft['softBtn'] = $soft->softBtn()->select()->toArray(); + if (empty($soft['softBtn'])) { + $soft['softBtn'] = [['name'=>'','url'=>'','md5'=>'']]; + } + return $soft->toArray(); + } + + /** + * 编辑数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editData($data):bool + { + $this->startTrans(); + try { + $soft = $this->find($data['id']); + if ($soft) { + $result2 = $soft->softBtn->delete(); + $result1 = $soft->save($data); + //先将原先的全部删除 +// $result = false; + if ($result1 && $result2) { + //处理数据结构 + foreach ($data['softBtn'] as $key => $value) { + $data['softBtn'][$key]['soft_manual_id'] = $data['id']; + $data['softBtn'][$key]['btn_tips'] = $value['btn_tips']; + $data['softBtn'][$key]['url'] = $value['url']; + $data['softBtn'][$key]['file_name'] = $value['file_name']; + $data['softBtn'][$key]['md5'] = $value['md5']; + } + //新增 + $result = $soft->softBtn()->saveAll($data['softBtn']); + } +// return $result; + } + $this->commit(); + return true; + } catch (\Exception $e) { + $this->rollback(); + return false; + } + } + + /** + * 删除数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData($data):bool + { + $soft = $this->find($data['id']); + $result1 = $soft->delete(); + //先将原先的全部删除 + $result2 = $soft->softBtn->delete();; + return $result1 && $result2; + } + + /** + * 编辑排序 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function changeSort($data):bool + { + $result = $this->find($data['id']); + return $result && $result->save($data); + } + + /** + * 查询文档驱动是否被引用 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSoftManualUsed($data) + { + $result = GoodsSoftManual::where('soft_manual_id',$data['id'])->find(); + return (bool) $result; + } +} diff --git a/app/api/model/SoftManualBtn.php b/app/api/model/SoftManualBtn.php new file mode 100644 index 0000000..4ce4f12 --- /dev/null +++ b/app/api/model/SoftManualBtn.php @@ -0,0 +1,20 @@ + 'int', + 'soft_manual_id'=> 'int', + 'btn_tips' => 'string', + 'url' => 'string', + 'file_name' => 'string', + 'md5' => 'string', + 'create_time' => 'int', + 'update_time' => 'int', + ]; +} diff --git a/app/api/model/SystemConfig.php b/app/api/model/SystemConfig.php new file mode 100644 index 0000000..6532517 --- /dev/null +++ b/app/api/model/SystemConfig.php @@ -0,0 +1,26 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'type' =>'int', + 'page' =>'string', + 'pos' =>'string', + 'name' =>'string', + 'value' =>'string', + 'image' =>'string', + 'create_time' =>'int', + 'update_time' =>'int' + ]; +} diff --git a/app/api/model/User.php b/app/api/model/User.php new file mode 100644 index 0000000..fc2c51e --- /dev/null +++ b/app/api/model/User.php @@ -0,0 +1,97 @@ + 'int', + 'uc_id' => 'int', + 'admin_id' => 'int', + 'role_id' => 'int', + 'org_id' => 'int', + 'dept_id' => 'int', + 'staff_code' => 'string', + 'nickname' => 'string', + 'mobile' => 'string', + 'email' => 'string', + 'avatar' => 'string', + 'gender' => 'int', + 'create_time' => 'int', + 'update_time' => 'int', + 'signin_time' => 'int', + 'signin_ip' => 'string', + 'status' => 'int', + ]; + + /** + * 获取详情 + * @param array $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($data) : array + { + if (isset($data['admin_id'])) { + $result = $this->where('uc_id',$data['admin_id'])->find(); + return $result ? $result->toArray() : []; + } + if (isset($data['uc_id'])) { + $result = $this->where('uc_id',$data['uc_id'])->find(); + return $result ? $result->toArray() : []; + } + return []; + } + + + /** + * 通过角色ID,摘取对应菜单ID + * @param array $data + * @return array + */ + public function getMenuList(array $data):array + { + return $this->getMenuListUserCode($data['staff_code']); + } + + /** + * 获取角色名称 + * @param $roleId + * @return array|\think\Model|null + */ + public function getRolesName($roleId):string + { + $result = $this->getRoleDetailId($roleId); + return $result['role_name'] ?? ''; + } + + + /** + * 查找菜单列表 + * @param $arr + * @return array + */ + public function getMenuSiderList($arr):array + { + $result = $this->getMenuListApp(); + if(!empty($result)) { + $newData = []; + foreach ($result as $datum) { + if (in_array($datum['id'],$arr)) { + array_push($newData,$datum); + } + } + return $newData; + } else { + return []; + } + } + +} diff --git a/app/api/model/Video.php b/app/api/model/Video.php new file mode 100644 index 0000000..d9c6c6c --- /dev/null +++ b/app/api/model/Video.php @@ -0,0 +1,24 @@ + 'int', + 'platform_id' => 'int', + 'site_id' => 'int', + 'name' => 'string', + 'image' => 'string', + 'url' => 'string', + 'is_top' => 'int', + 'sort' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + +} diff --git a/app/api/route/v1.php b/app/api/route/v1.php new file mode 100644 index 0000000..058c19f --- /dev/null +++ b/app/api/route/v1.php @@ -0,0 +1,431 @@ + + // +---------------------------------------------------------------------- + //全局CDN链接,减少改变静态地址而打包前端代码 + Route::group('v1',function () { + Route::group('cdn',function(){ + Route::any('get_cdn_url','Base@getCDNUrl'); + }); + + //后台登录模块路由 + Route::group('auth',function() { + Route::post('login','Auth@login'); //登录路由 + Route::post('info','Auth@info'); //已登录管理员信息 + Route::post('all_info','Auth@allInfo'); //获取所有信息 + Route::post('get_auth','Auth@getAuth'); //获取用户所有权限 + Route::post('update_pwd','Auth@updatePwd'); //个人中心修改密码 + Route::post('update_head_img','Auth@updateHeadImg'); //个人中心修改头像 + Route::post('update_info','Auth@updateInfo'); //个人中心修改基本信息 + }); + + //后台管理员模块路由组 + Route::group('admin',function (){ + Route::post('list','Admin@list');//管理员列表 + Route::post('add','Admin@add');//新增管理员 + Route::post('info','Admin@read');//获取管理员信息 + Route::post('update','Admin@update');//修改管理信息 + Route::post('forbidden','Admin@forbidden');//禁用 + }); + + //后台菜单模块路由组 + Route::group('menu', function () { + Route::post('list','Menu@tree');/*菜单列表结构*/ + Route::post('get_menu_select_list','Menu@selectList');/*菜单仅查询列表结构*/ + Route::post('get_menu_change_list','Menu@changeList');/*菜单可编辑列表结构*/ + Route::post('info','Menu@read');/*菜单详情*/ + Route::post('create','Menu@create');/*菜单新增*/ + Route::post('update','Menu@update');/*菜单编辑*/ + Route::post('upload','Menu@upload');/*菜单图标上传*/ + Route::post('change_status','Menu@updateStatus');/*修改状态*/ + Route::post('del','Menu@del');/*菜单删除*/ + Route::post('sort','Menu@sort');/*菜单排序*/ + }); + + //后台角色模块路由组 + Route::group('role', function () { + Route::post('list','Role@index');/*列表*/ + Route::post('info','Role@read');/*详情*/ + Route::post('add','Role@create');/*新增*/ + Route::post('update','Role@update');/*编辑*/ + Route::post('del','Role@del');/*删除*/ + + Route::post('dis_auth_select','Role@distributeAuthForSelect');/*分配权限 */ + Route::post('dis_auth_change','Role@distributeAuthForChange');/*分配权限 */ + }); + + //后台站点模块路由组 + Route::group('site', function () { + Route::post('list','Site@index');/*列表*/ + Route::post('site_list','Site@siteIndex');/*列表*/ + Route::post('create','Site@create');/*新增*/ + Route::post('info','Site@read');/*更新*/ + Route::post('update','Site@update');/*更新*/ + Route::post('del','Site@del');/*删除*/ + Route::post('change_status','Site@changeStatus');/*删除*/ + Route::post('get_nav','Site@getNavigatorList');/*获取导航栏*/ + }); + + //后台语言包模块路由组 + Route::group('lang', function () { + Route::post('list','Language@index');/*列表*/ + Route::post('create','Language@create');/*新增*/ + Route::post('info','Language@read');/*更新*/ + Route::post('update','Language@update');/*更新*/ + Route::post('upload','Language@upload');/*上传图标*/ + Route::post('del','Language@del');/*删除*/ + Route::post('change_status','Language@changeStatus');/*启用禁用*/ + }); + + //后台平台模块路由组 + Route::group('plat', function () { + Route::post('list','Platform@index');/*列表*/ + Route::post('lang_list','Platform@languageList');/*列表*/ + Route::post('info','Platform@read');/*详情*/ + Route::post('create','Platform@create');/*新增*/ + Route::post('update','Platform@update');/*更新*/ + Route::post('upload','Platform@upload');/*上传图标*/ + Route::post('del','Platform@del');/*删除*/ + }); + + //后台导航栏模块路由组 + Route::group('nav', function () { + Route::post('list','Navigator@tree');/*列表*/ + Route::post('top_list','Navigator@topTree');/*列表*/ + Route::post('info','Navigator@read');/*列表*/ + Route::post('create','Navigator@create');/*新增*/ + Route::post('update','Navigator@update');/*更新*/ + Route::post('upload','Navigator@upload');/*上传图标*/ + Route::post('del','Navigator@del');/*删除*/ + Route::post('change_status','Navigator@changeStatus');/*启用禁用*/ + }); + + //后台国家模块路由组 + Route::group('country', function () { + Route::post('list','Country@index');/*列表*/ + Route::post('info','Country@read');/*详情*/ + Route::post('create','Country@create');/*新增*/ + Route::post('update','Country@update');/*更新*/ + Route::post('upload','Country@upload');/*上传图标*/ + Route::post('del','Country@del');/*删除*/ + }); + + //后台用户反馈模块路由组 + Route::group('question', function () { + Route::post('list','Question@index');/*列表*/ + Route::post('info','Question@read');/*列表*/ + Route::post('is_done','Question@isDone');/*列表*/ + Route::post('create','Question@create');/*新增*/ + Route::post('send_email','Question@sendEmail');/*新增*/ + Route::post('check_email','Question@validateEmail');/*新增*/ + // Route::post('update','Question@update');/*更新*/ + // Route::post('upload','Question@upload');/*上传图标*/ + Route::post('del','Question@del');/*删除*/ + }); + + //后台手册文档模块路由组 + Route::group('soft_manual', function () { + Route::post('list','SoftManual@index');/*列表*/ + Route::post('info','SoftManual@read');/*列表*/ + Route::post('create','SoftManual@create');/*新增*/ + Route::post('update','SoftManual@update');/*更新*/ + Route::post('upload','SoftManual@upload');/*上传图标*/ + Route::post('upload_file','ImagesFile@uploadFile');/*上传图标*/ + Route::post('check_file','ImagesFile@checkFile');/*上传图标*/ + Route::post('change_sort','SoftManual@changeSort');/*修改排序*/ + Route::post('del','SoftManual@del');/*删除*/ + Route::post('change_status','SoftManual@changeStatus');/*启用禁用*/ + }); + + //后台评测文章模块路由组 + Route::group('article', function () { + Route::post('list','Article@index');/*列表*/ + Route::post('info','Article@read');/*列表*/ + Route::post('create','Article@create');/*新增*/ + Route::post('update','Article@update');/*更新*/ + Route::post('upload','Article@upload');/*上传图标*/ + Route::post('change_status','Article@changeStatus');/*上传图标*/ + Route::post('del','Article@del');/*删除*/ + }); + + + //后台组织模块路由组 + Route::group('org',function () { + Route::post('list','app\api\controller\Organization@list'); + Route::post('info','app\api\controller\Organization@info'); + Route::post('add','app\api\controller\Organization@add'); + Route::post('edit','app\api\controller\Organization@edit'); + Route::post('delete','app\api\controller\Organization@delete'); + }); + + //后台商品分类模块路由组 + Route::group('category', function () { + Route::post('list','GoodsCategory@tree');/*列表*/ + Route::post('category_goods_list','GoodsCategory@categoryGoodsList');/*列表*/ + Route::post('category_goods_info','GoodsCategory@categoryGoodsInfo');/*列表*/ + Route::post('info','GoodsCategory@read');/*详情*/ + Route::post('create','GoodsCategory@create');/*新增*/ + Route::post('update','GoodsCategory@update');/*更新*/ + Route::post('upload','GoodsCategory@upload');/*上传图标*/ + Route::post('del','GoodsCategory@del');/*删除*/ + Route::post('change_status','GoodsCategory@changeStatus');/*启用禁用*/ + }); + + //后台商品分类模块路由组 + Route::group('attr', function () { + Route::post('list','Attribute@index');/*列表*/ + Route::post('info','Attribute@read');/*详情*/ + Route::post('create','Attribute@create');/*新增*/ + Route::post('update','Attribute@update');/*更新*/ + Route::post('del','Attribute@del');/*删除*/ + }); + + //后台商品模块路由组 + Route::group('goods', function () { + Route::post('list','Goods@index');/*列表*/ + Route::post('language_list','Goods@languageList');/*列表*/ + Route::post('info','Goods@read');/*列表*/ + Route::post('create','Goods@create');/*新增*/ + Route::post('update','Goods@update');/*更新*/ + Route::post('upload','Goods@upload');/*上传图标*/ + Route::post('del','Goods@del');/*删除*/ + Route::any('ue_upload','Goods@ueditorUpload');/*百度富文本上传*/ + Route::post('change_status','Goods@changeStatus');/*删除*/ + Route::post('sort','Goods@changeSort');/*排序*/ + Route::post('batch_del','Goods@batchGoodsDel');/*批量删除*/ + Route::post('batch_enable','Goods@batchGoodsEnable');/*批量删除*/ + Route::post('batch_disable','Goods@batchGoodsDisable');/*批量删除*/ + Route::post('batch_category_change','Goods@batchCategoryModify');/*批量修改分类*/ + }); + + //后台文件类型路由组 + Route::group('file_type', function () { + Route::post('list','FileType@index');/*列表*/ + Route::post('sort','FileType@sort');/*列表*/ + Route::post('create','FileType@create');/*新增*/ + Route::post('update','FileType@update');/*更新*/ + Route::post('del','FileType@del');/*删除*/ + }); + + //后台评论路由组 + Route::group('comment', function () { + Route::post('list','Comment@index');/*列表*/ + Route::post('info','Comment@read');/*列表*/ + Route::post('create','Comment@create');/*新增*/ + Route::post('update','Comment@update');/*更新*/ + Route::post('upload','Comment@upload');/*上传图标*/ + Route::post('del','Comment@del');/*删除*/ + }); + + //后台大量采购路由组 + Route::group('bulk_buy', function () { + Route::post('list','BulkBuy@index');/*列表*/ + Route::post('info','BulkBuy@read');/*列表*/ + Route::post('create','BulkBuy@create');/*新增*/ + Route::post('update','BulkBuy@update');/*更新*/ + Route::post('upload','BulkBuy@upload');/*上传图标*/ + Route::post('del','BulkBuy@del');/*删除*/ + }); + + //后台广告模块路由组 + Route::group('ad', function () { + Route::post('list','Advertisement@index');/*列表*/ + Route::post('info','Advertisement@read');/*列表*/ + Route::post('create','Advertisement@create');/*新增*/ + Route::post('update','Advertisement@update');/*更新*/ + Route::post('upload','Advertisement@upload');/*上传图标*/ + Route::post('del','Advertisement@del');/*删除*/ + }); + + //后台广告位模块路由组 + Route::group('ad_space', function () { + Route::post('list','AdvertiseSpace@index');/*列表*/ + Route::post('invalid_list','AdvertiseSpace@invalidList');/*列表*/ + Route::post('info','AdvertiseSpace@read');/*列表*/ + Route::post('create','AdvertiseSpace@create');/*新增*/ + Route::post('update','AdvertiseSpace@update');/*更新*/ + Route::post('upload','AdvertiseSpace@upload');/*上传图标*/ + Route::post('del','AdvertiseSpace@del');/*删除*/ + }); + + //后台广告所属页模块路由组 + Route::group('ad_page', function () { + Route::post('list','AdvertisePage@index');/*列表*/ + Route::post('create','AdvertisePage@create');/*新增*/ + Route::post('update','AdvertisePage@update');/*更新*/ + Route::post('del','AdvertisePage@del');/*删除*/ + }); + + //后台优惠券模块路由组 + Route::group('coupon', function () { + Route::post('list','GoodsCoupon@index');/*列表*/ + Route::post('create','GoodsCoupon@create');/*新增*/ + }); + + //后台优惠券领取记录模块路由组 + Route::group('coupon_subscribe', function () { + Route::post('list','CouponSubscribe@index');/*列表*/ + Route::post('create','CouponSubscribe@create');/*新增*/ + Route::post('del','CouponSubscribe@del');/*删除*/ + }); + + //后台币种模块路由组 + Route::group('currency', function () { + Route::post('list','Currency@index');/*列表*/ + Route::post('info','Currency@read');/*列表*/ + Route::post('create','Currency@create');/*新增*/ + Route::post('update','Currency@update');/*更新*/ + Route::post('del','Currency@del');/*删除*/ + Route::post('change_status','Currency@changeStatus');/*删除*/ + }); + + //后台faq模块路由组 + Route::group('faq', function () { + Route::post('list','Faq@index');/*列表*/ + Route::post('info','Faq@read');/*列表*/ + Route::post('create','Faq@create');/*新增*/ + Route::post('update','Faq@update');/*更新*/ + Route::post('del','Faq@del');/*删除*/ + }); + + //后台faq模块路由组 + Route::group('faq_type', function () { + Route::post('list','FaqType@index');/*列表*/ + Route::post('create','FaqType@create');/*新增*/ + Route::post('update','FaqType@update');/*更新*/ + Route::post('del','FaqType@del');/*删除*/ + }); + + //后台广告所属页模块路由组 + Route::group('log', function () { + Route::post('list','LogVisit@index');/*列表*/ + Route::post('info','LogVisit@read');/*列表*/ + Route::post('del','LogVisit@del');/*删除*/ + }); + + //后台文章类型路由组 + Route::group('article_type', function () { + Route::post('list','ArticleType@index');/*列表*/ + Route::post('update','ArticleType@update');/*更新*/ + Route::post('del','ArticleType@del');/*删除*/ + }); + + //后台文章模块路由组 + Route::group('article', function () { + Route::post('list','Article@index');/*列表*/ + Route::post('info','Article@read');/*列表*/ + Route::post('create','Article@create');/*新增*/ + Route::post('update','Article@update');/*更新*/ + Route::post('del','Article@del');/*删除*/ + }); + + //后台品牌矩阵类型路由组 + Route::group('brand_type', function () { + Route::post('list','BrandType@index');/*列表*/ + Route::post('update','BrandType@update');/*更新*/ + Route::post('del','BrandType@del');/*删除*/ + }); + + //后台品牌矩阵模块路由组 + Route::group('brand', function () { + Route::post('list','Brand@index');/*列表*/ + Route::post('info','Brand@read');/*列表*/ + Route::post('create','Brand@create');/*新增*/ + Route::post('update','Brand@update');/*更新*/ + Route::post('del','Brand@del');/*删除*/ + Route::post('upload','Brand@upload');/*上传*/ + Route::post('change_status','Brand@changeStatus');/*修改状态*/ + }); + //后台资源中心类型路由组 + Route::group('resource_type', function () { + Route::post('list','ResourceType@index');/*列表*/ + Route::post('update','ResourceType@update');/*更新*/ + Route::post('del','ResourceType@del');/*删除*/ + }); + + //后台资源中心模块路由组 + Route::group('resource', function () { + Route::post('list','Resource@index');/*列表*/ + Route::post('info','Resource@read');/*列表*/ + Route::post('create','Resource@create');/*新增*/ + Route::post('update','Resource@update');/*更新*/ + Route::post('del','Resource@del');/*删除*/ + Route::post('upload','Resource@upload');/*上传*/ + Route::post('change_status','Resource@changeStatus');/*修改状态*/ + }); + //后台新闻动态类型路由组 + Route::group('news_type', function () { + Route::post('list','NewsType@index');/*列表*/ + Route::post('update','NewsType@update');/*更新*/ + Route::post('del','NewsType@del');/*删除*/ + }); + + //后台新闻动态模块路由组 + Route::group('news', function () { + Route::post('list','News@index');/*列表*/ + Route::post('info','News@read');/*列表*/ + Route::post('create','News@create');/*新增*/ + Route::post('update','News@update');/*更新*/ + Route::post('del','News@del');/*删除*/ + Route::post('upload','News@upload');/*上传*/ + Route::post('change_status','News@changeStatus');/*修改状态*/ + }); + //后台加入我们类型路由组 + Route::group('join_type', function () { + Route::post('list','JoinType@index');/*列表*/ + Route::post('update','JoinType@update');/*更新*/ + Route::post('del','JoinType@del');/*删除*/ + }); + //后台新闻动态模块路由组 + Route::group('video', function () { + Route::post('list','Video@index');/*列表*/ + Route::post('info','Video@read');/*列表*/ + Route::post('create','Video@create');/*新增*/ + Route::post('update','Video@update');/*更新*/ + Route::post('del','Video@del');/*删除*/ + Route::post('upload','Video@upload');/*上传*/ + Route::post('change_status','Video@changeStatus');/*修改状态*/ + }); + //后台加入我们模块路由组 + Route::group('join', function () { + Route::post('list','Join@index');/*列表*/ + Route::post('info','Join@read');/*列表*/ + Route::post('create','Join@create');/*新增*/ + Route::post('update','Join@update');/*更新*/ + Route::post('del','Join@del');/*删除*/ + Route::post('upload','Join@upload');/*上传*/ + Route::post('change_status','Join@changeStatus');/*修改状态*/ + }); + // + Route::group('config', function () { + Route::post('list','SystemConfig@index');/*列表*/ + Route::post('info','SystemConfig@read');/*详情*/ + Route::post('create','SystemConfig@create');/*新增*/ + Route::post('update','SystemConfig@update');/*更新*/ + Route::post('upload','SystemConfig@upload');/*上传*/ + Route::post('del','SystemConfig@del');/*删除*/ + }); + + + })->prefix('app\\api\\controller\\v1\\')->middleware([ + app\api\middleware\Auth::class, + app\api\middleware\LogVisit::class + ]), + + // +---------------------------------------------------------------------- + // | 后台管理系统路由 - 结束 + // +---------------------------------------------------------------------- + // | Author: yulinzhihou + // +---------------------------------------------------------------------- + + //全局错误路由 + Route::miss(function() { + return json(["status"=>500,'message'=>'请使用正确的接口地址和参数','route'=>request()->url(),'create_time'=>time(),'date_time'=>date("Y-m-d H:i:s",time())]); + }) +]; diff --git a/app/api/validate/Admin.php b/app/api/validate/Admin.php new file mode 100644 index 0000000..da80543 --- /dev/null +++ b/app/api/validate/Admin.php @@ -0,0 +1,43 @@ + ['require', 'length:2,20'], + 'password' => ['require', 'length:0,32'], + 'mobile' => ['require', 'mobile'], + 'id' => ['require','integer','gt:0'] + ]; + + + /** + * 验证器错误提示信息汇总 + * @var array + */ + protected $message = []; + + + /** + * 验证器验证场景 + * @var array + */ + protected $scene = [ + 'login' => ['username','password'], + 'add' => ['username','password', 'mobile'], + 'update' => ['id'], + 'forbidden' => ['id'] + ]; + + +} diff --git a/app/api/validate/AdvertisePage.php b/app/api/validate/AdvertisePage.php new file mode 100644 index 0000000..db1e23c --- /dev/null +++ b/app/api/validate/AdvertisePage.php @@ -0,0 +1,48 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'name|广告页名称' => ['length:1,30','require','unique:advertise_page,name^site_id^platform_id'], + 'sort|排序' => ['between:1,255'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + /** + * @var + */ + protected $scene = [ + 'index' => [''], + 'create' => ['site_id','name'], + 'update' => ['id','name'], + 'batchCreate' => ['site_id','name'], + 'batchUpdate' => ['id','name'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/AdvertiseSpace.php b/app/api/validate/AdvertiseSpace.php new file mode 100644 index 0000000..6c7cceb --- /dev/null +++ b/app/api/validate/AdvertiseSpace.php @@ -0,0 +1,52 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言版本' => ['integer','gt:0'], + 'name|广告位名称' => ['length:1,50','require','unique:advertise_space,name^site_id^platform_id'], + 'sort|排序' => ['between:1,255'], + 'advertise_page_id|所属页面'=>['integer','gt:0'], + 'max_num|数量上限' => ['integer','between:1,15'], + 'width|尺寸要求-宽度' => ['integer','gt:0','elt:1920'], + 'height|尺寸要求-高度' => ['integer','gt:0','elt:1920'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','advertise_page_id'], + 'read' => ['id'], + 'create' => ['site_id','advertise_page_id','name','max_num','width','height','sort'], + 'update' => ['id','advertise_page_id','name','max_num','width','height','sort'], + 'del' => ['id'], + 'invalidList' => [''] + ]; +} diff --git a/app/api/validate/Advertisement.php b/app/api/validate/Advertisement.php new file mode 100644 index 0000000..f186df1 --- /dev/null +++ b/app/api/validate/Advertisement.php @@ -0,0 +1,61 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言版本' => ['integer','gt:0'], + 'name|广告名称' => ['length:1,50','require'], + 'sort|排序' => ['between:1,255'], + 'advertise_space_id|广告位' => ['integer','gt:0','require'], + 'image|图片上传' => ['length:1,128','require'], + 'url|关联链接' => ['length:1,128'], + 'command|悬浮提示' => ['length:1,128'], + 'start_time|开始时间' => ['integer','gt:0'], + 'stop_time|结束时间' => ['integer','gt:0'], + 'play_order|轮播顺序' => ['integer','gt:0'], + 'status|状态' => ['in:0,1','integer'], + 'avatar|广告图' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,bmp,gif,jpeg', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['site_id','advertise_space_id','name','image','url','play_order','command'], + 'update' => ['id','advertise_space_id','name','image','url','play_order','command','status'], + 'del' => ['id'], + 'upload' => [''] + ]; +} diff --git a/app/api/validate/Article.php b/app/api/validate/Article.php new file mode 100644 index 0000000..e0aff0c --- /dev/null +++ b/app/api/validate/Article.php @@ -0,0 +1,64 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'language_id|语言包' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'article_type_id|所属分类' => ['integer','gt:0'], + 'is_outer_chain|外链文章' => ['require','integer','egt:0','in:0,1'], + 'status|状态' => ['integer','egt:0','in:0,1'], + 'title|文章标题' => ['require','length:1,128'], + 'brief|文章摘要' => ['length:1,255'], + 'thumb|封面图片' => ['length:1,255'], + 'url|链接' => ['length:1,255'], + 'keywords|Keywords' => ['length:1,255'], + 'desc|Description' => ['length:1,255'], + 'meta_title|页面Meta-title' => ['length:1,255'], + 'detail|图文详情' => ['length:1,65530'], + 'click_num|点击次数' => ['integer','egt:0'], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg,gif,webp,tiff,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif,image/webp,image/tiff,image/bmp' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','article_type_id'], + 'read' => ['id'], + 'create' => ['site_id','title','desc','thumb','url','detail','is_outer_chain','brief','article_type_id','keywords','meta_title'], + 'update' => ['id','site_id','title','desc','thumb','url','detail','is_outer_chain','brief','article_type_id','keywords','meta_title'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => ['image'], + ]; +} diff --git a/app/api/validate/ArticleType.php b/app/api/validate/ArticleType.php new file mode 100644 index 0000000..42d7cac --- /dev/null +++ b/app/api/validate/ArticleType.php @@ -0,0 +1,38 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:article_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/Attribute.php b/app/api/validate/Attribute.php new file mode 100644 index 0000000..e10ee6a --- /dev/null +++ b/app/api/validate/Attribute.php @@ -0,0 +1,37 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|所属站点' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'name|属性名称' => ['length:1,50','require','unique:attribute,name^site_id^platform_id'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id'], + 'read' => ['id'], + 'update' => ['id','name'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/Base.php b/app/api/validate/Base.php new file mode 100644 index 0000000..011e070 --- /dev/null +++ b/app/api/validate/Base.php @@ -0,0 +1,52 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'icon|图标' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,bmp,gif,jpeg', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ], + 'file|文件' => [ + 'fileSize' => 1024 * 1024 * 10, + 'fileExt' => 'xls,xlsx,jpg,png,docx,doc', + 'fileMime' => 'application/vnd.ms-excel,image/jpeg,image/png,image/gif,application/x-rar-compressed,application/zip,application/pdf,audio/ogg,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ], + 'driver|驱动' => [ + 'fileSize' => 1024 * 1024 * 10, + 'fileExt' => 'xls,xlsx,jpg,png,docx,doc,rar,zip', + 'fileMime' => 'image/jpeg,image/png,image/gif,application/x-rar-compressed,application/zip,application/pdf,audio/ogg,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'file' => ['file'], + 'image' => ['image'], + 'icon' => ['icon'], + 'driver' => ['driver'], + ]; + +} diff --git a/app/api/validate/Brand.php b/app/api/validate/Brand.php new file mode 100644 index 0000000..c1475c9 --- /dev/null +++ b/app/api/validate/Brand.php @@ -0,0 +1,73 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'language_id|语言包' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'brand_type_id|所属分类' => ['integer','gt:0'], + 'is_outer_chain|外链文章' => ['require','integer','egt:0','in:0,1'], + 'status|状态' => ['integer','egt:0','in:0,1'], + 'title|文章标题' => ['require','length:1,128'], + 'brief|文章摘要' => ['length:1,255'], + 'thumb|封面图片' => ['length:1,255'], + 'url|链接' => ['length:1,255'], + 'keywords|Keywords' => ['length:1,255'], + 'desc|Description' => ['length:1,255'], + 'meta_title|页面Meta-title' => ['length:1,255'], + 'detail|图文详情' => ['length:1,65530'], + 'click_num|点击次数' => ['integer','egt:0'], + 'website' => ['length:1,255'], + 'cname' => ['length:1,255'], + 'en_name' => ['length:1,255'], + 'belong' => ['length:1,255'], + 'turnover' => ['length:1,255'], + 'brand_cate' => ['length:1,255'], + 'work_address' => ['length:1,255'], + 'founded' => ['length:1,255'], + 'founder' => ['length:1,255'], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg,gif,webp,tiff,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif,image/webp,image/tiff,image/bmp' + ] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','Brand_type_id'], + 'read' => ['id'], + 'create' => ['site_id','title','desc','thumb','url','detail','is_outer_chain','brief','brand_type_id','keywords','meta_title'], + 'update' => ['id','site_id','title','desc','thumb','url','detail','is_outer_chain','brief','brand_type_id','keywords','meta_title'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => ['image'], + ]; +} diff --git a/app/api/validate/BrandType.php b/app/api/validate/BrandType.php new file mode 100644 index 0000000..71e2974 --- /dev/null +++ b/app/api/validate/BrandType.php @@ -0,0 +1,38 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:brand_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/BulkBuy.php b/app/api/validate/BulkBuy.php new file mode 100644 index 0000000..93d86a8 --- /dev/null +++ b/app/api/validate/BulkBuy.php @@ -0,0 +1,52 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言包ID' => ['integer','gt:0'], + 'name|客户名称' => ['length:1,30','require'], + 'sort|排序' => ['require','between:1,255'], + 'mode_number|产品型号' => ['length:1,128','require'], + 'needed_num|需要数量' => ['integer','gt:0'], + 'email|邮箱' => ['length:1,60','require'], + 'arrival_country|收货国家'=> ['length:1,128','require'], + 'delivery_time|发货时间' => ['integer','gt:0'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * 场景 + * @var + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['site_id','name','mode_number','needed_num','email','arrival_country','sort','delivery_time'], + 'update' => ['id','name','mode_number','needed_num','email','arrival_country','sort','delivery_time'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/Comment.php b/app/api/validate/Comment.php new file mode 100644 index 0000000..afd60be --- /dev/null +++ b/app/api/validate/Comment.php @@ -0,0 +1,54 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言版本' => ['integer','gt:0'], + 'sort|排序' => ['require','integer','gt:0','lt:256'], + 'avatar|客户头像' => [ + 'fileSize' => 1024 * 1024 * 1, + 'fileExt' => 'jpg,png,ico', + 'fileMime' => 'image/jpeg,image/png,image/gif', + ], + 'image|评价配图' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,bmp,gif,jpeg', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ], + 'nickname|客户昵称' => ['length:1,20'], + 'comment|评价内容' => ['length:1,1500'], + 'url|产品链接' => ['length:1,128'], + ]; + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size','nickname'], + 'read' => ['id'], + 'create' => ['site_id','name','nickname','comment','url','sort'], + 'update' => ['id','name','nickname','comment','url','sort'], + 'del' => ['id'], + 'upload' => ['avatar','image'] + ]; +} diff --git a/app/api/validate/CouponSubscribe.php b/app/api/validate/CouponSubscribe.php new file mode 100644 index 0000000..c47a1f1 --- /dev/null +++ b/app/api/validate/CouponSubscribe.php @@ -0,0 +1,29 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer'], + 'platform_id' => ['integer','gt:0'], + 'site_id' => ['integer','gt:0'], + 'goods_coupon_id' => ['integer','gt:0'], + 'email' => ['email'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/Currency.php b/app/api/validate/Currency.php new file mode 100644 index 0000000..fad3698 --- /dev/null +++ b/app/api/validate/Currency.php @@ -0,0 +1,46 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'name|币种名称' => ['length:1,10','require','unique:currency,name'], + 'code|币种缩写' => ['length:1,10','require','unique:currency,code'], + 'signal|币种符号' => ['length:1,10','require'], + 'status|状态' => ['in:0,1','integer'], + ]; + + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['name','code','signal','status'], + 'update' => ['id','name','code','signal','status'], + 'del' => ['id'], + 'changeStatus'=> ['id','status'], + ]; +} diff --git a/app/api/validate/Faq.php b/app/api/validate/Faq.php new file mode 100644 index 0000000..6f8b0f5 --- /dev/null +++ b/app/api/validate/Faq.php @@ -0,0 +1,45 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言版本' => ['integer','gt:0'], + 'faq_type_id|问题分类' => ['integer','gt:0'], + 'question|回答问题' => ['length:1,150','require','unique:faq,question^site_id^platform_id'], + 'answer|回答内容' => ['length:1,3000'], + 'sort|排序' => ['between:1,255'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + protected $scene = [ + 'index' => ['page','size','answer'], + 'read' => ['id'], + 'create' => ['site_id','faq_type_id','question','answer','sort'], + 'update' => ['id','faq_type_id','question','answer','sort'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/FaqType.php b/app/api/validate/FaqType.php new file mode 100644 index 0000000..41db641 --- /dev/null +++ b/app/api/validate/FaqType.php @@ -0,0 +1,40 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id' => ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,60','require','unique:faq_type,name^site_id'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['site_id','name','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'], + ]; +} diff --git a/app/api/validate/FileType.php b/app/api/validate/FileType.php new file mode 100644 index 0000000..9d41405 --- /dev/null +++ b/app/api/validate/FileType.php @@ -0,0 +1,37 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:file_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/Goods.php b/app/api/validate/Goods.php new file mode 100644 index 0000000..a40f79f --- /dev/null +++ b/app/api/validate/Goods.php @@ -0,0 +1,71 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|选择语言' => ['integer','gt:0'], + 'goods_category_id|所属分类' => ['require','integer','gt:0'], + 'name|商品标题' => ['length:1,220','unique:goods,name^site_id'], + 'model_number|商品型号' => ['length:1,128','unique:goods,model_number^site_id'], + 'price|价格' => ['float','gt:0'], + 'details|图文介绍' => ['length:1,65534'], + 'title|标题' => ['length:1,255','unique:goods,title^site_id'], + 'keywords|关键词' => ['length:1,255'], + 'description|描述' => ['length:1,255'], + 'status|上架状态' => ['in:0,1','integer'], + 'is_new|是否新品' => ['in:0,1','integer'], + 'is_discount|是否折扣' => ['in:0,1','integer'], + 'is_hot|是否热门' => ['in:0,1','integer'], + 'is_recommend|是否推荐' => ['in:0,1','integer'], + 'sort|排序' => ['between:1,255'], + 'image|产品主图' => [ + 'fileSize' => 1024 * 1024 * 1, + 'fileExt' => 'jpg,png,gif,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['site_id','goods_category_id','name','model_number','price','details','title','keywords','description','status'], + 'update' => ['id','name','goods_category_id','model_number','price','details','title','keywords','description','status'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'batchGoodsDel' => ['id'], + 'batchGoodsEnable' => ['id','status'], + 'batchGoodsDisable' => ['id','status'], + 'batchCategoryModify' => ['id','goods_category_id'], + 'upload' => ['image'], + 'changeSort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/GoodsBuyNow.php b/app/api/validate/GoodsBuyNow.php new file mode 100644 index 0000000..c1d68bd --- /dev/null +++ b/app/api/validate/GoodsBuyNow.php @@ -0,0 +1,28 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer'], + 'goods_id|商品ID' => ['require','integer','gt:0'], + 'name|链接名称' => ['require','length:1,128'], + 'url|链接地址' => ['require','length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/GoodsCategory.php b/app/api/validate/GoodsCategory.php new file mode 100644 index 0000000..bd63218 --- /dev/null +++ b/app/api/validate/GoodsCategory.php @@ -0,0 +1,47 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|所属站点' => ['require','integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,50','require','unique:goods_category,name^site_id'], + 'status|状态' => ['in:0,1','integer'], + 'pid|上级分类' => ['require','integer','egt:0'], + 'icon|图标' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['status'], + 'tree' => ['status'], + 'read' => ['id'], + 'create' => ['site_id','name','desc','pid','sort','status'], + 'update' => ['id','name','desc','pid','sort','status'], + 'del' => ['id'], + 'upload' => ['icon'], + 'sort' => ['id','sort'], + 'changeStatus' => ['id','status'], + 'categoryGoodsList' => [''], + 'categoryGoodsInfo' => [''], + ]; +} diff --git a/app/api/validate/GoodsConnect.php b/app/api/validate/GoodsConnect.php new file mode 100644 index 0000000..10ab314 --- /dev/null +++ b/app/api/validate/GoodsConnect.php @@ -0,0 +1,28 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'goods_id|商品ID' => ['integer','require','gt:0'], + 'goods_category_id|商品分类ID' => ['integer','require','gt:0'], + 'connect_good_id|关联商品ID' => ['integer','gt:0','require'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/GoodsCoupon.php b/app/api/validate/GoodsCoupon.php new file mode 100644 index 0000000..6ee153a --- /dev/null +++ b/app/api/validate/GoodsCoupon.php @@ -0,0 +1,47 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言包ID' => ['integer','gt:0'], +// 'old_code|旧口令' => ['length:1,30'], + 'new_code|新口令' => ['require','length:1,30','unique:goods_coupon,new_code^old_code^id'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['site_id','old_code','new_code'], + 'update' => ['id','old_code','new_code'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/GoodsImages.php b/app/api/validate/GoodsImages.php new file mode 100644 index 0000000..e0900f4 --- /dev/null +++ b/app/api/validate/GoodsImages.php @@ -0,0 +1,27 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer'], + 'goods_id|商品ID' => ['integer','require','gt:0'], + 'image|图片' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/GoodsSoftManual.php b/app/api/validate/GoodsSoftManual.php new file mode 100644 index 0000000..d116423 --- /dev/null +++ b/app/api/validate/GoodsSoftManual.php @@ -0,0 +1,30 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer','require','gt:0'], + 'soft_manual_id' => ['integer','require','gt:0'], + 'btn_tips' => ['length:1,128'], + 'url' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = []; +} diff --git a/app/api/validate/Investment.php b/app/api/validate/Investment.php new file mode 100644 index 0000000..d3064e4 --- /dev/null +++ b/app/api/validate/Investment.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/Join.php b/app/api/validate/Join.php new file mode 100644 index 0000000..f5a1576 --- /dev/null +++ b/app/api/validate/Join.php @@ -0,0 +1,64 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'language_id|语言包' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'join_type_id|所属分类' => ['integer','gt:0'], + 'is_outer_chain|外链文章' => ['require','integer','egt:0','in:0,1'], + 'status|状态' => ['integer','egt:0','in:0,1'], + 'title|文章标题' => ['require','length:1,128'], + 'brief|文章摘要' => ['length:1,255'], + 'thumb|封面图片' => ['length:1,255'], + 'url|链接' => ['length:1,255'], + 'keywords|Keywords' => ['length:1,255'], + 'desc|Description' => ['length:1,255'], + 'meta_title|页面Meta-title' => ['length:1,255'], + 'detail|图文详情' => ['length:1,65530'], + 'click_num|点击次数' => ['integer','egt:0'], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg,gif,webp,tiff,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif,image/webp,image/tiff,image/bmp' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','Join_type_id'], + 'read' => ['id'], + 'create' => ['site_id','title','desc','thumb','url','detail','is_outer_chain','brief','Join_type_id','keywords','meta_title'], + 'update' => ['id','site_id','title','desc','thumb','url','detail','is_outer_chain','brief','Join_type_id','keywords','meta_title'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => ['image'], + ]; +} diff --git a/app/api/validate/JoinType.php b/app/api/validate/JoinType.php new file mode 100644 index 0000000..e12e651 --- /dev/null +++ b/app/api/validate/JoinType.php @@ -0,0 +1,38 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:join_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/Language.php b/app/api/validate/Language.php new file mode 100644 index 0000000..beaa45b --- /dev/null +++ b/app/api/validate/Language.php @@ -0,0 +1,50 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'name|语言名称' => ['length:1,10','require','unique:language,name'], + 'code|语言代号' => ['length:1,10','require','unique:language,code'], + 'icon|预览图' => ['length:1,128','require'], + 'status|状态' => ['in:0,1','integer'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * 验证场景定义 + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['name','code','icon','url','status'], + 'update' => ['id','name','code','icon','url','status'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => [''] + ]; +} diff --git a/app/api/validate/Menu.php b/app/api/validate/Menu.php new file mode 100644 index 0000000..3178396 --- /dev/null +++ b/app/api/validate/Menu.php @@ -0,0 +1,51 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'name|菜单名称' => ['length:1,12','require'], + 'icon|图标' => ['length:1,128','require'], + 'sort|排序' => ['between:1,255','require'], + 'path|菜单路径' => ['length:1,64','require'], + 'component|操作' => ['length:1,128','require'], + 'redirect|跳转' => ['length:1,128','require'], + 'is_menu|是否为菜单' => ['in:0,1','integer'], + 'pid|父ID' => ['integer','require','egt:0'], + 'status|状态' => ['in:0,1','integer'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size','name'], + 'tree' => [''], + 'read' => ['id'], + 'create' => ['name','icon','path','component','redirect','is_menu','pid','sort','status'], + 'update' => ['id','name','icon','path','component','redirect','is_menu','pid','sort','status'], + 'del' => ['id'], + 'sort' => ['id','sort'], + ]; +} diff --git a/app/api/validate/MenuPlatform.php b/app/api/validate/MenuPlatform.php new file mode 100644 index 0000000..3d890d6 --- /dev/null +++ b/app/api/validate/MenuPlatform.php @@ -0,0 +1,28 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer','require','gt:0'], + 'menu_id|菜单ID' => ['integer','require','gt:0'], + 'platform_id|品牌ID' => ['integer','gt:0'], + 'status|状态' => ['integer','in:1,0'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/Navigator.php b/app/api/validate/Navigator.php new file mode 100644 index 0000000..bbe6618 --- /dev/null +++ b/app/api/validate/Navigator.php @@ -0,0 +1,53 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|所属站点'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|栏目名称' => ['length:1,128','require','unique:navigator,name^site_id^platform_id'], + 'is_top|顶部导航' => ['in:0,1','integer'], + 'is_foot|底部导航' => ['in:0,1','integer'], + 'pid|上级栏目' => ['require','integer','egt:0'], + 'icon|图标' => ['length:1,128'], + 'desc|描述' => ['length:1,128'], + 'url|文件路径' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'tree' => [''], + 'read' => ['id'], + 'create' => ['site_id','name','desc','pid','icon','url','sort','is_top','is_foot'], + 'update' => ['id','name','desc','pid','icon','url','sort','is_top','is_foot'], + 'del' => ['id'], + 'sort' => ['id','sort'], + 'changeStatus' => ['id','is_top','is_foot'], + 'topTree' => [''], + 'upload' => [''] + ]; +} diff --git a/app/api/validate/News.php b/app/api/validate/News.php new file mode 100644 index 0000000..a795fba --- /dev/null +++ b/app/api/validate/News.php @@ -0,0 +1,64 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'language_id|语言包' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'news_type_id|所属分类' => ['integer','gt:0'], + 'is_outer_chain|外链文章' => ['require','integer','egt:0','in:0,1'], + 'status|状态' => ['integer','egt:0','in:0,1'], + 'title|文章标题' => ['require','length:1,128'], + 'brief|文章摘要' => ['length:1,255'], + 'thumb|封面图片' => ['length:1,255'], + 'url|链接' => ['length:1,255'], + 'keywords|Keywords' => ['length:1,255'], + 'desc|Description' => ['length:1,255'], + 'meta_title|页面Meta-title' => ['length:1,255'], + 'detail|图文详情' => ['length:1,65530'], + 'click_num|点击次数' => ['integer','egt:0'], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg,gif,webp,tiff,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif,image/webp,image/tiff,image/bmp' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','News_type_id'], + 'read' => ['id'], + 'create' => ['site_id','title','desc','thumb','url','detail','is_outer_chain','brief','News_type_id','keywords','meta_title'], + 'update' => ['id','site_id','title','desc','thumb','url','detail','is_outer_chain','brief','News_type_id','keywords','meta_title'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => ['image'], + ]; +} diff --git a/app/api/validate/NewsType.php b/app/api/validate/NewsType.php new file mode 100644 index 0000000..d27871e --- /dev/null +++ b/app/api/validate/NewsType.php @@ -0,0 +1,38 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:news_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/Platform.php b/app/api/validate/Platform.php new file mode 100644 index 0000000..6c6ea27 --- /dev/null +++ b/app/api/validate/Platform.php @@ -0,0 +1,51 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|品牌名称' => ['length:1,50','require','unique:platform,name'], + 'status|状态' => ['in:0,1','integer'], + 'vi_color1|品牌VI色标准色' => ['length:1,10','require','different:vi_color2','different:vi_color3','regex:^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$'], + 'vi_color2|品牌VI色辅助色-深' => ['length:1,10','require','different:vi_color3','different:vi_color1','regex:^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$'], + 'vi_color3|品牌VI色辅助色-浅' => ['length:1,10','require','different:vi_color1','different:vi_color2','regex:^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$'], + 'currency_id|默认币种' => ['integer','gt:0'], + 'language_id|默认语言' => ['integer','gt:0'], + 'icon|品牌logo' => ['length:1,128'], + + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * 验证场景定义 + * @var array + */ + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['name','vi_color1','vi_color2','vi_color3','language_id','currency_id','desc','icon','status'], + 'update' => ['id','vi_color1','vi_color2','vi_color3','language_id','currency_id','desc','icon','status'], + 'del' => ['id'], + 'upload' => [''], + 'langeuageList' => [''] + ]; +} diff --git a/app/api/validate/Question.php b/app/api/validate/Question.php new file mode 100644 index 0000000..084fa3a --- /dev/null +++ b/app/api/validate/Question.php @@ -0,0 +1,60 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'name|姓名' => ['length:1,40','require'], + 'country_id|国家' => ['length:1,30','require'], + 'email|邮箱' => ['length:1,60'], + 'phone|手机号码' => ['length:1,20','regex:/^1[23456789]{1}\d{9}$/'], + 'order_sn|SKU' => ['length:1,50'], + 'product_model|产品型号' => ['length:1,128'], + 'is_done|解决与否' => ['integer','in:0,1'], + 'os|操作系统' => ['length:1,50'], + 'image' => [ + 'fileSize' => 1024 * 1024 * 10, + 'fileExt' => 'xls,xlsx,jpg,png,docx,doc,rar,zip', + 'fileMime' => 'image/jpeg,image/png,image/gif,application/x-rar-compressed,application/zip,application/pdf,audio/ogg,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document' + ] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','is_done','product_model'], + 'read' => ['id'], + 'create' => ['site_id','country_id','name','email','phone','order_sn','product_model','os','desc','sort'], + 'update' => ['id','country_id','name','email','phone','order_sn','product_model','os','desc','sort'], + 'del' => ['id'], + 'isDone' => ['id','is_done'], + 'upload' => ['image'] + ]; +} diff --git a/app/api/validate/QuestionAttachment.php b/app/api/validate/QuestionAttachment.php new file mode 100644 index 0000000..0f16f8c --- /dev/null +++ b/app/api/validate/QuestionAttachment.php @@ -0,0 +1,27 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer','require','gt:0'], + 'question_id|问题ID' => ['integer','require','gt:0'], + 'attach|附件' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/Resource.php b/app/api/validate/Resource.php new file mode 100644 index 0000000..17b1901 --- /dev/null +++ b/app/api/validate/Resource.php @@ -0,0 +1,65 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'language_id|语言包' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'resource_type_id|所属分类' => ['integer','gt:0'], + 'is_outer_chain|外链文章' => ['require','integer','egt:0','in:0,1'], + 'status|状态' => ['integer','egt:0','in:0,1'], + 'title|文章标题' => ['require','length:1,128'], + 's_title|小标题' => ['require','length:1,255'], + 'brief|文章摘要' => ['length:1,255'], + 'thumb|封面图片' => ['length:1,255'], + 'url|链接' => ['length:1,255'], + 'keywords|Keywords' => ['length:1,255'], + 'desc|Description' => ['length:1,255'], + 'meta_title|页面Meta-title' => ['length:1,255'], + 'detail|图文详情' => ['length:1,65530'], + 'click_num|点击次数' => ['integer','egt:0'], + 'image|图片' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg,gif,webp,tiff,bmp', + 'fileMime' => 'image/jpeg,image/png,image/gif,image/webp,image/tiff,image/bmp' + ], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => ['page','size','Resource_type_id'], + 'read' => ['id'], + 'create' => ['site_id','title','desc','thumb','url','detail','is_outer_chain','brief','Resource_type_id','keywords','meta_title'], + 'update' => ['id','site_id','title','desc','thumb','url','detail','is_outer_chain','brief','Resource_type_id','keywords','meta_title'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], + 'upload' => ['image'], + ]; +} diff --git a/app/api/validate/ResourceType.php b/app/api/validate/ResourceType.php new file mode 100644 index 0000000..46d88d1 --- /dev/null +++ b/app/api/validate/ResourceType.php @@ -0,0 +1,38 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'site_id|语言包ID'=> ['integer','gt:0'], + 'sort|排序' => ['require','between:1,255'], + 'name|分类名称' => ['length:1,20','require','unique:resource_type,name^site_id'] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => [''], + 'create' => ['name','site_id','sort'], + 'update' => ['id','name','sort'], + 'del' => ['id'], + 'sort' => ['id','sort'] + ]; +} diff --git a/app/api/validate/Role.php b/app/api/validate/Role.php new file mode 100644 index 0000000..e3c0b2f --- /dev/null +++ b/app/api/validate/Role.php @@ -0,0 +1,41 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'name' => ['length:1,50','require'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size'], + 'read' => ['id'], + 'create' => ['name'], + 'update' => ['id','name'], + 'del' => ['id'], + ]; +} diff --git a/app/api/validate/Site.php b/app/api/validate/Site.php new file mode 100644 index 0000000..ed41177 --- /dev/null +++ b/app/api/validate/Site.php @@ -0,0 +1,48 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'status|状态' => ['in:0,1','integer'], + 'currency_id|默认币种' => ['integer','gt:0'], + 'language_id|站点语言'=> ['integer','gt:0'], + 'platform_id|所属品牌'=> ['integer','gt:0'], + 'domain|站点域名' => ['length:1,128','require'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size','platform_id'], + 'read' => ['id'], + 'create' => ['platform_id','language_id','currency_id','domain','status'], + 'update' => ['id','platform_id','currency_id','domain','status'], + 'del' => ['id'], + 'get_nav' => ['id'], + 'changeStatus' => ['id','status'], + 'siteIndex' => [''] + ]; +} diff --git a/app/api/validate/SoftManual.php b/app/api/validate/SoftManual.php new file mode 100644 index 0000000..1f25476 --- /dev/null +++ b/app/api/validate/SoftManual.php @@ -0,0 +1,63 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言版本' => ['require','integer','gt:0'], + 'file_type_id|文件分类' => ['integer','gt:0'], + 'name|下载名称' => ['length:1,50','unique:soft_manual,name^site_id^platform_id'], + 'introduce|下载介绍' => ['length:1,255'], + 'support|支持型号' => ['length:1,255'], + 'os|操作系统' => ['length:1,60'], + 'sort|排序' => ['require','between:1,255'], + 'download_count|下载次数' => ['integer','gt:0'], +// 'image|预览图' => [ +// 'fileSize' => 1024 * 1024 * 10, +// 'fileExt' => 'jpg,png,gif', +// 'fileMime' => 'image/jpeg,image/png,image/gif' +// ], +// 'file|驱动文件' => [ +// 'fileSize' => 1024 * 1024 * 100, +// 'fileExt' => 'xls,xlsx,jpg,png,docx,doc,rar,zip,pdf,chm', +// 'fileMime' => 'image/jpeg,image/png,image/gif,application/x-rar-compressed,application/zip,application/pdf,audio/ogg,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-htmlhelp' +// ], + + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'name.length' => '下载名称不能超过50个字符', + 'introduce.length' => '下载介绍不能超过255个字符', + 'support.length' => '支持型号不能超过255个字符', + 'os.length' => '操作系统不能超过60个字符', + ]; + + protected $scene = [ + 'index' => [''], + 'read' => ['id'], + 'create' => ['site_id','file_type_id','name','introduce','support','os','sort'], + 'update' => ['id','file_type_id','name','introduce','support','os','sort'], + 'del' => ['id'], + 'changeStatus' => ['id','status'], +// 'upload' => ['image','file'] + ]; +} diff --git a/app/api/validate/SoftManualBtn.php b/app/api/validate/SoftManualBtn.php new file mode 100644 index 0000000..234e400 --- /dev/null +++ b/app/api/validate/SoftManualBtn.php @@ -0,0 +1,35 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['integer','gt:0','require'], + 'soft_manual_id|文档手册' => ['integer','gt:0'], + 'btn_tips|按钮名称' => ['length:1,20'], + 'url|下载链接' => ['length:1,128'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + /** + * @var array + */ + protected $scene = [ + 'index' => [], + ]; +} diff --git a/app/api/validate/SystemConfig.php b/app/api/validate/SystemConfig.php new file mode 100644 index 0000000..1bf1902 --- /dev/null +++ b/app/api/validate/SystemConfig.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/api/validate/Video.php b/app/api/validate/Video.php new file mode 100644 index 0000000..08728d4 --- /dev/null +++ b/app/api/validate/Video.php @@ -0,0 +1,54 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id|语言包' => ['integer','gt:0'], + 'name|视频名称' => ['length:1,40'], + 'is_top|是否置顶' => ['integer','in:0,1'], + 'sort|排序' => ['integer','between:1,200'], + 'image' => [ + 'fileSize' => 1024 * 1024 * 5, + 'fileExt' => 'jpg,png,ico,jpeg', + 'fileMime' => 'image/jpeg,image/png,image/gif' + ], + 'url' => [ + 'fileSize' => 1024 * 1024 * 50, + 'fileExt' => 'mp4', + 'fileMime' => 'video/mp4' + ] + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size','name'], + 'read' => ['id'], + 'create' => ['site_id','name','sort','is_top'], + 'update' => ['id','site_id','name','sort','is_top'], + 'del' => ['id'], + 'upload' => ['image','url'], + 'change_status' => ['id','is_top','sort'], + 'sort' => ['id','is_top','sort'], + ]; +} diff --git a/app/common.php b/app/common.php new file mode 100644 index 0000000..db97c85 --- /dev/null +++ b/app/common.php @@ -0,0 +1,498 @@ +insert($add_data,false,true); + +} + + +/** + * 组装绝对url + * @param $url + * @return string + */ +function build_image_fullurl($url, $qiniu=true, $type='public') +{ + $rootPath = ''; + if (empty($url) || stripos($url, 'http://') !== false || stripos($url, 'https://') !== false) { + return $url; + } else if (stripos($url, '.') == 0) { + $url = mb_substr($url, 1); + } + + if (stripos($url, '/') == 0) { + if (false !== stripos($url, '/attachs')) { + $rootPath = 'https://www.f2b211.com'; + } + if (false !== stripos($url, '/paycard')) { + $rootPath = 'https://api.f2b211.com'; + } + if (false !== stripos($url, '/payimg')) { + $rootPath = 'https://api.f2b211.com'; + } + if (false !== stripos($url, '/Public/goods')) { + $rootPath = 'https://www.f2b211.com'; + } + } else { + // 七牛地址 + if ($qiniu) { + $rootPath = \utils\QiniuUploader::$domain; + } else { + if ($type == 'public') { + $rootPath = request()->domain() . \think\facade\Filesystem::getConfig('disks.public.url'); + } else { + $rootPath = request()->domain() . '/'; + } + } + } + + return $rootPath . $url; +} +/** + * 返回json格式的数组 + * @param + * @param + * @param [array] $data [随带的数据] + * @return [string] [json字符串] + */ +function json_return($data) +{ + header("Content-Type: application/json; charset=UTF-8"); + + exit(json_encode($data)); +} + + +/** + * 将数值金额转换为中文大写金额 + * @param $amount float 金额(支持到分) + * @param $type int 补整类型,0:到角补整;1:到元补整 + * @return mixed 中文大写金额 + */ +function convertAmountToCn($amount, $type = 1) { + // 判断输出的金额是否为数字或数字字符串 + if(!is_numeric($amount)){ + return "要转换的金额只能为数字!"; + } + + // 金额为0,则直接输出"零元整" + if($amount == 0) { + return "人民币零元整"; + } + + // 金额不能为负数 + if($amount < 0) { + return "要转换的金额不能为负数!"; + } + + // 金额不能超过万亿,即12位 + if(strlen($amount) > 12) { + return "要转换的金额不能为万亿及更高金额!"; + } + + // 预定义中文转换的数组 + $digital = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'); + // 预定义单位转换的数组 + $position = array('仟', '佰', '拾', '亿', '仟', '佰', '拾', '万', '仟', '佰', '拾', '元'); + + // 将金额的数值字符串拆分成数组 + $amountArr = explode('.', $amount); + + // 将整数位的数值字符串拆分成数组 + $integerArr = str_split($amountArr[0], 1); + + // 将整数部分替换成大写汉字 + $result = '人民币'; + $integerArrLength = count($integerArr); // 整数位数组的长度 + $positionLength = count($position); // 单位数组的长度 + $zeroCount = 0; // 连续为0数量 + for($i = 0; $i < $integerArrLength; $i++) { + // 如果数值不为0,则正常转换 + if($integerArr[$i] != 0){ + // 如果前面数字为0需要增加一个零 + if($zeroCount >= 1){ + $result .= $digital[0]; + } + $result .= $digital[$integerArr[$i]] . $position[$positionLength - $integerArrLength + $i]; + $zeroCount = 0; + }else{ + $zeroCount += 1; + // 如果数值为0, 且单位是亿,万,元这三个的时候,则直接显示单位 + if(($positionLength - $integerArrLength + $i + 1)%4 == 0){ + $result = $result . $position[$positionLength - $integerArrLength + $i]; + } + } + } + + // 如果小数位也要转换 + if($type == 0) { + // 将小数位的数值字符串拆分成数组 + $decimalArr = str_split($amountArr[1], 1); + // 将角替换成大写汉字. 如果为0,则不替换 + if($decimalArr[0] != 0){ + $result = $result . $digital[$decimalArr[0]] . '角'; + } + // 将分替换成大写汉字. 如果为0,则不替换 + if($decimalArr[1] != 0){ + $result = $result . $digital[$decimalArr[1]] . '分'; + } + }else{ +// $result = $result . '整'; + $result = $result; + } + return $result; +} + + + +/** + * 获取客户端ip + */ +function get_client_ip($type = 0) { + $type = $type ? 1 : 0; + static $ip = NULL; + if ($ip !== NULL) return $ip[$type]; + if(isset($_SERVER['HTTP_X_REAL_IP'])){//nginx 代理模式下,获取客户端真实IP + $ip=$_SERVER['HTTP_X_REAL_IP']; + }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip + $ip = $_SERVER['HTTP_CLIENT_IP']; + }elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关 + $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + $pos = array_search('unknown',$arr); + if(false !== $pos) unset($arr[$pos]); + $ip = trim($arr[0]); + }elseif (isset($_SERVER['REMOTE_ADDR'])) { + $ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址 + }else{ + $ip=$_SERVER['REMOTE_ADDR']; + } + // IP地址合法验证 + $long = sprintf("%u",ip2long($ip)); + $ip = $long ? array($ip, $long) : array('0.0.0.0', 0); + return $ip[$type]; +} + + +/** + * 列表转换为树形结构 + * @param array $list 需要处理的树形结构数据 + * @param int $isOver 是否有限级别,比如2表示只输出2级分类结构,0表示有多少级全部输出 + * @param string $pk 主键字段名 + * @param string $pid_name 父类字段名 + * @param string $child_name 子数据结构名 + * @param string $level_name 层级结构名 + * @param int $pid 父ID + * @param int $level 层级数量,1=一层分类,2=二层 + * @return array + */ +function list_to_tree($list,$isOver = 0, $pk='id', $pid_name='pid', $child_name='children', $level_name='level', $pid=0, $level=1) +{ + $tree = []; + foreach ($list as $key => $value) + { + if ($value[$pid_name] == $pid) + { + $value[$level_name] = $level; + if ($isOver == $level) { + continue; + } else { + $child = list_to_tree($list,$isOver, $pk, $pid_name, $child_name, $level_name, $value[$pk], $level+1); + } + if (!empty($child)) $value[$child_name] = $child; + $tree[] = $value; + } + } + + return $tree; +} + +/** + * 列表转换为树形结构 + */ +function list_to_top_tree($data,$cid) +{ + $arr = []; + foreach ($data as $item) { + if ($cid == $item['id']) { + $arr[] = $item; + $arr = array_merge(list_to_top_tree($data,$item['pid']),$arr); + } + } + return $arr; +} + +/** + * 通过分类id查找所有父ID + */ +function category_to_all_pid($data,$cid) +{ + $arr = []; + foreach ($data as $item) { + if ($cid == $item['id']) { + $arr[] = $item['id']; + $arr = array_merge(category_to_all_pid($data,$item['pid']),$arr); + } + } + return $arr; +} + +/** + * 当前分类ID,获取所有子分类ID + */ +function category_to_all_children_id($data,$cid) +{ + $arr = []; + foreach ($data as $item) { + if ($cid == $item['pid']) { + $arr[] = $item['id']; + $arr = array_merge(category_to_all_children_id($data,$item['id']),$arr); + } + $arr[] = $cid; + } + return $arr; +} + + +/** + * 获取唯一id + */ +function unique_id($length = 20, $prefix = '') +{ + $id = $prefix; + $addLength = $length - 13; + $id .= uniqid(); + if (function_exists('random_bytes')) { + $id .= substr(bin2hex(random_bytes(ceil(($addLength) / 2))),0,$addLength); + } elseif (function_exists('openssl_random_pseudo_bytes')) { + $id .= substr(bin2hex(openssl_random_pseudo_bytes(ceil($addLength / 2))),0,$addLength); + } else { + $id .= mt_rand(1*pow(10,($addLength)),9*pow(10,($addLength))); + } + return $id; +} + +///** +// * 获取随机字符串 +// */ +//function rand_str($length) +//{ +// $pattern = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ'; +// $result = ''; +// for($i=0;$i<$length;$i++) +// { +// $result .= $pattern{mt_rand(0,35)}; //生成php随机数 +// } +// return $result; +//} + +/** + * 格式化价格 + * @param $price int 价格 + * @param $divisor int 除数 + * @param $bit int 保留位数 + * @return string + */ +function format_price($price, $divisor=100, $bit=2) +{ + $format = "%." . $bit . "f"; + return sprintf($format, $price / $divisor); +} + +/** + * 数据是否合法 + */ +function is_valid_data($data) +{ + return isset($data) && $data != ''; +} + +/** + * 隐藏电话号码 + */ +function hide_mobile($mobile) +{ + $IsWhat = preg_match('/(0[0-9]{2,3}[\-]?[2-9][0-9]{6,7}[\-]?[0-9]?)/i',$mobile); //固定电话 + if($IsWhat == 1){ + return preg_replace('/(0[0-9]{2,3}[\-]?[2-9])[0-9]{3,4}([0-9]{3}[\-]?[0-9]?)/i','$1****$2',$mobile); + }else{ + return preg_replace('/(1[358]{1}[0-9])[0-9]{4}([0-9]{4})/i','$1****$2',$mobile); + } +} + +function curl_get($url){ + $headerArray = array( + "Content-type: application/json" + ); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray); + $output = curl_exec($ch); + curl_close($ch); + $output = json_decode($output, true); + return $output; +} + +function curl_post($url, $data){ + $data = json_encode($data); + $headerArray = array( + "Content-type: application/json" + ); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $output = curl_exec($curl); + curl_close($curl); + return json_decode($output, true); +} + + +/** 根据物料编码查69码 + * @param $fnumber 编码 + */ +function get_FBARCODE($fnumber){ + $formid = 'BD_MATERIAL'; + $TopRowCount = 0; + $Limit = 0; + $StartRow = 0; + $FilterString = "FUseOrgId.fnumber=101 and FForbidStatus='A' and FNumber='$fnumber'";//dump($FilterString);die; + $OrderString = 'FMATERIALID'; + $FieldKeys = 'FBARCODE'; + $erp = new ERP(); + $geterp = $erp->getproduct($formid, $FieldKeys, $FilterString, $OrderString, $StartRow, $TopRowCount, $Limit); + $fnumber = json_decode($geterp[0],true); + $CheckBox = $fnumber[0][0]; + return $CheckBox; +} +/** 根据69码查物料型号 + * @param $code 69码 + */ +function FBARCODE_Getmodel($code){ + $formid = 'BD_MATERIAL'; + $TopRowCount = 0; + $Limit = 0; + $StartRow = 0; + $FilterString = "FUseOrgId.fnumber=101 and FForbidStatus='A' and FBARCODE='$code'";//dump($FilterString);die; + $OrderString = 'FMATERIALID'; + $FieldKeys = 'FSpecification'; + $erp = new ERP(); + $geterp = $erp->getproduct($formid, $FieldKeys, $FilterString, $OrderString, $StartRow, $TopRowCount, $Limit); + $fnumber = json_decode($geterp[0],true); + if($fnumber==null){ + $CheckBox=null; + }else{ + $CheckBox = $fnumber[0][0]; + } + + return $CheckBox; +} + + +/** + * 处理图片绝对路径转相对路径算法 + * @param $url + * @return mixed|string + */ +function doImageURLtoRelativePath($url) +{ + $arr = explode(think\facade\Env::get('QINIU.cdn'),$url); + if (isset($arr[1])) { + return $arr[1]; + } else { + //可以拆分域名朋问题 + if (false === strrpos(think\facade\Env::get('QINIU.cdn'),$url)) { + return $url; + } else { + $domain = explode('/',$url)[2]; + $arr = explode($domain[2],$url); + return ltrim('/',$arr[1]); + } + + } +} + +if (!function_exists('is_image')) { + + function is_image($file) { + return file_exists($file) && @getimagesize($file) ? true : false; + } +} + + +/** + * 处理二维数组站点与语言ID互换的问题 + */ +if (!function_exists('array_copy_column')) { + function array_copy_column($array) { + foreach ($array as $key => $item) { + if (isset($item['language_id'])) { + $array[$key]['site_id'] = $item['language_id']; + } + } + return $array; + } +} + +if (function_exists('show')) { + /** + * 返回json格式的数组 + * @param [int] $status [代表返回时的状态:0失败,1成功] + * @param [string] $message [提示信息] + * @param [array] $data [随带的数据] + * @return [string] [json字符串] + */ + function show($status, $message, $data = []) + { + header("Content-Type: application/json; charset=UTF-8"); + + $result = [ + 'status' => $status, + 'message' => $message, + 'data' => $data + ]; + + exit(json_encode($result)); + } +} + +/** + * 递归 + * @param $data array 需要递归的数据 + * @param $pid integer 上级ID + * @param $pf string 上级的字段名 + * @param $unset bool 为true则去除pid字段 + * @return array + */ +if (!function_exists('recursion_func')) { + function recursion_func($data, $pid = 0, $pf = 'pid', $unset = false) { + $result = []; + foreach ($data as $key => $val) { + if ($val[$pf] == $pid) { + if ($unset) unset($val[$pf]); + $result[$key] = $val; + if ($recur = recursion_func($data, $val['id'], $pf, $unset)) { + $result[$key]['children'] = array_values($recur); + } + } + } + return $result; + } +} \ No newline at end of file diff --git a/app/event.php b/app/event.php new file mode 100644 index 0000000..e9851bb --- /dev/null +++ b/app/event.php @@ -0,0 +1,17 @@ + [ + ], + + 'listen' => [ + 'AppInit' => [], + 'HttpRun' => [], + 'HttpEnd' => [], + 'LogLevel' => [], + 'LogWrite' => [], + ], + + 'subscribe' => [ + ], +]; diff --git a/app/index/common.php b/app/index/common.php new file mode 100644 index 0000000..1243615 --- /dev/null +++ b/app/index/common.php @@ -0,0 +1,2 @@ + env('lang.default_lang', 'zh-cn'), + // 允许的语言列表 + 'allow_lang_list' => ['zh-cn', 'en-us'], + // 多语言自动侦测变量名 + 'detect_var' => 'lang', + // 是否使用Cookie记录 + 'use_cookie' => true, + // 多语言cookie变量 + 'cookie_var' => 'think_lang', + // 扩展语言包 + 'extend_list' => [], + // Accept-Language转义为对应语言包名称 + 'accept_language' => [ + 'zh-cn' => 'zh-cn', + 'en-us' => 'en-us' + ], + // 是否支持语言分组 + 'allow_group' => true, +]; \ No newline at end of file diff --git a/app/index/config/view.php b/app/index/config/view.php new file mode 100644 index 0000000..6a40943 --- /dev/null +++ b/app/index/config/view.php @@ -0,0 +1,34 @@ + 'Think', + // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 + 'auto_rule' => 1, + // 模板目录名 + 'view_dir_name' => 'view', + // 模板后缀 + 'view_suffix' => 'html', + // 模板文件名分隔符 + 'view_depr' => DIRECTORY_SEPARATOR, + // 模板引擎普通标签开始标记 + 'tpl_begin' => '{', + // 模板引擎普通标签结束标记 + 'tpl_end' => '}', + // 标签库标签开始标记 + 'taglib_begin' => '{', + // 标签库标签结束标记 + 'taglib_end' => '}', + + // 模板变量 + 'tpl_replace_string' => [ + '__STATIC__' => Env::get('cdn.url','/'), + '__LOCAL__' => Env::get('cdn.local','/'), + ], + 'tpl_cache' => false, +]; diff --git a/app/index/controller/About.php b/app/index/controller/About.php new file mode 100644 index 0000000..89b17b8 --- /dev/null +++ b/app/index/controller/About.php @@ -0,0 +1,41 @@ +model = new \app\index\model\About(); + } + + /** + * 显示资源列表 + * + */ + public function index() + { + $inputData = $this->request->param(); + $resource = []; +// $resource['banner'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-banner'); +// $resource['banner_mobile'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-手机-banner'); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'about'); + View::assign('meta',$metaTitle); + View::assign('resource',$resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'about/about_us'); + } + + public function mileage(){ + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'about/mileage'); + } + +} diff --git a/app/index/controller/Base.php b/app/index/controller/Base.php new file mode 100644 index 0000000..042468a --- /dev/null +++ b/app/index/controller/Base.php @@ -0,0 +1,249 @@ +'test'] + * @var array + */ + protected $vague = []; + + /** + * 精准查询,精确字段,格式['language_id'=> 1] + * @var array + */ + protected $focus = []; + + /** + * 排序字段。格式 ['sort'=>'desc'] + * @var array + */ + protected $sort = []; + + /** + * 模型 + * @var array + */ + protected $model = null; + + /** + * 语言ID + * @var int|mixed + */ + protected $languageId = 1; + + /** + * 导航栏模型 + * @var null + */ + protected $navModel = null; + + /** + * 系统配置模型 + * @var null + */ + protected $systemConfigModel = null; + + /** + * 接口监控数据 + * @var string[] + */ + protected $apiLog = [ + 'items' => '', /*项目名称*/ + 'forum' => '', /*模块*/ + 'forum_code' => '', /*模块日志编码*/ + 'url' => '', /*访问页*/ + 'refer' => '', /*访问来源*/ + 'click' => '', /*点击次数*/ + 'content' => '', /*访问内容*/ + 'ip' => '', /*访客IP*/ + 'country' => '', /*国家*/ + 'province' => '', /*省*/ + 'city' => '', /*市*/ + 'start_time' => '', /*点击时间*/ + 'drive' => '', /*PC OR 移动端*/ + 'system' => '', /*设备系统*/ + 'brower' => '', /*浏览器*/ + 'models' => '', /*设备型号*/ + 'date_time' => '' /*生成时间*/ + ]; + + /** + * 判断请求来源是否是手机设备 + * @return bool + */ + private function isMobile() : bool + { + //如果有HTTP_X_WAP_PROFILE则一定是移动设备 + if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) { + return true; + } + //如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息 + if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], 'wap')) { + return true; + } + //野蛮方法,判断手机发送的客户端标志,兼容性有待提高 + if (isset($_SERVER['HTTP_USER_AGENT'])) { + + $clientKeywords = ['nokia','sony','ericsson','mot','samsung','htc','sgh','lg','sharp','sie-','philips','panasonic','alcatel','lenovo','iphone','ipod','blackberry','meizu','android','netfront','symbian','ucweb','windowsce','palm','operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile']; + + //从HTTP_USER_AGENT中查找手机浏览器的关键字 + if (preg_match("/(".implode('|', $clientKeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) { + return true; + } + } + //协议法,因为有可能不准确,放到最后判断 + if (isset($_SERVER['HTTP_ACCEPT'])) { + //如果只支持wml并且不支持html那一定是移动设备 + //如果支持wml和html但是wml在html之前则是移动设备 + if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) { + return true; + } + } + return false; + } + + /** + * 初始化 + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function initialize() + { + $controller = $this->request->controller(); + + $this->languageId = $this->request->language_id??1; + //通过中间件过来的语言包,动态设置 + Lang::setLangSet($this->request->language_code??'zh-cn'); + //重新加载动态设置的语言包 + $this->app->loadLangPack(Lang::getLangSet()); + // 初始化公共模型 + $this->navModel = new Navigator(); + + $this->systemConfigModel = new SystemConfig(); + + // 初始化公共页面,判断语言包 + // 导航 + $navInfo = $this->navModel->getNavInfo($this->languageId,$this->platformId,$controller); + $navInfo = recursion_func($navInfo); + $footerNavInfo = $this->navModel->getFootNavInfo($this->languageId,$this->platformId); + $footerNavInfo = recursion_func($footerNavInfo); + // 头部版本号 + // 静态版本号 + $version = Env::get('front.version'); + // 尾部数据 + $footerInfo = $this->systemConfigModel->getFooterInfo($this->languageId); + // 首页多网站切换 + $multiLanguage = $this->systemConfigModel->getWebSiteInfo($this->languageId); + // 其他公共数据 + // 增加标签显示 + $metaTitle = $this->systemConfigModel->getMetaTitle($this->languageId,'common'); + View::assign('meta',$metaTitle); + View::assign('nav_info',$navInfo); + View::assign('nav_footer_info',$footerNavInfo); + View::assign('footer_info',$footerInfo); + View::assign('multi_lang',$multiLanguage); + View::assign('ver',$version); + View::assign('is_dev',Env::get('APP_DEBUG')); + View::assign('is_mobile',$this->isMobile()); + } + + /** + * 访问日志监控,提交kafka生产者接口 + * @return \think\response\Json + * @throws \GeoIp2\Exception\AddressNotFoundException + * @throws \MaxMind\Db\Reader\InvalidDatabaseException + */ + public function submitActionLog() + { + $inputData = $this->request->param(); + $model = explode('//',$inputData['url']); + $model = explode('/',$model[1]); + $this->apiLog['items'] = Env::get('platform_name','官网'); + $this->apiLog['forum'] = count($model) > 1 && $model[1] != '' ? $model[1] : 'index'; + $this->apiLog['forum_code'] = 200; + $this->apiLog['url'] = $inputData['url']; + $this->apiLog['refer'] = $inputData['url']; + $this->apiLog['content'] = $inputData['content']; + $this->apiLog['click'] = $inputData['click']; + $this->apiLog['start_time'] = date('Y-m-d H:i:s',(int)ceil(($inputData['date_time'] - (int)ceil((int)$inputData['start_time'])) / 1000) ); + $this->apiLog['date_time'] = date('Y-m-d H:i:s',(int)ceil($inputData['date_time'] / 1000) ); + //获取应用启动时间 + //获取访问设备,系统版本,浏览器,设备型号 + $userAgent = $inputData['drive']; + AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE); + $dd = new DeviceDetector($userAgent); + $dd->parse(); + + if ($dd->isBot()) { + $this->apiLog['brower'] = '未知'; + $this->apiLog['system'] = '未知'; + $this->apiLog['drive'] = '未知'; + $this->apiLog['models'] = '爬虫'; + } else { + $clientInfo = $dd->getClient(); + $osInfo = $dd->getOs(); + $device = $dd->getDeviceName(); + $brand = $dd->getBrandName(); + $model = $dd->getModel(); + $this->apiLog['brower'] = !empty($clientInfo) ? $clientInfo['name'].' '.$clientInfo['version'] : '未知'; + $this->apiLog['system'] = !empty($osInfo) ? $osInfo['name'].' '.$osInfo['version'] : '未知'; + $this->apiLog['models'] = $device . " " . $brand . " ". $model; + $this->apiLog['drive'] = $device; + } + //解析IP地址,得到国家,城市,地址, + $this->apiLog['ip'] = $inputData['ip']; + + if (!filter_var($inputData['ip'],FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_NULL_ON_FAILURE)) { + $this->apiLog['country'] = '本地'; + $this->apiLog['province'] = '本地'; + $this->apiLog['city'] = '本地'; + } else { + $readerCity = new Reader(public_path() . 'GeoLite2-City.mmdb'); + $record = $readerCity->city($inputData['ip']); + $country = $record->country->names['zh-CN']; + $province = $record->subdivisions[0]->names['zh-CN']??''; + $city = $record->city->names['zh-CN']??$record->city->names['en']; + $china = ['香港','澳门','台湾']; + if (in_array($country,$china)) { + $province = $city = $country; + $country = '中国'; + } + + $this->apiLog['country'] = $country; + $this->apiLog['province'] = $province; + $this->apiLog['city'] = $city; + } +// Cache::set('this-api-log',$this->apiLog); + // 返回信息前,写入kafka log日志 + $result = $this->sendLogsToKafkaProduce($this->apiLog,'action_logs',Env::get('database.database'),'add'); + return $result ? json('提交成功') : json('提交失败',504); + } +} \ No newline at end of file diff --git a/app/index/controller/Contact.php b/app/index/controller/Contact.php new file mode 100644 index 0000000..e31f91a --- /dev/null +++ b/app/index/controller/Contact.php @@ -0,0 +1,37 @@ +model = new \app\index\model\About(); + } + + /** + * 显示资源列表 + * + */ + public function index() + { + $inputData = $this->request->param(); + $resource = []; +// $resource['banner'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-banner'); +// $resource['banner_mobile'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-手机-banner'); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'contact'); + View::assign('meta',$metaTitle); + View::assign('resource',$resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'contact/contact'); + } + +} diff --git a/app/index/controller/Download.php b/app/index/controller/Download.php new file mode 100644 index 0000000..19515c8 --- /dev/null +++ b/app/index/controller/Download.php @@ -0,0 +1,61 @@ +model = new SoftManualModel(); + } + + public function index() + { + $resource = []; + $inputData = $this->request->param(); + $resource['type'] = $this->model->getDownloadType(); + + if (isset($inputData['keyword']) && $inputData['keyword'] != '') { + $this->vague['name'] = ($inputData['keyword']); + } +// $this->request->pathinfo() + if (isset($inputData['file_type_id']) && $inputData['file_type_id'] != '' && $inputData['file_type_id'] != 0) { + $this->focus['file_type_id'] = $inputData['file_type_id']; + } + + $this->sort['sort'] = 'desc'; + $this->focus['status'] = "0"; + $result = $this->model->getAllList($inputData,$this->vague,$this->focus,$this->sort); +// dump($result); + //构建数据 + if ((isset($result['page']) && !empty($result['page'])) && !empty($result)) { + $resource['list'] = $result; + } else { + if (isset($inputData['keyword']) && $inputData['keyword'] != '') { + $this->vague['introduce'] = ($inputData['keyword']); + } + $result = $this->model->getAllList($inputData,$this->vague,$this->focus,$this->sort); + $resource['list'] = $result; + } + +// dump($this->model->getLastSql()); +// dump($resource); +// $resource['page'] = $result->render(); +// $resource['list'] = $result->toArray(); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'download'); + View::assign('meta',$metaTitle); + View::assign('resource',$resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'download/download'); + } + +} diff --git a/app/index/controller/Goods.php b/app/index/controller/Goods.php new file mode 100644 index 0000000..14f64fe --- /dev/null +++ b/app/index/controller/Goods.php @@ -0,0 +1,105 @@ +model = new \app\index\model\Goods(); + } + + /** + * 显示资源列表 + */ + public function index() + { + $inputData = $this->request->param(); + $resource = []; + $query = []; + if (isset($inputData['model_number']) && $inputData['model_number'] != '') { + $query['model_number'] = $inputData['model_number']; + } + //分类 + $resource['category'] = $this->model->getFirstLeveCategory($inputData); + $resource['checked1'] = 0; + $resource['url'] = explode('.html', $this->request->query())[0]; + if (isset($inputData['cate1']) && $inputData['cate1'] != '') { + $categoryTwo = $this->model->getSecondLevelCategory($inputData); + $resource['category_two'] = $categoryTwo; + $resource['checked2'] = $inputData['cate2']??0; + } + if (isset($inputData['cate2']) && $inputData['cate2'] != '') { + $categoryThree = $this->model->getThreeLevelCategory($inputData); + $resource['category_three'] = $categoryThree; + $resource['checked3'] = $inputData['cate3']??0; + } + + $forth = [ + 'is_all','is_recommend','is_hot','is_new' + ]; + + // + $url = 'index/goods/index?'; + for ($i=1;$i<=3;$i++) { + $cate = 'cate'.$i; + if (isset($inputData[$cate]) && $inputData[$cate] != '') { + $url .= http_build_query([$cate =>$inputData[$cate]])."&"; + $resource['checked'.$i] = $inputData[$cate]; + $resource['url'.$i] = rtrim($url, '&'); + $query['cate'.$i] = $inputData[$cate]; + } + $resource['url'] = rtrim($url, '&'); + } + + + $resource['checked4'] = ''; + foreach ($forth as $fort) { + if (isset($inputData[$fort]) && $inputData[$fort] != '') { + if ($inputData[$fort] == 1) { + $resource['checked4'] = $fort; + $query[$fort] = $inputData[$fort]; + } + } + } + // 查询对应的 + $goodsPaginate = $this->model->getGoodsList($query, $resource['url']); + //dump($goodsPaginate); + $resource['page'] = $goodsPaginate->render(); + $resource['list'] = $goodsPaginate->toArray(); + // dump($this->model->getLastSql()); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'goods_list'); + View::assign('meta',$metaTitle); + View::assign('resource', $resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'goods/list'); + } + + /** + * 显示资源列表 + */ + public function detail() + { + $inputData = $this->request->param(); + $resource = []; + if (isset($inputData['id']) && $inputData['id'] > 0) { + $resource['bread'] = $this->model->getCategoryToParent($inputData['id']); +// dump($resource); + $goodsInfo = $this->model->getInfo($inputData); + $goodsInfo['details'] = htmlspecialchars_decode($goodsInfo['details']); +// dump($goodsInfo); + if (empty($goodsInfo) || $goodsInfo['status'] == 1) { + View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'goods/404'); + } + } + $resource['goodsInfo'] = $goodsInfo; +// dump($goodsInfo); + View::assign('resource', $resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'goods/detail'); + } +} \ No newline at end of file diff --git a/app/index/controller/Index.php b/app/index/controller/Index.php new file mode 100644 index 0000000..ea2bcad --- /dev/null +++ b/app/index/controller/Index.php @@ -0,0 +1,53 @@ +model = new IndexModel(); + parent::initialize(); + } + + /** + * @return string + */ + public function index():string + { + $inputData = $this->request->param(); + // banner + $bannerList = $this->model->getIndexBanner($this->languageId,$inputData); + // 商品banner + $goodsBanner = $this->model->getGoodsBanner($this->languageId,$inputData); + // 获取推荐商品 + $bannerListMobile = $this->model->getIndexBannerMobile($this->languageId,$inputData); + // 商品分类 + $goodsCategoryList = $this->model->getIndexGoodsCategoryList($this->languageId,$inputData); + // 推荐商品 + $goodsCommandList = $this->model->getIndexGoodsRecommandList($this->languageId,$inputData); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'index'); + // 首页4张图 + $forthImg = $this->model->getGoodsBanner($this->languageId); + + View::assign('meta',$metaTitle); + View::assign('f_image',$forthImg); + View::assign('banner_list',$bannerList); + View::assign('banner_list_mobile',$bannerListMobile); + View::assign('goods_category',$goodsCategoryList); + View::assign('goods_is_new',$goodsCommandList); + View::assign('goods_banner',$goodsBanner); + + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'index/index'); + } +} diff --git a/app/index/controller/Join.php b/app/index/controller/Join.php new file mode 100644 index 0000000..b1fdf4e --- /dev/null +++ b/app/index/controller/Join.php @@ -0,0 +1,78 @@ +model = new JoinModel(); + parent::initialize(); + } + + /** + * 显示资源列表 + */ + public function index():string + { + $inputData = $this->request->param(); + $join = []; + $join['banner'] = $this->model->getJoinBanner($this->languageId,'加入我们-banner'); + $join['list'] = $this->model->getJoinList($this->languageId,$inputData); + $join['type'] = $this->model->getJoinTypeList($this->languageId,$inputData); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'join'); + View::assign('meta',$metaTitle); + View::assign('join',$join); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'join/join_us'); + } + + + /** + * 显示详情资源列表 + */ + public function detail():string + { + $inputData = $this->request->param(); + //banner + $join = $this->model->getInfo($inputData); + View::assign('join',$join); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'join/join_detail'); + } + + + /** + * 更多列表页 + */ + public function list():string + { + $inputData = $this->request->param(); + $where = [ + 'site_id' => $this->languageId, + 'status' => 0, + ]; + if (isset($inputData['join_type_id']) && $inputData['join_type_id'] != 0) { + $where['join_type_id'] = $inputData['join_type_id']; + } + $listRow = [ + 'query' => ['join_type_id'=>$inputData['join_type_id']], //url额外参数 + 'fragment' => '', //url锚点 + 'var_page' => 'page', //分页变量 + 'list_rows' => $inputData['size']??4, //每页数量 + ]; + $result = $this->model->where($where)->paginate($listRow); + View::assign('join',$result->render()); + View::assign('list',$result->toArray()); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'join/join_list'); + } + + +} diff --git a/app/index/controller/News.php b/app/index/controller/News.php new file mode 100644 index 0000000..9822902 --- /dev/null +++ b/app/index/controller/News.php @@ -0,0 +1,62 @@ +model = new NewsModel(); + parent::initialize(); + } + + + /** + * 显示资源列表 + */ + public function index() + { + $inputData = $this->request->param(); + $news = []; + $news['banner_list'] = $this->model->getNewsBanner($this->languageId,'新闻列表页面-banner'); + $news['banner_list_mobile'] = $this->model->getNewsBanner($this->languageId,'新闻列表页面-手机-banner'); + + $newsPaginate = $this->model->getNewsList($this->languageId,$inputData); + $news['page'] = $newsPaginate->render(); + $news['list'] = $newsPaginate->toArray(); + $news['type'] = $this->model->getNewsTypeList($this->languageId,$inputData); + if (!empty($news['list']['data'])) { + foreach ($news['list']['data'] as $key => $item) { + $news['list']['data'][$key]['create_time'] = date('Y年m月d日',strtotime($item['create_time'])); + } + } + View::assign('news',$news); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'news/news'); + } + + + /** + * 显示资源列表 + */ + public function detail() + { + $inputData = $this->request->param(); + //banner + $news = $this->model->getInfo($inputData); + $news['banner_detail'] = $this->model->getNewsBanner($this->languageId,'新闻详情页面-banner'); + $news['banner_detail_mobile'] = $this->model->getNewsBanner($this->languageId,'新闻详情页面-手机-banner'); + $news['create_time'] = date('Y年m月d日',strtotime($news['create_time'])); + // 获取上一篇下一篇 + $news['extra'] = $this->model->getPreNexInfo($inputData); + View::assign('news',$news); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'news/news_detail'); + } +} diff --git a/app/index/controller/Test.php b/app/index/controller/Test.php new file mode 100644 index 0000000..865f2a6 --- /dev/null +++ b/app/index/controller/Test.php @@ -0,0 +1,37 @@ +model = new \app\index\model\Test(); + } + + /** + * 显示资源列表 + * + */ + public function index() + { + $inputData = $this->request->param(); + $resource = []; +// $resource['banner'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-banner'); +// $resource['banner_mobile'] = $this->model->getAboutBanner($this->languageId,'关于我们页面-手机-banner'); + // 增加标签显示 + $metaTitle = $this->model->getMetaTitle($this->languageId,'about'); + View::assign('meta',$metaTitle); + View::assign('resource',$resource); + return View::fetch(Lang::getLangSet().DIRECTORY_SEPARATOR.'about/test'); + } + +} diff --git a/app/index/event.php b/app/index/event.php new file mode 100644 index 0000000..4eff890 --- /dev/null +++ b/app/index/event.php @@ -0,0 +1,5 @@ + 'Get list succeeded', + '获取列表失败' => 'Failed to get list', + '提交成功' => 'Submitted successfully', + '提交失败' => 'Submission failed', + '分类参数不正确,请检查!' => 'The classification parameters are incorrect, please check!', + '获取成功' => 'Get success', + '获取失败' => 'Acquisition failed', + '新增成功' => 'Successfully added', + '新增失败' => 'Failed to add', + '修改成功' => 'Modified successfully', + '修改失败' => 'Modification failed', + '已经提交,不要重新提交' => 'Submitted, do not resubmit', + '请选择上传的文件' => 'Submitted, do not resubmit', + '上传成功' => 'Upload succeeded', + '上传失败' => 'Upload failed', + '接口密钥不正确,请检查!' => 'The interface key is incorrect, please check!', + '无效的语言包请求' => 'Invalid language pack request', + '绑定域名不正确,请检查后台设置' => 'The binding domain is incorrect. Please check the backend settings', + "上传失败。文件的最大大小为10MB" => 'Upload failed. The maximum file size is 10MB', + '上传失败。文件后缀不允许' => 'Upload failed. File suffix not allowed', + '上传失败。文件MIME类型不允许' => 'Upload failed. File MIME type not allowed', + '语言包不正确' => 'Incorrect language pack', + '平台参数错误' => 'Platform parameter error', + '平台不存在,请联系管理员' => 'The platform does not exist, please contact the administrator', + + // Validate Error Message + ':attribute require' => ':attribute不能为空', + ':attribute must' => ':attribute必须', + ':attribute must be numeric' => ':attribute必须是数字', + ':attribute must be integer' => ':attribute必须是整数', + ':attribute must be float' => ':attribute必须是浮点数', + ':attribute must be bool' => ':attribute必须是布尔值', + ':attribute not a valid email address' => ':attribute格式不符', + ':attribute not a valid mobile' => ':attribute格式不符', + ':attribute must be a array' => ':attribute必须是数组', + ':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1', + ':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式', + ':attribute not a valid file' => ':attribute不是有效的上传文件', + ':attribute not a valid image' => ':attribute不是有效的图像文件', + ':attribute must be alpha' => ':attribute只能是字母', + ':attribute must be alpha-numeric' => ':attribute只能是字母和数字', + ':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-', + ':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP', + ':attribute must be chinese' => ':attribute只能是汉字', + ':attribute must be chinese or alpha' => ':attribute只能是汉字、字母', + ':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字', + ':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-', + ':attribute not a valid url' => ':attribute不是有效的URL地址', + ':attribute not a valid ip' => ':attribute不是有效的IP地址', + ':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule', + ':attribute must be in :rule' => ':attribute必须在 :rule 范围内', + ':attribute be notin :rule' => ':attribute不能在 :rule 范围内', + ':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间', + ':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间', + 'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule', + 'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule', + 'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule', + ':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule', + ':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule', + ':attribute not within :rule' => '不在有效期内 :rule', + 'access IP is not allowed' => '不允许的IP访问', + 'access IP denied' => '禁止的IP访问', + ':attribute out of accord with :2' => ':attribute和确认字段:2不一致', + ':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同', + ':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule', + ':attribute must greater than :rule' => ':attribute必须大于 :rule', + ':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule', + ':attribute must less than :rule' => ':attribute必须小于 :rule', + ':attribute must equal :rule' => ':attribute必须等于 :rule', + ':attribute has exists' => ':attribute已存在', + ':attribute not conform to the rules' => ':attribute不符合指定规则', + 'invalid Request method' => '无效的请求类型', + 'invalid token' => '令牌数据无效', + 'not conform to the rules' => '规则错误', + +]; \ No newline at end of file diff --git a/app/index/lang/zh-cn.php b/app/index/lang/zh-cn.php new file mode 100644 index 0000000..84cc327 --- /dev/null +++ b/app/index/lang/zh-cn.php @@ -0,0 +1,8 @@ +host(); + //兼容老数据,1=英文,或者传 us-en, zh-cn,jp + $language = $request->param()['language_id']??'zh-cn'; + + if ($language == 'zh-cn') { + $languageId = 1; + } else { + if (is_numeric($language)) { + show(-999,lang('无效的语言包请求')); + } + $lang = new Language(); + $info = $lang->where('code',$language)->where('status',0)->findOrEmpty()->toArray(); + if (empty($info)) { + show(-998,lang('语言包ID不正确')); + } + $languageId = $info['id']; + } + // 查找当前品牌所有的语言站点 + $site = new Site(); + $domain = []; + $languageCode = ''; + if (Cache::has('site_info')) { + $siteInfo = Cache::get('site_info'); + $languageCode = Cache::get('language_info_'.$languageId) ?: 'zh-cn'; + $domain = array_column($siteInfo,'domain'); + } else { + $siteInfo = $site->where(['platform_id'=>1,'status'=>0])->select()->toArray(); + $languageInfo = $site->where(['language_id'=>$languageId,'platform_id'=>1,'status'=>0])->select()->toArray(); + if (!empty($languageInfo)) { + $languageCode = $languageInfo[0]['code'] ?? 'zh-cn'; + } + + if (!empty($siteInfo)) { + $domain = array_column($siteInfo,'domain'); + } + Cache::set('site_info',$siteInfo,7200); + Cache::set('language_info_'.$languageId,$languageCode,7200); + } + + //检测域名是否合法,添加测试域名 + $devDomain = ['setmspace.test','setmspace.com','setmspace.cn','dev.setm.f2b211.com']; + $domain = array_column($domain,'domain'); + $wholeDomain = array_merge($devDomain,$domain); + + if (!in_array($url,$wholeDomain)) { + //表示请求域名不是绑定的域名,抛出异常 + show(-995,lang("绑定域名不正确,请检查后台设置")); + } + + //老站点英文站兼容密钥 + $request->platform_id = 1;/*强制为1*/ + $request->language_id = $languageId; + $request->language_code = $languageCode; + //组装语言ID请求数据 + $post = $request->post(); + $post['language_id'] = $languageId; + $request->withPost($post); + return $next($request); + } +} diff --git a/app/index/model/About.php b/app/index/model/About.php new file mode 100644 index 0000000..5bbd18c --- /dev/null +++ b/app/index/model/About.php @@ -0,0 +1,28 @@ +select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } +} diff --git a/app/index/model/AdvertisePage.php b/app/index/model/AdvertisePage.php new file mode 100644 index 0000000..c2d94e5 --- /dev/null +++ b/app/index/model/AdvertisePage.php @@ -0,0 +1,23 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/AdvertiseSpace.php b/app/index/model/AdvertiseSpace.php new file mode 100644 index 0000000..dd3a266 --- /dev/null +++ b/app/index/model/AdvertiseSpace.php @@ -0,0 +1,25 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'advertise_page_id'=>'int', + 'max_num' =>'int', + 'width' =>'int', + 'height' =>'int', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + +} diff --git a/app/index/model/Advertisement.php b/app/index/model/Advertisement.php new file mode 100644 index 0000000..0d22fbb --- /dev/null +++ b/app/index/model/Advertisement.php @@ -0,0 +1,31 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'advertise_space_id' =>'int', + 'command' =>'string', + 'name' =>'string', + 'image' =>'string', + 'url' =>'string', + 'start_time' =>'int', + 'stop_time' =>'int', + 'play_order' =>'int', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/Attribute.php b/app/index/model/Attribute.php new file mode 100644 index 0000000..acf5073 --- /dev/null +++ b/app/index/model/Attribute.php @@ -0,0 +1,20 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' => 'int', + 'name' =>'string', + 'create_time' =>'int', + 'update_time' =>'int', + ]; +} diff --git a/app/index/model/BaseModel.php b/app/index/model/BaseModel.php new file mode 100644 index 0000000..806765b --- /dev/null +++ b/app/index/model/BaseModel.php @@ -0,0 +1,247 @@ +schema); + $collection = $this->where(function ($query) use ($data,$fields,$simple,$focus) { + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->order($sort)->select()->toArray(); + return ['page'=>$page,'count'=>$count]; + } else { + return $collection->order($sort)->select()->toArray(); + } + } + + /** + * 获取详情 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getInfo($data) + { + $result = $this->find($data['id']); + return $result ? $result->toArray() : []; + } + + /** + * 增加数据 + * @param $data + * @return bool + */ + public function addData($data) + { + return $this->save($data); + } + + /** + * 编辑数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function editData($data) + { + $result = $this->find($data['id']); + return $result && $result->save($data); + } + + /** + * 删除数据 + * @param $id + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function delData($id) + { + $result = $this->find($id['id']); + if ($result) { + return $result->delete(); + } + return false; + } + + /** + * 查询对应ID有没有子项目,比如菜单类,通过ID查询子菜单是否存在 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function checkChildren($data) + { + $result = $this->where('pid',$data['id'])->find(); + return (bool)$result; + } + + /** + * 批量编辑数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function batchEditData($data) + { + $result = $result1 = true; + foreach ($data as $item) { + $models = $this->find($item['id']); + if ($models) { + $result1 = $models->save($item); + } + $result = $result && $result1; + } + return $result; + } + + /** + * 批量删除数据 + * @param $data + * @return bool + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function batchDelData($data) + { + return $this->destroy($data); + } + + /** + * 获取最新一条数据 + * @return array|Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLatestData($data) + { + return $this->where($data)->order($this->pk,'desc')->find(); + } + + /** + * 获取语言名称 + * @param $id + * @return string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getLanguageName($id) + { + $site = Site::find($id); + $result = Language::find($site['language_id']); + return $result ? $result['name'] : ''; + } + + /** + * 获取国家名称 + * @param $id + * @return mixed|string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getCountryName($id) + { + $result = Country::find($id); + return $result ? $result['zh'] : ''; + } + + /** + * 通过ID获取广告位名称 + * @param $id + * @return mixed|string + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAdvertiseSpaceNameById($id) + { + $result = AdvertiseSpace::find($id); + return $result ? $result['name'] : ''; + } + + /** + * 通过广告页ID,获取对应的BANNER + * @param $languageId + * @param $spaceId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getBanner($languageId,$spaceId):array + { + $where = [ + 'site_id' => $languageId, + 'advertise_space_id' => $spaceId + ]; + return Advertisement::field(['id','image'])->where($where)->select()->toArray(); + } + + + /** + * 获取浏览器标签 + * @param int $languageId + * @param string $type + * @return array + */ + public function getMetaTitle(int $languageId,string $type) : array + { + $result = SystemConfig::field('name,value')->where('site_id',$languageId)->where('pos',$type)->column('value','name'); + if (empty($result)) { + return SystemConfig::field('name,value')->where('site_id',$languageId)->where('pos','common')->column('value','name'); + } + return $result; + } + +} diff --git a/app/index/model/Brand.php b/app/index/model/Brand.php new file mode 100644 index 0000000..312f8b1 --- /dev/null +++ b/app/index/model/Brand.php @@ -0,0 +1,75 @@ + $languageId, + 'status' => 0, + ]; + if (isset($data['brand_type_id']) && $data['brand_type_id'] != 0) { + $where['brand_type_id'] = $data['brand_type_id']; + } + return $this->where($where)->order('sort','desc')->select()->toArray(); + } + + /** + * 获取品牌矩阵分类 + * @param $languageId + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getBrandTypeList($languageId,$data):array + { + $result = BrandType::where('site_id',$languageId)->select()->toArray(); + if (!empty($result)) { + $arr[] = [ + 'id' => 0, + 'name' => '全部', + ]; + $result = array_merge($arr,$result); + foreach ($result as $key => $item) { + $result[$key]['is_display'] = !empty($data) ? isset($data['brand_type_id']) && $data['brand_type_id'] == $item['id'] : $item['id'] == 0; + } + return $result; + } + return []; + } + + /** + * @param $languageId + * @param $data + * @return array|string[] + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getBrandBanner($languageId,$data):array + { + $space = AdvertiseSpace::where('name',$data)->select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } + +} diff --git a/app/index/model/BrandType.php b/app/index/model/BrandType.php new file mode 100644 index 0000000..e7b6620 --- /dev/null +++ b/app/index/model/BrandType.php @@ -0,0 +1,24 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/Common.php b/app/index/model/Common.php new file mode 100644 index 0000000..7548ba4 --- /dev/null +++ b/app/index/model/Common.php @@ -0,0 +1,14 @@ +select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } +} diff --git a/app/index/model/Goods.php b/app/index/model/Goods.php new file mode 100644 index 0000000..9a6d600 --- /dev/null +++ b/app/index/model/Goods.php @@ -0,0 +1,305 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'main_img' =>'string', + 'model_number' =>'string', + 'goods_category_id' =>'int', + 'price' =>'int', + 'is_new' =>'int', + 'is_discount' =>'int', + 'details' =>'string', + 'title' =>'string', + 'keywords' =>'string', + 'description' =>'string', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + /** + * 商品链接关联模型 + */ + public function GoodsBuyNow() + { + return $this->hasMany(GoodsBuyNow::class); + } + + /** + * 商品关联商品 + */ + public function GoodsConnect() + { + return $this->hasMany(GoodsConnect::class); + } + + /** + * 商品手册关联模型 + * @return \think\model\relation\HasMany + */ + public function GoodsSoftManual() + { + return $this->hasMany(GoodsSoftManual::class); + } + + /** + * 商品主图关联模型 + * @return \think\model\relation\HasMany + */ + public function GoodsImages() + { + return $this->hasMany(GoodsImages::class); + } + + /** + * 商品属性关联 + * @return \think\model\relation\HasMany + */ + public function goodsAttr() + { + return $this->hasMany(GoodsAttribute::class); + } + + /** + * 获取父级分类 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFirstLeveCategory($data) + { + return GoodsCategory::where('pid',0)->where('status',0)->where('site_id',1)->order('sort','desc')->select()->toArray(); + } + + /** + * 获取二级分类 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSecondLevelCategory($data) + { + return GoodsCategory::where('pid',$data['cate1'])->where('status',0)->where('site_id',1)->order('sort','desc')->select()->toArray(); + } + + /** + * 获取三级分类 + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getThreeLevelCategory($data) + { + return GoodsCategory::where('pid',$data['cate2'])->where('status',0)->where('site_id',1)->order('sort','desc')->select()->toArray(); + } + + /** + * 获取所有子分类 + * @param $id + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllSonCategory($id) + { + $arr = GoodsCategory::where('status',0)->where('site_id',1)->order('sort','desc')->select()->toArray(); + $feeds = category_to_all_children_id($arr,$id); + + return $feeds; + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @return \think\Paginator + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodsList($data,$qstring) + { + $qs = explode('index/goods/index?',$qstring); + parse_str($qs[1],$out); + + $query = $queryOther = []; + $forth = [ + 'is_all','is_recommend','is_hot','is_new' + ]; + foreach ($forth as $f) { + if (in_array($f,array_keys($data))) { + $queryOther[$f] = $data[$f]; + } + } + // 判断是否选择了分类 + for ($i=1;$i<=3;$i++) { + if (isset($data['cate'.$i])) { + // 如果是3级分类 + if ($i === 3 && $data['cate'.$i] != 0) { + $query['goods_category_id'] = $data['cate'.$i]; + } + // 如果是2级分类 + if ($i === 2 && $data['cate'.$i] != 0) { + $arr = array_column($this->getThreeLevelCategory(['cate2'=>$data['cate2']]),'id'); + array_push($arr,(int)$data['cate2']); + $query['goods_category_id'] = $arr; + } + // 如果是1级分类 + if ($i === 1 && $data['cate'.$i] != 0) { + $query['goods_category_id'] = $this->getAllSonCategory($data['cate1']); + } + } + } + + $collection = $this->where('status',0); + if (isset($data['model_number'])) { + $collection = $collection->where('model_number','like','%'.$data['model_number'].'%')->whereOr('name','like','%'.$data['model_number'].'%')->whereOr('title','like','%'.$data['model_number'].'%'); + } else { + //查询 + if (!empty($queryOther) && !isset($queryOther['is_all'])) { + $collection = $collection->where($queryOther); + } + + if (!empty($query) && is_array($query['goods_category_id'])) { + // 表示是非3级分类 + $collection = $collection->whereIn('goods_category_id',$query['goods_category_id']); + } else { + $collection = $collection->where($query); + } + } + + $pageNum = SystemConfig::where('pos','goods')->where('name','list_num')->find()->toArray(); + $listRow = [ + 'query' => $out, //url额外参数 + 'fragment' => '', //url锚点 + 'var_page' => 'page', //分页变量 + 'list_rows' => (int)$pageNum['value']??4, //每页数量 + ]; + + //return $collection->order('create_time','desc')->paginate($listRow); + $resutl = $collection->order('create_time','desc')->paginate($listRow); + //dump($this->getLastSql()); + return $resutl; + } + + /** + * 通过商品ID,查出所有父级分类 + */ + public function getCategoryToParent($id) + { + $goods = $this->where('id',$id)->find()->toArray(); + $data = GoodsCategory::where('status',0)->order('sort','desc')->select()->toArray(); + $arr = category_to_all_pid($data,$goods['goods_category_id']); + $arr = GoodsCategory::whereIn('id',$arr)->order('sort','desc')->select()->toArray(); + + $url = ''; + for ($i=0;$i<=count($arr)-1;$i++) { + $cate = 'cate'.($i + 1); + $url .= http_build_query([$cate =>$arr[$i]['id']])."&"; + $arr[$i]['qs'] = rtrim($url,'&'); + } + $arr[0]['qs'] = 'cate1='.$arr[0]['id']; + return $arr; + } + + public function getInfo($data) + { + $result = $this->where('status',0)->find($data['id']); + if ($result) { + $goodsAttribute = $result->goodsAttr()->select()->toArray(); + $attr = $img = []; + if ($goodsAttribute) { + foreach ($goodsAttribute as $item) { + $attr[] = array_merge($item,['attribute_name'=>Attribute::where('id',$item['attribute_id'])->value('name')]); + } + } + $images = $result->goodsImages()->select()->toArray(); + $connect = $result->goodsConnect()->select()->toArray(); + if (!empty($connect)) { + foreach ($connect as $item) { + $res = $this->where('status',0)->find($item['connect_good_id']); + if ($item['connect_good_id'] != 0 && $item['connect_good_id'] != '' && $res) { + $tmp = $this->where('status',0)->find($item['connect_good_id'])->toArray(); + $tmp['main_img'] = Env::get('QINIU.cdn').$tmp['main_img']; + $connectData[] = array_merge($item,$tmp); + } + } + } + //处理相关下载 + $relate = $result->GoodsSoftManual()->select()->toArray(); + $newRelate = []; + foreach ($relate as $item) { + $soft = SoftManual::where('status',0)->find($item['soft_manual_id']); + if ($soft) { + $btn = SoftManualBtn::where('soft_manual_id',$item['soft_manual_id'])->select()->toArray(); + $soft = $soft->toArray(); + $soft['btn'] = $btn; + $newRelate[] = array_merge($soft,[]); + } + } + + if (!empty($newRelate)) { + foreach ($newRelate as $key => $item) { + $newRelate[$key]['image'] = Env::get('QINIU.cdn').$item['image']; + foreach ($item['btn'] as $item1) { + $tmp = [ + 'url' => Env::get('QINIU.cdn').$item1['url'], + 'name' => $item1['file_name'] + ]; + $arr[$item1['btn_tips']][] = array_merge($tmp,[]); + } + unset($newRelate[$key]['btn']); + $newRelate[$key]['getSoftBtn'] = $arr; + $arr = []; + } + } + //处理图片 + $result['main_img'] = Env::get('QINIU.cdn').$result['main_img']; +// $img[0] = ['image'=>$result['main_img']]; + foreach ($images as $item) { + $img[] = ['image'=>Env::get('QINIU.cdn').$item['image']]; + } + // + $categoryName = GoodsCategory::find($result['goods_category_id']); + $result['category_name'] = $categoryName['name']; + //buynow + $result['buy_now'] = $result->goodsBuyNow()->select()->toArray(); + $result['goods_attribute'] = $attr; + $result['relate_download'] = $newRelate; + $result['images'] = empty($img) ? [['image'=>$result['main_img']]] : $img; + $result['connect'] = empty($connectData) ? [] : $connectData; + + return $result->toArray(); + } else { + return []; + } + } + +} \ No newline at end of file diff --git a/app/index/model/GoodsCategory.php b/app/index/model/GoodsCategory.php new file mode 100644 index 0000000..9211bc0 --- /dev/null +++ b/app/index/model/GoodsCategory.php @@ -0,0 +1,27 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'name' =>'int', + 'desc' =>'int', + 'pid' =>'int', + 'icon' =>'int', + 'sort' =>'int', + 'status' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/Index.php b/app/index/model/Index.php new file mode 100644 index 0000000..5867f97 --- /dev/null +++ b/app/index/model/Index.php @@ -0,0 +1,137 @@ + $languageId, + 'advertise_space_id' => 1 + ]; + return $this->where($where)->select()->toArray(); + } + + /** + * 首页banner + * @param $data + * @param $languageId + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getIndexBannerMobile($languageId,$data):array + { + $where = [ + 'site_id' => $languageId, + 'advertise_space_id' => 9 + ]; + return $this->where($where)->select()->toArray(); + } + + /** + * 获取首页品牌矩阵 + * @param $data + * @param $languageId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getIndexGoodsCategoryList($languageId,$data):array + { + $where = [ + 'site_id' => $languageId, + 'status' => 0, + 'pid' => 0 + ]; + return GoodsCategory::where($where)->order('sort','desc')->select()->toArray(); + } + + /** + * @param $languageId + * @param $inputData + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getIndexGoodsRecommandList($languageId,$inputData):array + { + $where = [ + 'site_id' => $languageId, + 'status' => 0, + 'is_recommend' => 0 + ]; + $isNew = SystemConfig::where('pos','index')->where('name','is_new_num')->find()->toArray(); + return Goods::where($where)->order('sort','desc')->page(0)->limit((int)$isNew['value'])->select()->toArray(); + } + + + /** + * @param $languageId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getGoodsBanner($languageId):array + { + $where = [ + 'site_id' => $languageId, + ]; + $newData = SystemConfig::field('name,pos,value,image,type')->where($where)->where('pos','index_goods')->column('pos,value,image,type','name'); + $ret = [ + 'goods_one' => [ + 'value' => '', + 'image' => '' + ], + 'goods_two' => [ + 'value' => '', + 'image' => '' + ], + 'goods_three' => [ + 'value' => '', + 'image' => '' + ], + 'goods_four' => [ + 'value' => '', + 'image' => '' + ], + ]; + if (!empty($newData)) { + foreach ($newData as $key => $value) { + if ($value['image']) { + $images = json_decode($value['image'],true); + $newData[$key]['value'] = $value['value']??''; + $newData[$key]['image'] = $images[0]['image']??''; + } else { + $newData[$key]['value'] = ''; + $newData[$key]['image'] = ''; + } + } + return $newData; + } else { + return $ret; + } + + } + +} diff --git a/app/index/model/Join.php b/app/index/model/Join.php new file mode 100644 index 0000000..64233e9 --- /dev/null +++ b/app/index/model/Join.php @@ -0,0 +1,69 @@ + $languageId, + 'status' => 0, + ]; + if (isset($data['join_type_id']) && $data['join_type_id'] != 0) { + $where['join_type_id'] = $data['join_type_id']; + } + return $this->where($where)->order('sort','desc')->select()->toArray(); + } + + /** + * 获取品牌矩阵分类 + * @param $languageId + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getJoinTypeList($languageId,$data):array + { + $result = JoinType::where('site_id',$languageId)->select()->toArray(); + if (!empty($result)) { + foreach ($result as $key => $item) { + $result[$key]['is_display'] = !empty($data) ? isset($data['join_type_id']) && $data['join_type_id'] == $item['id'] : $item['id'] == 0; + } + return $result; + } + return []; + } + + /** + * @param $languageId + * @param $data + * @return array|string[] + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getJoinBanner($languageId,$data):array + { + $space = AdvertiseSpace::where('name',$data)->select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } +} diff --git a/app/index/model/JoinType.php b/app/index/model/JoinType.php new file mode 100644 index 0000000..4fb0cca --- /dev/null +++ b/app/index/model/JoinType.php @@ -0,0 +1,24 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/Language.php b/app/index/model/Language.php new file mode 100644 index 0000000..87311be --- /dev/null +++ b/app/index/model/Language.php @@ -0,0 +1,41 @@ + 'int', + 'name' => 'string', + 'code' => 'string', + 'icon' => 'string', + 'locale' => 'string', + 'coin' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList($data,$simple = null,$focus = null,$sort = null) + { + $lang = Site::where('platform_id',$data['platform_id'])->column('language_id'); + return $this->order($sort)->where('id','in',$lang)->select()->toArray(); + } +} diff --git a/app/index/model/Navigator.php b/app/index/model/Navigator.php new file mode 100644 index 0000000..84d9778 --- /dev/null +++ b/app/index/model/Navigator.php @@ -0,0 +1,83 @@ + 'int', + 'platform_id' => 'int', + 'site_id' => 'int', + 'language_id' => 'int', + 'pid' => 'int', + 'name' => 'string', + 'desc' => 'string', + 'icon' => 'string', + 'link' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'is_top' => 'int', + 'is_foot' => 'int', + 'create_time' => 'int', + 'update_time' => 'int' + ]; + + /** + * 获取首页导航菜单 + * @param $language_id + * @param $platform_id + * @param $controller + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getNavInfo($language_id,$platform_id,$controller):array + { + $result = $this->where(function($query) use ($language_id,$platform_id) { + $query->where('is_top',0)->where('status',0)->where('platform_id',$platform_id); + })->order('sort','desc')->select()->toArray(); + + if (!empty($result)) { + foreach ($result as $key => $item) { + if (isset($controller) && $controller != '') { + $url = explode('/',$item['url']); + if (count($url) <= 2 && $controller == 'Index') { + $result[$key]['is_show'] = true; + } else { + if (count($url) > 2) { + if ($url[2] == Str::snake($controller)) { + $result[$key]['is_show'] = true; + } else { + $result[$key]['is_show'] = false; + } + } else { + $result[$key]['is_show'] = false; + } + } + } + } + } + return $result; + } + + /** + * 获取首页导航菜单 + * @param $language_id + * @param $platform_id + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFootNavInfo($language_id,$platform_id):array + { + return $this->where(function($query) use ($language_id,$platform_id) { + $query->where('is_foot',0)->where('status',0)->where('platform_id',$platform_id); + })->order('sort','desc')->select()->toArray(); + } +} diff --git a/app/index/model/News.php b/app/index/model/News.php new file mode 100644 index 0000000..93da9f7 --- /dev/null +++ b/app/index/model/News.php @@ -0,0 +1,105 @@ + $languageId, + 'status' => 0, + ]; + if (isset($data['news_type_id']) && $data['news_type_id'] != 0) { + $where['news_type_id'] = $data['news_type_id']; + } + + $listRow = [ + 'query' => isset($data['news_type_id']) ? ['news_type_id'=>$data['news_type_id']??0] : [], //url额外参数 + 'fragment' => '', //url锚点 + 'var_page' => 'page', //分页变量 + 'list_rows' => $data['size']??6, //每页数量 + ]; + return $this->where($where)->order('create_time','desc')->paginate($listRow); + } + + /** + * 获取品牌矩阵分类 + * @param $languageId + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getNewsTypeList($languageId,$data):array + { + $result = NewsType::where('site_id',$languageId)->select()->toArray(); + if (!empty($result)) { + $arr[] = [ + 'id' => 0, + 'name' => '全部新闻', + ]; + $result = array_merge($arr,$result); + foreach ($result as $key => $item) { + $result[$key]['is_display'] = !empty($data) ? isset($data['news_type_id']) && $data['news_type_id'] == $item['id'] : $item['id'] == 0; + } + return $result; + } + return []; + } + + + /** + * @param $languageId + * @param $data + * @return array|string[] + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getNewsBanner($languageId,$data):array + { + $space = AdvertiseSpace::where('name',$data)->select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } + + /** + * 获取上一篇,下一篇 + */ + public function getPreNexInfo($data) + { + if (isset($data['id'])) { + $info = $this->find($data['id'])->toArray(); + // 下一条 + $next = $this->field(['id','title'])->where('news_type_id',$info['news_type_id'])->where('id','>',$data['id'])->limit(1)->select()->toArray(); + // 上一条 + $pre = $this->field(['id','title'])->where('news_type_id',$info['news_type_id'])->where('id','<',$data['id'])->limit(1)->select()->toArray(); + + return [ + 'pre' => empty($pre) ? [] : $pre[0], + 'next' => empty($next) ? [] : $next[0] + ]; + } + return []; + } +} diff --git a/app/index/model/NewsType.php b/app/index/model/NewsType.php new file mode 100644 index 0000000..9b726f7 --- /dev/null +++ b/app/index/model/NewsType.php @@ -0,0 +1,26 @@ +'int', + 'platform_id' =>'int', + 'site_id' =>'int', + 'name' =>'string', + 'desc' =>'string', + 'icon' =>'string', + 'sort' =>'int', + 'create_time' =>'int', + 'update_time' =>'int', + ]; + + +} diff --git a/app/index/model/Platform.php b/app/index/model/Platform.php new file mode 100644 index 0000000..593aa5e --- /dev/null +++ b/app/index/model/Platform.php @@ -0,0 +1,40 @@ + 'int', + 'vi_color1' => 'string', + 'vi_color2' => 'string', + 'vi_color3' => 'string', + 'language_id' => 'int', + 'coin_id' => 'int', + 'name' => 'string', + 'desc' => 'string', + 'icon' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + /** + * @param string $platformName + * @return int + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getPlatformId(string $platformName):int + { + $result = $this->where('name',$platformName)->find(); + return $result ? $result->id : 0; + } +} diff --git a/app/index/model/Product.php b/app/index/model/Product.php new file mode 100644 index 0000000..1c50d5e --- /dev/null +++ b/app/index/model/Product.php @@ -0,0 +1,27 @@ +select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } +} diff --git a/app/index/model/ReCenter.php b/app/index/model/ReCenter.php new file mode 100644 index 0000000..48cb750 --- /dev/null +++ b/app/index/model/ReCenter.php @@ -0,0 +1,64 @@ +select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } + + /** + * @param $languageId + * @param $data + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getResourceList($languageId,$data):array + { + return $this->where('site_id',$languageId)->where('status',0)->order('sort','desc')->select()->toArray(); + } + + + /** + * 获取上一篇,下一篇 + */ + public function getPreNexInfo($data) + { + if (isset($data['id'])) { + // 下一条 + $next = $this->field(['id','title'])->where('id','>',$data['id'])->limit(1)->select()->toArray(); + // 上一条 + $pre = $this->field(['id','title'])->where('id','<',$data['id'])->limit(1)->select()->toArray(); + + return [ + 'pre' => empty($pre) ? [] : $pre[0], + 'next' => empty($next) ? [] : $next[0] + ]; + } + return []; + } + +} diff --git a/app/index/model/Site.php b/app/index/model/Site.php new file mode 100644 index 0000000..af7ebb3 --- /dev/null +++ b/app/index/model/Site.php @@ -0,0 +1,20 @@ +where('platform_id',$platformId)->column(['domain','language_id']); + } +} diff --git a/app/index/model/SoftManual.php b/app/index/model/SoftManual.php new file mode 100644 index 0000000..f929938 --- /dev/null +++ b/app/index/model/SoftManual.php @@ -0,0 +1,126 @@ + 'int', + 'platform_id' => 'int', + 'site_id' => 'int', + 'language_id' => 'int', + 'file_type_id' => 'int', + 'name' => 'string', + 'introduce' => 'string', + 'support' => 'string', + 'os' => 'string', + 'download_count'=> 'int', + 'status' => 'int', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + + public function getSoftBtn() + { + return $this->hasMany(SoftManualBtn::class); + } + + /** + * 获取列表 + * @param array $data 查询条件 + * @param mixed $simple 模糊搜索条件 + * @param mixed $focus 精准搜索条件 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAllList($data,$simple = null,$focus = null,$sort = null) + { + $fields = array_keys($this->schema); + $collection = $this->where(function ($query) use ($data,$fields,$simple,$focus) { + //模糊查询条件 + if (!empty($simple)) { + foreach ($simple as $key => $item) { + if (in_array($key,$fields)) { + $query->whereOr($key,'like',"%".$item."%"); + } + } + } + //精准查询 + if (!empty($focus)) { + foreach ($focus as $key => $item) { + if (in_array($key,$fields)) { + $query->where($key,$item); + } + } + } + }); + + + +// $listRow = [ +// 'query' => 'index/download/index', //url额外参数 +// 'fragment' => '', //url锚点 +// 'var_page' => 'page', //分页变量 +// 'list_rows' => $data['size']??4, //每页数量 +// ]; +// return $collection->order($sort)->with('getSoftBtn')->paginate($listRow); + + + $arr = []; + if (isset($data['page']) && isset($data['size'])) { + $count = $collection->count() ?: 0; + $page = $collection->limit($data['size'])->page($data['page'])->order($sort)->with('getSoftBtn')->select()->toArray(); +// if (!empty($page)) { +// foreach ($page as $key => $item) { +// $page[$key]['image'] = Env::get('QINIU.cdn').$item['image']; +// foreach ($item['getSoftBtn'] as $item1) { +// $tmp = [ +// 'url' => Env::get('QINIU.cdn').$item1['url'], +// 'name' => $item1['file_name'] +// ]; +// $arr[$item1['btn_tips']][] = array_merge($tmp,[]); +// } +// $page[$key]['getSoftBtn'] = $arr; +// $arr = []; +// } +// } + return ['page'=>$page,'count'=>$count]; + } else { + $resData = $collection->order($sort)->with('getSoftBtn')->select()->toArray(); +// dump($resData); +// if (!empty($resData)) { +// foreach ($resData as $key => $item) { +// $resData[$key]['image'] = Env::get('QINIU.cdn').$item['image']; +// $tmp = []; +// foreach ($item['getSoftBtn'] as $item1) { +// $tmp = [ +// 'url' => Env::get('QINIU.cdn').$item1['url'], +// 'name' => $item1['file_name'] +// ]; +// $arr[$item1['btn_tips']][] = array_merge($tmp,[]); +// } +// $resData[$key]['getSoftBtn'] = $arr; +// } +// } +// dump($this->getLastSql()); + return $resData; + } + } + + + /** + * 获取分类 + */ + public function getDownloadType() + { + return FileType::select()->toArray(); + } +} diff --git a/app/index/model/SoftManualBtn.php b/app/index/model/SoftManualBtn.php new file mode 100644 index 0000000..6d864bc --- /dev/null +++ b/app/index/model/SoftManualBtn.php @@ -0,0 +1,19 @@ + 'int', + 'soft_manual_id'=> 'int', + 'btn_tips' => 'string', + 'url' => 'string', + 'file_name' => 'string', + 'create_time' => 'int', + 'update_time' => 'int', + ]; + +} diff --git a/app/index/model/SystemConfig.php b/app/index/model/SystemConfig.php new file mode 100644 index 0000000..a860522 --- /dev/null +++ b/app/index/model/SystemConfig.php @@ -0,0 +1,78 @@ +'int', + 'platform_id' =>'int', + 'language_id' =>'int', + 'site_id' =>'int', + 'type' =>'int', + 'page' =>'string', + 'pos' =>'string', + 'name' =>'string', + 'value' =>'string', + 'image' =>'string', + 'create_time' =>'int', + 'update_time' =>'int' + ]; + + + /** + * 获取尾部信息 + * @param $languageId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getFooterInfo($languageId):array + { + $result = $this->field(['name','value','image'])->where(['site_id'=>$languageId,'pos'=>'footer'])->select()->toArray(); + if (!empty($result)) { + $newData = []; + foreach ($result as $value) { + if ($value['image']) { + $images = json_decode($value['image'],true); + $newData[$value['name']]['value'] = $value['value'] != '' ? $value['value'] : $images[0]['image']; + } else { + $newData[$value['name']]['value'] = ''; + } + } + return $newData; + } + return []; + } + /** + * 获取尾部信息 + * @param $languageId + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getWebSiteInfo($languageId):array + { + $result = $this->field(['name','value','image'])->where(['site_id'=>$languageId,'pos'=>'index'])->select()->toArray(); + if (!empty($result)) { + $newData = []; + foreach ($result as $value) { + if ($value['image']) { + $images = json_decode($value['image'],true); + $newData[$value['name']]['value'] = $value['value'] != '' ? $value['value'] : $images[0]['image']; + } else { + $newData[$value['name']]['value'] = ''; + } + } + return $newData; + } + return []; + } +} \ No newline at end of file diff --git a/app/index/model/Test.php b/app/index/model/Test.php new file mode 100644 index 0000000..2581d00 --- /dev/null +++ b/app/index/model/Test.php @@ -0,0 +1,28 @@ +select()->toArray(); + if (!empty($space)) { + return $this->getBanner($languageId,$space[0]['id']); + } + return ['image' => '']; + } +} diff --git a/app/index/route/v1.php b/app/index/route/v1.php new file mode 100644 index 0000000..0b7ca80 --- /dev/null +++ b/app/index/route/v1.php @@ -0,0 +1,67 @@ +prefix('\\app\\index\\controller\\')->middleware([ + app\index\middleware\Auth::class +]); \ No newline at end of file diff --git a/app/index/validate/About.php b/app/index/validate/About.php new file mode 100644 index 0000000..391defa --- /dev/null +++ b/app/index/validate/About.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Brand.php b/app/index/validate/Brand.php new file mode 100644 index 0000000..b283929 --- /dev/null +++ b/app/index/validate/Brand.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Common.php b/app/index/validate/Common.php new file mode 100644 index 0000000..d822401 --- /dev/null +++ b/app/index/validate/Common.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Concept.php b/app/index/validate/Concept.php new file mode 100644 index 0000000..f93ba98 --- /dev/null +++ b/app/index/validate/Concept.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Contact.php b/app/index/validate/Contact.php new file mode 100644 index 0000000..f69840a --- /dev/null +++ b/app/index/validate/Contact.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Join.php b/app/index/validate/Join.php new file mode 100644 index 0000000..601ea1b --- /dev/null +++ b/app/index/validate/Join.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/News.php b/app/index/validate/News.php new file mode 100644 index 0000000..fc13a48 --- /dev/null +++ b/app/index/validate/News.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/Product.php b/app/index/validate/Product.php new file mode 100644 index 0000000..b85f89f --- /dev/null +++ b/app/index/validate/Product.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/ReCenter.php b/app/index/validate/ReCenter.php new file mode 100644 index 0000000..b06d19d --- /dev/null +++ b/app/index/validate/ReCenter.php @@ -0,0 +1,25 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = []; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; +} diff --git a/app/index/validate/SoftManual.php b/app/index/validate/SoftManual.php new file mode 100644 index 0000000..f53b341 --- /dev/null +++ b/app/index/validate/SoftManual.php @@ -0,0 +1,41 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => ['require','integer','gt:0'], + 'page' => ['integer','gt:0'], + 'size' => ['integer','gt:0'], + 'site_id' => ['integer','gt:0'], + 'file_type_id' => ['integer','gt:0'], + 'name' => ['length:1,40'], + 'introduce' => ['length:1,255'], + 'support' => ['length:1,255'], + 'os' => ['length:1,60'], + 'download_count'=> ['integer','gt:0'], + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = []; + + protected $scene = [ + 'index' => ['page','size','name'], + 'read' => ['id'], + ]; +} diff --git a/app/index/view/zh-cn/about/about_us.html b/app/index/view/zh-cn/about/about_us.html new file mode 100644 index 0000000..9a805a1 --- /dev/null +++ b/app/index/view/zh-cn/about/about_us.html @@ -0,0 +1,531 @@ +{include file='zh-cn/common/header' title='关于我们' keywords='关于我们' +description='关于我们'} {include file='zh-cn/common/nav' } + + + + +
+
+
+
+
+ Product +
+
+
+
+

+ 品牌简介 +
Brand Profile
+

+

+ 牛顿定律(NTONPOWER)是深圳市元创时代科技有限公司旗下的全球化科技品牌,成立于2015年,专注于智能充电领域的技术创新。公司以严谨的科学方法和系统性研究为导向,致力于在消费电子充电领域提供创新的技术解决方案。 +

+
+
+
+
+
+
+
+
+

+ 品牌使命 +
Brand Interpretation
+

+

+ 让生活电力十足。Power Up Your Life.
+ 以科学家严谨求真的精神和创新探索的态度,用智能充电科技释放生活的无限可能。
+ ● 安全:智能防护,守护充电瞬间
+ ● 实用:精准设计,满足多元场景
+ ● 创新:突破技术边界,简化使用体验 +

+
+
+
+
+ Product +
+
+
+
+
+
+
品牌里程
+
+
+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+
+
    +
    +

    创立初期(2015-2017年)

    +
  • +

    + 2015年,牛顿定律(NTONPOWER)成立,专注于智能生活充电产品(如:插线板、充电头)。 +

    +
  • +
    +
    +

    快速发展期(2018-2021年)

    +
  • +

    + 专注智能充电生态,创新覆盖多元应用场景。海外线上销售稳居行业前十,业务覆盖全球30多个国家   ,引领行业创新发展。 +

    +
  • +
    +
    +

    2022

    +
  • +

    + 拓展国内线上电商渠道,加强本土市场品牌认知度。 +

    +
  • +
    + +
    +

    2023

    +
  • +

    + 插线板全球销量1000万台。 +

    +
  • +
    +
    +

    2024

    +
  • +

    + 用户规模突破海内外用户3500万+、全球社交媒体粉丝60万+。 +

    +
  • +
    +
    +

    2025

    +
  • +

    + 全面进军新消费平台、锂电池和充电宝赛道,构建便携能源生态系统。 +

    +
  • +
    +
+
+
+
+
+
+
+
+
+
所获荣誉
+
+
+ +
+

旅行便携类 海外TOP 10

+
+
+
+ +
+
+
+
+ +
+

斩获红点奖、缪斯设计奖

+
+
+
+ +
+
+
+
+
+ + +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/index/view/zh-cn/about/mileage.html b/app/index/view/zh-cn/about/mileage.html new file mode 100644 index 0000000..826e253 --- /dev/null +++ b/app/index/view/zh-cn/about/mileage.html @@ -0,0 +1,453 @@ +{include file='zh-cn/common/header' title='关于我们' keywords='关于我们' +description='关于我们'} {include file='zh-cn/common/nav' } + + + + +
+ +
+
+
品牌里程
+
+
+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+
+
    +
    +

    创立初期(2015-2017年)

    +
  • +

    + 2015年,牛顿定律(NTONPOWER)成立,专注于智能生活充电产品(如:插线板、充电头)。 +

    +
  • +
    +
    +

    快速发展期(2018-2021年)

    +
  • +

    + 专注智能充电生态,创新覆盖多元应用场景。海外线上销售稳居行业前十,业务覆盖全球30多个国家   ,引领行业创新发展。 +

    +
  • +
    +
    +

    2022

    +
  • +

    + 拓展国内线上电商渠道,加强本土市场品牌认知度。 +

    +
  • +
    + +
    +

    2023

    +
  • +

    + 插线板全球销量1000万台。 +

    +
  • +
    +
    +

    2024

    +
  • +

    + 用户规模突破海内外用户3500万+、全球社交媒体粉丝60万+。 +

    +
  • +
    +
    +

    2025

    +
  • +

    + 全面进军新消费平台、锂电池和充电宝赛道,构建便携能源生态系统。 +

    +
  • +
    +
+
+
+
+
+
+
+
+ + +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/index/view/zh-cn/about/test.html b/app/index/view/zh-cn/about/test.html new file mode 100644 index 0000000..f153f41 --- /dev/null +++ b/app/index/view/zh-cn/about/test.html @@ -0,0 +1,311 @@ +{include file='zh-cn/common/header' title='关于我们' keywords='关于我们' +description='关于我们'} {include file='zh-cn/common/nav' } + + + + +
+
+
+
+
+ Product +
+
+
+
+

+ 品牌简介 +
Brand Profile
+

+

+ 牛顿定律(NTONPOWER)是深圳市元创时代科技有限公司旗下的全球化科技品牌,成立于2015年,专注于智能充电领域的技术创新。公司以严谨的科学方法和系统性研究为导向,致力于在消费电子充电领域提供创新的技术解决方案。 +

+
+
+
+
+
+
+
+
+

+ 品牌使命 +
Brand Interpretation
+

+

+ 让生活电力十足。Power Up Your Life.
+ 以科学家严谨求真的精神和创新探索的态度,用智能充电科技释放生活的无限可能。
+ ● 安全:智能防护,守护充电瞬间
+ ● 实用:精准设计,满足多元场景
+ ● 创新:突破技术边界,简化使用体验 +

+
+
+
+
+ Product +
+
+
+
+
+
+
品牌活动
+
+
+ +
+

旅行便携类 海外TOP 10

+
+
+
+ +
+
+
+
+ +
+

斩获红点奖、缪斯设计奖

+
+
+
+ +
+
+
+
+
+{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/index/view/zh-cn/common/footer.html b/app/index/view/zh-cn/common/footer.html new file mode 100644 index 0000000..08010ef --- /dev/null +++ b/app/index/view/zh-cn/common/footer.html @@ -0,0 +1,65 @@ + + diff --git a/app/index/view/zh-cn/common/header.html b/app/index/view/zh-cn/common/header.html new file mode 100644 index 0000000..8bd52a7 --- /dev/null +++ b/app/index/view/zh-cn/common/header.html @@ -0,0 +1,22 @@ + + + + + + + {$meta['meta_title']??''} + + + + {if false == $is_dev} + + {/if} + + + + + + + + + diff --git a/app/index/view/zh-cn/common/nav.html b/app/index/view/zh-cn/common/nav.html new file mode 100644 index 0000000..f51244f --- /dev/null +++ b/app/index/view/zh-cn/common/nav.html @@ -0,0 +1,146 @@ + +
+ +
+ + +
+ +
+
+
    +
  • + 中文 + +
  • + {foreach $nav_info as $item} +
  • + {$item.name} + {if isset($item['children'])} + + {/if} +
  • + {/foreach} +
+
+ + +
+ + + + +
+
+
+ + + + + diff --git a/app/index/view/zh-cn/common/script.html b/app/index/view/zh-cn/common/script.html new file mode 100644 index 0000000..2eab237 --- /dev/null +++ b/app/index/view/zh-cn/common/script.html @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/index/view/zh-cn/contact/contact.html b/app/index/view/zh-cn/contact/contact.html new file mode 100644 index 0000000..50148dc --- /dev/null +++ b/app/index/view/zh-cn/contact/contact.html @@ -0,0 +1,31 @@ +{include file='zh-cn/common/header' title='联系我们' keywords='联系我们' description='联系我们'} {include file='zh-cn/common/nav'} + + + +
+
+
+
+
+
+
+
+
+
400-6696-298
+ 全国统一服务热线 +

周一至周五:上午9:00 —下午6:00

+
+
+
+
+
+
+
+
+ +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script'} diff --git a/app/index/view/zh-cn/download/download.html b/app/index/view/zh-cn/download/download.html new file mode 100644 index 0000000..61603c9 --- /dev/null +++ b/app/index/view/zh-cn/download/download.html @@ -0,0 +1,93 @@ +{include file='zh-cn/common/header' title='服务与支持' keywords='服务与支持' description='服务与支持'} {include file='zh-cn/common/nav' } + + + +
+
+
+ +
+
+
+ {if count($resource.list) > 0} {foreach $resource.list as $list} +
+
+
+
+
+ Product +
+
+
+
+
+
+
{$list.name}
+ {$list.introduce | raw} +
+
+ 适合型号: +

{$list.support}

+ 支持系统: +

{$list.os}

+
+ + {$list.getSoftBtn.0.btn_tips} + +
+
+
+
+ {/foreach} {/if} +
+
+
+
+
+
+ +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/index/view/zh-cn/goods/detail.html b/app/index/view/zh-cn/goods/detail.html new file mode 100644 index 0000000..95cfc10 --- /dev/null +++ b/app/index/view/zh-cn/goods/detail.html @@ -0,0 +1,90 @@ +{include file='zh-cn/common/header' title='商品详情' keywords='商品详情' description='商品详情'} {include file='zh-cn/common/nav' } + + +
+
+
+ + + +
+
+
+ +
+
+
+
+ +
+
+ {foreach $resource.goodsInfo.images as $img} +
+ +
+ {/foreach} +
+
+
+
+ {foreach $resource.goodsInfo.images as $img} +
+ +
+ {/foreach} +
+
+
+
+
+

{$resource.goodsInfo.name}

+

{$resource.goodsInfo.description}

+
+
+
    +
  • 型号:{$resource.goodsInfo.model_number}
  • +
  • 类型:{$resource.goodsInfo.category_name}
  • +
+
+
+
+
+
+
+ +
+
+
+ +
+
+
{$resource.goodsInfo.details | raw}
+
+
+
+
+ {if count($resource.goodsInfo.goods_attribute) > 0} {foreach $resource.goodsInfo.goods_attribute as $attr} +
+
    +
  • {$attr.attribute_name}{$attr.value}
  • +
+
+ {/foreach} {/if} +
+
+
+
+
+
+
+ +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script'} diff --git a/app/index/view/zh-cn/goods/list.html b/app/index/view/zh-cn/goods/list.html new file mode 100644 index 0000000..a1ac1c3 --- /dev/null +++ b/app/index/view/zh-cn/goods/list.html @@ -0,0 +1,144 @@ +{include file='zh-cn/common/header' title='商品列表' keywords='商品列表' description='商品列表'} {include file='zh-cn/common/nav' } +
+
+ +
+
+
一级分类
+
+ {foreach $resource.category as $cate} + {$cate.name} + {/foreach} +
+
+
+
二级分类
+
+ {if !empty($resource.category_two)} {foreach $resource.category_two as $cate2} + {$cate2.name} + {/foreach} {else} + + {/if} +
+
+
+
三级分类
+
+ {if !empty($resource.category_three)} {foreach $resource.category_three as $cate3} + {$cate3.name} + {/foreach} {else} + + {/if} +
+
+
+
+
+
+ 全部 + 推荐 + 热门 + 最新 +
+
+
+
+
+ +
+
+
+
+
+
+
+ {if count($resource.list.data) > 0} {foreach $resource.list.data as $goods} +
+ +
+
+ Product +
+
+
{$goods.name}
+ {$goods.model_number} +
+ +
+
+ {/foreach} {else} +
+
+ +

暂无商品

+
+
+ {/if} +
+
+
+
+ +
+
{$resource.page | raw}
+
+ +
+ +
+
+ +{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/index/view/zh-cn/index/index.html b/app/index/view/zh-cn/index/index.html new file mode 100644 index 0000000..2d946fe --- /dev/null +++ b/app/index/view/zh-cn/index/index.html @@ -0,0 +1,112 @@ +{include file='zh-cn/common/header' title='首页' keywords='首页' description='首页'} {include file='zh-cn/common/nav' } + +
+ {foreach $banner_list as $item} +
+ {/foreach} +
+ + +
+
+
+
    + {foreach $nav_info as $item} {if isset($item.children)} {if $item.id === 1} {foreach $item.children as $it1} +
  • + +

    {$it1.name}

    +
    +
  • + {/foreach} {/if} {/if} {/foreach} +
+
+ + +
+ + + + +
+
+
+ +
+
+ +
+

SETMSPACE

+

+ {$f_image['goods_four']['value']??"" | raw } +

+
+
+
+ +
+
+
+
+
+
+

新品推荐

+
+ +
+
+ {foreach $goods_is_new as $good} +
+ +
+
+ Product +
+
+
{$good.name}
+ {$good.model_number} +
+ + + +
+
+ {/foreach} +
+
+ +
+
+
+
+
+{include file='zh-cn/common/footer'} {include file='zh-cn/common/script' } diff --git a/app/library/KafkaClient.php b/app/library/KafkaClient.php new file mode 100644 index 0000000..d1a67e2 --- /dev/null +++ b/app/library/KafkaClient.php @@ -0,0 +1,151 @@ +kafkaProducerConfig = [ + 'username' => 'orico', + 'password' => 'password',/**/ + 'broker_list' => '127.0.0.1:9092',/*如果有多个,ip:port,ip2:port,ip3:port*/ + 'topic' => 'topics' + ]; + } + + /** + * 初始化kafka消费配置 + * @return string[] + */ + private function initKafkaConsumerConfig() :array + { + return $this->kafkaConsumerConfig = [ + 'username' => 'orico', + 'password' => 'password',/**/ + 'brokerlist' => '127.0.0.1:9092',/*如果有多个,ip:port,ip2:port,ip3:port*/ + 'topic' => 'topics' + ]; + } + + /** + * kafka 生产者核心方法 + * @param array $config kafka 配置参数 + * @param array $data 需要生产的数据 + */ + public function kafkaProducer(array $config, array $data) + { + if (empty($this->kafkaProducerConfig)) { + $this->initKafkaProducerConfig(); + } + $conf = new \RdKafka\Conf(); + $conf->set('sasl.mechanisms', 'PLAIN'); + $conf->set('security.protocol', 'SASL_PLAINTEXT'); + $conf->set('sasl.username', $config['username']); + $conf->set('sasl.password', $config['password']); + $conf->set('socket.keepalive.enable', 'true'); // socket不操作保持长连 + $conf->set('log.connection.close', 'false'); // 静默所有自发断开连接日志 + $conf->set('metadata.broker.list', $config['broker_list']); + + $producer = new \RdKafka\Producer($conf); + + $topic = $producer->newTopic($this->topicProduce); + + for ($i = 0; $i < 10; $i++) { + $topic->produce(RD_KAFKA_PARTITION_UA, 0,$data); + $producer->poll(0); + } + + for ($flushRetries = 0; $flushRetries < 10; $flushRetries++) { + $result = $producer->flush(10000); + if (RD_KAFKA_RESP_ERR_NO_ERROR === $result) { + break; + } + } + + if (RD_KAFKA_RESP_ERR_NO_ERROR !== $result) { + throw new \RuntimeException('Was unable to flush, messages might be lost!'); + } + + } + + + /** + * kafka 消息者核心方法 + * @param array $config kafka 配置参数 + * @param array $data 需要生产的数据 + */ + public function kafkaConsumer(array $config, array $data) + { + if (empty($this->kafkaConsumerConfig)) { + $this->initKafkaConsumerConfig(); + } + return ($this->kafkaConfig()); + } + + /** + * curl请求 + * @param $url string 请求的url链接 + * @param $data string|array|mixed 请求的数据 + * @param bool $is_post 是否是post请求,默认false + * @param array $options 是否附带请求头 + * @return array|mixed + */ + private function http(string $url, array $data, bool $is_post=false, array $options=[]):array + { + $data = json_encode($data); + $headerArray = [ + 'Content-type: application/json;charset=utf-8', + 'Accept: application/json' + ]; + $curl = curl_init(); + $arr = []; + array_push($arr,$url); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); + if ($is_post) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + } + curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + if (!empty($options['cookie'])) { + curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']); + } + $output = curl_exec($curl); + $http_status = curl_errno($curl); + $http_msg = curl_error($curl); + curl_close($curl); + if ($http_status == 0) { + return json_decode($output, true); + } else { + return ['status' => $http_status, 'message' => $http_msg, 'data' => []]; + } + } + + + +} \ No newline at end of file diff --git a/app/library/LogToKafka.php b/app/library/LogToKafka.php new file mode 100644 index 0000000..4fde149 --- /dev/null +++ b/app/library/LogToKafka.php @@ -0,0 +1,154 @@ + Env::get('SSO.UC_URL'), + 'apiRoute' => '/journal/v1/kafkaproducer/send', + 'signStr' => 'logsmonitor', + 'secretKey' => 'logsmonitorscretlist', + 'dbName' => 'users' + ]; + } + + /** + * 发送请求,生成到api日志kafka + * @param array $data 请求数据 + * @param string $logType 日志类型 + * @param string $database 操作数据库 + * @param string $dotype 调用接口方式 + * @return bool + */ + public static function sendLogsToKafkaProduce(array $data, string $logType, string $database, string $dotype):bool + { + if (empty(self::$sendLogToKafkaConfig)) { + self::initLogConfig(); + } + $newData = [ + 'action_logs' => "", + 'api_logs' => "", + 'lg_logs_view' => "", + 'lg_task_queue' => "" + ]; + //先构建好数据 + if ($logType != '' && in_array($logType,self::$logType)) { + $newData[$logType] = json_encode($data); + } + //构建数据库 + if ($database) { + $newData['database'] = $database; + } + //构建写入kafka的类型, + if ($dotype != '' && in_array($dotype,self::$methodType)) { + $newData['dotype'] = $dotype; + } + //拿到数据,构建签名 + $newData['sign'] = self::getSign($newData); + //构建请求接口 + $url = self::$sendLogToKafkaConfig['LogsSSOUrl'].self::$sendLogToKafkaConfig['apiRoute']; + $result = self::http($url,$newData,true); + Cache::set('$url',$url,300); + Cache::set('result',$result,300); + if(isset($result['errno']) && $result['errno'] == 0) { + return true; + } + return false; + } + + /** + * 签名 + * @param array $param 用于验证数据完整性 + * @return string + */ + public static function getSign(array $param):string + { + ksort($param); + $signStr = self::$sendLogToKafkaConfig['signStr']; + $secretKey = self::$sendLogToKafkaConfig['secretKey']; + foreach ( $param as $key => $value ) { + $signStr = $signStr . $key . "=" . $value . "&"; + } + $signStr = substr($signStr, 0, -1); + return base64_encode(hash_hmac("sha1", $signStr, $secretKey, true)); + } + + + /** + * curl请求 + * @param $url string 请求的url链接 + * @param $data string|array|mixed 请求的数据 + * @param bool $is_post 是否是post请求,默认false + * @param array $options 是否附带请求头 + * @return array|mixed + */ + private static function http(string $url, array $data, bool $is_post=false, array $options=[]):array + { + $data = json_encode($data); + $headerArray = [ + 'Content-type: application/json;charset=utf-8', + 'Accept: application/json' + ]; + $curl = curl_init(); + $arr = []; + array_push($arr,$url); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); + if ($is_post) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + } + curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + if (!empty($options['cookie'])) { + curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']); + } + $output = curl_exec($curl); + $http_status = curl_errno($curl); + $http_msg = curl_error($curl); + curl_close($curl); + if ($http_status == 0) { + return json_decode($output, true); + } else { + return ['status' => $http_status, 'message' => $http_msg, 'data' => []]; + } + } + +} \ No newline at end of file diff --git a/app/library/SSOApi.php b/app/library/SSOApi.php new file mode 100644 index 0000000..a4cd039 --- /dev/null +++ b/app/library/SSOApi.php @@ -0,0 +1,459 @@ + '/authorize/token',/*获取应用授权接口*/ + 'getDeptList' => '/dept/list',/*部门分页数据*/ + 'getDeptDetail' => '/dept/detail',/*根据ID部门详细*/ + 'getDeptDetailDeptCode' => '/dept/detail/dept_code',/*根据编码部门详细*/ + 'getDeptHead' => '/dept/head',/*根据编码获取部门主管*/ + 'getDeptChainId' => '/dept/chain/id/{id}',/*根据部门ID获取部门上下级*/ + 'getDeptChainCode' => '/dept/chain/code/{code}',/*根据部门编码获取部门上下级*/ + 'getStaffList' => '/staff/list',/*员工分页数据*/ + 'getStaffListDept' => '/staff/list/dept',/*根据部门编码获取员工数据*/ + 'getUserDetailUid' => '/user/detail/uid',/*根据用户ID获取用户详细*/ + 'getUserDetailStaffCode' => '/user/detail/staff_code',/*根据用户(员工)编码获取用户(员工)详情*/ + 'getUserDepts' => '/user/depts',/*根据用户ID获取用户所属部门*/ + 'getUserDeptsStaffCode' => '/user/depts/staff_code',/*根据用户编码获取用户所属部门*/ + 'getUserDetailMobile' => '/user/detail/mobile',/*根据手机号获取用户详细*/ + 'getRoleDetailId' => '/role/detail/id/{id}',/*根据ID获取角色详细*/ + 'getRoleDetailCode' => '/role/detail/code/{code}',/*根据编码获取角色详细*/ + 'getMenuListApp' => '/menu/list/app',/*获取应用的菜单*/ + 'getMenuListUserCode' => '/menu/list/user/{code}',/*获取用户权限菜单*/ + ]; + + /** + * 初始化配置,需要手动去.env文件里面填写以下配置项 + * + * [SSO] + * UC_URL='https://uc.test' + * UC_CACHE_KEY='crm_dev' + * APPID='cfcd05b1f3576e90cf53dc8a3d221ff7' + * APPSECRET='271491c88ef42303da0251034aee3e5c' + * UC_API_VERSION=v1 + * PUB_KEY='-----BEGIN PUBLIC KEY----- + * -----END PUBLIC KEY-----' + * PRI_KEY='-----BEGIN PRIVATE KEY----- + * -----END PRIVATE KEY-----' + * + * UC_URL: 单点域名 + * UC_CACHE_KEY:单点应用 token 缓存key值,用于标识是哪个应用的,比如crm系统,线上使用orico_crm,测试使用 dev_crm, + * APPID : 应用ID + * APPSECRET:应用密钥 + */ + private function initSSOConfig(): array + { + if (Cache::has('app_get_auth') && Cache::get('app_get_auth') == 1) { + return $this->ssoApiConfig = [ + 'appId' => Cache::get('app')['app_id'],/*应用的APPID*/ + 'appSecret' => Cache::get('app')['app_secret'],/*应用密钥*/ + 'ssoApiUrl' => Env::get('SSO.UC_URL'),/*单点请求链接*/ + 'cacheKey' => Cache::get('app')['uc_cache_key'].'_app_token',/*应用token缓存key*/ + 'apiVersion' => '/api/'.Env::get('SSO.UC_API_VERSION')/*接口版本*/ + ]; + } else { + return $this->ssoApiConfig = [ + 'appId' => Session::get('app')['app_id'],/*应用的APPID*/ + 'appSecret' => Session::get('app')['app_secret'],/*应用密钥*/ + 'ssoApiUrl' => Env::get('SSO.UC_URL'),/*单点请求链接*/ + 'cacheKey' => Session::get('app')['uc_cache_key'].'_app_token',/*应用token缓存key*/ + 'apiVersion' => '/api/'.Env::get('SSO.UC_API_VERSION')/*接口版本*/ + ]; + } + + } + + /** + * 生成请求接口 + * @param array $data 请求数据 + * @param string $funcName 请求方法名 + * @param bool $isPost 请求类型,true = post| false = get + * @param array $options 请求头 + * @return array + */ + public function setRequestURI(array $data, string $funcName, bool $isPost = false,array $options = []):array + { +// if (empty($this->ssoApiConfig)) { + $this->initSSOConfig(); +// } + //设置接口token + if (empty($this->appToken) && $funcName != 'getAuthorizeToken') { + $this->getAuthorizeToken(); + } + + $arrToken = []; + if ($funcName != 'getAuthorizeToken') { + $arrToken['access_token'] = $this->appToken['access_token']; + $data['access_token'] = $this->appToken['access_token']; + } + $params = null; + if (false === $isPost) { + //get请求 + if ($funcName == 'getStaffListDept') { + $params = '?' . http_build_query($data); + } else { + $params = '?' . http_build_query($arrToken); + } + } + + //拼接请求链接 + $url = $this->ssoApiConfig['ssoApiUrl'].$this->ssoApiConfig['apiVersion'].$this->apis[$funcName];/*post 请求*/ + + if (!is_null($params)) { + //get 请求 + if (false === strpos($this->apis[$funcName],'{')) { + $url = $this->ssoApiConfig['ssoApiUrl'].$this->ssoApiConfig['apiVersion'].$this->apis[$funcName].$params; + } else { + //解析出参数,restful 接口。 id/{:id} + $arr = explode('/{',$this->apis[$funcName]); + if (2 === count($arr)) { + $param = rtrim($arr[1],'}'); + $newUrl = $arr[0]; + $url = $this->ssoApiConfig['ssoApiUrl'].$this->ssoApiConfig['apiVersion'].$newUrl.DIRECTORY_SEPARATOR.$data[$param].$params; + } + + } + } + //执行请求 + $result = $this->http($url,$data,$isPost,$options); +// \think\facade\Log::record($url); +// \think\facade\Log::record(json_encode($result)); + if (isset($result['status']) && $result['status'] == 200) { + return $result['data']; + } + return []; + } + + /** + * 获取应用token + */ + public function getAuthorizeToken():array + { +// if (empty($this->ssoApiConfig)) { + $this->initSSOConfig(); +// } + $data = [ + 'appid' => $this->ssoApiConfig['appId'], + 'app_secret'=> $this->ssoApiConfig['appSecret'] + ]; + $this->appToken = Cache::get($this->ssoApiConfig['cacheKey']); + if (is_null($this->appToken) || $this->appToken['expires_time'] - time() <= 600) { + $data = $this->setRequestURI($data,__FUNCTION__,true); + if (!empty($data)) { + $data['expires_time'] = time() + $data['expires_in']; + Cache::set($this->ssoApiConfig['cacheKey'], $data, $data['expires_in']-1000); + $this->appToken = $data; + return $data; + } + } + return $this->appToken; + } + + /** + * 部门分页数据 + * @param int $page 页码 + * @param int $size 每页条数 + * @param array $filter 查询条件,{"keywords":"dept_name=欧洲团"} + * @return array + */ + public function getDeptList(int $page = 0,int $size = 0,array $filter = []):array + { + $data = []; + + if ($page != 0) { + $data['page'] = $page; + } + + if ($size != 0) { + $data['size'] = $size; + } + + if (!empty($filter)) { + $data['filter'] = $filter; + } + + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据ID部门详细 + * @param int $deptId 部门ID + * @return array + */ + public function getDeptDetail(int $deptId):array + { + $data = [ + 'id' => $deptId + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据ID部门详细 + * @param string $deptCode 部门dept_code + * @return array + */ + public function getDeptDetailDeptCode(string $deptCode):array + { + $data = [ + 'dept_code' => $deptCode + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据编码获取部门主管 + * @param string $deptCode 部门dept_codes + * @return array + */ + public function getDeptHead(string $deptCode):array + { + $data = [ + 'dept_code' => $deptCode + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 根据部门ID获取部门上下级 + * @param int $deptId 部门ID + * @return array + */ + public function getDeptChainId(int $deptId):array + { + $data = [ + 'id' => $deptId + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 根据部门code获取部门上下级 + * @param string $deptCode 部门dept_code + * @return array + */ + public function getDeptChainCode(string $deptCode):array + { + $data = [ + 'code' => $deptCode + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 员工分页数据 + * @param int $page 页码 + * @param int $size 每页条数 + * @return array + */ + public function getStaffList(int $page = 0,int $size = 0):array + { + $data = []; + + if ($page != 0) { + $data['page'] = $page; + } + + if ($size != 0) { + $data['size'] = $size; + } + + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据部门编码获取员工数据 + * @param string $deptCode 部门dept_code + * @return array + */ + public function getStaffListDept(string $deptCode):array + { + $data = [ + 'dept_code' => $deptCode + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 根据用户ID获取用户详细 + * @param int $uid 部门ID + * @return array + */ + public function getUserDetailUid(int $uid):array + { + $data = [ + 'uid' => $uid + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据用户(员工)编码获取用户(员工)详情 + * @param string $staffCode 员工staff_code + * @return array + */ + public function getUserDetailStaffCode(string $staffCode):array + { + $data = [ + 'staff_code' => $staffCode + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据用户ID获取用户所属部门 + * @param int $uid 部门ID + * @return array + */ + public function getUserDepts(int $uid):array + { + $data = [ + 'uid' => $uid + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据用户编码获取用户所属部门 + * @param string $staffCode 员工staff_code + * @return array + */ + public function getUserDeptsStaffCode(string $staffCode):array + { + $data = [ + 'staff_code' => $staffCode + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据手机号获取用户详细 + * @param string $mobile 手机号 + * @return array + */ + public function getUserDetailMobile(string $mobile):array + { + $data = [ + 'mobile' => $mobile + ]; + return $this->setRequestURI($data,__FUNCTION__,true); + } + + /** + * 根据ID获取角色详细 + * @param int $roleId 角色role_id + * @return array + */ + public function getRoleDetailId(int $roleId):array + { + $data = [ + 'id' => $roleId + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 根据编码获取角色详细 + * @param string $roleCode 角色role_code + * @return array + */ + public function getRoleDetailCode(string $roleCode):array + { + $data = [ + 'code' => $roleCode + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * 获取应用的菜单 + * @return array + */ + public function getMenuListApp():array + { + return $this->setRequestURI([],__FUNCTION__); + } + + /** + * 获取用户权限菜单 + * @param string $staffCode 用户staff_code + * @return array + */ + public function getMenuListUserCode(string $staffCode):array + { + // 是否是用于检测有没有权限 + $this->appToken = []; + + $data = [ + 'code' => $staffCode + ]; + return $this->setRequestURI($data,__FUNCTION__); + } + + /** + * curl请求 + * @param $url string 请求的url链接 + * @param $data string|array|mixed 请求的数据 + * @param bool $is_post 是否是post请求,默认false + * @param array $options 是否附带请求头 + * @return array|mixed + */ + private function http(string $url, array $data, bool $is_post=false, array $options=[]):array + { + $data = json_encode($data); + $headerArray = [ + 'Content-type: application/json;charset=utf-8', + 'Accept: application/json' + ]; + $curl = curl_init(); + $arr = []; + array_push($arr,$url); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); + if ($is_post) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + } + curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + if (!empty($options['cookie'])) { + curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']); + } + $output = curl_exec($curl); + $http_status = curl_errno($curl); + $http_msg = curl_error($curl); + curl_close($curl); + if ($http_status == 0) { + return json_decode($output, true); + } else { + return ['status' => $http_status, 'message' => $http_msg, 'data' => []]; + } + } + +} \ No newline at end of file diff --git a/app/middleware.php b/app/middleware.php new file mode 100644 index 0000000..b6ab063 --- /dev/null +++ b/app/middleware.php @@ -0,0 +1,10 @@ + Request::class, + 'think\exception\Handle' => ExceptionHandle::class, +]; diff --git a/app/service.php b/app/service.php new file mode 100644 index 0000000..db1ee6a --- /dev/null +++ b/app/service.php @@ -0,0 +1,9 @@ +=7.1.0", + "topthink/framework": "^6.0.0", + "topthink/think-orm": "^2.0", + "topthink/think-migration": "^3.0", + "topthink/think-multi-app": "^1.0", + "topthink/think-captcha": "^3.0", + "qiniu/php-sdk": "^7.3", + "phpmailer/phpmailer": "^6.4", + "phpoffice/phpspreadsheet": "^1.17", + "egulias/email-validator": "^3.1", + "fcesky/test": "^1.0", + "geoip2/geoip2": "~2.0", + "matomo/device-detector": "^5.0", + "rosell-dk/webp-convert": "^2.9", + "baiy/think-async": "^1.0", + "topthink/think-view": "^1.0" + }, + "require-dev": { + "symfony/var-dumper": "^4.2", + "topthink/think-trace":"^1.0" + }, + "autoload": { + "psr-4": { + "app\\": "app" + }, + "psr-0": { + "": "extend/" + } + }, + "config": { + "preferred-install": "dist" + }, + "scripts": { + "post-autoload-dump": [ + "@php think service:discover", + "@php think vendor:publish" + ] + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..1eb4be6 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3847 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f699ecd893f3ddbe6c52c701d71001d7", + "packages": [ + { + "name": "baiy/think-async", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/baiy/think-async.git", + "reference": "0b625ac58134ca139d9314c379801f8401ff43bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/baiy/think-async/zipball/0b625ac58134ca139d9314c379801f8401ff43bc", + "reference": "0b625ac58134ca139d9314c379801f8401ff43bc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "topthink/think-queue": "^3.0" + }, + "type": "library", + "extra": { + "think": { + "services": [ + "Baiy\\ThinkAsync\\Service" + ], + "config": { + "async": "src/config.php" + } + } + }, + "autoload": { + "psr-4": { + "Baiy\\ThinkAsync\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "baiy", + "email": "wo@baiy.org" + } + ], + "description": "thinkphp 异步代码执行/异步延迟执行/异步事件订阅", + "homepage": "https://github.com/baiy/think-async", + "support": { + "issues": "https://github.com/baiy/think-async/issues", + "source": "https://github.com/baiy/think-async/tree/1.0.1" + }, + "time": "2021-09-26T07:46:39+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.3.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-10-28T20:44:15+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-02-28T11:07:21+00:00" + }, + { + "name": "egulias/email-validator", + "version": "3.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "a5ed8d58ed0c340a7c2109f587951b1c84cf6286" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/a5ed8d58ed0c340a7c2109f587951b1c84cf6286", + "reference": "a5ed8d58ed0c340a7c2109f587951b1c84cf6286", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "doctrine/lexer": "^1.2", + "php": ">=7.2", + "symfony/polyfill-intl-idn": "^1.15" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^8.5.8|^9.3.3", + "vimeo/psalm": "^4" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/3.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2022-05-28T22:19:18+00:00" + }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.14.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75", + "reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.2" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0" + }, + "time": "2021-12-25T01:21:49+00:00" + }, + { + "name": "fcesky/test", + "version": "v1.0.7", + "source": { + "type": "git", + "url": "https://github.com/sdftcsdftc/upload_test.git", + "reference": "109e2a13fe455f4d66169fb333192d6795ca1cbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sdftcsdftc/upload_test/zipball/109e2a13fe455f4d66169fb333192d6795ca1cbb", + "reference": "109e2a13fe455f4d66169fb333192d6795ca1cbb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6.0" + }, + "type": "l", + "autoload": { + "psr-4": { + "FceskyUpload\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "FCesky", + "email": "sdftcsdftc@outlook.com" + } + ], + "description": "This is a test package,please use it with caution.", + "support": { + "issues": "https://github.com/sdftcsdftc/upload_test/issues", + "source": "https://github.com/sdftcsdftc/upload_test/tree/v1.0.7" + }, + "time": "2021-03-02T03:05:10+00:00" + }, + { + "name": "geoip2/geoip2", + "version": "v2.12.2", + "source": { + "type": "git", + "url": "https://github.com/maxmind/GeoIP2-php.git", + "reference": "83adb44ac4b9553d36b579a14673ed124583082f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/83adb44ac4b9553d36b579a14673ed124583082f", + "reference": "83adb44ac4b9553d36b579a14673ed124583082f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "maxmind-db/reader": "~1.8", + "maxmind/web-service-common": "~0.8", + "php": ">=7.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "GeoIp2\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory J. Oschwald", + "email": "goschwald@maxmind.com", + "homepage": "https://www.maxmind.com/" + } + ], + "description": "MaxMind GeoIP2 PHP API", + "homepage": "https://github.com/maxmind/GeoIP2-php", + "keywords": [ + "IP", + "geoip", + "geoip2", + "geolocation", + "maxmind" + ], + "support": { + "issues": "https://github.com/maxmind/GeoIP2-php/issues", + "source": "https://github.com/maxmind/GeoIP2-php/tree/v2.12.2" + }, + "time": "2021-11-30T18:15:25+00:00" + }, + { + "name": "league/flysystem", + "version": "1.1.9", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "094defdb4a7001845300334e7c1ee2335925ef99" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/094defdb4a7001845300334e7c1ee2335925ef99", + "reference": "094defdb4a7001845300334e7c1ee2335925ef99", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-fileinfo": "*", + "league/mime-type-detection": "^1.3", + "php": "^7.2.5 || ^8.0" + }, + "conflict": { + "league/flysystem-sftp": "<1.0.6" + }, + "require-dev": { + "phpspec/prophecy": "^1.11.1", + "phpunit/phpunit": "^8.5.8" + }, + "suggest": { + "ext-ftp": "Allows you to use FTP server storage", + "ext-openssl": "Allows you to use FTPS server storage", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", + "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", + "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/1.1.9" + }, + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "other" + } + ], + "time": "2021-12-09T09:40:50+00:00" + }, + { + "name": "league/flysystem-cached-adapter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-cached-adapter.git", + "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/d1925efb2207ac4be3ad0c40b8277175f99ffaff", + "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "league/flysystem": "~1.0", + "psr/cache": "^1.0.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^3.4", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0", + "tedivm/stash": "~0.12" + }, + "suggest": { + "ext-phpredis": "Pure C implemented extension for PHP" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Cached\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "frankdejonge", + "email": "info@frenky.net" + } + ], + "description": "An adapter decorator to enable meta-data caching.", + "support": { + "issues": "https://github.com/thephpleague/flysystem-cached-adapter/issues", + "source": "https://github.com/thephpleague/flysystem-cached-adapter/tree/master" + }, + "time": "2020-07-25T15:56:04+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2022-04-17T13:12:02+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "211e9ba1530ea5260b45d90c9ea252f56ec52729" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/211e9ba1530ea5260b45d90c9ea252f56ec52729", + "reference": "211e9ba1530ea5260b45d90c9ea252f56ec52729", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "myclabs/php-enum": "^1.5", + "php": "^7.4 || ^8.0", + "psr/http-message": "^1.0", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "ext-zip": "*", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", + "vimeo/psalm": "^4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.2.1" + }, + "funding": [ + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2022-05-18T15:52:06+00:00" + }, + { + "name": "markbaker/complex", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/ab8bc271e404909db09ff2d5ffa1e538085c0f22", + "reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.1" + }, + "time": "2021-06-29T15:32:53+00:00" + }, + { + "name": "markbaker/matrix", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "c66aefcafb4f6c269510e9ac46b82619a904c576" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/c66aefcafb4f6c269510e9ac46b82619a904c576", + "reference": "c66aefcafb4f6c269510e9ac46b82619a904c576", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", + "sebastian/phpcpd": "^4.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@demon-angel.eu" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.0" + }, + "time": "2021-07-01T19:01:15+00:00" + }, + { + "name": "matomo/device-detector", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/matomo-org/device-detector.git", + "reference": "cd1283126b4cf5081fdc0381b5b5e7849333cfa4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/cd1283126b4cf5081fdc0381b5b5e7849333cfa4", + "reference": "cd1283126b4cf5081fdc0381b5b5e7849333cfa4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "mustangostang/spyc": "*", + "php": "^7.2|^8.0" + }, + "replace": { + "piwik/device-detector": "self.version" + }, + "require-dev": { + "matthiasmullie/scrapbook": "^1.4.7", + "mayflower/mo4-coding-standard": "^v8.0.0", + "phpstan/phpstan": "^0.12.52", + "phpunit/phpunit": "^8.5.8", + "psr/cache": "^1.0.1", + "psr/simple-cache": "^1.0.1", + "symfony/yaml": "^5.1.7" + }, + "suggest": { + "doctrine/cache": "Can directly be used for caching purpose", + "ext-yaml": "Necessary for using the Pecl YAML parser" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeviceDetector\\": "" + }, + "exclude-from-classmap": [ + "Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The Matomo Team", + "email": "hello@matomo.org", + "homepage": "https://matomo.org/team/" + } + ], + "description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.", + "homepage": "https://matomo.org", + "keywords": [ + "devicedetection", + "parser", + "useragent" + ], + "support": { + "forum": "https://forum.matomo.org/", + "issues": "https://github.com/matomo-org/device-detector/issues", + "source": "https://github.com/matomo-org/matomo", + "wiki": "https://dev.matomo.org/" + }, + "time": "2022-03-08T09:22:55+00:00" + }, + { + "name": "maxmind-db/reader", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", + "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/b1f3c0699525336d09cc5161a2861268d9f2ae5b", + "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2" + }, + "conflict": { + "ext-maxminddb": "<1.10.1,>=2.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "php-coveralls/php-coveralls": "^2.1", + "phpstan/phpstan": "*", + "phpunit/phpcov": ">=6.0.0", + "phpunit/phpunit": ">=8.0.0,<10.0.0", + "squizlabs/php_codesniffer": "3.*" + }, + "suggest": { + "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" + }, + "type": "library", + "autoload": { + "psr-4": { + "MaxMind\\Db\\": "src/MaxMind/Db" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory J. Oschwald", + "email": "goschwald@maxmind.com", + "homepage": "https://www.maxmind.com/" + } + ], + "description": "MaxMind DB Reader API", + "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", + "keywords": [ + "database", + "geoip", + "geoip2", + "geolocation", + "maxmind" + ], + "support": { + "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.11.0" + }, + "time": "2021-10-18T15:23:10+00:00" + }, + { + "name": "maxmind/web-service-common", + "version": "v0.9.0", + "source": { + "type": "git", + "url": "https://github.com/maxmind/web-service-common-php.git", + "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", + "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "composer/ca-bundle": "^1.0.3", + "ext-curl": "*", + "ext-json": "*", + "php": ">=7.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "MaxMind\\Exception\\": "src/Exception", + "MaxMind\\WebService\\": "src/WebService" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory Oschwald", + "email": "goschwald@maxmind.com" + } + ], + "description": "Internal MaxMind Web Service API", + "homepage": "https://github.com/maxmind/web-service-common-php", + "support": { + "issues": "https://github.com/maxmind/web-service-common-php/issues", + "source": "https://github.com/maxmind/web-service-common-php/tree/v0.9.0" + }, + "time": "2022-03-28T17:43:20+00:00" + }, + { + "name": "mustangostang/spyc", + "version": "0.6.3", + "source": { + "type": "git", + "url": "git@github.com:mustangostang/spyc.git", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + }, + "autoload": { + "files": [ + "Spyc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "mustangostang", + "email": "vlad.andersen@gmail.com" + } + ], + "description": "A simple YAML loader/dumper class for PHP", + "homepage": "https://github.com/mustangostang/spyc/", + "keywords": [ + "spyc", + "yaml", + "yml" + ], + "time": "2019-09-10T13:16:29+00:00" + }, + { + "name": "myclabs/php-enum", + "version": "1.6.6", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "32c4202886c51fbe5cc3a7c34ec5c9a4a790345e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/32c4202886c51fbe5cc3a7c34ec5c9a4a790345e", + "reference": "32c4202886c51fbe5cc3a7c34ec5c9a4a790345e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/master" + }, + "time": "2019-02-04T21:18:49+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.58.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/97a34af22bde8d0ac20ab34b29d7bfe360902055", + "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.0", + "doctrine/orm": "^2.7", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.54 || ^1.0", + "phpunit/php-file-iterator": "^2.0.5", + "phpunit/phpunit": "^7.5.20 || ^8.5.23", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2022-04-25T19:31:17+00:00" + }, + { + "name": "phpmailer/phpmailer", + "version": "v6.6.1", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "a4bf414da618f22fd9ffd88afd6ed0bc287ab932" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a4bf414da618f22fd9ffd88afd6ed0bc287ab932", + "reference": "a4bf414da618f22fd9ffd88afd6ed0bc287ab932", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.2", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.3.5", + "roave/security-advisories": "dev-latest", + "squizlabs/php_codesniffer": "^3.6.2", + "yoast/phpunit-polyfills": "^1.0.0" + }, + "suggest": { + "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", + "league/oauth2-google": "Needed for Google XOAUTH2 authentication", + "psr/log": "For optional PSR-3 debug logging", + "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication", + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPMailer\\PHPMailer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-only" + ], + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "support": { + "issues": "https://github.com/PHPMailer/PHPMailer/issues", + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.1" + }, + "funding": [ + { + "url": "https://github.com/Synchro", + "type": "github" + } + ], + "time": "2022-06-14T08:19:03+00:00" + }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.23.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/21e4cf62699eebf007db28775f7d1554e612ed9e", + "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.13", + "maennchen/zipstream-php": "^2.1", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": "^7.3 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/simple-cache": "^1.0 || ^2.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dompdf/dompdf": "^1.0", + "friendsofphp/php-cs-fixer": "^3.2", + "jpgraph/jpgraph": "^4.0", + "mpdf/mpdf": "8.0.17", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.6", + "tecnickcom/tcpdf": "^6.4" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)", + "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.23.0" + }, + "time": "2022-04-24T13:53:10+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/master" + }, + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "qiniu/php-sdk", + "version": "v7.6.0", + "source": { + "type": "git", + "url": "https://github.com/qiniu/php-sdk.git", + "reference": "57033fab64c92f8c7ae165222dd958553741e711" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/qiniu/php-sdk/zipball/57033fab64c92f8c7ae165222dd958553741e711", + "reference": "57033fab64c92f8c7ae165222dd958553741e711", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "myclabs/php-enum": "1.6.6", + "php": ">=5.3.3" + }, + "require-dev": { + "paragonie/random_compat": ">=2", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~3.6" + }, + "type": "library", + "autoload": { + "files": [ + "src/Qiniu/functions.php" + ], + "psr-4": { + "Qiniu\\": "src/Qiniu" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Qiniu", + "email": "sdk@qiniu.com", + "homepage": "http://www.qiniu.com" + } + ], + "description": "Qiniu Resource (Cloud) Storage SDK for PHP", + "homepage": "http://developer.qiniu.com/", + "keywords": [ + "cloud", + "qiniu", + "sdk", + "storage" + ], + "support": { + "issues": "https://github.com/qiniu/php-sdk/issues", + "source": "https://github.com/qiniu/php-sdk/tree/v7.6.0" + }, + "time": "2022-06-08T10:05:47+00:00" + }, + { + "name": "rosell-dk/exec-with-fallback", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/exec-with-fallback.git", + "reference": "f88a6b29abd0b580566056b7c1eb0434eb5db20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/exec-with-fallback/zipball/f88a6b29abd0b580566056b7c1eb0434eb5db20d", + "reference": "f88a6b29abd0b580566056b7c1eb0434eb5db20d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^5.6 | ^7.0 | ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "suggest": { + "php-stan/php-stan": "Suggested for dev, in order to analyse code before committing" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "ExecWithFallback\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + } + ], + "description": "An exec() with fallback to emulations (proc_open, etc)", + "keywords": [ + "command", + "exec", + "fallback", + "open_proc", + "resiliant", + "sturdy" + ], + "support": { + "issues": "https://github.com/rosell-dk/exec-with-fallback/issues", + "source": "https://github.com/rosell-dk/exec-with-fallback/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2021-12-08T12:09:43+00:00" + }, + { + "name": "rosell-dk/file-util", + "version": "0.1.1", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/file-util.git", + "reference": "2ff895308c37f448b34b031cfbfd8e45f43936fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/file-util/zipball/2ff895308c37f448b34b031cfbfd8e45f43936fd", + "reference": "2ff895308c37f448b34b031cfbfd8e45f43936fd", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4", + "rosell-dk/exec-with-fallback": "^1.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "mikey179/vfsstream": "^1.6", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "FileUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + } + ], + "description": "Functions for dealing with files and paths", + "keywords": [ + "files", + "path", + "util" + ], + "support": { + "issues": "https://github.com/rosell-dk/file-util/issues", + "source": "https://github.com/rosell-dk/file-util/tree/0.1.1" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2022-04-19T10:12:31+00:00" + }, + { + "name": "rosell-dk/image-mime-type-guesser", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/image-mime-type-guesser.git", + "reference": "72f7040e95a78937ae2edece452530224fcacea6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/image-mime-type-guesser/zipball/72f7040e95a78937ae2edece452530224fcacea6", + "reference": "72f7040e95a78937ae2edece452530224fcacea6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^5.6 | ^7.0 | ^8.0", + "rosell-dk/image-mime-type-sniffer": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "ImageMimeTypeGuesser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + } + ], + "description": "Guess mime type of images", + "keywords": [ + "image", + "images", + "mime", + "mime type" + ], + "support": { + "issues": "https://github.com/rosell-dk/image-mime-type-guesser/issues", + "source": "https://github.com/rosell-dk/image-mime-type-guesser/tree/1.1.1" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2022-05-19T09:57:15+00:00" + }, + { + "name": "rosell-dk/image-mime-type-sniffer", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/image-mime-type-sniffer.git", + "reference": "9ed14cc5d2c14c417660a4dd1946b5f056494691" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/image-mime-type-sniffer/zipball/9ed14cc5d2c14c417660a4dd1946b5f056494691", + "reference": "9ed14cc5d2c14c417660a4dd1946b5f056494691", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "mikey179/vfsstream": "^1.6", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "ImageMimeTypeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + } + ], + "description": "Sniff mime type (images only)", + "keywords": [ + "image", + "images", + "mime", + "mime type" + ], + "support": { + "issues": "https://github.com/rosell-dk/image-mime-type-sniffer/issues", + "source": "https://github.com/rosell-dk/image-mime-type-sniffer/tree/1.1.1" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2022-04-20T14:31:25+00:00" + }, + { + "name": "rosell-dk/locate-binaries", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/locate-binaries.git", + "reference": "bd2f493383ecd55aa519828dd2898e30f3b9cbb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/locate-binaries/zipball/bd2f493383ecd55aa519828dd2898e30f3b9cbb0", + "reference": "bd2f493383ecd55aa519828dd2898e30f3b9cbb0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6", + "rosell-dk/exec-with-fallback": "^1.0.0", + "rosell-dk/file-util": "^0.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "LocateBinaries\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + } + ], + "description": "Locate a binaries by means of exec() or similar", + "keywords": [ + "binary", + "discover", + "locate", + "whereis", + "which" + ], + "support": { + "issues": "https://github.com/rosell-dk/locate-binaries/issues", + "source": "https://github.com/rosell-dk/locate-binaries/tree/1.0" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2022-04-20T07:20:07+00:00" + }, + { + "name": "rosell-dk/webp-convert", + "version": "2.9.2", + "source": { + "type": "git", + "url": "https://github.com/rosell-dk/webp-convert.git", + "reference": "5ccba85ebe3b28ae229459fd0baed25314616ac9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rosell-dk/webp-convert/zipball/5ccba85ebe3b28ae229459fd0baed25314616ac9", + "reference": "5ccba85ebe3b28ae229459fd0baed25314616ac9", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^5.6 | ^7.0 | ^8.0", + "rosell-dk/exec-with-fallback": "^1.0.0", + "rosell-dk/image-mime-type-guesser": "^1.1.1", + "rosell-dk/locate-binaries": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "3.*" + }, + "suggest": { + "ext-gd": "to use GD extension for converting. Note: Gd must be compiled with webp support", + "ext-imagick": "to use Imagick extension for converting. Note: Gd must be compiled with webp support", + "ext-vips": "to use Vips extension for converting.", + "php-stan/php-stan": "Suggested for dev, in order to analyse code before committing" + }, + "type": "library", + "extra": { + "scripts-descriptions": { + "ci": "Run tests before CI", + "phpcs": "Checks coding styles (PSR2) of file/dir, which you must supply. To check all, supply 'src'", + "phpcbf": "Fix coding styles (PSR2) of file/dir, which you must supply. To fix all, supply 'src'", + "cs-fix-all": "Fix the coding style of all the source files, to comply with the PSR-2 coding standard", + "cs-fix": "Fix the coding style of a PHP file or directory, which you must specify.", + "test": "Launches the preconfigured PHPUnit" + } + }, + "autoload": { + "psr-4": { + "WebPConvert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bjørn Rosell", + "homepage": "https://www.bitwise-it.dk/contact", + "role": "Project Author" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Collaborator" + } + ], + "description": "Convert JPEG & PNG to WebP with PHP", + "keywords": [ + "Webp", + "cwebp", + "gd", + "image conversion", + "images", + "imagick", + "jpg", + "jpg2webp", + "png", + "png2webp" + ], + "support": { + "issues": "https://github.com/rosell-dk/webp-convert/issues", + "source": "https://github.com/rosell-dk/webp-convert/tree/2.9.2" + }, + "funding": [ + { + "url": "https://github.com/rosell-dk", + "type": "github" + }, + { + "url": "https://ko-fi.com/rosell", + "type": "ko_fi" + } + ], + "time": "2022-05-19T13:56:36+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-09-14T14:02:44+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-24T11:49:31+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-24T11:49:31+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", + "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-24T11:49:31+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-10T07:21:04+00:00" + }, + { + "name": "symfony/process", + "version": "v4.4.41", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "9eedd60225506d56e42210a70c21bb80ca8456ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/9eedd60225506d56e42210a70c21bb80ca8456ce", + "reference": "9eedd60225506d56e42210a70c21bb80ca8456ce", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v4.4.41" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-04-04T10:19:07+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "9ba011309943955a3807b8236c17cff3b88f67b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/9ba011309943955a3807b8236c17cff3b88f67b6", + "reference": "9ba011309943955a3807b8236c17cff3b88f67b6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.3|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.0.9" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-06T14:27:17+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9", + "reference": "c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:55:41+00:00" + }, + { + "name": "topthink/framework", + "version": "v6.0.12", + "source": { + "type": "git", + "url": "https://github.com/top-think/framework.git", + "reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/framework/zipball/e478316ac843c1a884a3b3a7a94db17c4001ff5c", + "reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "league/flysystem": "^1.1.4", + "league/flysystem-cached-adapter": "^1.0", + "php": ">=7.2.5", + "psr/container": "~1.0", + "psr/http-message": "^1.0", + "psr/log": "~1.0", + "psr/simple-cache": "^1.0", + "topthink/think-helper": "^3.1.1", + "topthink/think-orm": "^2.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^2.1.0", + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "autoload": { + "files": [], + "psr-4": { + "think\\": "src/think/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + }, + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP Framework.", + "homepage": "http://thinkphp.cn/", + "keywords": [ + "framework", + "orm", + "thinkphp" + ], + "support": { + "issues": "https://github.com/top-think/framework/issues", + "source": "https://github.com/top-think/framework/tree/v6.0.12" + }, + "time": "2022-01-21T06:31:07+00:00" + }, + { + "name": "topthink/think-captcha", + "version": "v3.0.7", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-captcha.git", + "reference": "a450602932a5d9ba183e288b79921ba3b9a92331" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-captcha/zipball/a450602932a5d9ba183e288b79921ba3b9a92331", + "reference": "a450602932a5d9ba183e288b79921ba3b9a92331", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "topthink/framework": "^6.0.0" + }, + "type": "library", + "extra": { + "think": { + "services": [ + "think\\captcha\\CaptchaService" + ], + "config": { + "captcha": "src/config.php" + } + } + }, + "autoload": { + "files": [ + "src/helper.php" + ], + "psr-4": { + "think\\captcha\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "captcha package for thinkphp", + "support": { + "issues": "https://github.com/top-think/think-captcha/issues", + "source": "https://github.com/top-think/think-captcha/tree/v3.0.7" + }, + "time": "2022-04-23T02:38:14+00:00" + }, + { + "name": "topthink/think-helper", + "version": "v3.1.6", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-helper.git", + "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff", + "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/helper.php" + ], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP6 Helper Package", + "support": { + "issues": "https://github.com/top-think/think-helper/issues", + "source": "https://github.com/top-think/think-helper/tree/v3.1.6" + }, + "time": "2021-12-15T04:27:55+00:00" + }, + { + "name": "topthink/think-migration", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-migration.git", + "reference": "5717d9e5f3ea745f6dbfd1e30b4402aaadff9a79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-migration/zipball/5717d9e5f3ea745f6dbfd1e30b4402aaadff9a79", + "reference": "5717d9e5f3ea745f6dbfd1e30b4402aaadff9a79", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "topthink/framework": "^6.0.0", + "topthink/think-helper": "^3.0.3" + }, + "require-dev": { + "fzaninotto/faker": "^1.8" + }, + "suggest": { + "fzaninotto/faker": "Required to use the factory builder (^1.8)." + }, + "type": "library", + "extra": { + "think": { + "services": [ + "think\\migration\\Service" + ] + } + }, + "autoload": { + "psr-4": { + "Phinx\\": "phinx/src/Phinx", + "think\\migration\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "support": { + "issues": "https://github.com/top-think/think-migration/issues", + "source": "https://github.com/top-think/think-migration/tree/v3.0.3" + }, + "time": "2020-12-07T05:54:22+00:00" + }, + { + "name": "topthink/think-multi-app", + "version": "v1.0.14", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-multi-app.git", + "reference": "ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-multi-app/zipball/ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3", + "reference": "ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0", + "topthink/framework": "^6.0.0" + }, + "type": "library", + "extra": { + "think": { + "services": [ + "think\\app\\Service" + ] + } + }, + "autoload": { + "psr-4": { + "think\\app\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "thinkphp6 multi app support", + "support": { + "issues": "https://github.com/top-think/think-multi-app/issues", + "source": "https://github.com/top-think/think-multi-app/tree/master" + }, + "time": "2020-07-12T13:50:37+00:00" + }, + { + "name": "topthink/think-orm", + "version": "v2.0.52", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-orm.git", + "reference": "407a60658f37fc57422ab95a9922c6f69af90f46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-orm/zipball/407a60658f37fc57422ab95a9922c6f69af90f46", + "reference": "407a60658f37fc57422ab95a9922c6f69af90f46", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "ext-pdo": "*", + "php": ">=7.1.0", + "psr/log": "~1.0", + "psr/simple-cache": "^1.0", + "topthink/think-helper": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7|^8|^9.5" + }, + "type": "library", + "autoload": { + "files": [ + "stubs/load_stubs.php" + ], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "think orm", + "keywords": [ + "database", + "orm" + ], + "support": { + "issues": "https://github.com/top-think/think-orm/issues", + "source": "https://github.com/top-think/think-orm/tree/v2.0.52" + }, + "time": "2022-01-25T06:00:05+00:00" + }, + { + "name": "topthink/think-queue", + "version": "v3.0.7", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-queue.git", + "reference": "cded7616e313f9daa55c0ad0de5791f0d1fb3066" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-queue/zipball/cded7616e313f9daa55c0ad0de5791f0d1fb3066", + "reference": "cded7616e313f9daa55c0ad0de5791f0d1fb3066", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "nesbot/carbon": "^2.16", + "symfony/process": "^4.2", + "topthink/framework": "^6.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^6.2", + "topthink/think-migration": "^3.0.0" + }, + "type": "library", + "extra": { + "think": { + "services": [ + "think\\queue\\Service" + ], + "config": { + "queue": "src/config.php" + } + } + }, + "autoload": { + "files": [ + "src/common.php" + ], + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP6 Queue Package", + "support": { + "issues": "https://github.com/top-think/think-queue/issues", + "source": "https://github.com/top-think/think-queue/tree/v3.0.7" + }, + "time": "2021-12-20T08:04:36+00:00" + }, + { + "name": "topthink/think-template", + "version": "v2.0.8", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-template.git", + "reference": "abfc293f74f9ef5127b5c416310a01fe42e59368" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-template/zipball/abfc293f74f9ef5127b5c416310a01fe42e59368", + "reference": "abfc293f74f9ef5127b5c416310a01fe42e59368", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0", + "psr/simple-cache": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "the php template engine", + "support": { + "issues": "https://github.com/top-think/think-template/issues", + "source": "https://github.com/top-think/think-template/tree/v2.0.8" + }, + "time": "2020-12-10T07:52:03+00:00" + }, + { + "name": "topthink/think-view", + "version": "v1.0.14", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-view.git", + "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-view/zipball/edce0ae2c9551ab65f9e94a222604b0dead3576d", + "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0", + "topthink/think-template": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "think\\view\\driver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "thinkphp template driver", + "support": { + "issues": "https://github.com/top-think/think-view/issues", + "source": "https://github.com/top-think/think-view/tree/v1.0.14" + }, + "time": "2019-11-06T11:40:13+00:00" + } + ], + "packages-dev": [ + { + "name": "symfony/var-dumper", + "version": "v4.4.42", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/742aab50ad097bcb62d91fccb613f66b8047d2ca", + "reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<3.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^3.4|^4.0|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^1.43|^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v4.4.42" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-21T10:00:54+00:00" + }, + { + "name": "topthink/think-trace", + "version": "v1.4", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-trace.git", + "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-trace/zipball/9a9fa8f767b6c66c5a133ad21ca1bc96ad329444", + "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1.0", + "topthink/framework": "^6.0.0" + }, + "type": "library", + "extra": { + "think": { + "services": [ + "think\\trace\\Service" + ], + "config": { + "trace": "src/config.php" + } + } + }, + "autoload": { + "psr-4": { + "think\\trace\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "liu21st", + "email": "liu21st@gmail.com" + } + ], + "description": "thinkphp debug trace", + "support": { + "issues": "https://github.com/top-think/think-trace/issues", + "source": "https://github.com/top-think/think-trace/tree/v1.4" + }, + "time": "2020-06-29T05:27:28+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.1.0" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..8c15313 --- /dev/null +++ b/config/app.php @@ -0,0 +1,32 @@ + env('app.host', ''), + // 应用的命名空间 + 'app_namespace' => '', + // 是否启用路由 + 'with_route' => true, + // 默认应用 + 'default_app' => 'index', + // 默认时区 + 'default_timezone' => 'Asia/Shanghai', + + // 应用映射(自动多应用模式有效) + 'app_map' => [], + // 域名绑定(自动多应用模式有效) + 'domain_bind' => [], + // 禁止URL访问的应用列表(自动多应用模式有效) + 'deny_app_list' => [], + + // 异常页面的模板文件 + 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', + + // 错误显示信息,非调试模式有效 + 'error_message' => '页面错误!请稍后再试~', + // 显示错误信息 + 'show_error_msg' => true, +]; diff --git a/config/async.php b/config/async.php new file mode 100644 index 0000000..ae72195 --- /dev/null +++ b/config/async.php @@ -0,0 +1,31 @@ + 'async_exec_method', + // 异步执行自定义队列 + 'async_exec_method_custom_queue' => [ + 'async_exec_method_custom' => '自定义异步执行队列', + ], + + // 异步订阅默认队列名称 + 'subscribe_default_queue' => 'subscribe_default', + // 异步订阅事件获取类 + 'subscribe_event_get_class' => ConfigFileEventGetter::class, + // 异步订阅事件配置(可通过修改`subscribe_event_get_class`改变配置来源) + 'subscribe_event_config' => [ + [ + 'name' => 'demo', + 'title' => '演示事件', + 'queue' => 'async_subscribe_demo', // 事件处理队列 为空使用异步订阅默认队列 + + // 事件订阅者配置 + 'subscriber' => [ + [DemoSubscriber::class, 'handle'], + ] + ] + ] +]; \ No newline at end of file diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..f12267d --- /dev/null +++ b/config/cache.php @@ -0,0 +1,38 @@ + env('cache.driver', 'redis'), + + // 缓存连接方式配置 + 'stores' => [ + 'file' => [ + // 驱动方式 + 'type' => 'File', + // 缓存保存目录 + 'path' => '', + // 缓存前缀 + 'prefix' => '', + // 缓存有效期 0表示永久缓存 + 'expire' => 0, + // 缓存标签前缀 + 'tag_prefix' => 'tag:', + // 序列化机制 例如 ['serialize', 'unserialize'] + 'serialize' => [], + ], + 'redis' => [ + 'type' => 'redis', + 'host' => Env::get('redis.host'), + 'port' => Env::get('redis.port'), + 'password' => Env::get('redis.pass'), + 'select' => Env::get('redis.select'), + ] + // 更多的缓存连接 + ], +]; diff --git a/config/captcha.php b/config/captcha.php new file mode 100644 index 0000000..9bbf529 --- /dev/null +++ b/config/captcha.php @@ -0,0 +1,39 @@ + 5, + // 验证码字符集合 + 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY', + // 验证码过期时间 + 'expire' => 1800, + // 是否使用中文验证码 + 'useZh' => false, + // 是否使用算术验证码 + 'math' => false, + // 是否使用背景图 + 'useImgBg' => false, + //验证码字符大小 + 'fontSize' => 25, + // 是否使用混淆曲线 + 'useCurve' => true, + //是否添加杂点 + 'useNoise' => true, + // 验证码字体 不设置则随机 + 'fontttf' => '', + //背景颜色 + 'bg' => [243, 251, 254], + // 验证码图片高度 + 'imageH' => 0, + // 验证码图片宽度 + 'imageW' => 0, + + // 添加额外的验证码设置 + // verify => [ + // 'length'=>4, + // ... + //], +]; diff --git a/config/console.php b/config/console.php new file mode 100644 index 0000000..a818a98 --- /dev/null +++ b/config/console.php @@ -0,0 +1,9 @@ + [ + ], +]; diff --git a/config/cookie.php b/config/cookie.php new file mode 100644 index 0000000..9c4732a --- /dev/null +++ b/config/cookie.php @@ -0,0 +1,20 @@ + 0, + // cookie 保存路径 + 'path' => '/', + // cookie 有效域名 + 'domain' => '', + // cookie 启用安全传输 + 'secure' => true, + // httponly设置 + 'httponly' => false, + // 是否使用 setcookie + 'setcookie' => true, + // samesite 设置,支持 'strict' 'lax' + 'samesite' => '', +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..1686f59 --- /dev/null +++ b/config/database.php @@ -0,0 +1,59 @@ + env('database.driver', 'mysql'), + + // 自定义时间查询规则 + 'time_query_rule' => [], + + // 自动写入时间戳字段 + // true为自动识别类型 false关闭 + // 字符串则明确指定时间字段类型 支持 int timestamp datetime date + 'auto_timestamp' => true, + + // 时间字段取出后的默认时间格式 + 'datetime_format' => 'Y-m-d H:i:s', + + // 数据库连接配置信息 + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => env('database.type', 'mysql'), + // 服务器地址 + 'hostname' => env('database.hostname', '127.0.0.1'), + // 数据库名 + 'database' => env('database.database', ''), + // 用户名 + 'username' => env('database.username', 'root'), + // 密码 + 'password' => env('database.password', ''), + // 端口 + 'hostport' => env('database.hostport', '3306'), + // 数据库连接参数 + 'params' => [], + // 数据库编码默认采用utf8 + 'charset' => env('database.charset', 'utf8'), + // 数据库表前缀 + 'prefix' => env('database.prefix', ''), + + // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'deploy' => 0, + // 数据库读写是否分离 主从式有效 + 'rw_separate' => false, + // 读写分离后 主服务器数量 + 'master_num' => 1, + // 指定从服务器序号 + 'slave_no' => '', + // 是否严格检查字段是否存在 + 'fields_strict' => true, + // 是否需要断线重连 + 'break_reconnect' => false, + // 监听SQL + 'trigger_sql' => env('app_debug', true), + // 开启字段缓存 + 'fields_cache' => false, + ] + // 更多的数据库配置信息 + ], +]; diff --git a/config/filesystem.php b/config/filesystem.php new file mode 100644 index 0000000..965297e --- /dev/null +++ b/config/filesystem.php @@ -0,0 +1,24 @@ + env('filesystem.driver', 'local'), + // 磁盘列表 + 'disks' => [ + 'local' => [ + 'type' => 'local', + 'root' => app()->getRuntimePath() . 'storage', + ], + 'public' => [ + // 磁盘类型 + 'type' => 'local', + // 磁盘路径 + 'root' => app()->getRootPath() . 'public/storage', + // 磁盘路径对应的外部URL路径 + 'url' => '/storage', + // 可见性 + 'visibility' => 'public', + ], + // 更多的磁盘配置信息 + ], +]; diff --git a/config/lang.php b/config/lang.php new file mode 100644 index 0000000..6b00300 --- /dev/null +++ b/config/lang.php @@ -0,0 +1,27 @@ + env('lang.default_lang', ''), + // 允许的语言列表 + 'allow_lang_list' => [], + // 多语言自动侦测变量名 + 'detect_var' => 'lang', + // 是否使用Cookie记录 + 'use_cookie' => false, + // 多语言cookie变量 + 'cookie_var' => '', + // 多语言header变量 + 'header_var' => '', + // 扩展语言包 + 'extend_list' => [], + // Accept-Language转义为对应语言包名称 + 'accept_language' => [ +// 'zh-hans-cn' => 'zh-cn', + ], + // 是否支持语言分组 + 'allow_group' => false, +]; diff --git a/config/log.php b/config/log.php new file mode 100644 index 0000000..ea24ff9 --- /dev/null +++ b/config/log.php @@ -0,0 +1,45 @@ + env('log.channel', 'file'), + // 日志记录级别 + 'level' => [], + // 日志类型记录的通道 ['error'=>'email',...] + 'type_channel' => [], + // 关闭全局日志写入 + 'close' => false, + // 全局日志处理 支持闭包 + 'processor' => null, + + // 日志通道列表 + 'channels' => [ + 'file' => [ + // 日志记录方式 + 'type' => 'File', + // 日志保存目录 + 'path' => '', + // 单文件日志写入 + 'single' => false, + // 独立日志级别 + 'apart_level' => [], + // 最大日志文件数量 + 'max_files' => 0, + // 使用JSON格式记录 + 'json' => false, + // 日志处理 + 'processor' => null, + // 关闭通道日志写入 + 'close' => false, + // 日志输出格式化 + 'format' => '[%s][%s] %s', + // 是否实时写入 + 'realtime_write' => false, + ], + // 其它日志通道配置 + ], + +]; diff --git a/config/middleware.php b/config/middleware.php new file mode 100644 index 0000000..7e1972f --- /dev/null +++ b/config/middleware.php @@ -0,0 +1,8 @@ + [], + // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行 + 'priority' => [], +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..10988b3 --- /dev/null +++ b/config/queue.php @@ -0,0 +1,41 @@ + +// +---------------------------------------------------------------------- + +use think\facade\Env; + +return [ + 'default' => 'redis', + 'connections' => [ + 'sync' => [ + 'type' => 'sync', + ], + 'database' => [ + 'type' => 'database', + 'queue' => 'default', + 'table' => 'jobs', + 'connection' => null, + ], + 'redis' => [ + 'type' => 'redis', + 'queue' => 'default', + 'host' => Env::get('redis.host'), + 'port' => Env::get('redis.port'), + 'password' => Env::get('redis.pass'), + 'select' => Env::get('redis.select'), + 'timeout' => 0, + 'persistent' => false, + ], + ], + 'failed' => [ + 'type' => 'none', + 'table' => 'failed_jobs', + ], +]; diff --git a/config/route.php b/config/route.php new file mode 100644 index 0000000..5bdb299 --- /dev/null +++ b/config/route.php @@ -0,0 +1,45 @@ + '/', + // URL伪静态后缀 + 'url_html_suffix' => 'html', + // URL普通方式参数 用于自动生成 + 'url_common_param' => true, + // 是否开启路由延迟解析 + 'url_lazy_route' => true, + // 是否强制使用路由 + 'url_route_must' => false, + // 合并路由规则 + 'route_rule_merge' => false, + // 路由是否完全匹配 + 'route_complete_match' => true, + // 访问控制器层名称 + 'controller_layer' => 'controller', + // 空控制器名 + 'empty_controller' => 'Error', + // 是否使用控制器后缀 + 'controller_suffix' => false, + // 默认的路由变量规则 + 'default_route_pattern' => '[\w\.]+', + // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 + 'request_cache_key' => false, + // 请求缓存有效期 + 'request_cache_expire' => null, + // 全局请求缓存排除规则 + 'request_cache_except' => [], + // 默认控制器名 + 'default_controller' => 'Index', + // 默认操作名 + 'default_action' => 'index', + // 操作方法后缀 + 'action_suffix' => '', + // 默认JSONP格式返回的处理方法 + 'default_jsonp_handler' => 'jsonpReturn', + // 默认JSONP处理方法 + 'var_jsonp_handler' => 'callback', +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..b3fed5e --- /dev/null +++ b/config/session.php @@ -0,0 +1,19 @@ + 'PHPSESSID', + // SESSION_ID的提交变量,解决flash上传跨域 + 'var_session_id' => '', + // 驱动方式 支持file cache + 'type' => 'cache', + // 存储连接标识 当type使用cache的时候有效 + 'store' => null, + // 过期时间 + 'expire' => 3600, + // 前缀 + 'prefix' => '', +]; diff --git a/config/trace.php b/config/trace.php new file mode 100644 index 0000000..fad2392 --- /dev/null +++ b/config/trace.php @@ -0,0 +1,10 @@ + 'Html', + // 读取的日志通道名 + 'channel' => '', +]; diff --git a/config/view.php b/config/view.php new file mode 100644 index 0000000..01259a0 --- /dev/null +++ b/config/view.php @@ -0,0 +1,25 @@ + 'Think', + // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 + 'auto_rule' => 1, + // 模板目录名 + 'view_dir_name' => 'view', + // 模板后缀 + 'view_suffix' => 'html', + // 模板文件名分隔符 + 'view_depr' => DIRECTORY_SEPARATOR, + // 模板引擎普通标签开始标记 + 'tpl_begin' => '{', + // 模板引擎普通标签结束标记 + 'tpl_end' => '}', + // 标签库标签开始标记 + 'taglib_begin' => '{', + // 标签库标签结束标记 + 'taglib_end' => '}', +]; diff --git a/database/migrations/20210324015153_admin_create.php b/database/migrations/20210324015153_admin_create.php new file mode 100644 index 0000000..496f694 --- /dev/null +++ b/database/migrations/20210324015153_admin_create.php @@ -0,0 +1,52 @@ +table('admin',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'管理员表'])->addIndex('id'); + $table + ->addColumn('mobile','string',['limit'=>11,'default'=>'','null'=>false,'comment'=>'手机号']) + ->addColumn('code','string',['limit'=>10,'default'=>'','null'=>false,'comment'=>'业务员编码']) + ->addColumn('role_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'角色ID']) + ->addColumn('org_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'组织ID']) + ->addColumn('dept_group_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'部门分组ID']) + ->addColumn('dept_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'部门ID']) + ->addColumn('avatar','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'头像']) + ->addColumn('nickname','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'昵称']) + ->addColumn('username','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'用户名']) + ->addColumn('password','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'密码']) + ->addColumn('create_ip','string',['limit'=>15,'default'=>'0.0.0.0','null'=>false,'comment'=>'注册IP']) + ->addColumn('last_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'最后登录时间']) + ->addColumn('last_ip','string',['limit'=>15,'default'=>'0.0.0.0','null'=>false,'comment'=>'最后登录IP']) + ->addColumn('status','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210324044700_role_create.php b/database/migrations/20210324044700_role_create.php new file mode 100644 index 0000000..8998a7e --- /dev/null +++ b/database/migrations/20210324044700_role_create.php @@ -0,0 +1,39 @@ +table('role',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'角色表'])->addIndex('id'); + $table + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'角色名称']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210324055445_menu_create.php b/database/migrations/20210324055445_menu_create.php new file mode 100644 index 0000000..be73be7 --- /dev/null +++ b/database/migrations/20210324055445_menu_create.php @@ -0,0 +1,45 @@ +table('menu',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'菜单表'])->addIndex('id'); +// $table +// ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) +// ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'菜单名称']) +// ->addColumn('action','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'菜单规则']) +// ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图标']) +// ->addColumn('pid','integer',['limit'=> MysqlAdapter::INT_SMALL,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'父ID']) +// ->addColumn('sort','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>255,'null'=>false,'comment'=>'排序']) +// ->addColumn('is_show','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>1,'null'=>false,'comment'=>'是否显示,0=隐藏,1=显示']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->create(); + } +} diff --git a/database/migrations/20210324061342_role_to_menu_create.php b/database/migrations/20210324061342_role_to_menu_create.php new file mode 100644 index 0000000..3f9ff96 --- /dev/null +++ b/database/migrations/20210324061342_role_to_menu_create.php @@ -0,0 +1,42 @@ +table('role_to_menu',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'角色菜单表'])->addIndex('id'); +// $table +// ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) +// ->addColumn('role_id','integer',['limit'=> MysqlAdapter::INT_SMALL,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'角色ID']) +// ->addColumn('menu_id','integer',['limit'=> MysqlAdapter::INT_SMALL,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'菜单ID']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->addIndex(['role_id','menu_id'],['unique'=>true]) +// ->create(); + } +} diff --git a/database/migrations/20210329054522_menu_modify.php b/database/migrations/20210329054522_menu_modify.php new file mode 100644 index 0000000..a5959a9 --- /dev/null +++ b/database/migrations/20210329054522_menu_modify.php @@ -0,0 +1,40 @@ +table('menu'); +// $table +// ->addColumn('path','string',['limit'=>64,'after'=>'icon','default'=>'','null'=>false,'comment'=>'菜单路径']) +// ->addColumn('component','string',['limit'=>128,'default'=>'','after'=>'path','null'=>false,'comment'=>'操作,如:/api/info']) +// ->addColumn('redirect','string',['limit'=>128,'default'=>'','after'=>'component','null'=>false,'comment'=>'跳转']) +// ->addColumn('is_menu','integer',['limit'=> MysqlAdapter::INT_SMALL,'after'=>'redirect','signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否为菜单,0=否,1=是']) +// ->update(); + } +} diff --git a/database/migrations/20210329081619_goods_category_create.php b/database/migrations/20210329081619_goods_category_create.php new file mode 100644 index 0000000..433711a --- /dev/null +++ b/database/migrations/20210329081619_goods_category_create.php @@ -0,0 +1,46 @@ +table('goods_category',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'分类名']) + ->addColumn('desc','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('pid','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'父ID']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'电脑端分类图标']) + ->addColumn('sort','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=禁用,1=启用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210329084545_language_create.php b/database/migrations/20210329084545_language_create.php new file mode 100644 index 0000000..13085f2 --- /dev/null +++ b/database/migrations/20210329084545_language_create.php @@ -0,0 +1,46 @@ +table('language',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'语言包表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('name','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'语言包名']) + ->addColumn('code','string',['limit'=>20,'default'=>'','null'=>false,'comment'=>'标识']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图标']) + ->addColumn('locale','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'作用范围']) + ->addColumn('coin','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'货币']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210329090112_goods_create.php b/database/migrations/20210329090112_goods_create.php new file mode 100644 index 0000000..6a7af97 --- /dev/null +++ b/database/migrations/20210329090112_goods_create.php @@ -0,0 +1,51 @@ +table('goods',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品标题']) + ->addColumn('model_number','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品型号']) + ->addColumn('goods_category_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'商品分类ID']) + ->addColumn('price','decimal',['scale'=>2,'precision'=>10,'signed'=>false,'default'=>0.00,'null'=>false,'comment'=>'商品价格']) + ->addColumn('details','text',['comment'=>'商品详情']) + ->addColumn('params','text',['comment'=>'商品参数']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'页面title']) + ->addColumn('keywords','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'关键词']) + ->addColumn('description','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'页面描述SEO用']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210331061712_nav_menu_create.php b/database/migrations/20210331061712_nav_menu_create.php new file mode 100644 index 0000000..03f9c96 --- /dev/null +++ b/database/migrations/20210331061712_nav_menu_create.php @@ -0,0 +1,48 @@ +table('navigator',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'导航栏表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('pid','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'父ID']) + ->addColumn('name','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图标']) + ->addColumn('link','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0 启用 1 禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + + } +} diff --git a/database/migrations/20210331071533_platform_create.php b/database/migrations/20210331071533_platform_create.php new file mode 100644 index 0000000..c5dffa1 --- /dev/null +++ b/database/migrations/20210331071533_platform_create.php @@ -0,0 +1,43 @@ +table('platform',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'平台表'])->addIndex('id'); + $table + ->addColumn('name','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0 启用 1 禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210401012551_question_create.php b/database/migrations/20210401012551_question_create.php new file mode 100644 index 0000000..3956930 --- /dev/null +++ b/database/migrations/20210401012551_question_create.php @@ -0,0 +1,48 @@ +table('question',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'用户反馈'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('country_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'国家ID']) + ->addColumn('name','string',['limit'=>40,'default'=>'','null'=>false,'comment'=>'姓名']) + ->addColumn('email','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'邮箱']) + ->addColumn('order_sn','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('product_model','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品型号']) + ->addColumn('os','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'操作系统']) + ->addColumn('desc','text',['comment'=>'描述']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210401013411_country_create.php b/database/migrations/20210401013411_country_create.php new file mode 100644 index 0000000..697bf46 --- /dev/null +++ b/database/migrations/20210401013411_country_create.php @@ -0,0 +1,43 @@ +table('country',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'国家表'])->addIndex('id'); + $table + ->addColumn('code','string',['limit'=>4,'default'=>'','null'=>false,'comment'=>'地区码']) + ->addColumn('en','string',['limit'=>30,'default'=>'','null'=>false,'comment'=>'英文名']) + ->addColumn('locale','string',['limit'=>10,'default'=>'','null'=>false,'comment'=>'缩写']) + ->addColumn('zh','string',['limit'=>20,'default'=>'','null'=>false,'comment'=>'简体中文名']) + ->addColumn('tw','string',['limit'=>20,'default'=>'','null'=>false,'comment'=>'繁体中文名']) + ->addColumn('icon','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'国旗图标']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210401060214_soft_manual_create.php b/database/migrations/20210401060214_soft_manual_create.php new file mode 100644 index 0000000..3008ff7 --- /dev/null +++ b/database/migrations/20210401060214_soft_manual_create.php @@ -0,0 +1,46 @@ +table('soft_manual',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'软件帮助手册表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('file_type_id','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'文件类型ID']) + ->addColumn('name','string',['limit'=>40,'default'=>'','null'=>false,'comment'=>'名称']) + ->addColumn('introduce','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'下载介绍']) + ->addColumn('support','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'支持型号']) + ->addColumn('os','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'操作系统']) + ->addColumn('download_count','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'下载次数']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210401065205_article_create.php b/database/migrations/20210401065205_article_create.php new file mode 100644 index 0000000..bb37557 --- /dev/null +++ b/database/migrations/20210401065205_article_create.php @@ -0,0 +1,47 @@ +table('article',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'文章表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文章标题']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章描述']) + ->addColumn('thumb','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章缩略图']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('detail','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('click_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'点击次数']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210402074714_log_visit_create.php b/database/migrations/20210402074714_log_visit_create.php new file mode 100644 index 0000000..5bc27b6 --- /dev/null +++ b/database/migrations/20210402074714_log_visit_create.php @@ -0,0 +1,46 @@ +table('log_visit',['engine'=>'innodb','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'日志记录表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('admin_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'管理员ID']) + ->addColumn('admin_name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'管理员名称']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'请求的URL']) + ->addColumn('params','text',['comment'=>'请求参数']) + ->addColumn('controller','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'操作模块']) + ->addColumn('action','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'操作方法']) + ->addColumn('ip','string',['limit'=>15,'default'=>'','null'=>false,'comment'=>'访问IP']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->addIndex(['controller','create_time']) + ->create(); + } +} diff --git a/database/migrations/20210406071303_goods_images_create.php b/database/migrations/20210406071303_goods_images_create.php new file mode 100644 index 0000000..5c6b790 --- /dev/null +++ b/database/migrations/20210406071303_goods_images_create.php @@ -0,0 +1,40 @@ +table('goods_images',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品主图表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品ID']) + ->addColumn('image','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品图片']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406071431_goods_buy_now_create.php b/database/migrations/20210406071431_goods_buy_now_create.php new file mode 100644 index 0000000..1b6fe37 --- /dev/null +++ b/database/migrations/20210406071431_goods_buy_now_create.php @@ -0,0 +1,41 @@ +table('goods_buy_now',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品链接表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品ID']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'链接名称']) + ->addColumn('url','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'链接地址']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406071843_goods_connect_create.php b/database/migrations/20210406071843_goods_connect_create.php new file mode 100644 index 0000000..8c4315e --- /dev/null +++ b/database/migrations/20210406071843_goods_connect_create.php @@ -0,0 +1,41 @@ +table('goods_connect',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品相关表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品ID']) + ->addColumn('goods_category_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品分类ID']) + ->addColumn('connect_good_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'关联商品ID']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406074619_bulk_buy_create.php b/database/migrations/20210406074619_bulk_buy_create.php new file mode 100644 index 0000000..db26e09 --- /dev/null +++ b/database/migrations/20210406074619_bulk_buy_create.php @@ -0,0 +1,46 @@ +table('bulk_buy',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'大量采购表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品标题']) + ->addColumn('mode_number','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品型号']) + ->addColumn('email','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'邮箱']) + ->addColumn('arrival_country','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'收货地址']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('delivery_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'交货日期']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406080230_file_type_create.php b/database/migrations/20210406080230_file_type_create.php new file mode 100644 index 0000000..18e1dff --- /dev/null +++ b/database/migrations/20210406080230_file_type_create.php @@ -0,0 +1,44 @@ +table('file_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'文件类型'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406081049_comment_create.php b/database/migrations/20210406081049_comment_create.php new file mode 100644 index 0000000..fb1942b --- /dev/null +++ b/database/migrations/20210406081049_comment_create.php @@ -0,0 +1,46 @@ +table('comment',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'客户评价表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('avatar','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'头像']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('nickname','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'客户昵称']) + ->addColumn('comment','text',['comment'=>'评论']) + ->addColumn('url','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'产品链接']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210406082129_comment_image_create.php b/database/migrations/20210406082129_comment_image_create.php new file mode 100644 index 0000000..c6fce31 --- /dev/null +++ b/database/migrations/20210406082129_comment_image_create.php @@ -0,0 +1,40 @@ +table('comment_image',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'客户评价图片表'])->addIndex('id'); + $table + ->addColumn('comment_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'评论ID']) + ->addColumn('image','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图片']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210407060030_goods_soft_manual_create.php b/database/migrations/20210407060030_goods_soft_manual_create.php new file mode 100644 index 0000000..dcdd0bb --- /dev/null +++ b/database/migrations/20210407060030_goods_soft_manual_create.php @@ -0,0 +1,41 @@ +table('goods_soft_manual',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品手册驱动表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'文件类型ID']) + ->addColumn('file_type_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'文件类型ID']) + ->addColumn('soft_manual_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'文档驱动ID']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210408015958_admin_add_field.php b/database/migrations/20210408015958_admin_add_field.php new file mode 100644 index 0000000..6b30f44 --- /dev/null +++ b/database/migrations/20210408015958_admin_add_field.php @@ -0,0 +1,36 @@ +table('admin'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'after'=>'id','default'=>0,'null'=>false,'comment'=>'平台ID']) + ->update(); + } +} diff --git a/database/migrations/20210408055250_question_attachment.php b/database/migrations/20210408055250_question_attachment.php new file mode 100644 index 0000000..1353b5d --- /dev/null +++ b/database/migrations/20210408055250_question_attachment.php @@ -0,0 +1,39 @@ +table('question_attachment',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'用户反馈附件表'])->addIndex('id'); + $table + ->addColumn('question_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'反馈ID']) + ->addColumn('attach','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'附件']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210408074527_advertisement_create.php b/database/migrations/20210408074527_advertisement_create.php new file mode 100644 index 0000000..28f0ad9 --- /dev/null +++ b/database/migrations/20210408074527_advertisement_create.php @@ -0,0 +1,50 @@ +table('advertisement',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'广告表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('advertise_space_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'广告位ID']) + ->addColumn('advertise_space_name','string',['limit'=>30,'signed'=>false,'default'=>'','null'=>false,'comment'=>'广告位名称']) + ->addColumn('ad_name','string',['limit'=>40,'default'=>'','null'=>false,'comment'=>'名称']) + ->addColumn('image','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'广告图']) + ->addColumn('url','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'广告图链接']) + ->addColumn('start_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'开始时间']) + ->addColumn('stop_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'结束时间']) + ->addColumn('play_order','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'轮播顺序']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=可用,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210408082344_advertise_space_create.php b/database/migrations/20210408082344_advertise_space_create.php new file mode 100644 index 0000000..8fcba09 --- /dev/null +++ b/database/migrations/20210408082344_advertise_space_create.php @@ -0,0 +1,46 @@ +table('advertise_space',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'广告位表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('advertise_page_id','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'广告页面ID']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'广告位名称']) + ->addColumn('max_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'数量上限']) + ->addColumn('width','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'宽,单位像素']) + ->addColumn('height','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'长,单位像素']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210408083002_advertise_page_create.php b/database/migrations/20210408083002_advertise_page_create.php new file mode 100644 index 0000000..b649018 --- /dev/null +++ b/database/migrations/20210408083002_advertise_page_create.php @@ -0,0 +1,43 @@ +table('advertise_page',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'广告所属页表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>30,'default'=>'','null'=>false,'comment'=>'页面名称']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + + } +} diff --git a/database/migrations/20210409085237_goods_coupon_create.php b/database/migrations/20210409085237_goods_coupon_create.php new file mode 100644 index 0000000..8bb11a6 --- /dev/null +++ b/database/migrations/20210409085237_goods_coupon_create.php @@ -0,0 +1,43 @@ +table('goods_coupon',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'优惠券表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('old_code','string',['limit'=>30,'default'=>'','null'=>false,'comment'=>'旧口令']) + ->addColumn('new_code','string',['limit'=>30,'default'=>'','null'=>false,'comment'=>'新口令']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + + } +} diff --git a/database/migrations/20210410020249_platform_add_field.php b/database/migrations/20210410020249_platform_add_field.php new file mode 100644 index 0000000..796ef12 --- /dev/null +++ b/database/migrations/20210410020249_platform_add_field.php @@ -0,0 +1,38 @@ +table('platform'); + $table + ->addColumn('vi_color1','string',['limit'=>10,'after'=>'name','default'=>'','null'=>false,'comment'=>'品牌vi色1']) + ->addColumn('vi_color2','string',['limit'=>10,'after'=>'vi_color1','default'=>'','null'=>false,'comment'=>'品牌vi色2']) + ->addColumn('vi_color3','string',['limit'=>10,'after'=>'vi_color2','default'=>'','null'=>false,'comment'=>'品牌vi色3']) + ->addColumn('language_id','integer',['limit'=>10,'after'=>'vi_color3','signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言ID']) + ->addColumn('currency_id','integer',['limit'=>10,'after'=>'language_id','signed'=>false,'default'=>0,'null'=>false,'comment'=>'币种ID']) + ->update(); + } +} diff --git a/database/migrations/20210410023648_currency_create.php b/database/migrations/20210410023648_currency_create.php new file mode 100644 index 0000000..f379c7f --- /dev/null +++ b/database/migrations/20210410023648_currency_create.php @@ -0,0 +1,42 @@ +table('currency',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'币种表'])->addIndex('id'); + $table + ->addColumn('name','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'货币名称']) + ->addColumn('code','string',['limit'=>20,'default'=>'','null'=>false,'comment'=>'英文缩写']) + ->addColumn('signal','string',['limit'=>20,'default'=>'','null'=>false,'comment'=>'符号']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210411131000_platform_language_create.php b/database/migrations/20210411131000_platform_language_create.php new file mode 100644 index 0000000..8021bd0 --- /dev/null +++ b/database/migrations/20210411131000_platform_language_create.php @@ -0,0 +1,38 @@ +table('platform_language',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'平台语言表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言ID']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210411132944_menu_language_create.php b/database/migrations/20210411132944_menu_language_create.php new file mode 100644 index 0000000..332688f --- /dev/null +++ b/database/migrations/20210411132944_menu_language_create.php @@ -0,0 +1,39 @@ +table('menu_language',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'菜单语言表'])->addIndex('id'); +// $table +// ->addColumn('menu_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'菜单ID']) +// ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言ID']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->create(); + } +} diff --git a/database/migrations/20210412015616_platform_coin_create.php b/database/migrations/20210412015616_platform_coin_create.php new file mode 100644 index 0000000..a9b3adf --- /dev/null +++ b/database/migrations/20210412015616_platform_coin_create.php @@ -0,0 +1,39 @@ +table('platform_coin',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'平台币种表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('currency_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'币种ID']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210412021449_platform_menu_create.php b/database/migrations/20210412021449_platform_menu_create.php new file mode 100644 index 0000000..b498256 --- /dev/null +++ b/database/migrations/20210412021449_platform_menu_create.php @@ -0,0 +1,39 @@ +table('platform_menu',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'平台菜单表'])->addIndex('id'); +// $table +// ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言ID']) +// ->addColumn('menu_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'菜单ID']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->create(); + } +} diff --git a/database/migrations/20210412030346_site_create.php b/database/migrations/20210412030346_site_create.php new file mode 100644 index 0000000..c64f426 --- /dev/null +++ b/database/migrations/20210412030346_site_create.php @@ -0,0 +1,43 @@ +table('site',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'站点表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'所属品牌ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('currency_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'币种ID']) + ->addColumn('domain','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'域名']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210412031252_site_menu_create.php b/database/migrations/20210412031252_site_menu_create.php new file mode 100644 index 0000000..ed45172 --- /dev/null +++ b/database/migrations/20210412031252_site_menu_create.php @@ -0,0 +1,40 @@ +table('site_menu',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'站点栏目表'])->addIndex('id'); +// $table +// ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言ID']) +// ->addColumn('menu_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'菜单ID']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->create(); + + } +} diff --git a/database/migrations/20210412092533_drop_platform_menu_create.php b/database/migrations/20210412092533_drop_platform_menu_create.php new file mode 100644 index 0000000..da0bf9c --- /dev/null +++ b/database/migrations/20210412092533_drop_platform_menu_create.php @@ -0,0 +1,33 @@ +table('platform_menu')->drop(); + } +} diff --git a/database/migrations/20210412095945_site_menu_change.php b/database/migrations/20210412095945_site_menu_change.php new file mode 100644 index 0000000..1ab1390 --- /dev/null +++ b/database/migrations/20210412095945_site_menu_change.php @@ -0,0 +1,36 @@ +table('site_menu'); +// $table +// ->renameColumn('menu_id','navigator_id') +// ->update(); + } +} diff --git a/database/migrations/20210413083208_menu_platform_create.php b/database/migrations/20210413083208_menu_platform_create.php new file mode 100644 index 0000000..ff7ce47 --- /dev/null +++ b/database/migrations/20210413083208_menu_platform_create.php @@ -0,0 +1,41 @@ +table('menu_platform',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'站点栏目表'])->addIndex('id'); +// $table +// ->addColumn('menu_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'菜单ID']) +// ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'品牌ID']) +// ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) +// ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) +// ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) +// ->create(); + } +} diff --git a/database/migrations/20210413130939_menu_change_field_is_show_to_status.php b/database/migrations/20210413130939_menu_change_field_is_show_to_status.php new file mode 100644 index 0000000..91af359 --- /dev/null +++ b/database/migrations/20210413130939_menu_change_field_is_show_to_status.php @@ -0,0 +1,36 @@ +table('menu'); +// $table +// ->renameColumn('is_show','status') +// ->update(); + } +} diff --git a/database/migrations/20210414160618_soft_manual_add_field.php b/database/migrations/20210414160618_soft_manual_add_field.php new file mode 100644 index 0000000..9da98c0 --- /dev/null +++ b/database/migrations/20210414160618_soft_manual_add_field.php @@ -0,0 +1,40 @@ +table('soft_manual'); + $table + ->addColumn('file_name','string',['limit'=>60,'after'=>'introduce','default'=>'','null'=>false,'comment'=>'下载名称']) + ->addColumn('url','string',['limit'=>128,'after'=>'file_name','default'=>'','null'=>false,'comment'=>'下载链接']) + ->addColumn('btn_tips','string',['limit'=>50,'after'=>'file_name','default'=>'','null'=>false,'comment'=>'下载提示语']) + ->changeColumn('introduce','string',['limit'=>500,'default'=>'','null'=>false,'comment'=>'下载介绍']) + ->update(); + + } +} diff --git a/database/migrations/20210415014222_faq_create.php b/database/migrations/20210415014222_faq_create.php new file mode 100644 index 0000000..03ad644 --- /dev/null +++ b/database/migrations/20210415014222_faq_create.php @@ -0,0 +1,45 @@ +table('faq',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'常见问题表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'所属品牌ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('faq_type_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'常见问题分类ID']) + ->addColumn('question','string',['limit'=>150,'default'=>'','null'=>false,'comment'=>'问题内容']) + ->addColumn('answer','text',['comment'=>'回答内容']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210415014325_faq_type_create.php b/database/migrations/20210415014325_faq_type_create.php new file mode 100644 index 0000000..015473e --- /dev/null +++ b/database/migrations/20210415014325_faq_type_create.php @@ -0,0 +1,44 @@ +table('faq_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'常见问题分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210415074326_comment_modify_field.php b/database/migrations/20210415074326_comment_modify_field.php new file mode 100644 index 0000000..648f8ba --- /dev/null +++ b/database/migrations/20210415074326_comment_modify_field.php @@ -0,0 +1,36 @@ +table('comment'); + $table + ->changeColumn('avatar','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'头像']) + ->update(); + } +} diff --git a/database/migrations/20210415092350_advertisement_modify_field.php b/database/migrations/20210415092350_advertisement_modify_field.php new file mode 100644 index 0000000..2354091 --- /dev/null +++ b/database/migrations/20210415092350_advertisement_modify_field.php @@ -0,0 +1,37 @@ +table('advertisement'); + $table + ->renameColumn('ad_name','name') + ->changeColumn('name','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'名称']) + ->update(); + } +} diff --git a/database/migrations/20210415094038_question_add_field.php b/database/migrations/20210415094038_question_add_field.php new file mode 100644 index 0000000..256285f --- /dev/null +++ b/database/migrations/20210415094038_question_add_field.php @@ -0,0 +1,37 @@ +table('question'); + $table + ->addColumn('is_done','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'sort','signed'=>false,'default'=>0,'null'=>false,'comment'=>'解决与否,0=未解决,1=已解决']) + ->update(); + } +} diff --git a/database/migrations/20210415100810_coupon_subscribe.php b/database/migrations/20210415100810_coupon_subscribe.php new file mode 100644 index 0000000..c3cb05e --- /dev/null +++ b/database/migrations/20210415100810_coupon_subscribe.php @@ -0,0 +1,42 @@ +table('coupon_subscribe',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'优惠券领用记录表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'所属品牌ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('goods_coupon_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'优惠券ID']) + ->addColumn('email','string',['limit'=>150,'default'=>'','null'=>false,'comment'=>'订阅邮箱']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210417030635_goods_attribute_create.php b/database/migrations/20210417030635_goods_attribute_create.php new file mode 100644 index 0000000..61a10bf --- /dev/null +++ b/database/migrations/20210417030635_goods_attribute_create.php @@ -0,0 +1,43 @@ +table('goods_attribute',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品属性表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品ID']) + ->addColumn('attribute_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'属性ID']) + ->addColumn('value','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'商品属性值']) + ->addColumn('sort','integer',['limit'=> MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + + } +} diff --git a/database/migrations/20210417031148_attribute_create.php b/database/migrations/20210417031148_attribute_create.php new file mode 100644 index 0000000..996dc66 --- /dev/null +++ b/database/migrations/20210417031148_attribute_create.php @@ -0,0 +1,40 @@ +table('attribute',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'属性表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'属性名']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210417054827_goods_cates_create.php b/database/migrations/20210417054827_goods_cates_create.php new file mode 100644 index 0000000..a9852ed --- /dev/null +++ b/database/migrations/20210417054827_goods_cates_create.php @@ -0,0 +1,39 @@ +table('goods_cate',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'商品多分类表'])->addIndex('id'); + $table + ->addColumn('goods_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'商品ID']) + ->addColumn('goods_category_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'属性ID']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210417064504_goods_add_field.php b/database/migrations/20210417064504_goods_add_field.php new file mode 100644 index 0000000..359f646 --- /dev/null +++ b/database/migrations/20210417064504_goods_add_field.php @@ -0,0 +1,37 @@ +table('goods'); + $table + ->addColumn('main_img','string',['limit'=>128,'default'=>'','after'=>'model_number','null'=>false,'comment'=>'产品主图']) + ->removeColumn('params') + ->update(); + } +} diff --git a/database/migrations/20210417072211_goods_modify_field.php b/database/migrations/20210417072211_goods_modify_field.php new file mode 100644 index 0000000..491c3cd --- /dev/null +++ b/database/migrations/20210417072211_goods_modify_field.php @@ -0,0 +1,38 @@ +table('goods'); + $table + ->changeColumn('title','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'页面title']) + ->changeColumn('keywords','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'关键词']) + ->changeColumn('description','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'页面描述SEO用']) + ->update(); + } +} diff --git a/database/migrations/20210417084728_soft_manual_add_field_image.php b/database/migrations/20210417084728_soft_manual_add_field_image.php new file mode 100644 index 0000000..b192a30 --- /dev/null +++ b/database/migrations/20210417084728_soft_manual_add_field_image.php @@ -0,0 +1,36 @@ +table('soft_manual'); + $table + ->addColumn('image','string',['limit'=>60,'after'=>'url','default'=>'','null'=>false,'comment'=>'图片']) + ->update(); + } +} diff --git a/database/migrations/20210417092911_common_modify_field.php b/database/migrations/20210417092911_common_modify_field.php new file mode 100644 index 0000000..114dff2 --- /dev/null +++ b/database/migrations/20210417092911_common_modify_field.php @@ -0,0 +1,37 @@ +table('comment'); + $table + ->changeColumn('name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'评论标题']) + ->changeColumn('nickname','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'客户昵称']) + ->update(); + } +} diff --git a/database/migrations/20210419095734_language_remove_platform_id.php b/database/migrations/20210419095734_language_remove_platform_id.php new file mode 100644 index 0000000..ad50b57 --- /dev/null +++ b/database/migrations/20210419095734_language_remove_platform_id.php @@ -0,0 +1,34 @@ +table('language'); + $table->removeColumn('platform_id')->update(); + } +} diff --git a/database/migrations/20210420024741_soft_manual_modify_field.php b/database/migrations/20210420024741_soft_manual_modify_field.php new file mode 100644 index 0000000..6d1d672 --- /dev/null +++ b/database/migrations/20210420024741_soft_manual_modify_field.php @@ -0,0 +1,36 @@ +table('soft_manual'); + $table + ->changeColumn('name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'名称']) + ->update(); + } +} diff --git a/database/migrations/20210420031501_bulk_buy_add_field.php b/database/migrations/20210420031501_bulk_buy_add_field.php new file mode 100644 index 0000000..2b9b46e --- /dev/null +++ b/database/migrations/20210420031501_bulk_buy_add_field.php @@ -0,0 +1,36 @@ +table('bulk_buy'); + $table + ->addColumn('needed_num','integer',['limit'=>10,'after'=>'mode_number','default'=>0,'null'=>false,'comment'=>'需要数量']) + ->update(); + } +} diff --git a/database/migrations/20210420035207_faq_modify_field.php b/database/migrations/20210420035207_faq_modify_field.php new file mode 100644 index 0000000..bd9b459 --- /dev/null +++ b/database/migrations/20210420035207_faq_modify_field.php @@ -0,0 +1,37 @@ +table('faq'); + $table + ->changeColumn('question','text',['comment'=>'问题内容']) + ->update(); + + } +} diff --git a/database/migrations/20210420035731_soft_manual_modify_image_field.php b/database/migrations/20210420035731_soft_manual_modify_image_field.php new file mode 100644 index 0000000..257a459 --- /dev/null +++ b/database/migrations/20210420035731_soft_manual_modify_image_field.php @@ -0,0 +1,36 @@ +table('soft_manual'); + $table + ->changeColumn('image','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'图片']) + ->update(); + } +} diff --git a/database/migrations/20210421031859_goods_add_fields.php b/database/migrations/20210421031859_goods_add_fields.php new file mode 100644 index 0000000..d7b6fea --- /dev/null +++ b/database/migrations/20210421031859_goods_add_fields.php @@ -0,0 +1,38 @@ +table('goods'); + $table + ->addColumn('model','string',['limit'=>128,'default'=>'','after'=>'model_number','null'=>false,'comment'=>'模型型号']) + ->addColumn('sku','string',['limit'=>128,'default'=>'','after'=>'model','null'=>false,'comment'=>'SKU']) + ->addColumn('viewed','integer',['limit'=>10,'signed'=>false,'default'=>0,'after'=>'sku','null'=>false,'comment'=>'查看次数']) + ->update(); + } +} diff --git a/database/migrations/20210421121233_navigator_modify_field.php b/database/migrations/20210421121233_navigator_modify_field.php new file mode 100644 index 0000000..87fc76c --- /dev/null +++ b/database/migrations/20210421121233_navigator_modify_field.php @@ -0,0 +1,36 @@ +table('navigator'); + $table + ->renameColumn('link','url') + ->update(); + } +} diff --git a/database/migrations/20210421142424_soft_manual_add_field_status.php b/database/migrations/20210421142424_soft_manual_add_field_status.php new file mode 100644 index 0000000..56bf74a --- /dev/null +++ b/database/migrations/20210421142424_soft_manual_add_field_status.php @@ -0,0 +1,37 @@ +table('soft_manual'); + $table + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'download_count','signed'=>false,'default'=>0,'null'=>false,'comment'=>'状态,0=正常,1=禁用']) + ->update(); + } +} diff --git a/database/migrations/20210423015349_soft_manual_btn_create.php b/database/migrations/20210423015349_soft_manual_btn_create.php new file mode 100644 index 0000000..a36e0ea --- /dev/null +++ b/database/migrations/20210423015349_soft_manual_btn_create.php @@ -0,0 +1,40 @@ +table('soft_manual_btn',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'文档手册分表'])->addIndex('id'); + $table + ->addColumn('soft_manual_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'文档手册主表ID']) + ->addColumn('btn_tips','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'按钮名称']) + ->addColumn('url','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'下载链接']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210423044621_soft_manual_modify_field_file_name.php b/database/migrations/20210423044621_soft_manual_modify_field_file_name.php new file mode 100644 index 0000000..b4f7576 --- /dev/null +++ b/database/migrations/20210423044621_soft_manual_modify_field_file_name.php @@ -0,0 +1,36 @@ +table('soft_manual'); + $table + ->changeColumn('file_name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文件名']) + ->update(); + } +} diff --git a/database/migrations/20210430094547_goods_connect_modify_field.php b/database/migrations/20210430094547_goods_connect_modify_field.php new file mode 100644 index 0000000..0220e9f --- /dev/null +++ b/database/migrations/20210430094547_goods_connect_modify_field.php @@ -0,0 +1,37 @@ +table('goods_connect'); + $table + ->renameColumn('goods_category_id','type') + ->changeColumn('type','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'页面标识']) + ->update(); + } +} diff --git a/database/migrations/20210507084247_question_add_field_email.php b/database/migrations/20210507084247_question_add_field_email.php new file mode 100644 index 0000000..ec9502b --- /dev/null +++ b/database/migrations/20210507084247_question_add_field_email.php @@ -0,0 +1,40 @@ +table('question'); + $table + ->addColumn('is_send_email','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'is_done','signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否发送邮件,0=否,1=是']) + ->addColumn('is_send_status','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'is_send_email','signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否发送成功,0=否,1=是']) + ->addColumn('send_time','integer',['limit'=>10,'after'=>'is_send_status','signed'=>false,'default'=>0,'null'=>false,'comment'=>'发送时间']) + ->addColumn('send_details','text',['after'=>'send_time','null'=>true,'comment'=>'发送反馈']) + ->update(); + } +} diff --git a/database/migrations/20210514074651_soft_manual_add_field_sort.php b/database/migrations/20210514074651_soft_manual_add_field_sort.php new file mode 100644 index 0000000..176d953 --- /dev/null +++ b/database/migrations/20210514074651_soft_manual_add_field_sort.php @@ -0,0 +1,37 @@ +table('soft_manual'); + $table + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'os','signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->update(); + } +} diff --git a/database/migrations/20210517055631_navigator_add_field.php b/database/migrations/20210517055631_navigator_add_field.php new file mode 100644 index 0000000..4f4b8a7 --- /dev/null +++ b/database/migrations/20210517055631_navigator_add_field.php @@ -0,0 +1,38 @@ +table('navigator'); + $table + ->addColumn('is_top','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'status','signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否顶部导航,0=是,1=否']) + ->addColumn('is_foot','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'is_top','signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否底部导航,0=是,1=否']) + ->update(); + } +} diff --git a/database/migrations/20210602084418_goods_connect_modify_field_type.php b/database/migrations/20210602084418_goods_connect_modify_field_type.php new file mode 100644 index 0000000..e6556de --- /dev/null +++ b/database/migrations/20210602084418_goods_connect_modify_field_type.php @@ -0,0 +1,37 @@ +table('goods_connect'); + $table + ->changeColumn('type','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'商品分类ID']) + ->renameColumn('type','goods_category_id') + ->update(); + } +} diff --git a/database/migrations/20210611084756_do_select_id_to_null.php b/database/migrations/20210611084756_do_select_id_to_null.php new file mode 100644 index 0000000..461f341 --- /dev/null +++ b/database/migrations/20210611084756_do_select_id_to_null.php @@ -0,0 +1,142 @@ +table('advertise_space'); + $table + ->changeColumn('advertise_page_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'广告页面ID']) + ->update(); + + $table = $this->table('advertisement'); + $table + ->changeColumn('advertise_space_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'广告位ID']) + ->update(); + + $table = $this->table('coupon_subscribe'); + $table + ->changeColumn('goods_coupon_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'优惠券ID']) + ->update(); + + $table = $this->table('faq'); + $table + ->changeColumn('faq_type_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'常见问题分类ID']) + ->update(); + + $table = $this->table('faq'); + $table + ->changeColumn('faq_type_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'常见问题分类ID']) + ->update(); + + + $table = $this->table('goods'); + $table + ->changeColumn('goods_category_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品分类ID']) + ->update(); + + $table = $this->table('goods'); + $table + ->changeColumn('goods_category_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品分类ID']) + ->update(); + + + $table = $this->table('goods_attribute'); + $table + ->changeColumn('goods_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品ID']) + ->changeColumn('attribute_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'属性ID']) + ->update(); + + $table = $this->table('goods_buy_now'); + $table + ->changeColumn('goods_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品ID']) + ->update(); + + $table = $this->table('goods_connect'); + $table + ->changeColumn('goods_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品ID']) + ->changeColumn('goods_category_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品分类ID']) + ->changeColumn('connect_good_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'关联商品ID']) + ->update(); + + + $table = $this->table('goods_soft_manual'); + $table + ->changeColumn('goods_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'商品ID']) + ->changeColumn('file_type_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'文件类型ID']) + ->changeColumn('soft_manual_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'文档驱动ID']) + ->update(); + +// $table = $this->table('menu_language'); +// $table +// ->changeColumn('menu_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'菜单ID']) +// ->update(); + + +// $table = $this->table('menu_platform'); +// $table +// ->changeColumn('menu_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'菜单ID']) +// ->update(); +// +// $table = $this->table('menu_platform'); +// $table +// ->changeColumn('menu_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'菜单ID']) +// ->update(); + + $table = $this->table('question'); + $table + ->changeColumn('country_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'国家ID']) + ->changeColumn('order_sn','string',['limit'=>50,'default'=>'','null'=>false,'comment'=>'订单号']) + ->update(); + + + $table = $this->table('soft_manual'); + $table + ->changeColumn('file_type_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'文件类型ID']) + ->update(); + +// $table = $this->table('platform'); +// $table +// ->renameColumn('coin_id','currency_id') +// ->changeColumn('currency_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'币种ID']) +// ->update(); + +// $table = $this->table('platform_coin'); +// $table +// ->renameColumn('coin_id','currency_id') +// ->changeColumn('currency_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'币种ID']) +// ->update(); + +// $table = $this->table('site'); +// $table +// ->renameColumn('coin_id','currency_id') +// ->changeColumn('currency_id','integer',['limit'=>10,'default'=>null,'null'=>true,'comment'=>'币种ID']) +// ->update(); + + } +} diff --git a/database/migrations/20210612033548_goods_add_field_is_new.php b/database/migrations/20210612033548_goods_add_field_is_new.php new file mode 100644 index 0000000..88f4970 --- /dev/null +++ b/database/migrations/20210612033548_goods_add_field_is_new.php @@ -0,0 +1,38 @@ +table('goods'); + $table + ->addColumn('is_new','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'price','signed'=>false,'null'=>false,'default'=>1,'comment'=>'是否新品,0=是,1=否']) + ->addColumn('is_discount','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'price','signed'=>false,'null'=>false,'default'=>1,'comment'=>'折扣商品,0=是,1=否']) + ->update(); + } +} diff --git a/database/migrations/20210616031448_comment_modify_field_sort.php b/database/migrations/20210616031448_comment_modify_field_sort.php new file mode 100644 index 0000000..1a99a04 --- /dev/null +++ b/database/migrations/20210616031448_comment_modify_field_sort.php @@ -0,0 +1,37 @@ +table('comment'); + $table + ->changeColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'null'=>false,'default'=>1,'comment'=>'排序']) + ->update(); + } +} diff --git a/database/migrations/20210616041105_faq_type_modify_name.php b/database/migrations/20210616041105_faq_type_modify_name.php new file mode 100644 index 0000000..bfcaeda --- /dev/null +++ b/database/migrations/20210616041105_faq_type_modify_name.php @@ -0,0 +1,36 @@ +table('faq_type'); + $table + ->changeColumn('name','string',['limit'=>60,'null'=>false,'default'=>'','comment'=>'分类名称']) + ->update(); + } +} diff --git a/database/migrations/20210621034622_advertisement_add_fields.php b/database/migrations/20210621034622_advertisement_add_fields.php new file mode 100644 index 0000000..9d871af --- /dev/null +++ b/database/migrations/20210621034622_advertisement_add_fields.php @@ -0,0 +1,36 @@ +table('advertisement'); + $table + ->addColumn('command','string',['limit'=>255,'after'=>'play_order','null'=>false,'default'=>'','comment'=>'悬浮提示']) + ->update(); + } +} diff --git a/database/migrations/20210623020217_goods_modify_sort_filed_default.php b/database/migrations/20210623020217_goods_modify_sort_filed_default.php new file mode 100644 index 0000000..d52a03e --- /dev/null +++ b/database/migrations/20210623020217_goods_modify_sort_filed_default.php @@ -0,0 +1,36 @@ +table('goods'); + $table + ->changeColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>1,'null'=>false,'comment'=>'排序']) + ->update(); + } +} diff --git a/database/migrations/20210623025611_soft_manual_btn_add_field.php b/database/migrations/20210623025611_soft_manual_btn_add_field.php new file mode 100644 index 0000000..2e197ff --- /dev/null +++ b/database/migrations/20210623025611_soft_manual_btn_add_field.php @@ -0,0 +1,36 @@ +table('soft_manual_btn'); + $table + ->addColumn('file_name','string',['limit'=>128,'after'=>'url','null'=>false,'default'=>'','comment'=>'文件名称']) + ->update(); + } +} diff --git a/database/migrations/20210624081024_all_table_add_field_site_id.php b/database/migrations/20210624081024_all_table_add_field_site_id.php new file mode 100644 index 0000000..88cbd2a --- /dev/null +++ b/database/migrations/20210624081024_all_table_add_field_site_id.php @@ -0,0 +1,121 @@ +table('advertise_page'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('advertise_space'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('advertisement'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('article'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + + $table = $this->table('attribute'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('bulk_buy'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('comment'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + + $table = $this->table('coupon_subscribe'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('faq'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + + $table = $this->table('faq_type'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('file_type'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('goods'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + + $table = $this->table('goods_category'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('goods_coupon'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('navigator'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('question'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + + $table = $this->table('soft_manual'); + $table + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'after'=>'language_id','default'=>0,'null'=>false,'comment'=>'站点ID']) + ->update(); + } + +} diff --git a/database/migrations/20210628061201_goods_buy_now_url_modify.php b/database/migrations/20210628061201_goods_buy_now_url_modify.php new file mode 100644 index 0000000..a0c6524 --- /dev/null +++ b/database/migrations/20210628061201_goods_buy_now_url_modify.php @@ -0,0 +1,37 @@ +table('goods_buy_now'); + $table + ->changeColumn('url','text',['comment'=>'链接地址']) + ->update(); + + } +} diff --git a/database/migrations/20210702083911_soft_manual_add_field_file_md5.php b/database/migrations/20210702083911_soft_manual_add_field_file_md5.php new file mode 100644 index 0000000..224687e --- /dev/null +++ b/database/migrations/20210702083911_soft_manual_add_field_file_md5.php @@ -0,0 +1,36 @@ +table('soft_manual_btn'); + $table + ->addColumn('md5','string',['limit'=>32,'null'=>false,'after'=>'file_name','default'=>'','comment'=>'文件MD5值']) + ->update(); + } +} diff --git a/database/migrations/20210809075919_advertise_page_add_fields.php b/database/migrations/20210809075919_advertise_page_add_fields.php new file mode 100644 index 0000000..a9aab3c --- /dev/null +++ b/database/migrations/20210809075919_advertise_page_add_fields.php @@ -0,0 +1,36 @@ +table('advertise_page'); + $table + ->changeColumn('name', 'string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'页面名称']) + ->update(); + } +} diff --git a/database/migrations/20210811014604_article_type_create.php b/database/migrations/20210811014604_article_type_create.php new file mode 100644 index 0000000..01e1625 --- /dev/null +++ b/database/migrations/20210811014604_article_type_create.php @@ -0,0 +1,44 @@ +table('article_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'文章分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210811015327_article_add_field_create.php b/database/migrations/20210811015327_article_add_field_create.php new file mode 100644 index 0000000..1139c81 --- /dev/null +++ b/database/migrations/20210811015327_article_add_field_create.php @@ -0,0 +1,39 @@ +table('article'); + $table + ->addColumn('article_type_id','integer',['limit'=>10,'signed'=>false,'after'=>'site_id','default'=>0,'null'=>false,'comment'=>'文章分类ID']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'after'=>'sort','null'=>false,'comment'=>'状态,0=启动,1=禁用']) + ->changeColumn('detail','text',['comment'=>'文件详情']) + ->update(); + } +} diff --git a/database/migrations/20210811095547_article_add_field.php b/database/migrations/20210811095547_article_add_field.php new file mode 100644 index 0000000..868d0dc --- /dev/null +++ b/database/migrations/20210811095547_article_add_field.php @@ -0,0 +1,40 @@ +table('article'); + $table + ->addColumn('is_outer_chain','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'after'=>'status','null'=>false,'comment'=>'是否外链,0=是,1=否']) + ->addColumn('brief','string',['limit'=>255,'after'=>'is_outer_chain','default'=>'','null'=>false,'comment'=>'文章简介']) + ->addColumn('keywords','string',['limit'=>255,'after'=>'is_outer_chain','default'=>'','null'=>false,'comment'=>'关键字']) + ->addColumn('meta_title','string',['limit'=>255,'after'=>'is_outer_chain','default'=>'','null'=>false,'comment'=>'meta标题']) + ->update(); + } +} diff --git a/database/migrations/20210813033230_site_add_field.php b/database/migrations/20210813033230_site_add_field.php new file mode 100644 index 0000000..f9983fd --- /dev/null +++ b/database/migrations/20210813033230_site_add_field.php @@ -0,0 +1,37 @@ +table('site'); + $table + ->addColumn('app_id','string',['limit'=>32,'after'=>'status','default'=>'','null'=>false,'comment'=>'客户端APPID']) + ->addColumn('app_key','string',['limit'=>64,'after'=>'app_id','default'=>'','null'=>false,'comment'=>'客户端APPKEY']) + ->update(); + } +} diff --git a/database/migrations/20210823100319_two_level_create.php b/database/migrations/20210823100319_two_level_create.php new file mode 100644 index 0000000..5bf4b4e --- /dev/null +++ b/database/migrations/20210823100319_two_level_create.php @@ -0,0 +1,39 @@ +table('area',['engine'=>'innodb','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'地区联动表'])->addIndex('id'); + $table + ->addColumn('pid','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'父id']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'名称']) + ->addColumn('level','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'层级']) + ->addIndex(['pid']) + ->create(); + } +} diff --git a/database/migrations/20210824031002_buld_buy_add_field_area_id.php b/database/migrations/20210824031002_buld_buy_add_field_area_id.php new file mode 100644 index 0000000..f298057 --- /dev/null +++ b/database/migrations/20210824031002_buld_buy_add_field_area_id.php @@ -0,0 +1,36 @@ +table('bulk_buy'); + $table + ->addColumn('area_id','integer',['limit'=>10,'after'=>'site_id','default'=>0,'null'=>false,'comment'=>'地区ID']) + ->update(); + } +} diff --git a/database/migrations/20210824033049_buld_buy_add_field_phone.php b/database/migrations/20210824033049_buld_buy_add_field_phone.php new file mode 100644 index 0000000..385be48 --- /dev/null +++ b/database/migrations/20210824033049_buld_buy_add_field_phone.php @@ -0,0 +1,36 @@ +table('bulk_buy'); + $table + ->addColumn('phone','string',['limit'=>20,'after'=>'email','default'=>'','null'=>false,'comment'=>'联系电话']) + ->update(); + } +} diff --git a/database/migrations/20210824054435_coupon_scribe_add_field_phone.php b/database/migrations/20210824054435_coupon_scribe_add_field_phone.php new file mode 100644 index 0000000..ab8d7b2 --- /dev/null +++ b/database/migrations/20210824054435_coupon_scribe_add_field_phone.php @@ -0,0 +1,36 @@ +table('coupon_subscribe'); + $table + ->addColumn('phone','string',['limit'=>20,'default'=>'','after'=>'email','null'=>false,'comment'=>'手机号']) + ->update(); + } +} diff --git a/database/migrations/20210825095514_question_add_field_phone.php b/database/migrations/20210825095514_question_add_field_phone.php new file mode 100644 index 0000000..09f5786 --- /dev/null +++ b/database/migrations/20210825095514_question_add_field_phone.php @@ -0,0 +1,36 @@ +table('question'); + $table + ->addColumn('phone','string',['limit'=>20,'default'=>'','after'=>'email','null'=>false,'comment'=>'手机号']) + ->update(); + } +} diff --git a/database/migrations/20210923024657_images_files_create.php b/database/migrations/20210923024657_images_files_create.php new file mode 100644 index 0000000..8c935e3 --- /dev/null +++ b/database/migrations/20210923024657_images_files_create.php @@ -0,0 +1,45 @@ +table('attachment',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'附件表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('path','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'相对路径']) + ->addColumn('local','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'本地路径']) + ->addColumn('hash','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'文件hash']) + ->addColumn('md5','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'文件md5']) + ->addColumn('name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文件名']) + ->addColumn('type','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文件类型']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20210928085406_bulk_buy_modify_field.php b/database/migrations/20210928085406_bulk_buy_modify_field.php new file mode 100644 index 0000000..b1bb8e1 --- /dev/null +++ b/database/migrations/20210928085406_bulk_buy_modify_field.php @@ -0,0 +1,36 @@ +table('bulk_buy'); + $table + ->addColumn('model_name','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'产品型号']) + ->update(); + } +} diff --git a/database/migrations/20211012060159_advertise_modify_field.php b/database/migrations/20211012060159_advertise_modify_field.php new file mode 100644 index 0000000..01092f6 --- /dev/null +++ b/database/migrations/20211012060159_advertise_modify_field.php @@ -0,0 +1,36 @@ +table('advertisement'); + $table + ->changeColumn('play_order','integer',['limit'=>10,'signed'=>false,'default'=>1,'null'=>false,'comment'=>'轮播顺序']) + ->update(); + } +} diff --git a/database/migrations/20211223033655_user_create.php b/database/migrations/20211223033655_user_create.php new file mode 100644 index 0000000..03ca4b6 --- /dev/null +++ b/database/migrations/20211223033655_user_create.php @@ -0,0 +1,57 @@ +table('user',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8mb4','primary_key'=>'id','comment'=>'用户表'])->addIndex('id'); + $table + ->addColumn('uc_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'用户全局维一ID']) + ->addColumn('admin_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'管理员ID']) + ->addColumn('org_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'组织ID']) + ->addColumn('role_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'用户角色ID']) + ->addColumn('dept_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'部门ID']) + ->addColumn('staff_code','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'用户唯一标识符']) + ->addColumn('nickname','string',['limit'=>64,'default'=>'','null'=>false,'comment'=>'用户昵称']) + ->addColumn('mobile','string',['limit'=>11,'default'=>'','null'=>false,'comment'=>'手机号']) + ->addColumn('email','string',['limit'=>64,'default'=>'','null'=>false,'comment'=>'邮箱']) + ->addColumn('avatar','string',['limit'=>120,'default'=>'','null'=>false,'comment'=>'用户头像']) + ->addColumn('gender','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'0为保密;1为男;2为女']) + ->addColumn('signin_ip','string',['limit'=>15,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'登录ip']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'0为启用;1为禁用']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'注册时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->addColumn('signin_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'登录时间']) + ->addIndex('nickname') + ->addIndex('mobile') + ->addIndex('admin_id') + ->addIndex('dept_id') + ->addIndex('uc_id') + ->create(); + } +} diff --git a/database/migrations/20220321015125_investment_create.php b/database/migrations/20220321015125_investment_create.php new file mode 100644 index 0000000..593b416 --- /dev/null +++ b/database/migrations/20220321015125_investment_create.php @@ -0,0 +1,53 @@ +table('investment',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'招商留言表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('country_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'国家ID']) + ->addColumn('province_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'省']) + ->addColumn('city_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'市']) + ->addColumn('area','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'合作区域']) + ->addColumn('phone','string',['limit'=>30,'default'=>'','null'=>false,'comment'=>'手机号']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'姓名']) + ->addColumn('email','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'邮箱']) + ->addColumn('wechat','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'微信']) + ->addColumn('qq','string',['limit'=>60,'default'=>'','null'=>false,'comment'=>'QQ']) + ->addColumn('desc','text',['comment'=>'留言详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('is_open','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'厂家查看:0=否,1=是']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220328015901_investment_add_field.php b/database/migrations/20220328015901_investment_add_field.php new file mode 100644 index 0000000..33257ae --- /dev/null +++ b/database/migrations/20220328015901_investment_add_field.php @@ -0,0 +1,36 @@ +table('investment'); + $table + ->addColumn('from','string',['limit'=>30,'default'=>'','after'=>'area','null'=>false,'comment'=>'来源']) + ->update(); + } +} diff --git a/database/migrations/20220414085023_system_config_create.php b/database/migrations/20220414085023_system_config_create.php new file mode 100644 index 0000000..ab71518 --- /dev/null +++ b/database/migrations/20220414085023_system_config_create.php @@ -0,0 +1,47 @@ +table('system_config',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'系统配置'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('type','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'类型1=文本,2=图片,3=富文本']) + ->addColumn('page','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'所属页']) + ->addColumn('pos','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'位置']) + ->addColumn('name','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'配置名']) + ->addColumn('value','text',['null'=>true,'default'=>null,'comment'=>'配置值']) + ->addColumn('image','text',['null'=>true,'default'=>null,'comment'=>'图片']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064045_resource_create.php b/database/migrations/20220419064045_resource_create.php new file mode 100644 index 0000000..3d57112 --- /dev/null +++ b/database/migrations/20220419064045_resource_create.php @@ -0,0 +1,55 @@ +table('resource',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'资源中心表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('resource_type_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'资源中心分类ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文章标题']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章描述']) + ->addColumn('thumb','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章缩略图']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('detail','text',['comment'=>'详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('click_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'点击次数']) + ->addColumn('meta_title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'标题']) + ->addColumn('brief','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('keywords','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'关键字']) + ->addColumn('is_outer_chain','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'是否外链,0=是,1=否']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'状态,0=启动,1=禁用']) + ->addColumn('is_on_index','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'是否在首页,0=否,1=是']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064056_brand_create.php b/database/migrations/20220419064056_brand_create.php new file mode 100644 index 0000000..64ba1b6 --- /dev/null +++ b/database/migrations/20220419064056_brand_create.php @@ -0,0 +1,55 @@ +table('brand',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'品牌矩阵表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('brand_type_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'品牌矩阵分类ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文章标题']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章描述']) + ->addColumn('thumb','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章缩略图']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('detail','text',['comment'=>'详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('click_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'点击次数']) + ->addColumn('meta_title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'标题']) + ->addColumn('brief','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('keywords','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'关键字']) + ->addColumn('is_outer_chain','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'是否外链,0=是,1=否']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'状态,0=启动,1=禁用']) + ->addColumn('is_on_index','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'是否在首页,0=否,1=是']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064216_brand_type_create.php b/database/migrations/20220419064216_brand_type_create.php new file mode 100644 index 0000000..1f6a9cb --- /dev/null +++ b/database/migrations/20220419064216_brand_type_create.php @@ -0,0 +1,44 @@ +table('brand_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'品牌矩阵分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064224_resource_type_create.php b/database/migrations/20220419064224_resource_type_create.php new file mode 100644 index 0000000..afb3b01 --- /dev/null +++ b/database/migrations/20220419064224_resource_type_create.php @@ -0,0 +1,44 @@ +table('resource_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'资源中心分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064719_news_type_create.php b/database/migrations/20220419064719_news_type_create.php new file mode 100644 index 0000000..9ede708 --- /dev/null +++ b/database/migrations/20220419064719_news_type_create.php @@ -0,0 +1,44 @@ +table('news_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'新闻分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419064722_news_create.php b/database/migrations/20220419064722_news_create.php new file mode 100644 index 0000000..a1045ac --- /dev/null +++ b/database/migrations/20220419064722_news_create.php @@ -0,0 +1,55 @@ +table('news',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'新闻动态表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('news_type_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'品牌矩阵分类ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文章标题']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章描述']) + ->addColumn('thumb','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章缩略图']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('detail','text',['comment'=>'详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('click_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'点击次数']) + ->addColumn('meta_title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'标题']) + ->addColumn('brief','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('keywords','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'关键字']) + ->addColumn('is_outer_chain','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'是否外链,0=是,1=否']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'状态,0=启动,1=禁用']) + ->addColumn('is_on_index','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'是否在首页,0=否,1=是']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419082055_join_create.php b/database/migrations/20220419082055_join_create.php new file mode 100644 index 0000000..a964333 --- /dev/null +++ b/database/migrations/20220419082055_join_create.php @@ -0,0 +1,55 @@ +table('join',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'加入我们表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('language_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'语音包ID']) + ->addColumn('join_type_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'加入我们分类ID']) + ->addColumn('site_id','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'站点ID']) + ->addColumn('title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'文章标题']) + ->addColumn('desc','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章描述']) + ->addColumn('thumb','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'文章缩略图']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('detail','text',['comment'=>'详情']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'signed'=>false,'null'=>false,'comment'=>'排序']) + ->addColumn('click_num','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'点击次数']) + ->addColumn('meta_title','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'标题']) + ->addColumn('brief','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'描述']) + ->addColumn('keywords','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'关键字']) + ->addColumn('is_outer_chain','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'是否外链,0=是,1=否']) + ->addColumn('status','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>1,'null'=>false,'comment'=>'状态,0=启动,1=禁用']) + ->addColumn('is_on_index','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'是否在首页,0=否,1=是']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220419082058_join_type_create.php b/database/migrations/20220419082058_join_type_create.php new file mode 100644 index 0000000..eb8dd9d --- /dev/null +++ b/database/migrations/20220419082058_join_type_create.php @@ -0,0 +1,44 @@ +table('join_type',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'加入我们分类表'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'分类名称']) + ->addColumn('desc','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类描述']) + ->addColumn('icon','string',['limit'=>128,'default'=>'','null'=>false,'comment'=>'分类图标']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220420061448_resource_add_field.php b/database/migrations/20220420061448_resource_add_field.php new file mode 100644 index 0000000..4f44c93 --- /dev/null +++ b/database/migrations/20220420061448_resource_add_field.php @@ -0,0 +1,36 @@ +table('resource',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'资源中心表'])->addIndex('id'); + $table + ->addColumn('s_title','string',['limit'=>255,'default'=>'','after'=>'title','null'=>false,'comment'=>'小标题']) + ->update(); + } +} diff --git a/database/migrations/20220420071052_brand_add_field.php b/database/migrations/20220420071052_brand_add_field.php new file mode 100644 index 0000000..2ff5e14 --- /dev/null +++ b/database/migrations/20220420071052_brand_add_field.php @@ -0,0 +1,44 @@ +table('brand',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'品牌矩阵表'])->addIndex('id'); + $table + ->addColumn('website','string',['limit'=>128,'default'=>'','after'=>'brief','null'=>false,'comment'=>'网址']) + ->addColumn('cname','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'中文名']) + ->addColumn('en_name','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'英文名']) + ->addColumn('belong','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'所属公司']) + ->addColumn('turnover','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'营业额']) + ->addColumn('brand_cate','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'品牌类型']) + ->addColumn('work_address','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'办公地点']) + ->addColumn('founded','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'成立时间']) + ->addColumn('founder','string',['limit'=>255,'default'=>'','after'=>'brief','null'=>false,'comment'=>'创始人']) + ->update(); + } +} diff --git a/database/migrations/20220513072007_video_create.php b/database/migrations/20220513072007_video_create.php new file mode 100644 index 0000000..2ee1a7d --- /dev/null +++ b/database/migrations/20220513072007_video_create.php @@ -0,0 +1,45 @@ +table('video',['engine'=>'InnoDB','auto_increment'=>true,'charset'=>'utf8','primary_key'=>'id','comment'=>'视频管理'])->addIndex('id'); + $table + ->addColumn('platform_id','integer',['limit'=>10,'default'=>0,'null'=>false,'comment'=>'平台ID']) + ->addColumn('site_id','integer',['limit'=>MysqlAdapter::INT_TINY,'default'=>0,'null'=>false,'comment'=>'语言包ID']) + ->addColumn('name','string',['limit'=>32,'default'=>'','null'=>false,'comment'=>'视频名称']) + ->addColumn('image','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'视频图片']) + ->addColumn('url','string',['limit'=>255,'default'=>'','null'=>false,'comment'=>'链接']) + ->addColumn('sort','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'排序']) + ->addColumn('is_top','integer',['limit'=>MysqlAdapter::INT_TINY,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'是否置顶']) + ->addColumn('create_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'创建时间']) + ->addColumn('update_time','integer',['limit'=>10,'signed'=>false,'default'=>0,'null'=>false,'comment'=>'更新时间']) + ->create(); + } +} diff --git a/database/migrations/20220622100342_goods_add_field_hot.php b/database/migrations/20220622100342_goods_add_field_hot.php new file mode 100644 index 0000000..1053daa --- /dev/null +++ b/database/migrations/20220622100342_goods_add_field_hot.php @@ -0,0 +1,38 @@ +table('goods'); + $table + ->addColumn('is_hot','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'price','signed'=>false,'null'=>false,'default'=>1,'comment'=>'是否热门,0=是,1=否']) + ->addColumn('is_recommend','integer',['limit'=>MysqlAdapter::INT_TINY,'after'=>'price','signed'=>false,'null'=>false,'default'=>1,'comment'=>'是否推荐,0=是,1=否']) + ->update(); + } +} diff --git a/database/seeds/AdminAdd.php b/database/seeds/AdminAdd.php new file mode 100644 index 0000000..6b65a8f --- /dev/null +++ b/database/seeds/AdminAdd.php @@ -0,0 +1,89 @@ + null, + 'mobile' => '15207335533', + 'code' => 'YC001', + 'platform_id'=> 0, + 'role_id' => 1, + 'org_id' => 1, + 'dept_group_id'=> 1, + 'dept_id' => 1, + 'avatar' => 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + 'nickname' => 'admin', + 'username' => 'admin', + 'password' => 'a20dddcf28da48f605ac8412384b3e36', + 'create_ip' => '127.0.0.1', + 'create_time'=> time(), + 'update_time'=> time(), + ],[ + 'id' => null, + 'mobile' => '15207335533', + 'code' => 'YC002', + 'platform_id'=> 1, + 'role_id' => 1, + 'org_id' => 1, + 'dept_group_id'=> 1, + 'dept_id' => 1, + 'avatar' => 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + 'nickname' => 'yottamaster', + 'username' => 'yottamaster', + 'password' => 'a20dddcf28da48f605ac8412384b3e36', + 'create_ip' => '127.0.0.1', + 'create_time'=> time(), + 'update_time'=> time(), + ],[ + 'id' => null, + 'mobile' => '15207335533', + 'code' => 'YC003', + 'platform_id'=> 2, + 'role_id' => 1, + 'org_id' => 1, + 'dept_group_id'=> 1, + 'dept_id' => 1, + 'avatar' => 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + 'nickname' => 'idsonix', + 'username' => 'idsonix', + 'password' => 'a20dddcf28da48f605ac8412384b3e36', + 'create_ip' => '127.0.0.1', + 'create_time'=> time(), + 'update_time'=> time(), + ],[ + 'id' => null, + 'mobile' => '15207335533', + 'code' => 'YC004', + 'platform_id'=> 3, + 'role_id' => 1, + 'org_id' => 1, + 'dept_group_id'=> 1, + 'dept_id' => 1, + 'avatar' => 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + 'nickname' => 'ntonpower', + 'username' => 'ntonpower', + 'password' => 'a20dddcf28da48f605ac8412384b3e36', + 'create_ip' => '127.0.0.1', + 'create_time'=> time(), + 'update_time'=> time(), + ], + + ]; + + $table = $this->table('admin'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/AdminConfigInit.php b/database/seeds/AdminConfigInit.php new file mode 100644 index 0000000..360d6f9 --- /dev/null +++ b/database/seeds/AdminConfigInit.php @@ -0,0 +1,92 @@ + null, + "platform_id" => 1, + "language_id" => 0, + "site_id" => 1, + "type" => 2, + "page" => "logo", + "pos" => "logo", + "name" => "logo", + "value" => "", + "image" => "[[\"uid\" => \"1650272555373\",\"url\" => \"https => //cdn.yottamaster.com/2022/05/19/cms_165295142351423813XLYXCnNj.jpg\",\"image\" => \"2022/05/19/cms_165295142351423813XLYXCnNj.jpg\",\"md5\" => \"3795d70979842ad5706bdd4b8d367581\",\"status\" => \"success\"]]", + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 0, + "site_id" => 1, + "type" => 2, + "page" => "尾部-logo", + "pos" => "footer", + "name" => "logo", + "value" => "", + "image" => "[[\"uid\" => \"1650272555373\",\"url\" => \"https => //cdn.yottamaster.com/2022/05/19/cms_165295142351423813XLYXCnNj.jpg\",\"image\" => \"2022/05/19/cms_165295142351423813XLYXCnNj.jpg\",\"md5\" => \"3795d70979842ad5706bdd4b8d367581\",\"status\" => \"success\"]]", + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 0, + "site_id" => 1, + "type" => 1, + "page" => "尾部-版权", + "pos" => "footer", + "name" => "copyright", + "value" => "Copyright©2018-2028 ORICO Technologies Co.,Ltd 版权所有", + "image" => null, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 0, + "site_id" => 1, + "type" => 1, + "page" => "尾部-备案号1", + "pos" => "footer", + "name" => "beian1", + "value" => "粤ICP备2022066802号-1", + "image" => "", + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 0, + "site_id" => 1, + "type" => 1, + "page" => "尾部-备案号2", + "pos" => "footer", + "name" => "beian2", + "value" => "粤公网安备 44030702002297号", + "image" => null, + "create_time" => time(), + "update_time" => time() + ] + ]; + $table = $this->table('system_config'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/CountryInit.php b/database/seeds/CountryInit.php new file mode 100644 index 0000000..3cf074c --- /dev/null +++ b/database/seeds/CountryInit.php @@ -0,0 +1,1210 @@ + null, + 'code' => $item['code'], + 'en' => $item['en'], + 'locale' => $item['locale'], + 'zh' => $item['zh'], + 'tw' => $item['tw'], + 'icon' => '', + 'create_time' => time(), + ]; + } + + $table = $this->table('country'); + $table->insert($result)->saveData(); + + } +} \ No newline at end of file diff --git a/database/seeds/CurrencyInit.php b/database/seeds/CurrencyInit.php new file mode 100644 index 0000000..65169fd --- /dev/null +++ b/database/seeds/CurrencyInit.php @@ -0,0 +1,80 @@ + null, + 'name' => '人民币', + 'code' => 'CNY', + 'signal' => '¥', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '美元', + 'code' => 'USD', + 'signal' => '$', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '日元', + 'code' => 'JPY', + 'signal' => '¥', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '欧元', + 'code' => 'EUR', + 'signal' => '', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '越南盾', + 'code' => 'VND', + 'signal' => '', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '泰铢', + 'code' => 'THP', + 'signal' => 'BT.', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '盾', + 'code' => 'IDR', + 'signal' => 'Rps.', + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '巴西雷亚尔', + 'code' => 'BRL', + 'signal' => '', + 'status' => 0, + 'create_time' => time() + ] + ]; + + $table = $this->table('currency'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/LanguageInit.php b/database/seeds/LanguageInit.php new file mode 100644 index 0000000..e9ea8f8 --- /dev/null +++ b/database/seeds/LanguageInit.php @@ -0,0 +1,132 @@ + null, + 'name' => '中文', + 'code' => 'zh-cn', + 'icon' => 'zh-cn.jpg', + 'locale' => 'zh-cn', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '英文', + 'code' => 'en', + 'icon' => 'en.jpg', + 'locale' => 'en', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '日文', + 'code' => 'jp', + 'icon' => 'jp.jpg', + 'locale' => 'jp', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '越南语', + 'code' => 'VU', + 'icon' => 'VU.jpg', + 'locale' => 'VU', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '泰语', + 'code' => 'TH', + 'icon' => 'TH.jpg', + 'locale' => 'TH', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '印尼语', + 'code' => 'IN', + 'icon' => 'IN.jpg', + 'locale' => 'IN', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '韩语', + 'code' => 'KR', + 'icon' => 'kr.jpg', + 'locale' => 'KR', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '葡萄牙语', + 'code' => 'pt', + 'icon' => 'pt.jpg', + 'locale' => 'pt', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '德语', + 'code' => 'de', + 'icon' => 'de.jpg', + 'locale' => 'de', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '俄语', + 'code' => 'ru', + 'icon' => 'ru.jpg', + 'locale' => 'ru', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '法语', + 'code' => 'fr', + 'icon' => 'fr.jpg', + 'locale' => 'fr', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '阿拉伯语', + 'code' => 'al', + 'icon' => 'al.jpg', + 'locale' => 'al', + 'sort' => mt_rand(1,255), + 'status' => 0, + 'create_time' => time() + ] + ]; + + $table = $this->table('language'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/PlatformInit.php b/database/seeds/PlatformInit.php new file mode 100644 index 0000000..70a156f --- /dev/null +++ b/database/seeds/PlatformInit.php @@ -0,0 +1,39 @@ + 1, + "name" => Env::get('platform_name'), + "vi_color1" => "#1233ab", + "vi_color2" => "#1231cd", + "vi_color3" => "#1112ef", + "language_id" => 1, + "currency_id" => 1, + "desc" => "", + "icon" => "", + "sort" => 1, + "status" => 0, + "create_time" => time(), + "update_time" => time() + ] + ]; + + $table = $this->table('platform'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/RoleInitAdd.php b/database/seeds/RoleInitAdd.php new file mode 100644 index 0000000..e71e4dc --- /dev/null +++ b/database/seeds/RoleInitAdd.php @@ -0,0 +1,73 @@ + null, + 'name' => 'admin', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '财务', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '总经办', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '业务经理', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '业务员', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '供应链', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '产品经理', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '产品编辑', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '人力资源', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '商务/跟单', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '新媒体宣传', + 'create_time' => time() + ],[ + 'id' => null, + 'name' => '后台接口测试专用', + 'create_time' => time() + ] + ]; + + $table = $this->table('role'); + $table->insert($data)->saveData(); + + } +} \ No newline at end of file diff --git a/database/seeds/SiteCurrencyInit.php b/database/seeds/SiteCurrencyInit.php new file mode 100644 index 0000000..ac0cba7 --- /dev/null +++ b/database/seeds/SiteCurrencyInit.php @@ -0,0 +1,86 @@ + null, + "platform_id" => 1, + "currency_id" => 1, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 2, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 3, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 4, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 5, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 5, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 6, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 7, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "currency_id" => 8, + "create_time" => time(), + "update_time" => time() + ] + ]; + $table = $this->table('platform_coin'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/SiteInit.php b/database/seeds/SiteInit.php new file mode 100644 index 0000000..a467455 --- /dev/null +++ b/database/seeds/SiteInit.php @@ -0,0 +1,108 @@ + 1, + "platform_id" => 1, + "language_id" => 1, + "currency_id" => 1, + "domain" => $plat_en_name.".com", + "status" => 0, + "app_id" => "4d08fcadda5c097eb8b7eb4492551cdc", + "app_key" => "7145cc463e91d43a17810950d3819eb2", + "create_time" => 1650012195, + "update_time" => 1652947961 + ], + [ + "id" => 2, + "platform_id" => 1, + "language_id" => 2, + "currency_id" => 2, + "domain" => $plat_en_name.".us", + "status" => 0, + "app_id" => "a97b5fe1492ae774f1f0b12bf518d604", + "app_key" => "268674cd38f97540d6d990d8248cc6b3", + "create_time" => 1650012207, + "update_time" => 1652947965 + ], + [ + "id" => 3, + "platform_id" => 1, + "language_id" => 3, + "currency_id" => 3, + "domain" => $plat_en_name.".jp", + "status" => 0, + "app_id" => "0093bc0066f8c9a70c4389831019863a", + "app_key" => "0fb6f16ea1c7a3aaa3f6540ce8d0de99", + "create_time" => 1650012218, + "update_time" => 1652947969 + ], + [ + "id" => 4, + "platform_id" => 1, + "language_id" => 4, + "currency_id" => 5, + "domain" => $plat_en_name.".vn", + "status" => 0, + "app_id" => "cf45663d54e3f6426eb597f9f3e593da", + "app_key" => "0b55b377c51b0e5f81a31b79527e4916", + "create_time" => 1650012227, + "update_time" => 1652947975 + ], + [ + "id" => 5, + "platform_id" => 1, + "language_id" => 5, + "currency_id" => 6, + "domain" => $plat_en_name.".th", + "status" => 0, + "app_id" => "db448953994b5eed73c975b2b695bd95", + "app_key" => "edb87326041984651081237f802b41cb", + "create_time" => 1650012243, + "update_time" => 1652947980 + ], + [ + "id" => 6, + "platform_id" => 1, + "language_id" => 6, + "currency_id" => 7, + "domain" => $plat_en_name.".in", + "status" => 0, + "app_id" => "627f2bddcdf911bb4cdb66ec59b4164d", + "app_key" => "fc4b9fbd33f53d2da6619c1ea4151c34", + "create_time" => 1650012258, + "update_time" => 1652947985 + ], + [ + "id" => 7, + "platform_id" => 1, + "language_id" => 7, + "currency_id" => 1, + "domain" => $plat_en_name.".kr", + "status" => 0, + "app_id" => "0e082a09f3049391d857946ac0397946", + "app_key" => "3f67328e1ab41f9c8ada33ccad5d2e1f", + "create_time" => 1650012281, + "update_time" => 1652947990 + ] + ]; + $table = $this->table('site'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/SiteLanguageInit.php b/database/seeds/SiteLanguageInit.php new file mode 100644 index 0000000..cdc1faa --- /dev/null +++ b/database/seeds/SiteLanguageInit.php @@ -0,0 +1,58 @@ + null, + "platform_id" => 1, + "language_id" => 1, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 2, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 3, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 4, + "create_time" => time(), + "update_time" => time() + ], + [ + "id" => null, + "platform_id" => 1, + "language_id" => 5, + "create_time" => time(), + "update_time" => time() + ] + ]; + + $table = $this->table('platform_language'); + $table->insert($data)->saveData(); + } +} \ No newline at end of file diff --git a/database/seeds/TwoLevelData.php b/database/seeds/TwoLevelData.php new file mode 100644 index 0000000..51024de --- /dev/null +++ b/database/seeds/TwoLevelData.php @@ -0,0 +1,65 @@ + $item['code'], + 'pid' => 0, + 'name' => $item['name'], + 'level' => 1, + ]; + if (isset($item['children'])) { + foreach ($item['children'] as $item1) { + $result[] = [ + 'id' => $item1['code'], + 'pid' => $item['code'], + 'name' => $item1['name'], + 'level' => 2 + ]; + } + if (isset($item1['children'])) { + foreach ($item1['children'] as $item2) { + $result[] = [ + 'id' => $item2['code'], + 'pid' => $item1['code'], + 'name' => $item2['name'], + 'level' => 3 + ]; + } + if (isset($item2['children'])) { + foreach ($item2['children'] as $item3) { + $result[] = [ + 'id' => $item3['code'], + 'pid' => $item2['code'], + 'name' => $item3['name'], + 'level' => 4 + ]; + } + } + } + } + } + + $table = $this->table('area'); + $table->insert($result)->saveData(); + } +} \ No newline at end of file diff --git a/env.sample b/env.sample new file mode 100644 index 0000000..8ec03a8 --- /dev/null +++ b/env.sample @@ -0,0 +1,52 @@ +APP_DEBUG=trueIdsonix +PLATFORM_NAME="合金桌面" +PLATFORM_EN_NAME="setmspace" + +[APP] +DEFAULT_TIMEZONE=Asia/Shanghai + +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +DATABASE = setmspace +USERNAME = root +PASSWORD = 123456 +HOSTPORT = 3306 +CHARSET = utf8 +PREFIX = s_ +DEBUG = true + +[REDIS] +HOST=127.0.0.1 +PORT=6379 +PASS=orico@f2b211 +SELECT=0 + +[JWT_CONFIG] +ISS=setmspace +EXP=604801 + +[LANG] +default_lang=zh-cn + +[QINIU] +cdn=https://cdn.yottamaster.com/ + +[EMAIL] +MAIL_MAILER=smtp +MAIL_HOST=smtp.qiye.aliyun.com +MAIL_PORT=465 +MAIL_USERNAME=services@orico.com.cn +MAIL_PASSWORD= +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=services@orico.com.cn +MAIL_FROM_NAME=ORICO +#MAIL_TO_ADDRESS=supports@yottamaster.com +MAIL_TO_ADDRESS=yulinzhihou@163.com + +[SSO] +UC_URL=https://dev.uc.f2b211.com +UC_API_VERSION=v1 + +[CDN] +URL=https://cdn.yottamaster.com/ diff --git a/extend/apiRes/Api.php b/extend/apiRes/Api.php new file mode 100644 index 0000000..4ee34aa --- /dev/null +++ b/extend/apiRes/Api.php @@ -0,0 +1,101 @@ + [ + 'errno' => 0, + 'errmsg' => '操作成功!', + 'data' => [] + ], + 'error' => [ + 'errno' => 2001, + 'errmsg' => '操作错误!', + 'data' => [] + ], + 'NoData' => [ + 'errno' => 2002, + 'errmsg' => '没有数据!', + 'data' => [] + ], + 'NotLoggedIn' => [ + 'errno' => 2003, + 'errmsg' => '未登录', + 'data' => [] + ] + ]; + + private function __construct($erro) + { + isset($erro) || die('请确认返回类型!'); + $this->state = $this->default_states[$erro]; + return $this; + } + + // 单例 + public static function result($erro) + { + if (!self::$response) { + self::$response = new self($erro); + } + return self::$response; + } + + // 返回错误 + public static function error($msg='', $data=[], $to_array=false) + { + $ins = self::result('error'); + if ($msg) { + $ins = $ins->message($msg); + } + + return $ins->response($data, $to_array); + } + + // 返回成功 + public static function success($msg='', $data=[], $to_array=false) + { + $ins = self::result('success'); + if ($msg) { + $ins = $ins->message($msg); + } + + return $ins->response($data, $to_array); + } + + // 写入返回信息 + public function message($message='') + { + $message ? $this->state['errmsg'] = $message : ''; + return $this; + } + + // 返回结果 + public function response($data=[], $to_array=false) + { + if (!empty($data)) { + $this->state['data'] = $data; + } + if (request()->isJson() || $to_array) { + $output = $this->state; + } else { + $output = json_encode($this->state, JSON_UNESCAPED_UNICODE); + } + return $output; + } + + /** + * 转成数组 + */ + public function toArray() + { + if (is_array($this->state)) { + return $this->state; + } + return json_decode($this->state, true); + } +} diff --git a/extend/encryption/Rsa.php b/extend/encryption/Rsa.php new file mode 100644 index 0000000..2e2dac0 --- /dev/null +++ b/extend/encryption/Rsa.php @@ -0,0 +1,292 @@ +public_key = $this->getPublicKey($config['public']); + } else { + $this->public_key = openssl_pkey_get_public($config['public']); + if (!$this->public_key) { + die('请检查公钥是否正确'); + } + } + + if (is_file($config['private'])) { + $this->private_key = $this->getPrivateKey($config['private']); + } else { + $this->private_key = openssl_pkey_get_private($config['private']); + if (!$this->private_key) { + die('请检查私钥是否正确'); + } + } + } + if ($config['cert_save_path']) $this->cert_save_path = $config['cert_save_path']; + } + + /** + * 单例获取对象实例 + */ + public static function instance($config=array()) + { + if (!self::$rsa) { + if (empty($config)) { + $config = [ + 'public' => '', + 'private' => '', + 'cert_save_path' => '' + ]; + } + self::$rsa = new self($config); + } + return self::$rsa; + } + + /** + * 读取文件 + */ + private function fileGet($file) + { + if (!file_exists($file)) { + die($file . "不是文件"); + } + return file_get_contents($file); + } + + /** + * 获取公钥 + */ + private function getPublicKey($path) + { + $pubKey = $this->fileGet($path); + if (!$pubKey) { + die('请检查公钥路径是否正确'); + } + return openssl_pkey_get_public($pubKey); + } + + /** + * 获取私钥 + */ + private function getPrivateKey($path) + { + $priKey = $this->fileGet($path); + if (!$priKey) { + die('请检查私钥路径是否正确'); + } + return openssl_pkey_get_private($priKey); + } + + /** + * 使用私钥生成签名 + * @param string 用于生成签名的字符串 + * @return string 签名后的值 + */ + public function signPrivate($data) + { + $signature = false; + if (openssl_sign($data, $signature, $this->private_key)) { + $signature = base64_encode($signature); + } + return $signature; + } + + /** + * 使用公钥验签 + * @param $data = array('data'='','signature'='') + * @return bool + */ + public function verifyPublic($data) + { + $bool = false; + if (!$data['data'] || !$data['signature']) { + die('数据源或签名值为出错!'); + } + $result = base64_decode($data['signature']); + switch (openssl_verify($data['data'], $result, $this->public_key)) { + case 1: + $bool = true; + break; + case 0: + case -1: + $bool = false; + break; + default: + $bool = false; + } + return $bool; + } + + /** + * 使用公钥加密 + */ + public function encryptPublic($data) + { + $crypted = false; + if (is_array($data)) { + $data = json_encode($data); + } + $cryp = strrev($data); // 将数据前后反转再加密 + if (openssl_public_encrypt($cryp, $crypted, $this->public_key, OPENSSL_PKCS1_PADDING)) { + $crypted = base64_encode($crypted); + } + return $crypted; + } + + /** + * 使用公钥分块加密 + */ + public function chunkEncryptPublic($data, $limit = 117) + { + if (is_array($data)) { + $data = json_encode($data); + } + $datas = str_split($data, $limit); + + $crypteds = []; + foreach ($datas as $key => $val) { + $crypteds[$key] = $this->encryptPublic($val); + } + return $crypteds; + } + + /** + * 使用私钥解密 + */ + public function decryptPrivate($encrypted) + { + $decrypted = ''; + $data = base64_decode($encrypted); + if (openssl_private_decrypt($data, $decrypted, $this->private_key, OPENSSL_PKCS1_PADDING)) { + $decrypted = rtrim(strrev($decrypted), '\0'); + } + return $decrypted; + } + + /** + * 使用私钥分块解密 + */ + public function chunkDecryptPrivate($encrypteds) + { + $decrypted = ''; + $encrypteds = htmlspecialchars_decode($encrypteds); + if (!is_array($encrypteds)) { + $arr = explode(',', $encrypteds); + if ($arr) { + $encrypteds = $arr; + } else { + return json_decode($this->decryptPrivate($encrypteds)); + } + } + + foreach ($encrypteds as $key => $val) { + $decrypted .= $this->decryptPrivate($val); + } + + $res = json_decode($decrypted, true); + if (is_array($res)) return $res; + return json_decode($res, true); + } + + /** + * 生成公私钥 + */ + public function createRsa($writeFile=false) + { + $config = array("config" => $this->openssl_cnf_path); + + // 生成公私钥 + $privkey = openssl_pkey_new($config); + openssl_pkey_export($privkey, $private_key, null, $config); // 导出私钥$private_key + $public_key = openssl_pkey_get_details($privkey); // 导出公钥$public_key + + if (!$writeFile) { + return array('private_key' => $private_key, 'public_key' => $public_key['key']); + } + + $publicPath = $this->cert_save_path . "rsa_public_key.pem"; // 生成公钥路径 + $privatePath = $this->cert_save_path . "rsa_private_key.pem"; // 私钥文件路径 + + // 生成公钥文件 + if (!is_writeable($publicPath)) { + chmod($publicPath, 0755); + } + $fp = fopen($publicPath, "w"); + fwrite($fp, $public_key['key']); + fclose($fp); + // 生成私钥文件 + if (!is_writeable($privatePath)) { + chmod($privatePath, 0755); + } + $fp = fopen($privatePath, "w"); + fwrite($fp, $private_key); + fclose($fp); + } + + /** + * 生成证书和密钥 + */ + public function createCsr($writeFile=false) + { + $dn = array( + "countryName" => 'CN', // 所在国家名称 + "stateOrProvinceName" => 'Hunan', // 所在省份名称 + "localityName" => 'Changsha', // 所在城市名称 + "organizationName" => 'opd', // 注册人姓名 + "organizationalUnitName" => 'orico_opd', // 组织名称 + "commonName" => 'orico_opd', // 公共名称 + "emailAddress" => '735273025@qq.com' // 邮箱 + ); + + $privkeypass = self::SIGN_CERT_PWD; //私钥密码 + $config = array( + "config" => $this->openssl_cnf_path, + "digest_alg" => "sha1", + "private_key_bits" => 2048, + "private_key_type" => OPENSSL_KEYTYPE_DSA, + "encrypt_key" => false + ); + + $privkey = openssl_pkey_new($config); + $csr = openssl_csr_new($dn, $privkey, $config); + $sscert = openssl_csr_sign($csr, null, $privkey, 365, $config); + openssl_x509_export($sscert, $csrkey); // 导出证书$csrkey  + openssl_pkcs12_export($sscert, $private_key, $privkey, $privkeypass); // 导出密钥$private_key  + + if (!$writeFile) { + return array('csrkey' => $csrkey, 'private_key_pfx' => $private_key); + } + + $cerpath = $this->cert_save_path . "csrkey.cer"; // 生成证书路径 + $pfxpath = $this->cert_save_path . "private_key.pfx"; // 密钥文件路径 + + // 生成证书文件 + if (!is_writeable($cerpath)) { + chmod($cerpath, 0755); + } + $fp = fopen($cerpath, "w"); + fwrite($fp, $csrkey); + fclose($fp); + // 生成密钥文件 + if (!is_writeable($pfxpath)) { + chmod($pfxpath, 0755); + } + $fp = fopen($pfxpath, "w"); + fwrite($fp, $private_key); + fclose($fp); + } +} diff --git a/extend/encryption/cert/csrkey.cer b/extend/encryption/cert/csrkey.cer new file mode 100644 index 0000000..e69de29 diff --git a/extend/encryption/cert/private_key.pfx b/extend/encryption/cert/private_key.pfx new file mode 100644 index 0000000..e69de29 diff --git a/extend/encryption/cert/rsa_private_key.pem b/extend/encryption/cert/rsa_private_key.pem new file mode 100644 index 0000000..14e4cc6 --- /dev/null +++ b/extend/encryption/cert/rsa_private_key.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCb4X1wN9ret271gWrsXlSymFinlheMUz2kIsyKREtlfE7ajH6Bm5bEFxe/HnCDxh37ekUJq4JMeU1awJgYA4mlvaQ67DSf4/AZWk2Dg8TLQaE7VeBJoPadDyciIwuFhcWB2lfD62KRlbXqgjfji7IjZE4ysVB99DofpJ9c9xd0NtzzuBNjgxh+f6BsegsIkqLIpKGIONePrY9cCj+vOMaRdUgWczQOftWXtJXiRz5kUxwV6CSQQbbPFEySStlW2WMBF15FyeOTXERvpgOoP4O+j/0GMW3R+4dKUxFY+SPrmMMB6HmJgySgCIVuwlUJyLlmhZuaIumryyJ19Yc+jB0ZAgMBAAECggEAA82hoN5MAckZ9PV+ZVv71wuuhhA8bNkPFPUgZnM6H7TDu8NXxtPD/u7NToVwm1Z3Hs6h5pV/rVv8Ti2KyHM1pYyV+DYRJqGKFyRD5eSOJaNpSqhSu5koyzY2bzfJrS1RX1SzdX1Fv2WWta0NrgiXhROKcOQwoZIW5PTASqVgth4iztEmseuU9pgh/dnMOXCLGmGB26Z2HTnuV0tHC4/goMmsi0eGOy40VEBxPL0JJegWM+teRSbSWGzOfTu95wnpIr66FT0aOVdHVuhMTYYHUfbEh/lnCZExfqjNfEVuSLB+jHBeLfFXdg3TY/svVizXJ4SvzI1EzM6Y145zMTdk8QKBgQDPKT1BQHWIPyXs3IzqDpmP9koBOm03rZZ46CneGLFj9vRAeK9awAto6aqH/WHLb48fSK5LQteWf+rvRiqoPjansoFvzh1dgk+0FON1jUNk4LlwOVEL38WhD98cJ/SwOVdwsYfYySb2pwcZ3K4gdTmax264XFRNGU8Ar4l17NHVtQKBgQDAoVcyWHtpJ6Pk4CuOSWt1S5y1km1dAudJfRAyYlk+9G6Qq1zSoScio/1T/TAS58KHcoSV0SmGu9heF2p02ov4MzsFr//cnBh2Y3aiTnvnyxehp5V0M9CLy524gHDANHO3BxCjlV6tMFqvUuhJfurN36KarYvLJjGU3MoWLPiIVQKBgQCfuWozP2HfdODm6X30kOExsHGK1OOUxFB6VHbDeUJ8ktHsS6DYVa32bANB6slWM2OkeUN5X8Ydke8wIWeOZLl7PxSxgbf+exS9AkYGQq6tvt77ehXVE+mqrzQU33G31d5nU1oseZuDHXFKLW5MNFX/0ri5iOaus07Ido+Dzt5S6QKBgQCef+MEnQOmyaQ0vjN4l3bhA79FM9/i6XGv6UT7gCsY/v0+8pGlCk7uVOssQadd1u8cjiEEOR+nKkdlXHUPA4iqSFUnX+Ly/kmumDbUZCnV1ylxrTfvbncJoBf96UldDYutLRYG0/AcJy5nFpvlZZYEoh/kkCn3lUy0xVtPFd/GJQKBgQCDfPkSHDxyeSZQ2xlj+4xqIGfGLbK/ijO9AuC7rSnWE2bYD1cseItVK6O0nZ0Gw4vmmvHDF9Z6yxCobIzyf6fUExvVRm3oMwjSrjVWfycTKaUUb7CHAU6JH8zQ1DPsTQ+F+W+q1RZZCj1qUBO9cHe9xIPWoK6PN829/UmZAzJeyg== +-----END PRIVATE KEY----- diff --git a/extend/encryption/cert/rsa_public_key.pem b/extend/encryption/cert/rsa_public_key.pem new file mode 100644 index 0000000..8942179 --- /dev/null +++ b/extend/encryption/cert/rsa_public_key.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm+F9cDfa3rdu9YFq7F5UsphYp5YXjFM9pCLMikRLZXxO2ox+gZuWxBcXvx5wg8Yd+3pFCauCTHlNWsCYGAOJpb2kOuw0n+PwGVpNg4PEy0GhO1XgSaD2nQ8nIiMLhYXFgdpXw+tikZW16oI344uyI2ROMrFQffQ6H6SfXPcXdDbc87gTY4MYfn+gbHoLCJKiyKShiDjXj62PXAo/rzjGkXVIFnM0Dn7Vl7SV4kc+ZFMcFegkkEG2zxRMkkrZVtljARdeRcnjk1xEb6YDqD+Dvo/9BjFt0fuHSlMRWPkj65jDAeh5iYMkoAiFbsJVCci5ZoWbmiLpq8sidfWHPowdGQIDAQAB +-----END PUBLIC KEY----- diff --git a/extend/sitemap/sitemap.config.php b/extend/sitemap/sitemap.config.php new file mode 100644 index 0000000..fc07ce3 --- /dev/null +++ b/extend/sitemap/sitemap.config.php @@ -0,0 +1,89 @@ + +'; + +// Optionally configure debug options +$debug = array( + "add" => true, + "reject" => false, + "warn" => false +); + + +//Modify only if configuration version is broken +$version_config = 2; diff --git a/extend/sitemap/sitemap.functions.php b/extend/sitemap/sitemap.functions.php new file mode 100644 index 0000000..385c4c3 --- /dev/null +++ b/extend/sitemap/sitemap.functions.php @@ -0,0 +1,426 @@ + https://somewebsite.com/directory/ +// https://somewebsite.com/directory/subdir/ => https://somewebsite.com/directory/subdir/ +function get_path($path) +{ + $path_depth = explode("/", $path); + $len = strlen($path_depth[count($path_depth) - 1]); + return (substr($path, 0, strlen($path) - $len)); +} + +//Get the root of the domain +function domain_root($href) +{ + $url_parts = explode('/', $href); + return $url_parts[0] . '//' . $url_parts[2] . '/'; +} + +//The curl client is create outside of the function to avoid re-creating it for performance reasons +$curl_client = curl_init(); +function get_data($url) +{ + global $curl_validate_certificate, $curl_client, $index_pdf, $crawler_user_agent, $enable_modified; + + //Set URL + curl_setopt($curl_client, CURLOPT_URL, $url); + //Follow redirects and get new url + curl_setopt($curl_client, CURLOPT_RETURNTRANSFER, 1); + //Get headers + curl_setopt($curl_client, CURLOPT_HEADER, 1); + //Optionally avoid validating SSL + curl_setopt($curl_client, CURLOPT_SSL_VERIFYPEER, $curl_validate_certificate); + //Set user agent + curl_setopt($curl_client, CURLOPT_USERAGENT, $crawler_user_agent); + + //Get data + $data = curl_exec($curl_client); + $content_type = curl_getinfo($curl_client, CURLINFO_CONTENT_TYPE); + $http_code = curl_getinfo($curl_client, CURLINFO_HTTP_CODE); + $redirect_url = curl_getinfo($curl_client, CURLINFO_REDIRECT_URL); + + //Scan new url, if redirect + if ($redirect_url) { + logger("URL is a redirect.", 1); + if (strpos($redirect_url, '?') !== false) { + $redirect_url = explode($redirect_url, "?")[0]; + } + unset($url, $data); + + if (!check_blacklist($redirect_url)) { + echo logger("Redirected URL is in blacklist", 1); + + } else { + scan_url($redirect_url); + } + } + + //If content acceptable, return it. If not, `false` + $html = ($http_code != 200 || (!stripos($content_type, "html"))) ? false : $data; + + //Additional data + if ($enable_modified){ + curl_setopt($curl_client, CURLOPT_FILETIME, true); + $timestamp = curl_getinfo($curl_client, CURLINFO_FILETIME); + $modified = ($timestamp != -1) ? date('c', $timestamp) : null; + } + else $modified = null; + + if (stripos($content_type, "application/pdf") !== false && $index_pdf) { + $html = "This is a PDF"; + } + //Return it as an array + return array($html, $modified, (stripos($content_type, "image/") && $index_img)); +} + +//Try to match string against blacklist +function check_blacklist($string) +{ + global $blacklist; + if (is_array($blacklist)) { + foreach ($blacklist as $illegal) { + if (fnmatch($illegal, $string)) { + return false; + } + } + } + return true; +} + +//Extract array of URLs from html document inside of `href`s +function get_links($html, $parent_url, $regexp) +{ + if (preg_match_all("/$regexp/siU", $html, $matches)) { + if ($matches[2]) { + $found = array_map(function ($href) use (&$parent_url) { + global $real_site, $ignore_arguments; + + logger("Checking $href", 2); + + if (strpos($href, "#") !== false) { + logger("Dropping pound.", 2); + $href = preg_replace('/\#.*/', '', $href); + } + + //Seperate $href from $query_string + $query_string = ''; + if (strpos($href, '?') !== false) { + list($href, $query_string) = explode('?', $href); + + //Parse & to not break curl client. See issue #23 + $query_string = str_replace('&', '&', $query_string); + } + if ($ignore_arguments) { + $query_string = ''; + } + if (strpos($href, '?') !== false) { + echo "EFEASDEFSED"; + } + + if ((substr($href, 0, 7) != "http://") && (substr($href, 0, 8) != "https://")) { + // Link does not call (potentially) external page + if (strpos($href, ":")) { + logger("URL is an invalid protocol", 1); + return false; + } + if ($href == '/') { + logger("$href is domain root", 2); + $href = $real_site; + } elseif (substr($href, 0, 1) == '/') { + logger("$href is relative to root, convert to absolute", 2); + $href = domain_root($real_site) . substr($href, 1); + } else { + logger("$href is relative, convert to absolute", 2); + $href = get_path($parent_url) . $href; + } + } + logger("Result: $href", 2); + if (!filter_var($href, FILTER_VALIDATE_URL)) { + logger("URL is not valid. Rejecting.", 1); + return false; + } + if (substr($href, 0, strlen($real_site)) != $real_site) { + logger("URL is not part of the target domain. Rejecting.", 1); + return false; + } + if (is_scanned($href . ($query_string ? '?' . $query_string : ''))) { + //logger("URL has already been scanned. Rejecting.", 1); + return false; + } + if (!check_blacklist($href)) { + logger("URL is blacklisted. Rejecting.", 1); + return false; + } + return flatten_url($href . ($query_string ? '?' . $query_string : '')); + }, $matches[2]); + return $found; + } + } + logger("Found nothing", 2); + return array(); +} + +function scan_url($url) +{ + global $scanned, $deferredLinks, $file_stream, $freq, $priority, $enable_priority, $enable_frequency, $max_depth, $depth, $real_site, $indexed; + $depth++; + + logger("Scanning $url", 2); + if (is_scanned($url)) { + logger("URL has already been scanned. Rejecting.", 1); + return $depth--; + } + if (substr($url, 0, strlen($real_site)) != $real_site) { + logger("URL is not part of the target domain. Rejecting.", 1); + return $depth--; + } + if (!($depth <= $max_depth || $max_depth == 0)) { + logger("Maximum depth exceeded. Rejecting.", 1); + return $depth--; + } + + //Note that URL has been scanned + $scanned[$url] = 1; + + //Send cURL request + list($html, $modified, $is_image) = get_data($url); + + if ($is_image) { + //Url is an image + } + + if (!$html) { + logger("Invalid Document. Rejecting.", 1); + return $depth--; + } + + if (strpos($url, "&") && strpos($url, ";") === false) { + $url = str_replace("&", "&", $url); + } + + $map_row = "\n"; + $map_row .= "$url\n"; + if ($enable_frequency) { + $map_row .= "$freq\n"; + } + if ($enable_priority) { + $map_row .= "$priority\n"; + } + if ($modified) { + $map_row .= " $modified\n"; + } + $map_row .= "\n"; + fwrite($file_stream, $map_row); + $indexed++; + logger("Added: " . $url . (($modified) ? " [Modified: " . $modified . "]" : ''), 0); + unset($is_image, $map_row); + + // Extract urls from + $ahrefs = get_links($html, $url, "]*href=(\"|'??)([^\" >]*?)\\1[^>]*>(.*)<\/a>"); + + // Extract urls from + $framesrc = get_links($html, $url, "]*src=(\"|'??)([^\" >]*?)\\1[^>]*>"); + + $links = array_filter(array_merge($ahrefs, $framesrc), function ($item) use (&$deferredLinks) { + return $item && !isset($deferredLinks[$item]); + }); + unset($html, $url, $ahrefs, $framesrc); + + logger("Found urls: " . join(", ", $links), 2); + + //Note that URL has been deferred + foreach ($links as $href) { + if ($href) { + $deferredLinks[$href] = 1; + } + } + + foreach ($links as $href) { + if ($href) { + scan_url($href); + } + } + $depth--; +} + +// fnmatch() filler for non-POSIX systems + +if (!function_exists('fnmatch')) { + function fnmatch($pattern, $string) + { + return preg_match("#^" . strtr(preg_quote($pattern, '#'), array('\*' => '.*', '\?' => '.')) . "$#i", $string); + } // end +} // end if + +$version_functions = 2; diff --git a/extend/sitemap/sitemap.php b/extend/sitemap/sitemap.php new file mode 100644 index 0000000..9b4a13f --- /dev/null +++ b/extend/sitemap/sitemap.php @@ -0,0 +1,128 @@ +\n"); +fclose($file_stream); + +// Pretty-print sitemap + if ((PHP_OS == 'WINNT') ? `where xmllint` : `which xmllint`) { + logger("Found xmllint, pretty-printing sitemap", 0); + $responsevalue = exec('xmllint --format ' . $tempfile . ' -o ' . $tempfile . ' 2>&1', $discardedoutputvalue, $returnvalue); + if ($returnvalue) { + die("Error: " . $responsevalue . "\n"); + } +} + +// Generate and print out statistics +$time_elapsed_secs = round(microtime(true) - $start, 2); +logger("Sitemap has been generated in " . $time_elapsed_secs . " second" . (($time_elapsed_secs >= 1 ? 's' : '') . "and saved to $file"), 0); +$size = sizeof($scanned); +logger("Scanned a total of $size pages and indexed $indexed pages.", 0); + +// Rename partial file to the real file name. `rename()` overwrites any existing files +rename($tempfile, $file); + +// Apply permissions +chmod($file, $permissions); + +// Declare that the script has finished executing and exit +logger("Operation Completed", 0); diff --git a/extend/sso/SSOClient.php b/extend/sso/SSOClient.php new file mode 100644 index 0000000..0c4719e --- /dev/null +++ b/extend/sso/SSOClient.php @@ -0,0 +1,115 @@ +sso_url = config('sso.sso_url'); +// if (config('sso.app_id')) $this->app_id = config('sso.app_id'); +// if (config('sso.app_secret')) $this->app_secret = config('sso.app_secret'); +// if (config('sso.public_key')) $this->public_ssl_key = config('sso.public_key'); +// if (config('sso.private_key')) $this->private_ssl_key = config('sso.private_key'); + + $this->app_id = $data['app_id']; + $this->sso_url = $data['sso_url']; + $this->app_secret = $data['app_secret']; + $this->public_ssl_key = $data['public_key']; + $this->private_ssl_key = $data['private_key']; + } + + /** + * 校验code,返回access_token + */ + public function getAccessToken($code) + { + if (empty($code)) { + return Api::error('参数code不能为空', [], true); + } + $data = [ + 'app_id' => $this->app_id, + 'app_secret' => $this->app_secret, + 'code' => $code + ]; + return $this->http('authorize/access_token', $data, true, ['cookie'=>'PHPSESSID=' . Session::getId()]); + } + + /** + * 刷新access_token + */ + public function refreshToken($refresh_token, $sessid='') + { + if (empty($refresh_token)) { + return Api::error('参数refresh_token不能为空', [], true); + } + $data = [ + 'app_id' => $this->app_id, + 'app_secret' => $this->app_secret, + 'refresh_token' => $refresh_token + ]; + return $this->http('authorize/refresh_token', $data, true, ['cookie'=>'PHPSESSID=' . $sessid]); + } + + /** + * 通知sso退出登录 + */ + public function notifySSOServerSigninOut($access_token, $sessid='') + { + if (empty($access_token)) { + return Api::error('参数access_token不能为空', [], true); + } + $data = [ + 'app_id' => $this->app_id, + 'app_secret' => $this->app_secret, + 'access_token' => $access_token, + ]; + if (empty($sessid)) { + $sessid = Session::getId(); + } + return $this->http('authorize/signin_out', $data, true, ['cookie'=>'PHPSESSID=' . $sessid]); + } + + /** + * 请求数据 + */ + private function http($url, $data, $is_post=false, $options=[]) + { + $data = json_encode($data); + $headerArray = [ + 'Content-type: application/json;charset=utf-8', + 'Accept: application/json' + ]; + $url = $this->sso_url . $url; + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); + if ($is_post) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + } + curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + if (!empty($options['cookie'])) { + curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']); + } + $output = curl_exec($curl); + $http_status = curl_errno($curl); + $http_msg = curl_error($curl); + curl_close($curl); + if ($http_status == 0) { + return json_decode($output, true); + } else { + return ['errno' => $http_status, 'errmsg' => $http_msg, 'data' => []]; + } + } +} \ No newline at end of file diff --git a/extend/storage/LocalUploader.php b/extend/storage/LocalUploader.php new file mode 100644 index 0000000..4af4752 --- /dev/null +++ b/extend/storage/LocalUploader.php @@ -0,0 +1,204 @@ +config = [ + 'disks' => [ + 'local' => [ + 'driver' => LocalDriver::class, //上传类 + 'save_dir' => app()->getRootPath() . 'public/attachment', //上传保存路径 + 'file_path' => '/attachment', //上传保存路径 + 'tmp_dir' => root_path('runtime' . DIRECTORY_SEPARATOR . 'uploadtmp'),//临时目录 + 'slice_first' => 0, //从第几片开始 + ], + //继续添加其它仓库 + ], + 'default' => [ + 'disk' => 'local', //默认磁盘 + 'extensions' => 'jpg,png,mp4', //后缀 + 'mimeTypes' => 'image/*,video/*', //类型 + 'middlewares' => [], //中间件数组 + 'maxSize' => 1 * 1024 * 1024, //单包最大上传大小 2M + ] + ]; + + } + + + /**文件上传 + * @param $data + * @param $file + * @return array + */ + public function uploadFile($data, $file) + { + + if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + exit; // finish preflight CORS requests here + } + + try { + //处理部分数据 + $data['size'] = $file->getSize(); + $data['name'] = $file->getOriginalName(); + $data['ext'] = $file->extension(); + //检测文件大小 + if (!$this->checkSize($data['size'])) { + $this->_error = "超出文件上传大小限制"; + return ['code' => -1, 'data' => []]; + } + $config = $this->config; + $uploadManager = new UploadManager($config); + $fileInfo = new FileInfo(); + $fileInfo->identifier = $data['hash']; + $fileInfo->filename = $data['name']; + + $fileInfo->chunkNumber = $data['chunk'] ?? 0;; + $fileInfo->chunkNumber = intval($fileInfo->chunkNumber ?? 0); + + //未设置分片数量 则默认总数为1 当前为0 + $fileInfo->totalChunks = $data['chunks'] ?? 1; + $fileInfo->totalChunks = intval($fileInfo->totalChunks ?? 1); + $fileInfo->totalChunks = ($fileInfo->totalChunks > 0) ? $fileInfo->totalChunks : 1; + $fileInfo->totalSize = $data['size']; + //获取后缀 + + $fileInfo->ext = $data['ext']; + if (!$this->checkFileType($fileInfo->ext)) { + $this->_error = "禁止上传的文件类型"; + return ['code' => -1, 'data' => []]; + } + + $upload = $uploadManager->uploadFile($fileInfo); + //如果文件较小 直接上传完成 + if (isset($upload['savepath']) && $upload['code'] == 0) { + $upload = $this->buildFileUrl($upload); + return ['code' => 1, 'data' => $upload, 'msg' => '成功']; + } + $check = $uploadManager->checkFile($fileInfo); + //如果上传完成 + if (isset($check['savepath']) && $check['code'] == 0) { + $check = $this->buildFileUrl($check); + return ['code' => 1, 'data' => $check]; + } else { + $this->_error = "文件包不完整"; + return ['code' => 0, 'data' => $check]; + } + } catch (\Exception $e) { + $this->_error = $e->getMessage(); + return ['code' => -1, 'data' => $e->getMessage()]; + } + } + + + /** + * 处理文件 + * 扩展包存在问题 ,考虑后续更新 尽量不更改扩展包,在这里做文件的处理 + */ + public function buildFileUrl($data) + { + + if (isset($data['savepath']) && $data['savepath'] != '') { + + $conf = $this->config; + //获取除域名外的文件路径 + $save_dir = $conf['disks'][$conf['default']['disk']]['save_dir']; + $file_path = str_replace($save_dir, '', $data['savepath']); + //拼接域名 + $data['save_path'] = $conf['disks'][$conf['default']['disk']]['file_path'] . $file_path; + $data['file_path'] = $this->domain . $data['save_path']; + //删除多余的信息 + unset($data['savepath']); + unset($data['code']); + } + return $data; + } + + //检测文件上传大小 + public function checkSize($file_size) + { + + if ($file_size > $this->config['default']['maxSize']) { + return false; + } + return true; + } + + + /**检测文件类型 + * @param $file_ext + * @return array|bool + */ + public function checkFileType($file_ext) + { //获取配置信息 + $extensions = $this->config['default']['extensions']; + + //为空或者为 * 表示不过滤 + if ($extensions == "" || $extensions == '*') { + return true; + } + //字符转换成数组 + $exts = explode(',', $extensions); + if (in_array($file_ext, $exts)) { + $this->_error = "禁止上传该类型文件"; + return ['code' => 0, 'data' => '']; + } + return true; + } + + + /** + * 检测文件分片情况 + */ + public function checkFile($hash,$count){ + + $filePath = $this->config['disks'][$this->config['default']['disk']]['tmp_dir'] . $hash; //临时分片文件路径 + +// dump($filePath); + //检查分片是否存在 + $chunkExists = []; + for ($index = 0; $index < $count; $index++) { + if (file_exists("{$filePath}_{$index}")) { + array_push($chunkExists, $index); + } + } + //分片有缺失,返回已存在的分片 + $res['uploaded'] = $chunkExists; + return $res; + } + + + /** + * 删除文件 + * @param $path + */ + public function deleteFile($path){ + $path = app()->getRootPath() . 'public'.$path; + if (file_exists($path)){ + @unlink($path); + } + return true; + } + + /** + * 返回报错 + * @return string + */ + public function getError() + { + return $this->_error; + } + +} diff --git a/extend/storage/QiniuUploader.php b/extend/storage/QiniuUploader.php new file mode 100644 index 0000000..9409d02 --- /dev/null +++ b/extend/storage/QiniuUploader.php @@ -0,0 +1,160 @@ + 1024 * 1024 * 5, // 默认最大上传5M + 'fileExt' => 'jpeg,jpg,png', // 默认上传文件后缀 + 'fileMime' => 'image/jpeg,image/png,image/gif' // 默认上传文件mime + ]; + + private $dir = true; + private $originalName = false; + private $pathPrefix = ''; + private $fileNamePrefix = 'orico'; + + static public $domain = 'http://opdfile.f2b211.com/'; + + public function __construct($conf = []) + { + if (!empty($conf['bucket'])) { + $this->bucket = $conf['bucket']; + } + if (!empty($conf['accessKey'])) { + $this->accessKey = $conf['accessKey']; + } + if (!empty($conf['secretKey'])) { + $this->secretKey = $conf['secretKey']; + } + if (!empty($conf['pathPrefix'])) { + $this->pathPrefix = trim($conf['pathPrefix'], '/'); + } + } + + /** + * 生成随机字符串 + */ + private function random($length, $type = "string", $convert = "0") + { + $conf = [ + 'number' => '0123456789', + 'string' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', + 'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=' + ]; + $string = $conf[$type]; + if (!$string) { + $string = $conf['string']; + } + $strlen = strlen($string) - 1; + $char = ''; + for ($i = 0; $i < $length; $i++) { + $char .= $string[mt_rand(0, $strlen)]; + } + if ($convert > 0) { + $res = strtoupper($char); + } elseif ($convert == 0) { + $res = $char; + } elseif ($convert < 0) { + $res = strtolower($char); + } + return $res; + } + + /** + * 组装文件名 + */ + private function buildFileName() + { + return $this->fileNamePrefix . time() . substr(time(), -5) . substr(microtime(), 2, 3) . $this->random(8); + } + + /** + * 上传验证规则 + */ + public function validate($rule) + { + $this->rule = $rule; + } + + /** + * 上传文件到七牛云 + */ + public function uploadFile($name) + { + // 构建鉴权对象 + $auth = new Auth($this->accessKey, $this->secretKey); + + // 生成上传 Token + $token = $auth->uploadToken($this->bucket); + + // 初始化 UploadManager 对象并进行文件的上传。 + $uploadMgr = new UploadManager(); + + $file = request()->file($name); + + $aspectRatio = []; + if (!empty($this->rule['aspectRatio'])) { + $aspectRatio = $this->rule['aspectRatio']; + unset($this->rule['aspectRatio']); + } + $validate = validate([$name => $this->rule]); + if (!$validate->check([$name => $file])) { + throw new \Exception($validate->getError()); + } + + $fileName = $file->getOriginalName(); // 文件原名 + if (!$this->originalName) { + $fileName = $this->buildFileName() . '.' . $file->extension(); + if (!$this->dir && !empty($this->pathPrefix)) { + $fileName = $this->pathPrefix . '/' . $fileName; + } + } + if ($this->dir) { + $fileName = date('Y') . '/' . date('m') . '/' . date('d') . '/' . $fileName; + if (!empty($this->pathPrefix)) { + $fileName = $this->pathPrefix . '/' . $fileName; + } + } + $filePath = $file->getPathname(); // 临时路径 + if (!empty($aspectRatio)) { // 验证图片宽高 + list($width, $height, $type, $attr) = getimagesize($file); + if ($width != $aspectRatio['width'] || $height != $aspectRatio['height']) { + throw new \Exception('图片宽高不符合'); + } + } + $fileType = $file->getOriginalMime(); + list($ret, $err) = $uploadMgr->putFile($token, $fileName, $filePath, null, $fileType, false); + + if ($err !== null) { + throw new \Exception($err); + } else { + return ['hash' => $ret['hash'], 'filename' => $ret['key'], 'remote_url' => self::$domain . $ret['key']]; + } + } + + + /** + * 上传文件到七牛云 + */ + public function deleteFile($name) + { + // 构建鉴权对象 + $auth = new Auth($this->accessKey, $this->secretKey); + // 初始化 BucketManager 对象并进行文件的删除。 + $bucketManager = new BucketManager($auth); + $ret = $bucketManager->delete($this->bucket, $name); + return $ret; + } + + +} diff --git a/extend/utils/BusinessDaysCalculator.php b/extend/utils/BusinessDaysCalculator.php new file mode 100644 index 0000000..05669de --- /dev/null +++ b/extend/utils/BusinessDaysCalculator.php @@ -0,0 +1,78 @@ +date = $startDate; + $this->holidays=[]; + foreach($holidays as $holiday){ + array_push($this->holidays,new DateTime($holiday)); + } + $this->nonBusinessDays = $nonBusinessDays; + $this->specialBusinessDay = $specialBusinessDay; + } + + /** + * 指几个工作日后 + */ + public function addBusinessDays($howManyDays) { + $i = 0; + while ($i < $howManyDays) { + $this->date->modify("+1 day"); + if ($this->isBusinessDay($this->date)) { + $i++; + } + } + } + + public function getDate() { + return $this->date->format('Y-m-d'); + } + + private function isBusinessDay(DateTime $date) { + if(in_array($date->format('Y-m-d') , $this->specialBusinessDay)) return true; // 判断当前日期是否是因法定节假日调休而上班的周末,这种情况也算工作日 + + if (in_array((int)$date->format('N'), $this->nonBusinessDays)) { + return false; // 当前日期是周末 + } + + foreach ($this->holidays as $day) { + if ($date->format('Y-m-d') == $day->format('Y-m-d')) { + return false; // 当前日期是法定节假日 + } + } + + return true; + } + +} + +$holidays=["2017-01-27","2017-01-28","2017-01-29","2017-01-30","2017-01-31","2017-02-01","2017-02-02"]; // 从聚合数据接口获得 +$specialBusinessDay=["2017-01-22"]; // 因法定节假日调休而上班的周末,这种情况也算工作日.因为这种情况少,可以通过手动配置 +$calculator = new BusinessDaysCalculator( + new DateTime(), // 当前时间 + $holidays, + [BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::SUNDAY], + $specialBusinessDay +); + +$calculator->addBusinessDays(2); // 2个工作日后的时间 + +$afterBusinessDay=$calculator->getDate(); +echo $afterBusinessDay; \ No newline at end of file diff --git a/extend/utils/FileLog.php b/extend/utils/FileLog.php new file mode 100644 index 0000000..45272ff --- /dev/null +++ b/extend/utils/FileLog.php @@ -0,0 +1,48 @@ +time = date('Y-m-d H:i:s'); + $this->filepath = $filepath; + $this->filename = $filename; + $this->init(); + } + + public function init() + { + if (!is_dir($this->filepath)) + { + mkdir($this->filepath, 0777, true); + } + } + + public function write($content, $type='err') + { + $str = $type . '====='; + $str .= '当前时间为: ' . $this->time; + $str .= '====='; + $str .= $content . PHP_EOL; + + if (substr($this->filepath, -1) == '/') + { + $file = $this->filepath . $this->filename; + } + else + { + $file = $this->filepath . '/' . $this->filename; + } + + return file_put_contents($file, $str, FILE_APPEND); + } + +} \ No newline at end of file diff --git a/extend/utils/Jwt.php b/extend/utils/Jwt.php new file mode 100644 index 0000000..a2d15e5 --- /dev/null +++ b/extend/utils/Jwt.php @@ -0,0 +1,168 @@ +config = $config; + $this->init(); + } + + private function init() + { + $this->iss = $this->config['iss']; + $this->exp = $this->config['exp']; + $this->iat = time(); + } + + /** + * 获取token + * @param array $user_info + * @return string + */ + public function getToken(array $user_info):string + { + //头信息 + $header = [ + 'typ' => $this->typ, + 'alg' => $this->alg + ]; + $base64_header = base64_encode(json_encode($header)); + + //有效载荷 + $payload = [ + 'iss' => $this->iss, + 'exp' => $this->exp, + 'iat' => $this->iat, + 'user_info' => $user_info, + ]; + $base64_payload = base64_encode(json_encode($payload)); + + //签名信息 + $this->secret = $this->getSecret($user_info); + $signature = $base64_header . $base64_payload . $this->secret; + $base64_signature = $this->enc($this->alg, $signature); + + $jwt_token = $base64_header . '.' . $base64_payload . '.' . $base64_signature; + return $jwt_token; + } + + /** + * 校验token + * @param $jwt_token + * @return int + */ + public function checkToken($jwt_token) + { + $arr = explode('.', $jwt_token); + if (count($arr) < 3) { + return -1; + } + + $base64_header = $arr[0]; + $base64_payload = $arr[1]; + $base64_signature = $arr[2]; + + $payload = json_decode(base64_decode($base64_payload), true); + if (!is_array($payload) || !isset($payload['exp']) || !isset($payload['iat']) || !isset($payload['user_info'])) { + return -2; + } + + //生成签名,比较 + $this->secret = $this->getSecret($payload['user_info']); + $tmp_signature = $base64_header . $base64_payload . $this->secret; + $tmp_base64_signature = $this->enc($this->alg, $tmp_signature); + + if ($base64_signature !== $tmp_base64_signature) { + return -3; + } + + // 是否过期 + if ($payload['exp'] + $payload['iat'] - time() < 0) { + // token过期了 + return -4; + } else { + // token没有过期 + if ($payload['exp'] + $payload['iat'] - time() - $this->timeout < 0) { + return 201; + } + + return 200; + } + } + + /** + * 获取用户信息 + * @param $jwt_token + * @return array|mixed + */ + public function getUserInfo($jwt_token) + { + $arr = explode('.', $jwt_token); + if (count($arr) < 3) { + return []; + } + + $base64_payload = $arr[1]; + + $payload = json_decode(base64_decode($base64_payload), true); + if (!is_array($payload) || !isset($payload['user_info'])) { + return []; + } + + return $payload['user_info']; + } + + + /** + * 获取secret,保证每个用户的secret都不同 + * @param $user_info + * @return string + */ + private function getSecret($user_info) + { + return md5($this->key . json_encode($user_info)); + } + + /** + * 加密 + * @param $enc_type + * @param $content + * @return string + */ + private function enc($enc_type, $content) + { + if ($enc_type == 'HS256') + { + return hash('sha256', $content); + } + } + +} diff --git a/extend/utils/Mailer.php b/extend/utils/Mailer.php new file mode 100644 index 0000000..15c3fdd --- /dev/null +++ b/extend/utils/Mailer.php @@ -0,0 +1,87 @@ +subject = $subject; + return $this; + } + + /** + * 设置内容 + * @param string $body + */ + public function setBody($body) + { + $this->body = $body; + return $this; + } + + /** + * 设置不支持html时的内容 + * @param string $string 内容 + */ + public function setAltBody($string) + { + $this->altBody = $string; + return $this; + } + + /** + * 发送 + */ + public function send() + { + $success = false; + $mail = new PHPMailer(true); + try { + $mail->CharSet = self::CHARTSET; //设定邮件编码 + $mail->SMTPDebug = 0; // 调试模式输出 + $mail->isSMTP(); // 使用SMTP + $mail->Host = self::HOST; // SMTP服务器 + $mail->SMTPAuth = true; // 允许 SMTP 认证 + $mail->Username = $this->username; // SMTP 用户名 即邮箱的用户名 + $mail->Password = $this->password; // SMTP 密码 部分邮箱是授权码(例如163邮箱) + $mail->SMTPSecure = 'ssl'; // 允许 TLS 或者ssl协议 + $mail->Port = 465; // 服务器端口 25 或者 465 具体要看邮箱服务器支持 + + $mail->setFrom($this->fromAccount, $this->fromName); //发件人 + $mail->addAddress($this->toAccount, $this->toName); // 收件人 + $mail->isHTML(true); + $mail->Subject = $this->subject; + $mail->Body = $this->body; + $mail->AltBody = $this->altBody; + + $success = $mail->send(); + } catch (\Exception $error) { + exit($mail->ErrorInfo); + } + return $success; + } +} \ No newline at end of file diff --git a/extend/utils/OrederStatusSync4Redis.php b/extend/utils/OrederStatusSync4Redis.php new file mode 100644 index 0000000..e09b22d --- /dev/null +++ b/extend/utils/OrederStatusSync4Redis.php @@ -0,0 +1,148 @@ +key = Config::get('redis.erp.order_sync_stream.key'); + if (empty($this->key)) { + throw new \Exception('未配置默认STREAM标识key'); + } + $this->group = Config::get('redis.erp.order_sync_stream.group'); + if (empty($this->group)) { + throw new \Exception('未配置默认STREAM消费者组'); + } + $this->consumer = Config::get('redis.erp.order_sync_stream.consumer'); + if (empty($this->consumer)) { + throw new \Exception('未配置默认STREAM消费者'); + } + if (empty($config)) { + $config = Config::get('redis.erp.conf'); + } + $this->client = new Redis($config); + } + + /** + * @param string $key 设置stream标识key + */ + public function streamKey($key) + { + if (empty($key)) { + return false; + } + $this->key = $key; + } + + /** + * @param string $group 设置消费者组 + */ + public function streamGroup($group) + { + if (empty($group)) { + return false; + } + $this->group = $group; + } + + /** + * @param string $consumer 设置消费者 + */ + public function streamConsumer($consumer) + { + if (empty($consumer)) { + return false; + } + $this->consumer = $consumer; + } + + /** + * 检查是否存在消息组 + * @param string $streamGroup 消费者组 + * @return bool + */ + public function hasGroup($streamGroup='') + { + $groups = $this->client->xInfo('GROUPS', $this->key); + if (empty($groups)) { + return false; + } + if (empty($streamGroup)) { + $streamGroup = $this->group; // 使用配置的消费组 + } + if (!in_array($streamGroup, array_column($groups, 'name'))) { + return false; + } + return true; + } + + /** + * 创建消息组 + * @param string $streamGroup 消费者组 + * @param string $msgID 0为查看所有消息,$为查看最新消息 + */ + public function createGroup($streamGroup='', $msgID='0') + { + if (empty($streamGroup)) { + $streamGroup = $this->group; // 使用配置的消费组 + } + $this->client->xGroup('CREATE', $this->key, $streamGroup, $msgID); + } + + /** + * 获取新消息 + * @param int $count 获取条数 + * @param int $block 是否阻塞:0为永久阻塞,null为不阻塞,1000为阻塞1秒 + * @return array + */ + public function fetchMessage($count=null, $block=null) + { + $keys[$this->key] = '>'; // 获取新消息 + $messages = $this->client->xReadGroup($this->group, $this->consumer, $keys, $count, $block); + return !empty($messages) ? $messages[$this->key] : []; + } + + /** + * 获取未处理消费 + * @param int $count 获取条数 + * @param int $block 是否阻塞:0为永久阻塞,null为不阻塞,1000为阻塞1秒 + * @return array + */ + public function fetchMessage4UnAck($count=null, $block=null) + { + $keys[$this->key] = '0'; // 获取未处理的 + $messages = $this->client->xReadGroup($this->group, $this->consumer, $keys, $count, $block); + return !empty($messages) ? $messages[$this->key] : []; + } + + /** + * 获取处理PENDING中消息 + * @param int $count 获取条数 + * @return array + */ + public function fetchMessage4Pending($count = 10) + { + $messages = $this->client->xPending($this->key, $this->group, '-', '+', $count, $this->consumer); + return !empty($messages) ? $messages : []; + } + + /** + * 根据消息ID设为消息已处理 + * @param array|string 消息ID + * @param int 处理系数 + */ + public function ack($messagesID) + { + if (!is_array($messagesID)) { + $messagesID = [$messagesID]; + } + return $this->client->xAck($this->key, $this->group, $messagesID); + } +} \ No newline at end of file diff --git a/extend/utils/QiniuUploader.php b/extend/utils/QiniuUploader.php new file mode 100644 index 0000000..b4aa363 --- /dev/null +++ b/extend/utils/QiniuUploader.php @@ -0,0 +1,200 @@ + 1024 * 1024 * 5, // 默认最大上传5M + 'fileExt' => 'jpeg,jpg,png', // 默认上传文件后缀 + 'fileMime' => 'image/jpeg,image/png,image/gif' // 默认上传文件mime + ]; + + protected $dir = true; + protected $originalName = false; + protected $pathPrefix = ''; + protected $fileNamePrefix = 'cms_'; + + protected $domain = ''; + + public function __construct($conf = []) + { + $this->domain = Env::get("QINIU.cdn"); + if (!empty($conf['bucket'])) { + $this->bucket = $conf['bucket']; + } + if (!empty($conf['accessKey'])) { + $this->accessKey = $conf['accessKey']; + } + if (!empty($conf['secretKey'])) { + $this->secretKey = $conf['secretKey']; + } + if (!empty($conf['pathPrefix'])) { + $this->pathPrefix = trim($conf['pathPrefix'], '/'); + } + } + + /** + * 生成随机字符串 + */ + private function random($length, $type="string", $convert="0") + { + $conf = [ + 'number' => '0123456789', + 'string' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', + 'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=' + ]; + $string = $conf[$type]; + if(!$string) { + $string = $conf['string']; + } + $strlen = strlen($string) - 1; + $char = ''; + for($i=0; $i<$length; $i++) { + $char .= $string[mt_rand(0, $strlen)]; + } + if($convert > 0) { + $res = strtoupper($char); + } elseif ($convert == 0) { + $res = $char; + } elseif ($convert < 0) { + $res = strtolower($char); + } + return $res; + } + + /** + * 组装文件名 + */ + private function buildFileName() + { + return $this->fileNamePrefix . time().substr(time(),-5).substr(microtime(),2,3) . $this->random(8); + } + + /** + * 上传验证规则 + */ + public function validate($rule) + { + $this->rule = $rule; + } + + /** + * 上传文件到七牛云 + * @param $name + * @param bool $multi 多文件模式 + * @param int $num 多文件模式文件数量 + * @return array + * @throws \Exception + */ + public function uploadFile($name,$multi=false,$num = 1) + { + // 构建鉴权对象 + $auth = new Auth($this->accessKey, $this->secretKey); + + // 生成上传 Token + $token = $auth->uploadToken($this->bucket); + + // 初始化 UploadManager 对象并进行文件的上传。 + $uploadMgr = new UploadManager(); + + $data = []; + if (false === $multi) { + $file = request()->file($name); + $data = $this->doFileToQn($file, $uploadMgr, $token); + } else { + for ($i = 0; $i < $num; $i++) { + $file = request()->file($name)[$i]; + $data[] = $this->doFileToQn($file, $uploadMgr, $token); + } + } + return $data; + + + } + + + /** + * 七牛云上传本地文件,并且本地相对路由和七牛云路径完全一致 + * @param string $fullName 文件名称带全路径。/www/wwwroot/test.yulinzhihou.com/public/ueditor/php/upload/file/20210424/1619232876970230.png + * @param string $relativePath 相对路径,注意:前面不能以斜杠开头 如:ueditor/php/upload/file/20210424/1619232876970230.png + * @return array + * @throws \Exception + */ + public function uploadLocalFile($fullName,$relativePath) + { + // 构建鉴权对象 + $auth = new Auth($this->accessKey, $this->secretKey); + // 生成上传 Token + $token = $auth->uploadToken($this->bucket); + // 初始化 UploadManager 对象并进行文件的上传。 + $uploadMgr = new UploadManager(); + $file = ltrim($relativePath,'\/'); + list($ret, $err) = $uploadMgr->putFile($token,$file,$fullName); + if ($err !== null) { + throw new \Exception($err); + } else { + return ['hash'=>$ret['hash'], 'filename'=>$ret['key'], 'remote_url'=>$this->domain . $ret['key']]; + } + + } + + /** + * @param $file + * @param UploadManager $uploadMgr + * @param string $token + * @return array + * @throws \Exception + */ + private function doFileToQn($file, UploadManager $uploadMgr, string $token): array + { + $aspectRatio = []; + if (!empty($this->rule['aspectRatio'])) { + $aspectRatio = $this->rule['aspectRatio']; + unset($this->rule['aspectRatio']); + } + + $fileName = $file->getOriginalName(); // 文件原名 + + if (!$this->originalName) { + $fileName = $this->buildFileName() . '.' . $file->extension(); + if (!$this->dir && !empty($this->pathPrefix)) { + $fileName = $this->pathPrefix . '/' . $fileName; + } + } + + if ($this->dir) { + $fileName = date('Y') . '/' . date('m') . '/' . date('d') . '/' . $fileName; + if (!empty($this->pathPrefix)) { + $fileName = $this->pathPrefix . '/' . $fileName; + } + } + + $filePath = $file->getPathname(); // 临时路径 + if (!empty($aspectRatio)) { // 验证图片宽高 + list($width, $height, $type, $attr) = getimagesize($file); + if ($width != $aspectRatio['width'] || $height != $aspectRatio['height']) { + throw new \Exception('图片宽高不符合'); + } + } + $fileType = $file->getOriginalMime(); + list($ret, $err) = $uploadMgr->putFile($token, $fileName, $filePath, null, $fileType, false); + if ($err !== null) { + throw new \Exception($err); + } else { + return ['hash' => $ret['hash'], 'filename' => $ret['key'], 'remote_url' => $this->domain . $ret['key']]; + } + } +} \ No newline at end of file diff --git a/extend/utils/UEUploader.php b/extend/utils/UEUploader.php new file mode 100644 index 0000000..08ef9ab --- /dev/null +++ b/extend/utils/UEUploader.php @@ -0,0 +1,371 @@ + "临时文件错误", + "ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件", + "ERROR_SIZE_EXCEED" => "文件大小超出网站限制", + "ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许", + "ERROR_CREATE_DIR" => "目录创建失败", + "ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限", + "ERROR_FILE_MOVE" => "文件保存时出错", + "ERROR_FILE_NOT_FOUND" => "找不到上传文件", + "ERROR_WRITE_CONTENT" => "写入文件内容错误", + "ERROR_UNKNOWN" => "未知错误", + "ERROR_DEAD_LINK" => "链接不可用", + "ERROR_HTTP_LINK" => "链接不是http链接", + "ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确", + "INVALID_URL" => "非法 URL", + "INVALID_IP" => "非法 IP" + ); + + /** + * 构造函数 + * @param string $fileField 表单名称 + * @param array $config 配置项 + * @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名 + */ + public function __construct($fileField, $config, $type = "upload") + { + $this->fileField = $fileField; + $this->config = $config; + $this->type = $type; + if ($type == "remote") { + $this->saveRemote(); + } else if($type == "base64") { + $this->upBase64(); + } else { + $this->upFile(); + } + } + + /** + * 上传文件的主处理方法 + * @return mixed + */ + private function upFile() + { + $file = $this->file = $_FILES[$this->fileField]; + if (!$file) { + $this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND"); + return; + } + if ($this->file['error']) { + $this->stateInfo = $this->getStateInfo($file['error']); + return; + } else if (!file_exists($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND"); + return; + } else if (!is_uploaded_file($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMPFILE"); + return; + } + + $this->oriName = $file['name']; + $this->fileSize = $file['size']; + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //检查是否不允许的文件格式 + if (!$this->checkType()) { + $this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { + //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE"); + } else { + //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + } + + /** + * 处理base64编码的图片上传 + * @return mixed + */ + private function upBase64() + { + $base64Data = $_POST[$this->fileField]; + $img = base64_decode($base64Data); + + $this->oriName = $this->config['oriName']; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 拉取远程图片 + * @return mixed + */ + private function saveRemote() + { + $imgUrl = htmlspecialchars($this->fileField); + $imgUrl = str_replace("&", "&", $imgUrl); + + //http开头验证 + if (strpos($imgUrl, "http") !== 0) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK"); + return; + } + + preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches); + $host_with_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 判断是否是合法 url + if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) { + $this->stateInfo = $this->getStateInfo("INVALID_URL"); + return; + } + + preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches); + $host_without_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 此时提取出来的可能是 ip 也有可能是域名,先获取 ip + $ip = gethostbyname($host_without_protocol); + // 判断是否是私有 ip + if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { + $this->stateInfo = $this->getStateInfo("INVALID_IP"); + return; + } + + //获取请求头并检测死链 + $heads = get_headers($imgUrl, 1); + if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) { + $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK"); + return; + } + //格式验证(扩展名验证和Content-Type验证) + $fileType = strtolower(strrchr($imgUrl, '.')); + if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE"); + return; + } + + //打开输出缓冲区并获取远程图片 + ob_start(); + $context = stream_context_create( + array('http' => array( + 'follow_location' => false // don't follow redirects + )) + ); + readfile($imgUrl, false, $context); + $img = ob_get_contents(); + ob_end_clean(); + preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m); + + $this->oriName = $m ? $m[1]:""; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 上传错误检查 + * @param $errCode + * @return string + */ + private function getStateInfo($errCode) + { + return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode]; + } + + /** + * 获取文件扩展名 + * @return string + */ + private function getFileExt() + { + return strtolower(strrchr($this->oriName, '.')); + } + + /** + * 重命名文件 + * @return string + */ + private function getFullName() + { + //替换日期事件 + $t = time(); + $d = explode('-', date("Y-y-m-d-H-i-s")); + $format = $this->config["pathFormat"]; + $format = str_replace("{yyyy}", $d[0], $format); + $format = str_replace("{yy}", $d[1], $format); + $format = str_replace("{mm}", $d[2], $format); + $format = str_replace("{dd}", $d[3], $format); + $format = str_replace("{hh}", $d[4], $format); + $format = str_replace("{ii}", $d[5], $format); + $format = str_replace("{ss}", $d[6], $format); + $format = str_replace("{time}", $t, $format); + + //过滤文件名的非法自负,并替换文件名 + $oriName = substr($this->oriName, 0, strrpos($this->oriName, '.')); + $oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName); + $format = str_replace("{filename}", $oriName, $format); + + //替换随机字符串 + $randNum = rand(1, 10000000000) . rand(1, 10000000000); + if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) { + $format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format); + } + + $ext = $this->getFileExt(); + return $format . $ext; + } + + /** + * 获取文件名 + * @return string + */ + private function getFileName () { + return substr($this->filePath, strrpos($this->filePath, '/') + 1); + } + + /** + * 获取文件完整路径 + * @return string + */ + private function getFilePath() + { + $fullname = $this->fullName; + $rootPath = $_SERVER['DOCUMENT_ROOT']; + + if (substr($fullname, 0, 1) != '/') { + $fullname = '/' . $fullname; + } + return $rootPath . $fullname; + } + + /** + * 文件类型检测 + * @return bool + */ + private function checkType() + { + return in_array($this->getFileExt(), $this->config["allowFiles"]); + } + + /** + * 文件大小检测 + * @return bool + */ + private function checkSize() + { + return $this->fileSize <= ($this->config["maxSize"]); + } + + /** + * 获取当前上传成功文件的各项信息 + * @return array + */ + public function getFileInfo() + { + return array( + "state" => $this->stateInfo, + "url" => $this->fullName, + "title" => $this->fileName, + "original" => $this->oriName, + "type" => $this->fileType, + "size" => $this->fileSize + ); + } + +} \ No newline at end of file diff --git a/extend/utils/UnionpayB2C.php b/extend/utils/UnionpayB2C.php new file mode 100644 index 0000000..c2ff8e5 --- /dev/null +++ b/extend/utils/UnionpayB2C.php @@ -0,0 +1,146 @@ + '156' + ]; + + protected $currencyCode; + + #交易子类型列表,支付接口专用 + protected $txnSubType_list = [ + 'zizhu' => '01', + 'fenqi' => '03', + ]; + + protected $txnSubType; + + #接入类型 + protected $accessType = '0'; //商户直连 + + #签名算法 + protected $signMethod; + + #渠道类型列表 + protected $channelType_list = [ + 'pc' => '07', + 'mobile' => '08' + ]; + + protected $channelType; + + #商户号 + // protected $merId = '777290058181532'; //test + protected $merId = '802310057320534'; //线上 + + #接口url列表 + protected $dev_url_list = [ + 'pay' => 'https://gateway.test.95516.com/gateway/api/frontTransReq.do', + 'query' => 'https://gateway.test.95516.com/gateway/api/queryTrans.do', + ]; + + protected $prod_url_list = [ + 'pay' => 'https://gateway.95516.com/gateway/api/frontTransReq.do', + 'query' => 'https://gateway.95516.com/gateway/api/queryTrans.do', + ]; + + protected $url_list; + + private $logger; + + public function __construct() + { + parent::__construct(); + $this->init(); + } + + /** + * 初始化部分参数 + */ + private function init() + { + require_once app()->getRootPath() . '/extend/payment/unionpay/sdk/AcpService.php'; + $this->version = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->version; + $this->front_url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->frontUrl; + $this->back_url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->backUrl; + $this->signMethod = com\unionpay\acp\sdk\SDKConfig::getSDKConfig()->signMethod; + // $this->url_list = $this->dev_url_list; + $this->url_list = $this->prod_url_list; + + $date = explode('-', date('Y-m-d')); + $filepath = APP_PATH . 'Lib/pay/log/' . $date[0] . '-' . $date[1] . '/' . $date[2]; + $filename = $this->pay_type . '.log'; + import('ORG.Util.FileLog'); + $this->logger = new FileLog($filepath, $filename); + } + + /** + * 查询支付状态 + * @param $pay_log === pay_log表记录 + */ + public function query($pay_log) + { + $out_trade_no = $pay_log['out_trade_no']; + $txnTime = date('YmdHis', strtotime($pay_log['create_time'])); + $this->bizType = $this->bizType_list['query'][$pay_log['pay_type']]; + $this->channelType = $this->channelType_list[$pay_log['source']]; + $params = [ + 'version' => $this->version, //版本号 + 'encoding' => $this->encoding, //编码方式 + 'signMethod' => $this->signMethod, //签名方法 + 'txnType' => '00', //交易类型 + 'txnSubType' => '00', //交易子类 + 'bizType' => '000000', //业务类型 + 'accessType' => $this->accessType, //接入类型 + 'channelType' => $this->channelType, //渠道类型 + + 'orderId' => $out_trade_no, //请修改被查询的交易的订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数 + 'merId' => $this->merId, //商户代码,请改自己的测试商户号,此处默认取demo演示页面传递的参数 + 'txnTime' => $txnTime, //请修改被查询的交易的订单发送时间,格式为YYYYMMDDhhmmss,此处默认取demo演示页面传递的参数 + ]; + + com\unionpay\acp\sdk\AcpService::sign ( $params ); // 签名 + $url = $this->url_list['query']; + + $this->logger->write('查询请求参数: ' . json_encode($params) . '=====url: ' . $url, 'suc'); + $result_arr = com\unionpay\acp\sdk\AcpService::post ( $params, $url); + + if (count($result_arr) > 0 && + com\unionpay\acp\sdk\AcpService::validate ($result_arr) && + $result_arr["respCode"] == "00" && + $result_arr["origRespCode"] == "00" + ) + { + $this->logger->write('查询完成,交易成功,交易单号: ' . $out_trade_no, 'suc'); + return $result_arr; + } + + $this->logger->write('查询完成,交易失败,交易单号: ' . $out_trade_no); + return false; + } + + private function http_success() + { + header("HTTP/1.1 200 OK"); + exit; + } + + private function http_fail() + { + header("HTTP/1.1 500 ERROR"); + exit; + } +} + diff --git a/extend/utils/WorkingDay.php b/extend/utils/WorkingDay.php new file mode 100644 index 0000000..917be47 --- /dev/null +++ b/extend/utils/WorkingDay.php @@ -0,0 +1,68 @@ +time = time(); + } + + /** + * 获取当前年度的节假日 + */ + private function getHolidays() + { + $data = Db::name('holiday')->where('year', '=', date('Y'))->column('data'); + if (empty($data)) { + $this->holidays = []; + } + $this->holidays = $data; + } + + /** + * 获取工作日 + */ + public function getDates($adays) + { + // 获取节假日 + $this->getHolidays(); + + // 组装工作日 + $ctime = $this->time; + $days = []; + $i = 1; + while($adays>0) { + $day = strtotime("+ $i day", $ctime); + $week = date('w', $day); + // 剔除周六周日与假日 + if (0 != $week && 6 != $week && !in_array(date('Y-m-d', $day), $this->holidays)) { + $adays-=1; + $days[] = date('Y-m-d H:i:s', $day); + } + $i+=1; + } + return $days; + } + + /** + * 获取几个工作日后日期 + */ + public function getDate($adays, $ctime = 0) + { + if (!empty($ctime)) { + $this->time = $ctime; + } + $days = $this->getDates($adays); + rsort($days); + return $days[0]; + } +} + diff --git a/extend/utils/ueditor_config.json b/extend/utils/ueditor_config.json new file mode 100644 index 0000000..93fde49 --- /dev/null +++ b/extend/utils/ueditor_config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 20480000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 20480000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "", /* 图片访问路径前缀 */ + "catcherMaxSize": 20480000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..72f7b77 --- /dev/null +++ b/index.html @@ -0,0 +1,24 @@ + + + + +恭喜,站点创建成功! + + + + + +
+
+
+

恭喜, 站点创建成功!

+
+

站点创建成功,本页面由系统自动生成。

+

  • 本页面在FTP根目录下的index.html
  • +

  • 您可以删除或覆盖本页面
  • +

  • FTP相关信息,请到宝塔后台查看
  • +

  • 我们为您提供了完善的数据备份功能,请到后台进行相关设置21
  • +
    +
    + + \ No newline at end of file diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/public/.htaccess @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..99ff94f --- /dev/null +++ b/public/404.html @@ -0,0 +1,26 @@ + + + + + + +404 + + + + +

    404,您请求的文件不存在!

    + + diff --git a/public/assets/css/jquery.bxslider.css b/public/assets/css/jquery.bxslider.css new file mode 100644 index 0000000..05a05a1 --- /dev/null +++ b/public/assets/css/jquery.bxslider.css @@ -0,0 +1,197 @@ +.bx-wrapper { + position: relative; + margin: 0 auto 15px; + padding: 0; + *zoom: 1; + overflow: hidden; +} + +.bx-wrapper img { + max-width: 100%; + display: block; +} + +/** THEME +===================================*/ + +.bx-wrapper .bx-viewport { + /*fix other elements on the page moving (on Chrome)*/ + -webkit-transform: translatez(0); + -moz-transform: translatez(0); + -ms-transform: translatez(0); + -o-transform: translatez(0); + transform: translatez(0); +} + +.bx-wrapper .bx-pager, +.bx-wrapper .bx-controls-auto { + position: absolute; + bottom: 15px; + width: 100%; +} + +/* LOADER */ + +.bx-wrapper .bx-loading { + min-height: 50px; + background: url(../images/bx_loader.gif) center center no-repeat #fff; + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 2000; +} + +/* PAGER */ + +.bx-wrapper .bx-pager { + text-align: center; + font-size: 0.85em; + font-family: Arial; + font-weight: bold; + color: #666; + padding-top: 20px; +} + +.bx-wrapper .bx-pager .bx-pager-item, +.bx-wrapper .bx-controls-auto .bx-controls-auto-item { + display: inline-block; + *zoom: 1; + *display: inline; +} + +.bx-wrapper .bx-pager.bx-default-pager a { + background: rgba(255, 255, 255, 0.8); + text-indent: -9999px; + display: block; + width: 16px; + height: 16px; + margin: 0 5px; + outline: 0; + border-radius: 8px; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + -ms-border-radius: 8px; + -o-border-radius: 8px; +} + +.bx-wrapper .bx-pager.bx-default-pager a:hover, +.bx-wrapper .bx-pager.bx-default-pager a.active { + background: #fff; + width: 32px; +} + +@media only screen and (max-width: 575px) { + .bx-wrapper .bx-pager.bx-default-pager a { + width: 10px; + height: 10px; + } + .bx-wrapper .bx-pager.bx-default-pager a:hover, + .bx-wrapper .bx-pager.bx-default-pager a.active { + width: 20px; + } + .bx-wrapper .bx-pager, + .bx-wrapper .bx-controls-auto { + bottom: 5px; + } +} +/* DIRECTION CONTROLS (NEXT / PREV) */ + +.bx-wrapper .bx-prev { + left: 10px; +} + +.bx-wrapper .bx-next { + right: 10px; +} + +.bx-wrapper .bx-prev:hover { + background-position: 0 0; +} + +.bx-wrapper .bx-next:hover { + background-position: -43px 0; +} + +.bx-wrapper .bx-controls-direction a { + position: absolute; + top: 50%; + margin-top: -16px; + outline: 0; + width: 32px; + height: 32px; + text-indent: -9999px; + z-index: 9999; +} + +.bx-wrapper .bx-controls-direction a.disabled { + display: none; +} + +/* AUTO CONTROLS (START / STOP) */ + +.bx-wrapper .bx-controls-auto { + text-align: center; +} + +.bx-wrapper .bx-controls-auto .bx-start { + display: block; + text-indent: -9999px; + width: 10px; + height: 11px; + outline: 0; + background: url(../images/controls.png) -86px -11px no-repeat; + margin: 0 3px; +} + +.bx-wrapper .bx-controls-auto .bx-start:hover, +.bx-wrapper .bx-controls-auto .bx-start.active { + background-position: -86px 0; +} + +.bx-wrapper .bx-controls-auto .bx-stop { + display: block; + text-indent: -9999px; + width: 9px; + height: 11px; + outline: 0; + background: url(../images/controls.png) -86px -44px no-repeat; + margin: 0 3px; +} + +.bx-wrapper .bx-controls-auto .bx-stop:hover, +.bx-wrapper .bx-controls-auto .bx-stop.active { + background-position: -86px -33px; +} + +/* PAGER WITH AUTO-CONTROLS HYBRID LAYOUT */ + +.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-pager { + text-align: left; + width: 80%; +} + +.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-controls-auto { + right: 0; + width: 35px; +} + +/* IMAGE CAPTIONS */ + +.bx-wrapper .bx-caption { + position: absolute; + bottom: 0; + left: 0; + background: #666\9; + background: rgba(80, 80, 80, 0.75); + width: 100%; +} + +.bx-wrapper .bx-caption span { + color: #fff; + font-family: Arial; + display: block; + font-size: 0.85em; + padding: 10px; +} diff --git a/public/assets/css/plugins/images/ui-icons_444444_256x240.png b/public/assets/css/plugins/images/ui-icons_444444_256x240.png new file mode 100644 index 0000000..c2daae1 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_444444_256x240.png differ diff --git a/public/assets/css/plugins/images/ui-icons_555555_256x240.png b/public/assets/css/plugins/images/ui-icons_555555_256x240.png new file mode 100644 index 0000000..4784928 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_555555_256x240.png differ diff --git a/public/assets/css/plugins/images/ui-icons_777620_256x240.png b/public/assets/css/plugins/images/ui-icons_777620_256x240.png new file mode 100644 index 0000000..d2f58d2 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_777620_256x240.png differ diff --git a/public/assets/css/plugins/images/ui-icons_777777_256x240.png b/public/assets/css/plugins/images/ui-icons_777777_256x240.png new file mode 100644 index 0000000..1d53258 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_777777_256x240.png differ diff --git a/public/assets/css/plugins/images/ui-icons_cc0000_256x240.png b/public/assets/css/plugins/images/ui-icons_cc0000_256x240.png new file mode 100644 index 0000000..2825f20 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_cc0000_256x240.png differ diff --git a/public/assets/css/plugins/images/ui-icons_ffffff_256x240.png b/public/assets/css/plugins/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000..136a4f9 Binary files /dev/null and b/public/assets/css/plugins/images/ui-icons_ffffff_256x240.png differ diff --git a/public/assets/css/plugins/plugins.min.css b/public/assets/css/plugins/plugins.min.css new file mode 100644 index 0000000..6fc5834 --- /dev/null +++ b/public/assets/css/plugins/plugins.min.css @@ -0,0 +1,6976 @@ +@charset "UTF-8"; /*! + * animate.css - https://animate.style/ + * Version - 4.1.1 + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * + * Copyright (c) 2021 Animate.css + */ +:root { + --animate-duration: 1s; + --animate-delay: 1s; + --animate-repeat: 1; +} +.animate__animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-duration: var(--animate-duration); + animation-duration: var(--animate-duration); + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} +.animate__animated.animate__infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} +.animate__animated.animate__repeat-1 { + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-animation-iteration-count: var(--animate-repeat); + animation-iteration-count: var(--animate-repeat); +} +.animate__animated.animate__repeat-2 { + -webkit-animation-iteration-count: 2; + animation-iteration-count: 2; + -webkit-animation-iteration-count: calc(var(--animate-repeat) * 2); + animation-iteration-count: calc(var(--animate-repeat) * 2); +} +.animate__animated.animate__repeat-3 { + -webkit-animation-iteration-count: 3; + animation-iteration-count: 3; + -webkit-animation-iteration-count: calc(var(--animate-repeat) * 3); + animation-iteration-count: calc(var(--animate-repeat) * 3); +} +.animate__animated.animate__delay-1s { + -webkit-animation-delay: 1s; + animation-delay: 1s; + -webkit-animation-delay: var(--animate-delay); + animation-delay: var(--animate-delay); +} +.animate__animated.animate__delay-2s { + -webkit-animation-delay: 2s; + animation-delay: 2s; + -webkit-animation-delay: calc(var(--animate-delay) * 2); + animation-delay: calc(var(--animate-delay) * 2); +} +.animate__animated.animate__delay-3s { + -webkit-animation-delay: 3s; + animation-delay: 3s; + -webkit-animation-delay: calc(var(--animate-delay) * 3); + animation-delay: calc(var(--animate-delay) * 3); +} +.animate__animated.animate__delay-4s { + -webkit-animation-delay: 4s; + animation-delay: 4s; + -webkit-animation-delay: calc(var(--animate-delay) * 4); + animation-delay: calc(var(--animate-delay) * 4); +} +.animate__animated.animate__delay-5s { + -webkit-animation-delay: 5s; + animation-delay: 5s; + -webkit-animation-delay: calc(var(--animate-delay) * 5); + animation-delay: calc(var(--animate-delay) * 5); +} +.animate__animated.animate__faster { + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-animation-duration: calc(var(--animate-duration) / 2); + animation-duration: calc(var(--animate-duration) / 2); +} +.animate__animated.animate__fast { + -webkit-animation-duration: 0.8s; + animation-duration: 0.8s; + -webkit-animation-duration: calc(var(--animate-duration) * 0.8); + animation-duration: calc(var(--animate-duration) * 0.8); +} +.animate__animated.animate__slow { + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-duration: calc(var(--animate-duration) * 2); + animation-duration: calc(var(--animate-duration) * 2); +} +.animate__animated.animate__slower { + -webkit-animation-duration: 3s; + animation-duration: 3s; + -webkit-animation-duration: calc(var(--animate-duration) * 3); + animation-duration: calc(var(--animate-duration) * 3); +} +@media (prefers-reduced-motion: reduce), print { + .animate__animated { + -webkit-animation-duration: 1ms !important; + animation-duration: 1ms !important; + -webkit-transition-duration: 1ms !important; + transition-duration: 1ms !important; + -webkit-animation-iteration-count: 1 !important; + animation-iteration-count: 1 !important; + } + .animate__animated[class*='Out'] { + opacity: 0; + } +} +@-webkit-keyframes bounce { + 0%, + 20%, + 53%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0) scaleY(1.1); + transform: translate3d(0, -30px, 0) scaleY(1.1); + } + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0) scaleY(1.05); + transform: translate3d(0, -15px, 0) scaleY(1.05); + } + 80% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translateZ(0) scaleY(0.95); + transform: translateZ(0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, -4px, 0) scaleY(1.02); + transform: translate3d(0, -4px, 0) scaleY(1.02); + } +} +@keyframes bounce { + 0%, + 20%, + 53%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -30px, 0) scaleY(1.1); + transform: translate3d(0, -30px, 0) scaleY(1.1); + } + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -15px, 0) scaleY(1.05); + transform: translate3d(0, -15px, 0) scaleY(1.05); + } + 80% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translateZ(0) scaleY(0.95); + transform: translateZ(0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, -4px, 0) scaleY(1.02); + transform: translate3d(0, -4px, 0) scaleY(1.02); + } +} +.animate__bounce { + -webkit-animation-name: bounce; + animation-name: bounce; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} +@-webkit-keyframes flash { + 0%, + 50%, + to { + opacity: 1; + } + 25%, + 75% { + opacity: 0; + } +} +@keyframes flash { + 0%, + 50%, + to { + opacity: 1; + } + 25%, + 75% { + opacity: 0; + } +} +.animate__flash { + -webkit-animation-name: flash; + animation-name: flash; +} +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +@keyframes pulse { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +.animate__pulse { + -webkit-animation-name: pulse; + animation-name: pulse; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; +} +@-webkit-keyframes rubberBand { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +@keyframes rubberBand { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + 65% { + -webkit-transform: scale3d(0.95, 1.05, 1); + transform: scale3d(0.95, 1.05, 1); + } + 75% { + -webkit-transform: scale3d(1.05, 0.95, 1); + transform: scale3d(1.05, 0.95, 1); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +.animate__rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand; +} +@-webkit-keyframes shakeX { + 0%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} +@keyframes shakeX { + 0%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} +.animate__shakeX { + -webkit-animation-name: shakeX; + animation-name: shakeX; +} +@-webkit-keyframes shakeY { + 0%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } +} +@keyframes shakeY { + 0%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } +} +.animate__shakeY { + -webkit-animation-name: shakeY; + animation-name: shakeY; +} +@-webkit-keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} +@keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg); + } + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg); + } + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg); + } + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg); + } + 50% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} +.animate__headShake { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-name: headShake; + animation-name: headShake; +} +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); + } + 40% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + 60% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg); + } + 80% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg); + } + to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} +@keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); + } + 40% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + 60% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg); + } + 80% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg); + } + to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} +.animate__swing { + -webkit-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} +@-webkit-keyframes tada { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate(-3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate(-3deg); + } + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate(3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate(3deg); + } + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate(-3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate(-3deg); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +@keyframes tada { + 0% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } + 10%, + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate(-3deg); + transform: scale3d(0.9, 0.9, 0.9) rotate(-3deg); + } + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate(3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate(3deg); + } + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate(-3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate(-3deg); + } + to { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +.animate__tada { + -webkit-animation-name: tada; + animation-name: tada; +} +@-webkit-keyframes wobble { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate(-5deg); + transform: translate3d(-25%, 0, 0) rotate(-5deg); + } + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate(3deg); + transform: translate3d(20%, 0, 0) rotate(3deg); + } + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate(-3deg); + transform: translate3d(-15%, 0, 0) rotate(-3deg); + } + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate(2deg); + transform: translate3d(10%, 0, 0) rotate(2deg); + } + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate(-1deg); + transform: translate3d(-5%, 0, 0) rotate(-1deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes wobble { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate(-5deg); + transform: translate3d(-25%, 0, 0) rotate(-5deg); + } + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate(3deg); + transform: translate3d(20%, 0, 0) rotate(3deg); + } + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate(-3deg); + transform: translate3d(-15%, 0, 0) rotate(-3deg); + } + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate(2deg); + transform: translate3d(10%, 0, 0) rotate(2deg); + } + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate(-1deg); + transform: translate3d(-5%, 0, 0) rotate(-1deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} +@-webkit-keyframes jello { + 0%, + 11.1%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} +@keyframes jello { + 0%, + 11.1%, + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg); + } + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg); + } + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg); + } + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg); + } + 66.6% { + -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); + transform: skewX(-0.78125deg) skewY(-0.78125deg); + } + 77.7% { + -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); + transform: skewX(0.390625deg) skewY(0.390625deg); + } + 88.8% { + -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + transform: skewX(-0.1953125deg) skewY(-0.1953125deg); + } +} +.animate__jello { + -webkit-animation-name: jello; + animation-name: jello; + -webkit-transform-origin: center; + transform-origin: center; +} +@-webkit-keyframes heartBeat { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + 14% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 28% { + -webkit-transform: scale(1); + transform: scale(1); + } + 42% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 70% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes heartBeat { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + 14% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 28% { + -webkit-transform: scale(1); + transform: scale(1); + } + 42% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 70% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +.animate__heartBeat { + -webkit-animation-name: heartBeat; + animation-name: heartBeat; + -webkit-animation-duration: 1.3s; + animation-duration: 1.3s; + -webkit-animation-duration: calc(var(--animate-duration) * 1.3); + animation-duration: calc(var(--animate-duration) * 1.3); + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; +} +@-webkit-keyframes backInDown { + 0% { + -webkit-transform: translateY(-1200px) scale(0.7); + transform: translateY(-1200px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +@keyframes backInDown { + 0% { + -webkit-transform: translateY(-1200px) scale(0.7); + transform: translateY(-1200px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +.animate__backInDown { + -webkit-animation-name: backInDown; + animation-name: backInDown; +} +@-webkit-keyframes backInLeft { + 0% { + -webkit-transform: translateX(-2000px) scale(0.7); + transform: translateX(-2000px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +@keyframes backInLeft { + 0% { + -webkit-transform: translateX(-2000px) scale(0.7); + transform: translateX(-2000px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +.animate__backInLeft { + -webkit-animation-name: backInLeft; + animation-name: backInLeft; +} +@-webkit-keyframes backInRight { + 0% { + -webkit-transform: translateX(2000px) scale(0.7); + transform: translateX(2000px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +@keyframes backInRight { + 0% { + -webkit-transform: translateX(2000px) scale(0.7); + transform: translateX(2000px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +.animate__backInRight { + -webkit-animation-name: backInRight; + animation-name: backInRight; +} +@-webkit-keyframes backInUp { + 0% { + -webkit-transform: translateY(1200px) scale(0.7); + transform: translateY(1200px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +@keyframes backInUp { + 0% { + -webkit-transform: translateY(1200px) scale(0.7); + transform: translateY(1200px) scale(0.7); + opacity: 0.7; + } + 80% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } +} +.animate__backInUp { + -webkit-animation-name: backInUp; + animation-name: backInUp; +} +@-webkit-keyframes backOutDown { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateY(700px) scale(0.7); + transform: translateY(700px) scale(0.7); + opacity: 0.7; + } +} +@keyframes backOutDown { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateY(700px) scale(0.7); + transform: translateY(700px) scale(0.7); + opacity: 0.7; + } +} +.animate__backOutDown { + -webkit-animation-name: backOutDown; + animation-name: backOutDown; +} +@-webkit-keyframes backOutLeft { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateX(-2000px) scale(0.7); + transform: translateX(-2000px) scale(0.7); + opacity: 0.7; + } +} +@keyframes backOutLeft { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateX(-2000px) scale(0.7); + transform: translateX(-2000px) scale(0.7); + opacity: 0.7; + } +} +.animate__backOutLeft { + -webkit-animation-name: backOutLeft; + animation-name: backOutLeft; +} +@-webkit-keyframes backOutRight { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateX(2000px) scale(0.7); + transform: translateX(2000px) scale(0.7); + opacity: 0.7; + } +} +@keyframes backOutRight { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateX(0) scale(0.7); + transform: translateX(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateX(2000px) scale(0.7); + transform: translateX(2000px) scale(0.7); + opacity: 0.7; + } +} +.animate__backOutRight { + -webkit-animation-name: backOutRight; + animation-name: backOutRight; +} +@-webkit-keyframes backOutUp { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateY(-700px) scale(0.7); + transform: translateY(-700px) scale(0.7); + opacity: 0.7; + } +} +@keyframes backOutUp { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 1; + } + 20% { + -webkit-transform: translateY(0) scale(0.7); + transform: translateY(0) scale(0.7); + opacity: 0.7; + } + to { + -webkit-transform: translateY(-700px) scale(0.7); + transform: translateY(-700px) scale(0.7); + opacity: 0.7; + } +} +.animate__backOutUp { + -webkit-animation-name: backOutUp; + animation-name: backOutUp; +} +@-webkit-keyframes bounceIn { + 0%, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + to { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +@keyframes bounceIn { + 0%, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + 40% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + 80% { + -webkit-transform: scale3d(0.97, 0.97, 0.97); + transform: scale3d(0.97, 0.97, 0.97); + } + to { + opacity: 1; + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} +.animate__bounceIn { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-duration: calc(var(--animate-duration) * 0.75); + animation-duration: calc(var(--animate-duration) * 0.75); + -webkit-animation-name: bounceIn; + animation-name: bounceIn; +} +@-webkit-keyframes bounceInDown { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0) scaleY(3); + transform: translate3d(0, -3000px, 0) scaleY(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0) scaleY(0.9); + transform: translate3d(0, 25px, 0) scaleY(0.9); + } + 75% { + -webkit-transform: translate3d(0, -10px, 0) scaleY(0.95); + transform: translate3d(0, -10px, 0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, 5px, 0) scaleY(0.985); + transform: translate3d(0, 5px, 0) scaleY(0.985); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes bounceInDown { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0) scaleY(3); + transform: translate3d(0, -3000px, 0) scaleY(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0) scaleY(0.9); + transform: translate3d(0, 25px, 0) scaleY(0.9); + } + 75% { + -webkit-transform: translate3d(0, -10px, 0) scaleY(0.95); + transform: translate3d(0, -10px, 0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, 5px, 0) scaleY(0.985); + transform: translate3d(0, 5px, 0) scaleY(0.985); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} +@-webkit-keyframes bounceInLeft { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0) scaleX(3); + transform: translate3d(-3000px, 0, 0) scaleX(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0) scaleX(1); + transform: translate3d(25px, 0, 0) scaleX(1); + } + 75% { + -webkit-transform: translate3d(-10px, 0, 0) scaleX(0.98); + transform: translate3d(-10px, 0, 0) scaleX(0.98); + } + 90% { + -webkit-transform: translate3d(5px, 0, 0) scaleX(0.995); + transform: translate3d(5px, 0, 0) scaleX(0.995); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes bounceInLeft { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0) scaleX(3); + transform: translate3d(-3000px, 0, 0) scaleX(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0) scaleX(1); + transform: translate3d(25px, 0, 0) scaleX(1); + } + 75% { + -webkit-transform: translate3d(-10px, 0, 0) scaleX(0.98); + transform: translate3d(-10px, 0, 0) scaleX(0.98); + } + 90% { + -webkit-transform: translate3d(5px, 0, 0) scaleX(0.995); + transform: translate3d(5px, 0, 0) scaleX(0.995); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} +@-webkit-keyframes bounceInRight { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0) scaleX(3); + transform: translate3d(3000px, 0, 0) scaleX(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0) scaleX(1); + transform: translate3d(-25px, 0, 0) scaleX(1); + } + 75% { + -webkit-transform: translate3d(10px, 0, 0) scaleX(0.98); + transform: translate3d(10px, 0, 0) scaleX(0.98); + } + 90% { + -webkit-transform: translate3d(-5px, 0, 0) scaleX(0.995); + transform: translate3d(-5px, 0, 0) scaleX(0.995); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes bounceInRight { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0) scaleX(3); + transform: translate3d(3000px, 0, 0) scaleX(3); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0) scaleX(1); + transform: translate3d(-25px, 0, 0) scaleX(1); + } + 75% { + -webkit-transform: translate3d(10px, 0, 0) scaleX(0.98); + transform: translate3d(10px, 0, 0) scaleX(0.98); + } + 90% { + -webkit-transform: translate3d(-5px, 0, 0) scaleX(0.995); + transform: translate3d(-5px, 0, 0) scaleX(0.995); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} +@-webkit-keyframes bounceInUp { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0) scaleY(5); + transform: translate3d(0, 3000px, 0) scaleY(5); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0) scaleY(0.9); + transform: translate3d(0, -20px, 0) scaleY(0.9); + } + 75% { + -webkit-transform: translate3d(0, 10px, 0) scaleY(0.95); + transform: translate3d(0, 10px, 0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, -5px, 0) scaleY(0.985); + transform: translate3d(0, -5px, 0) scaleY(0.985); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes bounceInUp { + 0%, + 60%, + 75%, + 90%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0) scaleY(5); + transform: translate3d(0, 3000px, 0) scaleY(5); + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0) scaleY(0.9); + transform: translate3d(0, -20px, 0) scaleY(0.9); + } + 75% { + -webkit-transform: translate3d(0, 10px, 0) scaleY(0.95); + transform: translate3d(0, 10px, 0) scaleY(0.95); + } + 90% { + -webkit-transform: translate3d(0, -5px, 0) scaleY(0.985); + transform: translate3d(0, -5px, 0) scaleY(0.985); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} +@-webkit-keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} +@keyframes bounceOut { + 20% { + -webkit-transform: scale3d(0.9, 0.9, 0.9); + transform: scale3d(0.9, 0.9, 0.9); + } + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } +} +.animate__bounceOut { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-duration: calc(var(--animate-duration) * 0.75); + animation-duration: calc(var(--animate-duration) * 0.75); + -webkit-animation-name: bounceOut; + animation-name: bounceOut; +} +@-webkit-keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0) scaleY(0.985); + transform: translate3d(0, 10px, 0) scaleY(0.985); + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0) scaleY(0.9); + transform: translate3d(0, -20px, 0) scaleY(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0) scaleY(3); + transform: translate3d(0, 2000px, 0) scaleY(3); + } +} +@keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0) scaleY(0.985); + transform: translate3d(0, 10px, 0) scaleY(0.985); + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0) scaleY(0.9); + transform: translate3d(0, -20px, 0) scaleY(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0) scaleY(3); + transform: translate3d(0, 2000px, 0) scaleY(3); + } +} +.animate__bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} +@-webkit-keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0) scaleX(0.9); + transform: translate3d(20px, 0, 0) scaleX(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0) scaleX(2); + transform: translate3d(-2000px, 0, 0) scaleX(2); + } +} +@keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0) scaleX(0.9); + transform: translate3d(20px, 0, 0) scaleX(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0) scaleX(2); + transform: translate3d(-2000px, 0, 0) scaleX(2); + } +} +.animate__bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} +@-webkit-keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0) scaleX(0.9); + transform: translate3d(-20px, 0, 0) scaleX(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0) scaleX(2); + transform: translate3d(2000px, 0, 0) scaleX(2); + } +} +@keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0) scaleX(0.9); + transform: translate3d(-20px, 0, 0) scaleX(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0) scaleX(2); + transform: translate3d(2000px, 0, 0) scaleX(2); + } +} +.animate__bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} +@-webkit-keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0) scaleY(0.985); + transform: translate3d(0, -10px, 0) scaleY(0.985); + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0) scaleY(0.9); + transform: translate3d(0, 20px, 0) scaleY(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0) scaleY(3); + transform: translate3d(0, -2000px, 0) scaleY(3); + } +} +@keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0) scaleY(0.985); + transform: translate3d(0, -10px, 0) scaleY(0.985); + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0) scaleY(0.9); + transform: translate3d(0, 20px, 0) scaleY(0.9); + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0) scaleY(3); + transform: translate3d(0, -2000px, 0) scaleY(3); + } +} +.animate__bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes fadeIn { + 0% { + opacity: 0; + } + to { + opacity: 1; + } +} +.animate__fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} +@-webkit-keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} +@-webkit-keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} +@-webkit-keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} +@-webkit-keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} +@-webkit-keyframes fadeInTopLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, -100%, 0); + transform: translate3d(-100%, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInTopLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, -100%, 0); + transform: translate3d(-100%, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInTopLeft { + -webkit-animation-name: fadeInTopLeft; + animation-name: fadeInTopLeft; +} +@-webkit-keyframes fadeInTopRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, -100%, 0); + transform: translate3d(100%, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInTopRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, -100%, 0); + transform: translate3d(100%, -100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInTopRight { + -webkit-animation-name: fadeInTopRight; + animation-name: fadeInTopRight; +} +@-webkit-keyframes fadeInBottomLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 100%, 0); + transform: translate3d(-100%, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInBottomLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 100%, 0); + transform: translate3d(-100%, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInBottomLeft { + -webkit-animation-name: fadeInBottomLeft; + animation-name: fadeInBottomLeft; +} +@-webkit-keyframes fadeInBottomRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 100%, 0); + transform: translate3d(100%, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes fadeInBottomRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 100%, 0); + transform: translate3d(100%, 100%, 0); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__fadeInBottomRight { + -webkit-animation-name: fadeInBottomRight; + animation-name: fadeInBottomRight; +} +@-webkit-keyframes fadeOut { + 0% { + opacity: 1; + } + to { + opacity: 0; + } +} +@keyframes fadeOut { + 0% { + opacity: 1; + } + to { + opacity: 0; + } +} +.animate__fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} +@keyframes fadeOutDown { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} +.animate__fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} +@-webkit-keyframes fadeOutDownBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} +@keyframes fadeOutDownBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} +.animate__fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} +@keyframes fadeOutLeft { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} +.animate__fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} +@-webkit-keyframes fadeOutLeftBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} +@keyframes fadeOutLeftBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} +.animate__fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} +@keyframes fadeOutRight { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} +.animate__fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} +@-webkit-keyframes fadeOutRightBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} +@keyframes fadeOutRightBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} +.animate__fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} +@keyframes fadeOutUp { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} +.animate__fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} +@-webkit-keyframes fadeOutUpBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} +@keyframes fadeOutUpBig { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} +.animate__fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} +@-webkit-keyframes fadeOutTopLeft { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, -100%, 0); + transform: translate3d(-100%, -100%, 0); + } +} +@keyframes fadeOutTopLeft { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, -100%, 0); + transform: translate3d(-100%, -100%, 0); + } +} +.animate__fadeOutTopLeft { + -webkit-animation-name: fadeOutTopLeft; + animation-name: fadeOutTopLeft; +} +@-webkit-keyframes fadeOutTopRight { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, -100%, 0); + transform: translate3d(100%, -100%, 0); + } +} +@keyframes fadeOutTopRight { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, -100%, 0); + transform: translate3d(100%, -100%, 0); + } +} +.animate__fadeOutTopRight { + -webkit-animation-name: fadeOutTopRight; + animation-name: fadeOutTopRight; +} +@-webkit-keyframes fadeOutBottomRight { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 100%, 0); + transform: translate3d(100%, 100%, 0); + } +} +@keyframes fadeOutBottomRight { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 100%, 0); + transform: translate3d(100%, 100%, 0); + } +} +.animate__fadeOutBottomRight { + -webkit-animation-name: fadeOutBottomRight; + animation-name: fadeOutBottomRight; +} +@-webkit-keyframes fadeOutBottomLeft { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 100%, 0); + transform: translate3d(-100%, 100%, 0); + } +} +@keyframes fadeOutBottomLeft { + 0% { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 100%, 0); + transform: translate3d(-100%, 100%, 0); + } +} +.animate__fadeOutBottomLeft { + -webkit-animation-name: fadeOutBottomLeft; + animation-name: fadeOutBottomLeft; +} +@-webkit-keyframes flip { + 0% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn); + transform: perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + 40% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg); + transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + 50% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg); + transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translateZ(0) rotateY(0deg); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translateZ(0) rotateY(0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + to { + -webkit-transform: perspective(400px) scaleX(1) translateZ(0) rotateY(0deg); + transform: perspective(400px) scaleX(1) translateZ(0) rotateY(0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} +@keyframes flip { + 0% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn); + transform: perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + 40% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg); + transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + 50% { + -webkit-transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg); + transform: perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 80% { + -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translateZ(0) rotateY(0deg); + transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translateZ(0) rotateY(0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + to { + -webkit-transform: perspective(400px) scaleX(1) translateZ(0) rotateY(0deg); + transform: perspective(400px) scaleX(1) translateZ(0) rotateY(0deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} +.animate__animated.animate__flip { + -webkit-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} +@-webkit-keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotateX(-20deg); + transform: perspective(400px) rotateX(-20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 60% { + -webkit-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotateX(-5deg); + transform: perspective(400px) rotateX(-5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} +@keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotateX(-20deg); + transform: perspective(400px) rotateX(-20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 60% { + -webkit-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotateX(-5deg); + transform: perspective(400px) rotateX(-5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} +.animate__flipInX { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} +@-webkit-keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotateY(-20deg); + transform: perspective(400px) rotateY(-20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 60% { + -webkit-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotateY(-5deg); + transform: perspective(400px) rotateY(-5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} +@keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0; + } + 40% { + -webkit-transform: perspective(400px) rotateY(-20deg); + transform: perspective(400px) rotateY(-20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + 60% { + -webkit-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + opacity: 1; + } + 80% { + -webkit-transform: perspective(400px) rotateY(-5deg); + transform: perspective(400px) rotateY(-5deg); + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} +.animate__flipInY { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} +@-webkit-keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotateX(-20deg); + transform: perspective(400px) rotateX(-20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} +@keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotateX(-20deg); + transform: perspective(400px) rotateX(-20deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} +.animate__flipOutX { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-duration: calc(var(--animate-duration) * 0.75); + animation-duration: calc(var(--animate-duration) * 0.75); + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; +} +@-webkit-keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotateY(-15deg); + transform: perspective(400px) rotateY(-15deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} +@keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + 30% { + -webkit-transform: perspective(400px) rotateY(-15deg); + transform: perspective(400px) rotateY(-15deg); + opacity: 1; + } + to { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} +.animate__flipOutY { + -webkit-animation-duration: 0.75s; + animation-duration: 0.75s; + -webkit-animation-duration: calc(var(--animate-duration) * 0.75); + animation-duration: calc(var(--animate-duration) * 0.75); + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; +} +@-webkit-keyframes lightSpeedInRight { + 0% { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes lightSpeedInRight { + 0% { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__lightSpeedInRight { + -webkit-animation-name: lightSpeedInRight; + animation-name: lightSpeedInRight; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} +@-webkit-keyframes lightSpeedInLeft { + 0% { + -webkit-transform: translate3d(-100%, 0, 0) skewX(30deg); + transform: translate3d(-100%, 0, 0) skewX(30deg); + opacity: 0; + } + 60% { + -webkit-transform: skewX(-20deg); + transform: skewX(-20deg); + opacity: 1; + } + 80% { + -webkit-transform: skewX(5deg); + transform: skewX(5deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes lightSpeedInLeft { + 0% { + -webkit-transform: translate3d(-100%, 0, 0) skewX(30deg); + transform: translate3d(-100%, 0, 0) skewX(30deg); + opacity: 0; + } + 60% { + -webkit-transform: skewX(-20deg); + transform: skewX(-20deg); + opacity: 1; + } + 80% { + -webkit-transform: skewX(5deg); + transform: skewX(5deg); + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__lightSpeedInLeft { + -webkit-animation-name: lightSpeedInLeft; + animation-name: lightSpeedInLeft; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} +@-webkit-keyframes lightSpeedOutRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} +@keyframes lightSpeedOutRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} +.animate__lightSpeedOutRight { + -webkit-animation-name: lightSpeedOutRight; + animation-name: lightSpeedOutRight; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} +@-webkit-keyframes lightSpeedOutLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: translate3d(-100%, 0, 0) skewX(-30deg); + transform: translate3d(-100%, 0, 0) skewX(-30deg); + opacity: 0; + } +} +@keyframes lightSpeedOutLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: translate3d(-100%, 0, 0) skewX(-30deg); + transform: translate3d(-100%, 0, 0) skewX(-30deg); + opacity: 0; + } +} +.animate__lightSpeedOutLeft { + -webkit-animation-name: lightSpeedOutLeft; + animation-name: lightSpeedOutLeft; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} +@-webkit-keyframes rotateIn { + 0% { + -webkit-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +@keyframes rotateIn { + 0% { + -webkit-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +.animate__rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; + -webkit-transform-origin: center; + transform-origin: center; +} +@-webkit-keyframes rotateInDownLeft { + 0% { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +@keyframes rotateInDownLeft { + 0% { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +.animate__rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; + -webkit-transform-origin: left bottom; + transform-origin: left bottom; +} +@-webkit-keyframes rotateInDownRight { + 0% { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +@keyframes rotateInDownRight { + 0% { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +.animate__rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; + -webkit-transform-origin: right bottom; + transform-origin: right bottom; +} +@-webkit-keyframes rotateInUpLeft { + 0% { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +@keyframes rotateInUpLeft { + 0% { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +.animate__rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; + -webkit-transform-origin: left bottom; + transform-origin: left bottom; +} +@-webkit-keyframes rotateInUpRight { + 0% { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +@keyframes rotateInUpRight { + 0% { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + opacity: 1; + } +} +.animate__rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; + -webkit-transform-origin: right bottom; + transform-origin: right bottom; +} +@-webkit-keyframes rotateOut { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} +@keyframes rotateOut { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} +.animate__rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; + -webkit-transform-origin: center; + transform-origin: center; +} +@-webkit-keyframes rotateOutDownLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } +} +@keyframes rotateOutDownLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + opacity: 0; + } +} +.animate__rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; + -webkit-transform-origin: left bottom; + transform-origin: left bottom; +} +@-webkit-keyframes rotateOutDownRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } +} +@keyframes rotateOutDownRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } +} +.animate__rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; + -webkit-transform-origin: right bottom; + transform-origin: right bottom; +} +@-webkit-keyframes rotateOutUpLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } +} +@keyframes rotateOutUpLeft { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0; + } +} +.animate__rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; + -webkit-transform-origin: left bottom; + transform-origin: left bottom; +} +@-webkit-keyframes rotateOutUpRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} +@keyframes rotateOutUpRight { + 0% { + opacity: 1; + } + to { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} +.animate__rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; + -webkit-transform-origin: right bottom; + transform-origin: right bottom; +} +@-webkit-keyframes hinge { + 0% { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + 20%, + 60% { + -webkit-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + 40%, + 80% { + -webkit-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} +@keyframes hinge { + 0% { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + 20%, + 60% { + -webkit-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + 40%, + 80% { + -webkit-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} +.animate__hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; + -webkit-animation-duration: calc(var(--animate-duration) * 2); + animation-duration: calc(var(--animate-duration) * 2); + -webkit-animation-name: hinge; + animation-name: hinge; + -webkit-transform-origin: top left; + transform-origin: top left; +} +@-webkit-keyframes jackInTheBox { + 0% { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes jackInTheBox { + 0% { + opacity: 0; + -webkit-transform: scale(0.1) rotate(30deg); + transform: scale(0.1) rotate(30deg); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + } + 50% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + 70% { + -webkit-transform: rotate(3deg); + transform: rotate(3deg); + } + to { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} +.animate__jackInTheBox { + -webkit-animation-name: jackInTheBox; + animation-name: jackInTheBox; +} +@-webkit-keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate(-120deg); + transform: translate3d(-100%, 0, 0) rotate(-120deg); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate(-120deg); + transform: translate3d(-100%, 0, 0) rotate(-120deg); + } + to { + opacity: 1; + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} +@-webkit-keyframes rollOut { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate(120deg); + transform: translate3d(100%, 0, 0) rotate(120deg); + } +} +@keyframes rollOut { + 0% { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate(120deg); + transform: translate3d(100%, 0, 0) rotate(120deg); + } +} +.animate__rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} +@-webkit-keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + 50% { + opacity: 1; + } +} +@keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + 50% { + opacity: 1; + } +} +.animate__zoomIn { + -webkit-animation-name: zoomIn; + animation-name: zoomIn; +} +@-webkit-keyframes zoomInDown { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomInDown { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomInDown { + -webkit-animation-name: zoomInDown; + animation-name: zoomInDown; +} +@-webkit-keyframes zoomInLeft { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomInLeft { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomInLeft { + -webkit-animation-name: zoomInLeft; + animation-name: zoomInLeft; +} +@-webkit-keyframes zoomInRight { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomInRight { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomInRight { + -webkit-animation-name: zoomInRight; + animation-name: zoomInRight; +} +@-webkit-keyframes zoomInUp { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomInUp { + 0% { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomInUp { + -webkit-animation-name: zoomInUp; + animation-name: zoomInUp; +} +@-webkit-keyframes zoomOut { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + to { + opacity: 0; + } +} +@keyframes zoomOut { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + -webkit-transform: scale3d(0.3, 0.3, 0.3); + transform: scale3d(0.3, 0.3, 0.3); + } + to { + opacity: 0; + } +} +.animate__zoomOut { + -webkit-animation-name: zoomOut; + animation-name: zoomOut; +} +@-webkit-keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomOutDown { + -webkit-animation-name: zoomOutDown; + animation-name: zoomOutDown; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} +@-webkit-keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + } +} +@keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0); + } + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0); + transform: scale(0.1) translate3d(-2000px, 0, 0); + } +} +.animate__zoomOutLeft { + -webkit-animation-name: zoomOutLeft; + animation-name: zoomOutLeft; + -webkit-transform-origin: left center; + transform-origin: left center; +} +@-webkit-keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + } +} +@keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0); + } + to { + opacity: 0; + -webkit-transform: scale(0.1) translate3d(2000px, 0, 0); + transform: scale(0.1) translate3d(2000px, 0, 0); + } +} +.animate__zoomOutRight { + -webkit-animation-name: zoomOutRight; + animation-name: zoomOutRight; + -webkit-transform-origin: right center; + transform-origin: right center; +} +@-webkit-keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +@keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); + } + to { + opacity: 0; + -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); + } +} +.animate__zoomOutUp { + -webkit-animation-name: zoomOutUp; + animation-name: zoomOutUp; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; +} +@-webkit-keyframes slideInDown { + 0% { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes slideInDown { + 0% { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} +@-webkit-keyframes slideInLeft { + 0% { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes slideInLeft { + 0% { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} +@-webkit-keyframes slideInRight { + 0% { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes slideInRight { + 0% { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} +@-webkit-keyframes slideInUp { + 0% { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +@keyframes slideInUp { + 0% { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + to { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } +} +.animate__slideInUp { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; +} +@-webkit-keyframes slideOutDown { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} +@keyframes slideOutDown { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} +.animate__slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown; +} +@-webkit-keyframes slideOutLeft { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} +@keyframes slideOutLeft { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} +.animate__slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} +@-webkit-keyframes slideOutRight { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} +@keyframes slideOutRight { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} +.animate__slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} +@-webkit-keyframes slideOutUp { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} +@keyframes slideOutUp { + 0% { + -webkit-transform: translateZ(0); + transform: translateZ(0); + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} +.animate__slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:after, +.ui-helper-clearfix:before { + content: ''; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter: Alpha(Opacity=0); +} +.ui-front { + z-index: 100; +} +.ui-state-disabled { + cursor: default !important; + pointer-events: none; +} +.ui-icon { + display: inline-block; + vertical-align: middle; + margin-top: -0.25em; + position: relative; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} +.ui-widget-icon-block { + left: 50%; + margin-left: -8px; + display: block; +} +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin: 2px 0 0 0; + padding: 0.5em 0.5em 0.5em 0.7em; + font-size: 100%; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: 0; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + margin: 0; + cursor: pointer; + list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); +} +.ui-menu .ui-menu-item-wrapper { + position: relative; + padding: 3px 1em 3px 0.4em; +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-active, +.ui-menu .ui-state-focus { + margin: -1px; +} +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item-wrapper { + padding-left: 2em; +} +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: 0.2em; + margin: auto 0; +} +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +.ui-button { + padding: 0.4em 1em; + display: inline-block; + position: relative; + line-height: normal; + margin-right: 0.1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + overflow: visible; +} +.ui-button, +.ui-button:active, +.ui-button:hover, +.ui-button:link, +.ui-button:visited { + text-decoration: none; +} +.ui-button-icon-only { + width: 2em; + box-sizing: border-box; + text-indent: -9999px; + white-space: nowrap; +} +input.ui-button.ui-button-icon-only { + text-indent: 0; +} +.ui-button-icon-only .ui-icon { + position: absolute; + top: 50%; + left: 50%; + margin-top: -8px; + margin-left: -8px; +} +.ui-button.ui-icon-notext .ui-icon { + padding: 0; + width: 2.1em; + height: 2.1em; + text-indent: -9999px; + white-space: nowrap; +} +input.ui-button.ui-icon-notext .ui-icon { + width: auto; + height: auto; + text-indent: 0; + white-space: normal; + padding: 0.4em 1em; +} +button.ui-button::-moz-focus-inner, +input.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-controlgroup { + vertical-align: middle; + display: inline-block; +} +.ui-controlgroup > .ui-controlgroup-item { + float: left; + margin-left: 0; + margin-right: 0; +} +.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus, +.ui-controlgroup > .ui-controlgroup-item:focus { + z-index: 9999; +} +.ui-controlgroup-vertical > .ui-controlgroup-item { + display: block; + float: none; + width: 100%; + margin-top: 0; + margin-bottom: 0; + text-align: left; +} +.ui-controlgroup-vertical .ui-controlgroup-item { + box-sizing: border-box; +} +.ui-controlgroup .ui-controlgroup-label { + padding: 0.4em 1em; +} +.ui-controlgroup .ui-controlgroup-label span { + font-size: 80%; +} +.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item { + border-left: none; +} +.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item { + border-top: 0; +} +.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content { + border-right: 0; +} +.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content { + border-bottom: 0; +} +.ui-controlgroup-vertical .ui-spinner-input { + width: 75%; + width: calc(100% - 2.4em); +} +.ui-controlgroup-vertical .ui-spinner .ui-spinner-up { + border-top-style: solid; +} +.ui-checkboxradio-label .ui-icon-background { + box-shadow: inset 1px 1px 1px #fff; + border-radius: 0.12em; + border: 0; +} +.ui-checkboxradio-radio-label .ui-icon-background { + width: 16px; + height: 16px; + border-radius: 1em; + overflow: visible; + border: 0; +} +.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, +.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { + background-image: none; + width: 8px; + height: 8px; + border-width: 4px; + border-style: solid; +} +.ui-checkboxradio-disabled { + pointer-events: none; +} +.ui-datepicker { + width: 17em; + padding: 0.2em 0.2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: 0.2em 0; +} +.ui-datepicker .ui-datepicker-next, +.ui-datepicker .ui-datepicker-prev { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-next-hover, +.ui-datepicker .ui-datepicker-prev-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-next span, +.ui-datepicker .ui-datepicker-prev span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 45%; +} +.ui-datepicker table { + width: 100%; + font-size: 0.9em; + border-collapse: collapse; + margin: 0 0 0.4em; +} +.ui-datepicker th { + padding: 0.7em 0.3em; + text-align: center; + font-weight: 700; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td a, +.ui-datepicker td span { + display: block; + padding: 0.2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: 0.7em 0 0 0; + padding: 0 0.2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: 0.5em 0.2em 0.4em; + cursor: pointer; + padding: 0.2em 0.6em 0.3em 0.6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto 0.4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-datepicker .ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; + left: 0.5em; + top: 0.3em; +} +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: 0.2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: 0.4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: 0.1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: 0.3em; + top: 50%; + width: 20px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: 0.5em 1em; + background: 0; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: 0.5em; + padding: 0.3em 1em 0.5em 0.4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: 0.5em 0.4em 0.5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-n { + height: 2px; + top: 0; +} +.ui-dialog .ui-resizable-e { + width: 2px; + right: 0; +} +.ui-dialog .ui-resizable-s { + height: 2px; + bottom: 0; +} +.ui-dialog .ui-resizable-w { + width: 2px; + left: 0; +} +.ui-dialog .ui-resizable-ne, +.ui-dialog .ui-resizable-nw, +.ui-dialog .ui-resizable-se, +.ui-dialog .ui-resizable-sw { + width: 7px; + height: 7px; +} +.ui-dialog .ui-resizable-se { + right: 0; + bottom: 0; +} +.ui-dialog .ui-resizable-sw { + left: 0; + bottom: 0; +} +.ui-dialog .ui-resizable-ne { + right: 0; + top: 0; +} +.ui-dialog .ui-resizable-nw { + left: 0; + top: 0; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-draggable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable-autohide .ui-resizable-handle, +.ui-resizable-disabled .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url(data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==); + height: 100%; + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-selectable { + -ms-touch-action: none; + touch-action: none; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted #000; +} +.ui-selectmenu-menu { + padding: 0; + margin: 0; + position: absolute; + top: 0; + left: 0; + display: none; +} +.ui-selectmenu-menu .ui-menu { + overflow: auto; + overflow-x: hidden; + padding-bottom: 1px; +} +.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { + font-size: 1em; + font-weight: 700; + line-height: 1.5; + padding: 2px 0.4em; + margin: 0.5em 0 0 0; + height: auto; + border: 0; +} +.ui-selectmenu-open { + display: block; +} +.ui-selectmenu-text { + display: block; + margin-right: 20px; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-selectmenu-button.ui-button { + text-align: left; + white-space: nowrap; + width: 14em; +} +.ui-selectmenu-icon.ui-icon { + float: right; + margin-top: 0; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; + -ms-touch-action: none; + touch-action: none; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: 0.7em; + display: block; + border: 0; + background-position: 0 0; +} +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} +.ui-slider-horizontal { + height: 0.8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -0.3em; + margin-left: -0.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} +.ui-slider-vertical { + width: 0.8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -0.3em; + margin-left: 0; + margin-bottom: -0.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-sortable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: 0; + background: 0; + color: inherit; + padding: 0.222em 0; + margin: 0.2em 0; + vertical-align: middle; + margin-left: 0.4em; + margin-right: 2em; +} +.ui-spinner-button { + width: 1.6em; + height: 50%; + font-size: 0.5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +.ui-spinner a.ui-spinner-button { + border-top-style: none; + border-bottom-style: none; + border-right-style: none; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} +.ui-tabs { + position: relative; + padding: 0.2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: 0.2em 0.2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px 0.2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: 0.5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: 0; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; +} +body .ui-tooltip { + border-width: 2px; +} +.ui-widget { + font-family: Arial, Helvetica, sans-serif; + font-size: 1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget button, +.ui-widget input, +.ui-widget select, +.ui-widget textarea { + font-family: Arial, Helvetica, sans-serif; + font-size: 1em; +} +.ui-widget.ui-widget-content { + border: 1px solid #c5c5c5; +} +.ui-widget-content { + border: 1px solid #ddd; + background: #fff; + color: #333; +} +.ui-widget-content a { + color: #333; +} +.ui-widget-header { + border: 1px solid #ddd; + background: #e9e9e9; + color: #333; + font-weight: 700; +} +.ui-widget-header a { + color: #333; +} +.ui-button, +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default, +html .ui-button.ui-state-disabled:active, +html .ui-button.ui-state-disabled:hover { + border: 1px solid #c5c5c5; + background: #f6f6f6; + font-weight: 400; + color: #454545; +} +.ui-button, +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited, +a.ui-button, +a:link.ui-button, +a:visited.ui-button { + color: #454545; + text-decoration: none; +} +.ui-button:focus, +.ui-button:hover, +.ui-state-focus, +.ui-state-hover, +.ui-widget-content .ui-state-focus, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-focus, +.ui-widget-header .ui-state-hover { + border: 1px solid #fff; + background: #ededed; + font-weight: 400; + color: #2b2b2b; +} +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited, +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +a.ui-button:focus, +a.ui-button:hover { + color: #2b2b2b; + text-decoration: none; +} +.ui-visual-focus { + box-shadow: 0 0 3px 1px #5e9ed6; +} +.ui-button.ui-state-active:hover, +.ui-button:active, +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active, +a.ui-button:active { + border: 1px solid #003eff; + background: #007fff; + font-weight: 400; + color: #fff; +} +.ui-icon-background, +.ui-state-active .ui-icon-background { + border: #003eff; + background-color: #fff; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #fff; + text-decoration: none; +} +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #dad55e; + background: #fffa90; + color: #777620; +} +.ui-state-checked { + border: 1px solid #dad55e; + background: #fffa90; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #777620; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #f1a899; + background: #fddfdf; + color: #5f3f3f; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #5f3f3f; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #5f3f3f; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: 700; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: 0.7; + filter: Alpha(Opacity=70); + font-weight: 400; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: 0.35; + filter: Alpha(Opacity=35); + background-image: none; +} +.ui-state-disabled .ui-icon { + filter: Alpha(Opacity=35); +} +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url(images/ui-icons_444444_256x240.png); +} +.ui-widget-header .ui-icon { + background-image: url(images/ui-icons_444444_256x240.png); +} +.ui-button:focus .ui-icon, +.ui-button:hover .ui-icon, +.ui-state-focus .ui-icon, +.ui-state-hover .ui-icon { + background-image: url(images/ui-icons_555555_256x240.png); +} +.ui-button:active .ui-icon, +.ui-state-active .ui-icon { + background-image: url(images/ui-icons_ffffff_256x240.png); +} +.ui-button .ui-state-highlight.ui-icon, +.ui-state-highlight .ui-icon { + background-image: url(images/ui-icons_777620_256x240.png); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url(images/ui-icons_cc0000_256x240.png); +} +.ui-button .ui-icon { + background-image: url(images/ui-icons_777777_256x240.png); +} +.ui-icon-blank { + background-position: 16px 16px; +} +.ui-icon-caret-1-n { + background-position: 0 0; +} +.ui-icon-caret-1-ne { + background-position: -16px 0; +} +.ui-icon-caret-1-e { + background-position: -32px 0; +} +.ui-icon-caret-1-se { + background-position: -48px 0; +} +.ui-icon-caret-1-s { + background-position: -65px 0; +} +.ui-icon-caret-1-sw { + background-position: -80px 0; +} +.ui-icon-caret-1-w { + background-position: -96px 0; +} +.ui-icon-caret-1-nw { + background-position: -112px 0; +} +.ui-icon-caret-2-n-s { + background-position: -128px 0; +} +.ui-icon-caret-2-e-w { + background-position: -144px 0; +} +.ui-icon-triangle-1-n { + background-position: 0 -16px; +} +.ui-icon-triangle-1-ne { + background-position: -16px -16px; +} +.ui-icon-triangle-1-e { + background-position: -32px -16px; +} +.ui-icon-triangle-1-se { + background-position: -48px -16px; +} +.ui-icon-triangle-1-s { + background-position: -65px -16px; +} +.ui-icon-triangle-1-sw { + background-position: -80px -16px; +} +.ui-icon-triangle-1-w { + background-position: -96px -16px; +} +.ui-icon-triangle-1-nw { + background-position: -112px -16px; +} +.ui-icon-triangle-2-n-s { + background-position: -128px -16px; +} +.ui-icon-triangle-2-e-w { + background-position: -144px -16px; +} +.ui-icon-arrow-1-n { + background-position: 0 -32px; +} +.ui-icon-arrow-1-ne { + background-position: -16px -32px; +} +.ui-icon-arrow-1-e { + background-position: -32px -32px; +} +.ui-icon-arrow-1-se { + background-position: -48px -32px; +} +.ui-icon-arrow-1-s { + background-position: -65px -32px; +} +.ui-icon-arrow-1-sw { + background-position: -80px -32px; +} +.ui-icon-arrow-1-w { + background-position: -96px -32px; +} +.ui-icon-arrow-1-nw { + background-position: -112px -32px; +} +.ui-icon-arrow-2-n-s { + background-position: -128px -32px; +} +.ui-icon-arrow-2-ne-sw { + background-position: -144px -32px; +} +.ui-icon-arrow-2-e-w { + background-position: -160px -32px; +} +.ui-icon-arrow-2-se-nw { + background-position: -176px -32px; +} +.ui-icon-arrowstop-1-n { + background-position: -192px -32px; +} +.ui-icon-arrowstop-1-e { + background-position: -208px -32px; +} +.ui-icon-arrowstop-1-s { + background-position: -224px -32px; +} +.ui-icon-arrowstop-1-w { + background-position: -240px -32px; +} +.ui-icon-arrowthick-1-n { + background-position: 1px -48px; +} +.ui-icon-arrowthick-1-ne { + background-position: -16px -48px; +} +.ui-icon-arrowthick-1-e { + background-position: -32px -48px; +} +.ui-icon-arrowthick-1-se { + background-position: -48px -48px; +} +.ui-icon-arrowthick-1-s { + background-position: -64px -48px; +} +.ui-icon-arrowthick-1-sw { + background-position: -80px -48px; +} +.ui-icon-arrowthick-1-w { + background-position: -96px -48px; +} +.ui-icon-arrowthick-1-nw { + background-position: -112px -48px; +} +.ui-icon-arrowthick-2-n-s { + background-position: -128px -48px; +} +.ui-icon-arrowthick-2-ne-sw { + background-position: -144px -48px; +} +.ui-icon-arrowthick-2-e-w { + background-position: -160px -48px; +} +.ui-icon-arrowthick-2-se-nw { + background-position: -176px -48px; +} +.ui-icon-arrowthickstop-1-n { + background-position: -192px -48px; +} +.ui-icon-arrowthickstop-1-e { + background-position: -208px -48px; +} +.ui-icon-arrowthickstop-1-s { + background-position: -224px -48px; +} +.ui-icon-arrowthickstop-1-w { + background-position: -240px -48px; +} +.ui-icon-arrowreturnthick-1-w { + background-position: 0 -64px; +} +.ui-icon-arrowreturnthick-1-n { + background-position: -16px -64px; +} +.ui-icon-arrowreturnthick-1-e { + background-position: -32px -64px; +} +.ui-icon-arrowreturnthick-1-s { + background-position: -48px -64px; +} +.ui-icon-arrowreturn-1-w { + background-position: -64px -64px; +} +.ui-icon-arrowreturn-1-n { + background-position: -80px -64px; +} +.ui-icon-arrowreturn-1-e { + background-position: -96px -64px; +} +.ui-icon-arrowreturn-1-s { + background-position: -112px -64px; +} +.ui-icon-arrowrefresh-1-w { + background-position: -128px -64px; +} +.ui-icon-arrowrefresh-1-n { + background-position: -144px -64px; +} +.ui-icon-arrowrefresh-1-e { + background-position: -160px -64px; +} +.ui-icon-arrowrefresh-1-s { + background-position: -176px -64px; +} +.ui-icon-arrow-4 { + background-position: 0 -80px; +} +.ui-icon-arrow-4-diag { + background-position: -16px -80px; +} +.ui-icon-extlink { + background-position: -32px -80px; +} +.ui-icon-newwin { + background-position: -48px -80px; +} +.ui-icon-refresh { + background-position: -64px -80px; +} +.ui-icon-shuffle { + background-position: -80px -80px; +} +.ui-icon-transfer-e-w { + background-position: -96px -80px; +} +.ui-icon-transferthick-e-w { + background-position: -112px -80px; +} +.ui-icon-folder-collapsed { + background-position: 0 -96px; +} +.ui-icon-folder-open { + background-position: -16px -96px; +} +.ui-icon-document { + background-position: -32px -96px; +} +.ui-icon-document-b { + background-position: -48px -96px; +} +.ui-icon-note { + background-position: -64px -96px; +} +.ui-icon-mail-closed { + background-position: -80px -96px; +} +.ui-icon-mail-open { + background-position: -96px -96px; +} +.ui-icon-suitcase { + background-position: -112px -96px; +} +.ui-icon-comment { + background-position: -128px -96px; +} +.ui-icon-person { + background-position: -144px -96px; +} +.ui-icon-print { + background-position: -160px -96px; +} +.ui-icon-trash { + background-position: -176px -96px; +} +.ui-icon-locked { + background-position: -192px -96px; +} +.ui-icon-unlocked { + background-position: -208px -96px; +} +.ui-icon-bookmark { + background-position: -224px -96px; +} +.ui-icon-tag { + background-position: -240px -96px; +} +.ui-icon-home { + background-position: 0 -112px; +} +.ui-icon-flag { + background-position: -16px -112px; +} +.ui-icon-calendar { + background-position: -32px -112px; +} +.ui-icon-cart { + background-position: -48px -112px; +} +.ui-icon-pencil { + background-position: -64px -112px; +} +.ui-icon-clock { + background-position: -80px -112px; +} +.ui-icon-disk { + background-position: -96px -112px; +} +.ui-icon-calculator { + background-position: -112px -112px; +} +.ui-icon-zoomin { + background-position: -128px -112px; +} +.ui-icon-zoomout { + background-position: -144px -112px; +} +.ui-icon-search { + background-position: -160px -112px; +} +.ui-icon-wrench { + background-position: -176px -112px; +} +.ui-icon-gear { + background-position: -192px -112px; +} +.ui-icon-heart { + background-position: -208px -112px; +} +.ui-icon-star { + background-position: -224px -112px; +} +.ui-icon-link { + background-position: -240px -112px; +} +.ui-icon-cancel { + background-position: 0 -128px; +} +.ui-icon-plus { + background-position: -16px -128px; +} +.ui-icon-plusthick { + background-position: -32px -128px; +} +.ui-icon-minus { + background-position: -48px -128px; +} +.ui-icon-minusthick { + background-position: -64px -128px; +} +.ui-icon-close { + background-position: -80px -128px; +} +.ui-icon-closethick { + background-position: -96px -128px; +} +.ui-icon-key { + background-position: -112px -128px; +} +.ui-icon-lightbulb { + background-position: -128px -128px; +} +.ui-icon-scissors { + background-position: -144px -128px; +} +.ui-icon-clipboard { + background-position: -160px -128px; +} +.ui-icon-copy { + background-position: -176px -128px; +} +.ui-icon-contact { + background-position: -192px -128px; +} +.ui-icon-image { + background-position: -208px -128px; +} +.ui-icon-video { + background-position: -224px -128px; +} +.ui-icon-script { + background-position: -240px -128px; +} +.ui-icon-alert { + background-position: 0 -144px; +} +.ui-icon-info { + background-position: -16px -144px; +} +.ui-icon-notice { + background-position: -32px -144px; +} +.ui-icon-help { + background-position: -48px -144px; +} +.ui-icon-check { + background-position: -64px -144px; +} +.ui-icon-bullet { + background-position: -80px -144px; +} +.ui-icon-radio-on { + background-position: -96px -144px; +} +.ui-icon-radio-off { + background-position: -112px -144px; +} +.ui-icon-pin-w { + background-position: -128px -144px; +} +.ui-icon-pin-s { + background-position: -144px -144px; +} +.ui-icon-play { + background-position: 0 -160px; +} +.ui-icon-pause { + background-position: -16px -160px; +} +.ui-icon-seek-next { + background-position: -32px -160px; +} +.ui-icon-seek-prev { + background-position: -48px -160px; +} +.ui-icon-seek-end { + background-position: -64px -160px; +} +.ui-icon-seek-start { + background-position: -80px -160px; +} +.ui-icon-seek-first { + background-position: -80px -160px; +} +.ui-icon-stop { + background-position: -96px -160px; +} +.ui-icon-eject { + background-position: -112px -160px; +} +.ui-icon-volume-off { + background-position: -128px -160px; +} +.ui-icon-volume-on { + background-position: -144px -160px; +} +.ui-icon-power { + background-position: 0 -176px; +} +.ui-icon-signal-diag { + background-position: -16px -176px; +} +.ui-icon-signal { + background-position: -32px -176px; +} +.ui-icon-battery-0 { + background-position: -48px -176px; +} +.ui-icon-battery-1 { + background-position: -64px -176px; +} +.ui-icon-battery-2 { + background-position: -80px -176px; +} +.ui-icon-battery-3 { + background-position: -96px -176px; +} +.ui-icon-circle-plus { + background-position: 0 -192px; +} +.ui-icon-circle-minus { + background-position: -16px -192px; +} +.ui-icon-circle-close { + background-position: -32px -192px; +} +.ui-icon-circle-triangle-e { + background-position: -48px -192px; +} +.ui-icon-circle-triangle-s { + background-position: -64px -192px; +} +.ui-icon-circle-triangle-w { + background-position: -80px -192px; +} +.ui-icon-circle-triangle-n { + background-position: -96px -192px; +} +.ui-icon-circle-arrow-e { + background-position: -112px -192px; +} +.ui-icon-circle-arrow-s { + background-position: -128px -192px; +} +.ui-icon-circle-arrow-w { + background-position: -144px -192px; +} +.ui-icon-circle-arrow-n { + background-position: -160px -192px; +} +.ui-icon-circle-zoomin { + background-position: -176px -192px; +} +.ui-icon-circle-zoomout { + background-position: -192px -192px; +} +.ui-icon-circle-check { + background-position: -208px -192px; +} +.ui-icon-circlesmall-plus { + background-position: 0 -208px; +} +.ui-icon-circlesmall-minus { + background-position: -16px -208px; +} +.ui-icon-circlesmall-close { + background-position: -32px -208px; +} +.ui-icon-squaresmall-plus { + background-position: -48px -208px; +} +.ui-icon-squaresmall-minus { + background-position: -64px -208px; +} +.ui-icon-squaresmall-close { + background-position: -80px -208px; +} +.ui-icon-grip-dotted-vertical { + background-position: 0 -224px; +} +.ui-icon-grip-dotted-horizontal { + background-position: -16px -224px; +} +.ui-icon-grip-solid-vertical { + background-position: -32px -224px; +} +.ui-icon-grip-solid-horizontal { + background-position: -48px -224px; +} +.ui-icon-gripsmall-diagonal-se { + background-position: -64px -224px; +} +.ui-icon-grip-diagonal-se { + background-position: -80px -224px; +} +.ui-corner-all, +.ui-corner-left, +.ui-corner-tl, +.ui-corner-top { + border-top-left-radius: 3px; +} +.ui-corner-all, +.ui-corner-right, +.ui-corner-top, +.ui-corner-tr { + border-top-right-radius: 3px; +} +.ui-corner-all, +.ui-corner-bl, +.ui-corner-bottom, +.ui-corner-left { + border-bottom-left-radius: 3px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-br, +.ui-corner-right { + border-bottom-right-radius: 3px; +} +.ui-widget-overlay { + background: #aaa; + opacity: 0.003; + filter: Alpha(Opacity=.3); +} +.ui-widget-shadow { + -webkit-box-shadow: 0 0 5px #666; + box-shadow: 0 0 5px #666; +} +.nice-select { + -webkit-tap-highlight-color: transparent; + background-color: #fff; + border-radius: 5px; + border: solid 1px #e8e8e8; + box-sizing: border-box; + clear: both; + cursor: pointer; + display: block; + float: left; + font-family: inherit; + font-size: 14px; + font-weight: 400; + height: 42px; + line-height: 40px; + outline: 0; + padding-left: 18px; + padding-right: 30px; + position: relative; + text-align: left !important; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + width: auto; +} +.nice-select:hover { + border-color: #dbdbdb; +} +.nice-select.open, +.nice-select:active, +.nice-select:focus { + border-color: #999; +} +.nice-select:after { + border-bottom: 2px solid #999; + border-right: 2px solid #999; + content: ''; + display: block; + height: 5px; + margin-top: -4px; + pointer-events: none; + position: absolute; + right: 12px; + top: 50%; + -webkit-transform-origin: 66% 66%; + -ms-transform-origin: 66% 66%; + transform-origin: 66% 66%; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + -webkit-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; + width: 5px; +} +.nice-select.open:after { + -webkit-transform: rotate(-135deg); + -ms-transform: rotate(-135deg); + transform: rotate(-135deg); +} +.nice-select.open .list { + opacity: 1; + pointer-events: auto; + -webkit-transform: scale(1) translateY(0); + -ms-transform: scale(1) translateY(0); + transform: scale(1) translateY(0); +} +.nice-select.disabled { + border-color: #ededed; + color: #999; + pointer-events: none; +} +.nice-select.disabled:after { + border-color: #fff; +} +.nice-select.wide { + width: 100%; +} +.nice-select.wide .list { + left: 0 !important; + right: 0 !important; +} +.nice-select.right { + float: right; +} +.nice-select.right .list { + left: auto; + right: 0; +} +.nice-select.small { + font-size: 12px; + height: 36px; + line-height: 34px; +} +.nice-select.small:after { + height: 4px; + width: 4px; +} +.nice-select.small .option { + line-height: 34px; + min-height: 34px; +} +.nice-select .list { + background-color: #fff; + border-radius: 5px; + box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + box-sizing: border-box; + margin-top: 4px; + opacity: 0; + overflow: hidden; + padding: 0; + pointer-events: none; + position: absolute; + top: 100%; + left: 0; + -webkit-transform-origin: 50% 0; + -ms-transform-origin: 50% 0; + transform-origin: 50% 0; + -webkit-transform: scale(0.75) translateY(-21px); + -ms-transform: scale(0.75) translateY(-21px); + transform: scale(0.75) translateY(-21px); + -webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + z-index: 9; +} +.nice-select .list:hover .option:not(:hover) { + background-color: transparent !important; +} +.nice-select .option { + cursor: pointer; + font-weight: 400; + line-height: 40px; + list-style: none; + min-height: 40px; + outline: 0; + padding-left: 18px; + padding-right: 29px; + text-align: left; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.nice-select .option.focus, +.nice-select .option.selected.focus, +.nice-select .option:hover { + background-color: #f6f6f6; +} +.nice-select .option.selected { + font-weight: 700; +} +.nice-select .option.disabled { + background-color: transparent; + color: #999; + cursor: default; +} +.no-csspointerevents .nice-select .list { + display: none; +} +.no-csspointerevents .nice-select.open .list { + display: block; +} +@font-face { + font-family: swiper-icons; + src: url('data:application/font-woff;charset=utf-8;base64, d09GRgABAAAAAAZgABAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAGRAAAABoAAAAci6qHkUdERUYAAAWgAAAAIwAAACQAYABXR1BPUwAABhQAAAAuAAAANuAY7+xHU1VCAAAFxAAAAFAAAABm2fPczU9TLzIAAAHcAAAASgAAAGBP9V5RY21hcAAAAkQAAACIAAABYt6F0cBjdnQgAAACzAAAAAQAAAAEABEBRGdhc3AAAAWYAAAACAAAAAj//wADZ2x5ZgAAAywAAADMAAAD2MHtryVoZWFkAAABbAAAADAAAAA2E2+eoWhoZWEAAAGcAAAAHwAAACQC9gDzaG10eAAAAigAAAAZAAAArgJkABFsb2NhAAAC0AAAAFoAAABaFQAUGG1heHAAAAG8AAAAHwAAACAAcABAbmFtZQAAA/gAAAE5AAACXvFdBwlwb3N0AAAFNAAAAGIAAACE5s74hXjaY2BkYGAAYpf5Hu/j+W2+MnAzMYDAzaX6QjD6/4//Bxj5GA8AuRwMYGkAPywL13jaY2BkYGA88P8Agx4j+/8fQDYfA1AEBWgDAIB2BOoAeNpjYGRgYNBh4GdgYgABEMnIABJzYNADCQAACWgAsQB42mNgYfzCOIGBlYGB0YcxjYGBwR1Kf2WQZGhhYGBiYGVmgAFGBiQQkOaawtDAoMBQxXjg/wEGPcYDDA4wNUA2CCgwsAAAO4EL6gAAeNpj2M0gyAACqxgGNWBkZ2D4/wMA+xkDdgAAAHjaY2BgYGaAYBkGRgYQiAHyGMF8FgYHIM3DwMHABGQrMOgyWDLEM1T9/w8UBfEMgLzE////P/5//f/V/xv+r4eaAAeMbAxwIUYmIMHEgKYAYjUcsDAwsLKxc3BycfPw8jEQA/gZBASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTQZBgMAAMR+E+gAEQFEAAAAKgAqACoANAA+AEgAUgBcAGYAcAB6AIQAjgCYAKIArAC2AMAAygDUAN4A6ADyAPwBBgEQARoBJAEuATgBQgFMAVYBYAFqAXQBfgGIAZIBnAGmAbIBzgHsAAB42u2NMQ6CUAyGW568x9AneYYgm4MJbhKFaExIOAVX8ApewSt4Bic4AfeAid3VOBixDxfPYEza5O+Xfi04YADggiUIULCuEJK8VhO4bSvpdnktHI5QCYtdi2sl8ZnXaHlqUrNKzdKcT8cjlq+rwZSvIVczNiezsfnP/uznmfPFBNODM2K7MTQ45YEAZqGP81AmGGcF3iPqOop0r1SPTaTbVkfUe4HXj97wYE+yNwWYxwWu4v1ugWHgo3S1XdZEVqWM7ET0cfnLGxWfkgR42o2PvWrDMBSFj/IHLaF0zKjRgdiVMwScNRAoWUoH78Y2icB/yIY09An6AH2Bdu/UB+yxopYshQiEvnvu0dURgDt8QeC8PDw7Fpji3fEA4z/PEJ6YOB5hKh4dj3EvXhxPqH/SKUY3rJ7srZ4FZnh1PMAtPhwP6fl2PMJMPDgeQ4rY8YT6Gzao0eAEA409DuggmTnFnOcSCiEiLMgxCiTI6Cq5DZUd3Qmp10vO0LaLTd2cjN4fOumlc7lUYbSQcZFkutRG7g6JKZKy0RmdLY680CDnEJ+UMkpFFe1RN7nxdVpXrC4aTtnaurOnYercZg2YVmLN/d/gczfEimrE/fs/bOuq29Zmn8tloORaXgZgGa78yO9/cnXm2BpaGvq25Dv9S4E9+5SIc9PqupJKhYFSSl47+Qcr1mYNAAAAeNptw0cKwkAAAMDZJA8Q7OUJvkLsPfZ6zFVERPy8qHh2YER+3i/BP83vIBLLySsoKimrqKqpa2hp6+jq6RsYGhmbmJqZSy0sraxtbO3sHRydnEMU4uR6yx7JJXveP7WrDycAAAAAAAH//wACeNpjYGRgYOABYhkgZgJCZgZNBkYGLQZtIJsFLMYAAAw3ALgAeNolizEKgDAQBCchRbC2sFER0YD6qVQiBCv/H9ezGI6Z5XBAw8CBK/m5iQQVauVbXLnOrMZv2oLdKFa8Pjuru2hJzGabmOSLzNMzvutpB3N42mNgZGBg4GKQYzBhYMxJLMlj4GBgAYow/P/PAJJhLM6sSoWKfWCAAwDAjgbRAAB42mNgYGBkAIIbCZo5IPrmUn0hGA0AO8EFTQAA') + format('woff'); + font-weight: 400; + font-style: normal; +} +:root { + --swiper-theme-color: #007aff; +} +.swiper-container { + margin-left: auto; + margin-right: auto; + position: relative; + overflow: hidden; + list-style: none; + padding: 0; + z-index: 1; +} +.swiper-container-vertical > .swiper-wrapper { + flex-direction: column; +} +.swiper-wrapper { + position: relative; + width: 100%; + height: 100%; + z-index: 1; + display: flex; + transition-property: transform; + box-sizing: content-box; +} +.swiper-container-android .swiper-slide, +.swiper-wrapper { + transform: translate3d(0px, 0, 0); +} +.swiper-container-multirow > .swiper-wrapper { + flex-wrap: wrap; +} +.swiper-container-multirow-column > .swiper-wrapper { + flex-wrap: wrap; + flex-direction: column; +} +.swiper-container-free-mode > .swiper-wrapper { + transition-timing-function: ease-out; + margin: 0 auto; +} +.swiper-slide { + flex-shrink: 0; + width: 100%; + height: 100%; + position: relative; + transition-property: transform; +} +.swiper-slide-invisible-blank { + visibility: hidden; +} +.swiper-container-autoheight, +.swiper-container-autoheight .swiper-slide { + height: auto; +} +.swiper-container-autoheight .swiper-wrapper { + align-items: flex-start; + transition-property: transform, height; +} +.swiper-container-3d { + perspective: 1200px; +} +.swiper-container-3d .swiper-cube-shadow, +.swiper-container-3d .swiper-slide, +.swiper-container-3d .swiper-slide-shadow-bottom, +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-wrapper { + transform-style: preserve-3d; +} +.swiper-container-3d .swiper-slide-shadow-bottom, +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; +} +.swiper-container-3d .swiper-slide-shadow-left { + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); +} +.swiper-container-3d .swiper-slide-shadow-right { + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); +} +.swiper-container-3d .swiper-slide-shadow-top { + background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); +} +.swiper-container-3d .swiper-slide-shadow-bottom { + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); +} +.swiper-container-css-mode > .swiper-wrapper { + overflow: auto; + scrollbar-width: none; + -ms-overflow-style: none; +} +.swiper-container-css-mode > .swiper-wrapper::-webkit-scrollbar { + display: none; +} +.swiper-container-css-mode > .swiper-wrapper > .swiper-slide { + scroll-snap-align: start start; +} +.swiper-container-horizontal.swiper-container-css-mode > .swiper-wrapper { + scroll-snap-type: x mandatory; +} +.swiper-container-vertical.swiper-container-css-mode > .swiper-wrapper { + scroll-snap-type: y mandatory; +} +:root { + --swiper-navigation-size: 44px; +} +.swiper-button-next, +.swiper-button-prev { + position: absolute; + top: 50%; + width: calc(var(--swiper-navigation-size) / 44 * 27); + height: var(--swiper-navigation-size); + margin-top: calc(-1 * var(--swiper-navigation-size) / 2); + z-index: 10; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: var(--swiper-navigation-color, var(--swiper-theme-color)); +} +.swiper-button-next.swiper-button-disabled, +.swiper-button-prev.swiper-button-disabled { + opacity: 0.35; + cursor: auto; + pointer-events: none; +} +.swiper-button-next:after, +.swiper-button-prev:after { + font-family: swiper-icons; + font-size: var(--swiper-navigation-size); + text-transform: none !important; + letter-spacing: 0; + text-transform: none; + font-variant: initial; + line-height: 1; +} +.swiper-button-prev, +.swiper-container-rtl .swiper-button-next { + left: 10px; + right: auto; +} +.swiper-button-prev:after, +.swiper-container-rtl .swiper-button-next:after { + content: 'prev'; +} +.swiper-button-next, +.swiper-container-rtl .swiper-button-prev { + right: 10px; + left: auto; +} +.swiper-button-next:after, +.swiper-container-rtl .swiper-button-prev:after { + content: 'next'; +} +.swiper-button-next.swiper-button-white, +.swiper-button-prev.swiper-button-white { + --swiper-navigation-color: #fff; +} +.swiper-button-next.swiper-button-black, +.swiper-button-prev.swiper-button-black { + --swiper-navigation-color: #000; +} +.swiper-button-lock { + display: none; +} +.swiper-pagination { + position: absolute; + text-align: center; + transition: 0.3s opacity; + transform: translate3d(0, 0, 0); + z-index: 10; +} +.swiper-pagination.swiper-pagination-hidden { + opacity: 0; +} +.swiper-container-horizontal > .swiper-pagination-bullets, +.swiper-pagination-custom, +.swiper-pagination-fraction { + bottom: 10px; + left: 0; + width: 100%; +} +.swiper-pagination-bullets-dynamic { + overflow: hidden; + font-size: 0; +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet { + transform: scale(0.33); + position: relative; +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active { + transform: scale(1); +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-main { + transform: scale(1); +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev { + transform: scale(0.66); +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev-prev { + transform: scale(0.33); +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next { + transform: scale(0.66); +} +.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next-next { + transform: scale(0.33); +} +.swiper-pagination-bullet { + width: 8px; + height: 8px; + display: inline-block; + border-radius: 100%; + background: #000; + opacity: 0.2; +} +button.swiper-pagination-bullet { + border: 0; + margin: 0; + padding: 0; + box-shadow: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.swiper-pagination-clickable .swiper-pagination-bullet { + cursor: pointer; +} +.swiper-pagination-bullet-active { + opacity: 1; + background: var(--swiper-pagination-color, var(--swiper-theme-color)); +} +.swiper-container-vertical > .swiper-pagination-bullets { + right: 10px; + top: 50%; + transform: translate3d(0px, -50%, 0); +} +.swiper-container-vertical > .swiper-pagination-bullets .swiper-pagination-bullet { + margin: 6px 0; + display: block; +} +.swiper-container-vertical > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic { + top: 50%; + transform: translateY(-50%); + width: 8px; +} +.swiper-container-vertical > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet { + display: inline-block; + transition: 0.2s transform, 0.2s top; +} +.swiper-container-horizontal > .swiper-pagination-bullets .swiper-pagination-bullet { + margin: 0 4px; +} +.swiper-container-horizontal > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic { + left: 50%; + transform: translateX(-50%); + white-space: nowrap; +} +.swiper-container-horizontal > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet { + transition: 0.2s transform, 0.2s left; +} +.swiper-container-horizontal.swiper-container-rtl > .swiper-pagination-bullets-dynamic .swiper-pagination-bullet { + transition: 0.2s transform, 0.2s right; +} +.swiper-pagination-progressbar { + background: rgba(0, 0, 0, 0.25); + position: absolute; +} +.swiper-pagination-progressbar .swiper-pagination-progressbar-fill { + background: var(--swiper-pagination-color, var(--swiper-theme-color)); + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + transform: scale(0); + transform-origin: left top; +} +.swiper-container-rtl .swiper-pagination-progressbar .swiper-pagination-progressbar-fill { + transform-origin: right top; +} +.swiper-container-horizontal > .swiper-pagination-progressbar, +.swiper-container-vertical > .swiper-pagination-progressbar.swiper-pagination-progressbar-opposite { + width: 100%; + height: 4px; + left: 0; + top: 0; +} +.swiper-container-horizontal > .swiper-pagination-progressbar.swiper-pagination-progressbar-opposite, +.swiper-container-vertical > .swiper-pagination-progressbar { + width: 4px; + height: 100%; + left: 0; + top: 0; +} +.swiper-pagination-white { + --swiper-pagination-color: #fff; +} +.swiper-pagination-black { + --swiper-pagination-color: #000; +} +.swiper-pagination-lock { + display: none; +} +.swiper-scrollbar { + border-radius: 10px; + position: relative; + -ms-touch-action: none; + background: rgba(0, 0, 0, 0.1); +} +.swiper-container-horizontal > .swiper-scrollbar { + position: absolute; + left: 1%; + bottom: 3px; + z-index: 50; + height: 5px; + width: 98%; +} +.swiper-container-vertical > .swiper-scrollbar { + position: absolute; + right: 3px; + top: 1%; + z-index: 50; + width: 5px; + height: 98%; +} +.swiper-scrollbar-drag { + height: 100%; + width: 100%; + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; + left: 0; + top: 0; +} +.swiper-scrollbar-cursor-drag { + cursor: move; +} +.swiper-scrollbar-lock { + display: none; +} +.swiper-zoom-container { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} +.swiper-zoom-container > canvas, +.swiper-zoom-container > img, +.swiper-zoom-container > svg { + max-width: 100%; + max-height: 100%; + object-fit: contain; +} +.swiper-slide-zoomed { + cursor: move; +} +.swiper-lazy-preloader { + width: 42px; + height: 42px; + position: absolute; + left: 50%; + top: 50%; + margin-left: -21px; + margin-top: -21px; + z-index: 10; + transform-origin: 50%; + animation: swiper-preloader-spin 1s infinite linear; + box-sizing: border-box; + border: 4px solid var(--swiper-preloader-color, var(--swiper-theme-color)); + border-radius: 50%; + border-top-color: transparent; +} +.swiper-lazy-preloader-white { + --swiper-preloader-color: #fff; +} +.swiper-lazy-preloader-black { + --swiper-preloader-color: #000; +} +@keyframes swiper-preloader-spin { + 100% { + transform: rotate(360deg); + } +} +.swiper-container .swiper-notification { + position: absolute; + left: 0; + top: 0; + pointer-events: none; + opacity: 0; + z-index: -1000; +} +.swiper-container-fade.swiper-container-free-mode .swiper-slide { + transition-timing-function: ease-out; +} +.swiper-container-fade .swiper-slide { + pointer-events: none; + transition-property: opacity; +} +.swiper-container-fade .swiper-slide .swiper-slide { + pointer-events: none; +} +.swiper-container-fade .swiper-slide-active, +.swiper-container-fade .swiper-slide-active .swiper-slide-active { + pointer-events: auto; +} +.swiper-container-cube { + overflow: visible; +} +.swiper-container-cube .swiper-slide { + pointer-events: none; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + z-index: 1; + visibility: hidden; + transform-origin: 0 0; + width: 100%; + height: 100%; +} +.swiper-container-cube .swiper-slide .swiper-slide { + pointer-events: none; +} +.swiper-container-cube.swiper-container-rtl .swiper-slide { + transform-origin: 100% 0; +} +.swiper-container-cube .swiper-slide-active, +.swiper-container-cube .swiper-slide-active .swiper-slide-active { + pointer-events: auto; +} +.swiper-container-cube .swiper-slide-active, +.swiper-container-cube .swiper-slide-next, +.swiper-container-cube .swiper-slide-next + .swiper-slide, +.swiper-container-cube .swiper-slide-prev { + pointer-events: auto; + visibility: visible; +} +.swiper-container-cube .swiper-slide-shadow-bottom, +.swiper-container-cube .swiper-slide-shadow-left, +.swiper-container-cube .swiper-slide-shadow-right, +.swiper-container-cube .swiper-slide-shadow-top { + z-index: 0; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.swiper-container-cube .swiper-cube-shadow { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 100%; + background: #000; + opacity: 0.6; + -webkit-filter: blur(50px); + filter: blur(50px); + z-index: 0; +} +.swiper-container-flip { + overflow: visible; +} +.swiper-container-flip .swiper-slide { + pointer-events: none; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + z-index: 1; +} +.swiper-container-flip .swiper-slide .swiper-slide { + pointer-events: none; +} +.swiper-container-flip .swiper-slide-active, +.swiper-container-flip .swiper-slide-active .swiper-slide-active { + pointer-events: auto; +} +.swiper-container-flip .swiper-slide-shadow-bottom, +.swiper-container-flip .swiper-slide-shadow-left, +.swiper-container-flip .swiper-slide-shadow-right, +.swiper-container-flip .swiper-slide-shadow-top { + z-index: 0; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.vbox-overlay *, +.vbox-overlay :after, +.vbox-overlay :before { + -webkit-backface-visibility: hidden; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.vbox-overlay * { + -webkit-backface-visibility: visible; + backface-visibility: visible; +} +.vbox-overlay { + display: -webkit-flex; + display: flex; + -webkit-flex-direction: column; + flex-direction: column; + -webkit-justify-content: center; + justify-content: center; + -webkit-align-items: center; + align-items: center; + position: fixed; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 474747; +} +.vbox-title { + width: 100%; + height: 40px; + float: left; + text-align: center; + line-height: 28px; + font-size: 12px; + padding: 6px 50px; + overflow: hidden; + position: fixed; + display: none; + left: 0; + z-index: 89; +} +.vbox-close { + cursor: pointer; + position: fixed; + top: -1px; + right: 0; + width: 50px; + height: 40px; + padding: 6px; + display: block; + background-position: 10px center; + overflow: hidden; + font-size: 24px; + line-height: 1; + text-align: center; + z-index: 99; +} +.vbox-left { + cursor: pointer; + position: fixed; + left: 0; + height: 40px; + overflow: hidden; + line-height: 28px; + font-size: 12px; + z-index: 99; + display: flex; + align-items: center; +} +.vbox-num { + display: inline-block; + margin: 6px 0 6px 15px; +} +.vbox-share { + line-height: 28px; + font-size: 12px; + overflow: hidden; + position: fixed; + left: 0; + z-index: 98; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + text-align: center; +} +.vbox-share svg { + max-height: 28px; + width: 28px; + z-index: 10; + margin-left: 12px; + margin-top: 6px; + margin-bottom: 6px; + vertical-align: middle; +} +.vbox-next, +.vbox-prev { + position: fixed; + top: 50%; + margin-top: -15px; + overflow: hidden; + cursor: pointer; + display: block; + width: 45px; + height: 45px; + z-index: 99; +} +.vbox-next span, +.vbox-prev span { + position: relative; + width: 20px; + height: 20px; + border: 2px solid transparent; + border-top-color: #b6b6b6; + border-right-color: #b6b6b6; + text-indent: -100px; + position: absolute; + top: 8px; + display: block; +} +.vbox-prev { + left: 15px; +} +.vbox-next { + right: 15px; +} +.vbox-prev span { + left: 10px; + -ms-transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); +} +.vbox-next span { + -ms-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + right: 10px; +} +.vbox-inline { + width: 420px; + height: 315px; + height: 70vh; + padding: 10px; + background: #fff; + margin: 0 auto; + overflow: auto; + text-align: left; +} +.venoframe { + max-width: 100%; + width: 100%; + border: 0; + width: 100%; + height: 260px; + height: 70vh; +} +.venoframe.vbvid { + height: 260px; +} +@media (min-width: 768px) { + .vbox-inline, + .venoframe { + width: 90%; + height: 360px; + height: 70vh; + } + .venoframe.vbvid { + width: 640px; + height: 360px; + } +} +@media (min-width: 992px) { + .vbox-inline, + .venoframe { + max-width: 1200px; + width: 80%; + height: 540px; + height: 70vh; + } + .venoframe.vbvid { + width: 960px; + height: 540px; + } +} +.vbox-open { + overflow: hidden; +} +.vbox-container { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + overflow-x: hidden; + overflow-y: scroll; + overflow-scrolling: touch; + -webkit-overflow-scrolling: touch; + z-index: 20; + max-height: 100%; +} +.vbox-content { + text-align: center; + float: left; + width: 100%; + position: relative; + overflow: hidden; + padding: 20px 4%; +} +.vbox-container img { + max-width: 100%; + height: auto; +} +.vbox-figlio { + box-shadow: 0 0 12px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + max-width: 100%; + text-align: initial; +} +img.vbox-figlio { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; +} +.vbox-content.swipe-left { + margin-left: -200px !important; +} +.vbox-content.swipe-right { + margin-left: 200px !important; +} +.vbox-animated { + webkit-transition: margin 0.3s ease-out; + transition: margin 0.3s ease-out; +} +.sk-double-bounce, +.sk-rotating-plane { + width: 40px; + height: 40px; + margin: 40px auto; +} +.sk-rotating-plane { + background-color: #333; + -webkit-animation: sk-rotatePlane 1.2s infinite ease-in-out; + animation: sk-rotatePlane 1.2s infinite ease-in-out; +} +@-webkit-keyframes sk-rotatePlane { + 0% { + -webkit-transform: perspective(120px) rotateX(0) rotateY(0); + transform: perspective(120px) rotateX(0) rotateY(0); + } + 50% { + -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0); + transform: perspective(120px) rotateX(-180.1deg) rotateY(0); + } + 100% { + -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + } +} +@keyframes sk-rotatePlane { + 0% { + -webkit-transform: perspective(120px) rotateX(0) rotateY(0); + transform: perspective(120px) rotateX(0) rotateY(0); + } + 50% { + -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0); + transform: perspective(120px) rotateX(-180.1deg) rotateY(0); + } + 100% { + -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + } +} +.sk-double-bounce { + position: relative; +} +.sk-double-bounce .sk-child { + width: 100%; + height: 100%; + border-radius: 50%; + background-color: #333; + opacity: 0.6; + position: absolute; + top: 0; + left: 0; + -webkit-animation: sk-doubleBounce 2s infinite ease-in-out; + animation: sk-doubleBounce 2s infinite ease-in-out; +} +.sk-chasing-dots .sk-child, +.sk-spinner-pulse, +.sk-three-bounce .sk-child { + background-color: #333; + border-radius: 100%; +} +.sk-double-bounce .sk-double-bounce2 { + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +@-webkit-keyframes sk-doubleBounce { + 0%, + 100% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes sk-doubleBounce { + 0%, + 100% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +.sk-wave { + margin: 40px auto; + width: 50px; + height: 40px; + text-align: center; + font-size: 10px; +} +.sk-wave .sk-rect { + background-color: #333; + height: 100%; + width: 6px; + display: inline-block; + -webkit-animation: sk-waveStretchDelay 1.2s infinite ease-in-out; + animation: sk-waveStretchDelay 1.2s infinite ease-in-out; +} +.sk-wave .sk-rect1 { + -webkit-animation-delay: -1.2s; + animation-delay: -1.2s; +} +.sk-wave .sk-rect2 { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} +.sk-wave .sk-rect3 { + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +.sk-wave .sk-rect4 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} +.sk-wave .sk-rect5 { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} +@-webkit-keyframes sk-waveStretchDelay { + 0%, + 100%, + 40% { + -webkit-transform: scaleY(0.4); + transform: scaleY(0.4); + } + 20% { + -webkit-transform: scaleY(1); + transform: scaleY(1); + } +} +@keyframes sk-waveStretchDelay { + 0%, + 100%, + 40% { + -webkit-transform: scaleY(0.4); + transform: scaleY(0.4); + } + 20% { + -webkit-transform: scaleY(1); + transform: scaleY(1); + } +} +.sk-wandering-cubes { + margin: 40px auto; + width: 40px; + height: 40px; + position: relative; +} +.sk-wandering-cubes .sk-cube { + background-color: #333; + width: 10px; + height: 10px; + position: absolute; + top: 0; + left: 0; + -webkit-animation: sk-wanderingCube 1.8s ease-in-out -1.8s infinite both; + animation: sk-wanderingCube 1.8s ease-in-out -1.8s infinite both; +} +.sk-chasing-dots, +.sk-spinner-pulse { + width: 40px; + height: 40px; + margin: 40px auto; +} +.sk-wandering-cubes .sk-cube2 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} +@-webkit-keyframes sk-wanderingCube { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + 25% { + -webkit-transform: translateX(30px) rotate(-90deg) scale(0.5); + transform: translateX(30px) rotate(-90deg) scale(0.5); + } + 50% { + -webkit-transform: translateX(30px) translateY(30px) rotate(-179deg); + transform: translateX(30px) translateY(30px) rotate(-179deg); + } + 50.1% { + -webkit-transform: translateX(30px) translateY(30px) rotate(-180deg); + transform: translateX(30px) translateY(30px) rotate(-180deg); + } + 75% { + -webkit-transform: translateX(0) translateY(30px) rotate(-270deg) scale(0.5); + transform: translateX(0) translateY(30px) rotate(-270deg) scale(0.5); + } + 100% { + -webkit-transform: rotate(-360deg); + transform: rotate(-360deg); + } +} +@keyframes sk-wanderingCube { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + } + 25% { + -webkit-transform: translateX(30px) rotate(-90deg) scale(0.5); + transform: translateX(30px) rotate(-90deg) scale(0.5); + } + 50% { + -webkit-transform: translateX(30px) translateY(30px) rotate(-179deg); + transform: translateX(30px) translateY(30px) rotate(-179deg); + } + 50.1% { + -webkit-transform: translateX(30px) translateY(30px) rotate(-180deg); + transform: translateX(30px) translateY(30px) rotate(-180deg); + } + 75% { + -webkit-transform: translateX(0) translateY(30px) rotate(-270deg) scale(0.5); + transform: translateX(0) translateY(30px) rotate(-270deg) scale(0.5); + } + 100% { + -webkit-transform: rotate(-360deg); + transform: rotate(-360deg); + } +} +.sk-spinner-pulse { + -webkit-animation: sk-pulseScaleOut 1s infinite ease-in-out; + animation: sk-pulseScaleOut 1s infinite ease-in-out; +} +@-webkit-keyframes sk-pulseScaleOut { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 100% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0; + } +} +@keyframes sk-pulseScaleOut { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 100% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0; + } +} +.sk-chasing-dots { + position: relative; + text-align: center; + -webkit-animation: sk-chasingDotsRotate 2s infinite linear; + animation: sk-chasingDotsRotate 2s infinite linear; +} +.sk-chasing-dots .sk-child { + width: 60%; + height: 60%; + display: inline-block; + position: absolute; + top: 0; + -webkit-animation: sk-chasingDotsBounce 2s infinite ease-in-out; + animation: sk-chasingDotsBounce 2s infinite ease-in-out; +} +.sk-chasing-dots .sk-dot2 { + top: auto; + bottom: 0; + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +@-webkit-keyframes sk-chasingDotsRotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes sk-chasingDotsRotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@-webkit-keyframes sk-chasingDotsBounce { + 0%, + 100% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes sk-chasingDotsBounce { + 0%, + 100% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +.sk-three-bounce { + margin: 40px auto; + width: 80px; + text-align: center; +} +.sk-three-bounce .sk-child { + width: 20px; + height: 20px; + display: inline-block; + -webkit-animation: sk-three-bounce 1.4s ease-in-out 0s infinite both; + animation: sk-three-bounce 1.4s ease-in-out 0s infinite both; +} +.sk-circle .sk-child:before, +.sk-fading-circle .sk-circle:before { + display: block; + border-radius: 100%; + content: ''; + background-color: #333; +} +.sk-three-bounce .sk-bounce1 { + -webkit-animation-delay: -0.32s; + animation-delay: -0.32s; +} +.sk-three-bounce .sk-bounce2 { + -webkit-animation-delay: -0.16s; + animation-delay: -0.16s; +} +@-webkit-keyframes sk-three-bounce { + 0%, + 100%, + 80% { + -webkit-transform: scale(0); + transform: scale(0); + } + 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes sk-three-bounce { + 0%, + 100%, + 80% { + -webkit-transform: scale(0); + transform: scale(0); + } + 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +.sk-circle { + margin: 40px auto; + width: 40px; + height: 40px; + position: relative; +} +.sk-circle .sk-child { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; +} +.sk-circle .sk-child:before { + margin: 0 auto; + width: 15%; + height: 15%; + -webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out both; + animation: sk-circleBounceDelay 1.2s infinite ease-in-out both; +} +.sk-circle .sk-circle2 { + -webkit-transform: rotate(30deg); + -ms-transform: rotate(30deg); + transform: rotate(30deg); +} +.sk-circle .sk-circle3 { + -webkit-transform: rotate(60deg); + -ms-transform: rotate(60deg); + transform: rotate(60deg); +} +.sk-circle .sk-circle4 { + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.sk-circle .sk-circle5 { + -webkit-transform: rotate(120deg); + -ms-transform: rotate(120deg); + transform: rotate(120deg); +} +.sk-circle .sk-circle6 { + -webkit-transform: rotate(150deg); + -ms-transform: rotate(150deg); + transform: rotate(150deg); +} +.sk-circle .sk-circle7 { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.sk-circle .sk-circle8 { + -webkit-transform: rotate(210deg); + -ms-transform: rotate(210deg); + transform: rotate(210deg); +} +.sk-circle .sk-circle9 { + -webkit-transform: rotate(240deg); + -ms-transform: rotate(240deg); + transform: rotate(240deg); +} +.sk-circle .sk-circle10 { + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.sk-circle .sk-circle11 { + -webkit-transform: rotate(300deg); + -ms-transform: rotate(300deg); + transform: rotate(300deg); +} +.sk-circle .sk-circle12 { + -webkit-transform: rotate(330deg); + -ms-transform: rotate(330deg); + transform: rotate(330deg); +} +.sk-circle .sk-circle2:before { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} +.sk-circle .sk-circle3:before { + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +.sk-circle .sk-circle4:before { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} +.sk-circle .sk-circle5:before { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} +.sk-circle .sk-circle6:before { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; +} +.sk-circle .sk-circle7:before { + -webkit-animation-delay: -0.6s; + animation-delay: -0.6s; +} +.sk-circle .sk-circle8:before { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; +} +.sk-circle .sk-circle9:before { + -webkit-animation-delay: -0.4s; + animation-delay: -0.4s; +} +.sk-circle .sk-circle10:before { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; +} +.sk-circle .sk-circle11:before { + -webkit-animation-delay: -0.2s; + animation-delay: -0.2s; +} +.sk-circle .sk-circle12:before { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; +} +@-webkit-keyframes sk-circleBounceDelay { + 0%, + 100%, + 80% { + -webkit-transform: scale(0); + transform: scale(0); + } + 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +@keyframes sk-circleBounceDelay { + 0%, + 100%, + 80% { + -webkit-transform: scale(0); + transform: scale(0); + } + 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} +.sk-cube-grid { + width: 40px; + height: 40px; + margin: 40px auto; +} +.sk-cube-grid .sk-cube { + width: 33.33%; + height: 33.33%; + background-color: #333; + float: left; + -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; + animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; +} +.sk-cube-grid .sk-cube1 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} +.sk-cube-grid .sk-cube2 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-cube-grid .sk-cube3 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.sk-cube-grid .sk-cube4 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} +.sk-cube-grid .sk-cube5 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} +.sk-cube-grid .sk-cube6 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-cube-grid .sk-cube7 { + -webkit-animation-delay: 0s; + animation-delay: 0s; +} +.sk-cube-grid .sk-cube8 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} +.sk-cube-grid .sk-cube9 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} +@-webkit-keyframes sk-cubeGridScaleDelay { + 0%, + 100%, + 70% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } + 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} +@keyframes sk-cubeGridScaleDelay { + 0%, + 100%, + 70% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } + 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} +.sk-fading-circle { + margin: 40px auto; + width: 40px; + height: 40px; + position: relative; +} +.sk-fading-circle .sk-circle { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; +} +.sk-fading-circle .sk-circle:before { + margin: 0 auto; + width: 15%; + height: 15%; + -webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out both; + animation: sk-circleFadeDelay 1.2s infinite ease-in-out both; +} +.sk-fading-circle .sk-circle2 { + -webkit-transform: rotate(30deg); + -ms-transform: rotate(30deg); + transform: rotate(30deg); +} +.sk-fading-circle .sk-circle3 { + -webkit-transform: rotate(60deg); + -ms-transform: rotate(60deg); + transform: rotate(60deg); +} +.sk-fading-circle .sk-circle4 { + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.sk-fading-circle .sk-circle5 { + -webkit-transform: rotate(120deg); + -ms-transform: rotate(120deg); + transform: rotate(120deg); +} +.sk-fading-circle .sk-circle6 { + -webkit-transform: rotate(150deg); + -ms-transform: rotate(150deg); + transform: rotate(150deg); +} +.sk-fading-circle .sk-circle7 { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.sk-fading-circle .sk-circle8 { + -webkit-transform: rotate(210deg); + -ms-transform: rotate(210deg); + transform: rotate(210deg); +} +.sk-fading-circle .sk-circle9 { + -webkit-transform: rotate(240deg); + -ms-transform: rotate(240deg); + transform: rotate(240deg); +} +.sk-fading-circle .sk-circle10 { + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.sk-fading-circle .sk-circle11 { + -webkit-transform: rotate(300deg); + -ms-transform: rotate(300deg); + transform: rotate(300deg); +} +.sk-fading-circle .sk-circle12 { + -webkit-transform: rotate(330deg); + -ms-transform: rotate(330deg); + transform: rotate(330deg); +} +.sk-fading-circle .sk-circle2:before { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} +.sk-fading-circle .sk-circle3:before { + -webkit-animation-delay: -1s; + animation-delay: -1s; +} +.sk-fading-circle .sk-circle4:before { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} +.sk-fading-circle .sk-circle5:before { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} +.sk-fading-circle .sk-circle6:before { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; +} +.sk-fading-circle .sk-circle7:before { + -webkit-animation-delay: -0.6s; + animation-delay: -0.6s; +} +.sk-fading-circle .sk-circle8:before { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; +} +.sk-fading-circle .sk-circle9:before { + -webkit-animation-delay: -0.4s; + animation-delay: -0.4s; +} +.sk-fading-circle .sk-circle10:before { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; +} +.sk-fading-circle .sk-circle11:before { + -webkit-animation-delay: -0.2s; + animation-delay: -0.2s; +} +.sk-fading-circle .sk-circle12:before { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; +} +@-webkit-keyframes sk-circleFadeDelay { + 0%, + 100%, + 39% { + opacity: 0; + } + 40% { + opacity: 1; + } +} +@keyframes sk-circleFadeDelay { + 0%, + 100%, + 39% { + opacity: 0; + } + 40% { + opacity: 1; + } +} +.sk-folding-cube { + margin: 40px auto; + width: 40px; + height: 40px; + position: relative; + -webkit-transform: rotateZ(45deg); + transform: rotateZ(45deg); +} +.sk-folding-cube .sk-cube { + float: left; + width: 50%; + height: 50%; + position: relative; + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); +} +.sk-folding-cube .sk-cube:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #333; + -webkit-animation: sk-foldCubeAngle 2.4s infinite linear both; + animation: sk-foldCubeAngle 2.4s infinite linear both; + -webkit-transform-origin: 100% 100%; + -ms-transform-origin: 100% 100%; + transform-origin: 100% 100%; +} +.sk-folding-cube .sk-cube2 { + -webkit-transform: scale(1.1) rotateZ(90deg); + transform: scale(1.1) rotateZ(90deg); +} +.sk-folding-cube .sk-cube3 { + -webkit-transform: scale(1.1) rotateZ(180deg); + transform: scale(1.1) rotateZ(180deg); +} +.sk-folding-cube .sk-cube4 { + -webkit-transform: scale(1.1) rotateZ(270deg); + transform: scale(1.1) rotateZ(270deg); +} +.sk-folding-cube .sk-cube2:before { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-folding-cube .sk-cube3:before { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} +.sk-folding-cube .sk-cube4:before { + -webkit-animation-delay: 0.9s; + animation-delay: 0.9s; +} +@-webkit-keyframes sk-foldCubeAngle { + 0%, + 10% { + -webkit-transform: perspective(140px) rotateX(-180deg); + transform: perspective(140px) rotateX(-180deg); + opacity: 0; + } + 25%, + 75% { + -webkit-transform: perspective(140px) rotateX(0); + transform: perspective(140px) rotateX(0); + opacity: 1; + } + 100%, + 90% { + -webkit-transform: perspective(140px) rotateY(180deg); + transform: perspective(140px) rotateY(180deg); + opacity: 0; + } +} +@keyframes sk-foldCubeAngle { + 0%, + 10% { + -webkit-transform: perspective(140px) rotateX(-180deg); + transform: perspective(140px) rotateX(-180deg); + opacity: 0; + } + 25%, + 75% { + -webkit-transform: perspective(140px) rotateX(0); + transform: perspective(140px) rotateX(0); + opacity: 1; + } + 100%, + 90% { + -webkit-transform: perspective(140px) rotateY(180deg); + transform: perspective(140px) rotateY(180deg); + opacity: 0; + } +} +.progressbar { + width: 100%; + margin-top: 5px; + margin-bottom: 35px; + position: relative; + background-color: #fff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); +} +.proggress { + height: 8px; + width: 10px; +} +.percentCount { + float: right; + margin-top: 10px; + clear: both; + font-weight: bold; + font-family: Arial; +} diff --git a/public/assets/css/style.min.css b/public/assets/css/style.min.css new file mode 100644 index 0000000..f4f1e66 --- /dev/null +++ b/public/assets/css/style.min.css @@ -0,0 +1,9403 @@ +@charset "UTF-8"; +@import url(https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap); +*, +::after, +::before { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +body, +html { + height: 100%; +} +body { + font-family: 'Poppins', sans-serif; + font-size: 16px; + font-weight: 400; + font-style: normal; + line-height: 1.625; + position: relative; + visibility: visible; + color: #474747; +} +body[dir='rtl'] { + text-align: right; +} +h1, +h2, +h3, +h4, +h5, +h6 { + color: #000; +} +a, +button { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + text-decoration: none; + background-color: transparent; + border: 0; +} +textarea { + width: 100%; + padding-left: 20px; + padding-top: 20px; + outline: 0; +} +label { + margin-bottom: 15px; +} +.form-control { + display: block; + width: 100%; + min-height: 45px; + padding: 6px 80px 6px 20px; + font-size: 14px; + font-weight: 400; + line-height: 1.625; + color: #474747; + border-radius: 5px; + background-color: #fff; +} +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #ced4da; + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; +} +p:last-child { + margin-bottom: 0; +} +dl, +ol, +ul { + margin-top: 0; + margin-bottom: 0; + padding: 0; + margin: 0; + list-style: none; +} +li { + list-style: none; +} +button:focus, +input:focus { + outline: 0 dotted; + outline: 0 auto -webkit-focus-ring-color; + -webkit-box-shadow: none; + box-shadow: none; +} +input { + display: inline-block; + line-height: 50px; + height: 50px; + font-size: 15px; + width: 100%; + background: 0; + border-radius: 0; + -webkit-border-radius: 0; + text-align: left; + box-shadow: none; + -webkit-box-shadow: none; + padding-left: 20px; + padding-right: 10px; + outline: 0; +} +.img-responsive { + max-width: 100%; + display: block; + width: 100%; +} +.pt-100px { + padding-top: 100px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .pt-100px { + padding-top: 80px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .pt-100px { + padding-top: 60px; + } +} +@media only screen and (max-width: 767px) { + .pt-100px { + padding-top: 60px; + } +} +.pb-100px { + padding-bottom: 100px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .pb-100px { + padding-bottom: 80px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .pb-100px { + padding-bottom: 60px; + } +} +@media only screen and (max-width: 767px) { + .pb-100px { + padding-bottom: 20px; + } +} +.pt-70px { + padding-top: 70px; +} +.pb-40px { + padding-bottom: 40px; +} +.line-height-1 { + line-height: 1; +} +.mt-25px { + margin-top: 25px; +} +.mt-30px { + margin-top: 30px; +} +.mt-20px { + margin-top: 20px; +} +.mb-30px { + margin-bottom: 30px; +} +.ml-20px { + margin-left: 20px; +} +.ml-15px { + margin-left: 15px; +} +.mr-15px { + margin-right: 15px; +} +.ml-5px { + margin-left: 5px; +} +.ml-10px { + margin-left: 10px; +} +.pl-35px { + padding-left: 35px; +} +.pr-35px { + padding-right: 35px; +} +.mb-n-50 { + margin-bottom: -50px; +} +.mb-50px { + margin-bottom: 50px; +} +.mb-40px { + margin-bottom: 40px; +} +.ml-auto { + margin-left: auto; +} +.mr-auto { + margin-right: auto; +} +.bg-black { + background-color: #2f333a; +} +.bg-gray { + background-color: #f4f4f4; +} +.bg-white { + background-color: #fff; +} +#scrollUp { + width: 50px; + height: 50px; + background: #036eb8; + color: #fff; + right: 20px; + bottom: 60px; + text-align: center; + overflow: hidden; + border-radius: 50px; + z-index: 9811 !important; + font-size: 36px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +#scrollUp:hover { + background: #036eb8; + color: #fff; + -webkit-box-shadow: 0 5px 15px 0 rgba(153, 63, 107, 0.5); + box-shadow: 0 5px 15px 0 rgba(153, 63, 107, 0.5); + -webkit-transform: translateY(-1px); + transform: translateY(-1px); +} +.slider-animated-1 > * { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} +.swiper-slide-active .slider-animated-1 > * { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} +.swiper-slide-active .slider-animated-1 > :nth-child(1) { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.swiper-slide-active .slider-animated-1 > :nth-child(2) { + -webkit-animation-delay: 1s; + animation-delay: 1s; +} +.swiper-slide-active .slider-animated-1 > :nth-child(3) { + -webkit-animation-delay: 1.5s; + animation-delay: 1.5s; +} +.swiper-slide-active .slider-animated-1 > :nth-child(4) { + -webkit-animation-delay: 2s; + animation-delay: 2s; +} +.swiper-slide-active .slider-animated-1 > :nth-child(5) { + -webkit-animation-delay: 2.5s; + animation-delay: 2.5s; +} +.swiper-slide-active .slider-animated-1 > :nth-child(6) { + -webkit-animation-delay: 3s; + animation-delay: 3s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > * { + -webkit-animation-name: lightSpeedInLeft; + animation-name: lightSpeedInLeft; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(1) { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(2) { + -webkit-animation-delay: 1s; + animation-delay: 1s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(3) { + -webkit-animation-delay: 1.5s; + animation-delay: 1.5s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(4) { + -webkit-animation-delay: 2s; + animation-delay: 2s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(5) { + -webkit-animation-delay: 2.5s; + animation-delay: 2.5s; +} +.swiper-slide-active .slider-animated-1.slider-animated-2 > :nth-child(6) { + -webkit-animation-delay: 3s; + animation-delay: 3s; +} +.section-title { + line-height: 1; + padding: 0 300px; + margin-bottom: 50px; +} +.section-title .title { + font-size: 24px; + font-weight: 600; + display: inline-block; + color: #424242; + margin: 0 0 25px; + line-height: 27px; +} +@media only screen and (max-width: 767px) { + .section-title .title { + font-size: 30px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .section-title { + padding: 0 170px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .section-title { + padding: 0 80px; + } +} +@media only screen and (max-width: 767px) { + .section-title { + padding: 0; + } +} +@media only screen and (max-width: 479px) { + .section-title { + margin-bottom: 30px; + } +} +.section-title P { + line-height: 30px; + color: #747474; +} +@media only screen and (max-width: 479px) { + .section-title.mb-60px { + margin-bottom: 30px; + } +} +.sticky-nav.menu_fixed { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 99; + -webkit-animation: sticky 1s; + animation: sticky 1s; + -webkit-box-shadow: 2px 4px 8px rgba(51, 51, 51, 0.25); + box-shadow: 2px 4px 8px rgba(51, 51, 51, 0.25); + background-color: #fff; +} +@-webkit-keyframes sticky { + 0% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} +@keyframes sticky { + 0% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} +.header-to-bar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + color: #b5b5b5; + font-size: 14px; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + line-height: 50px; + background-color: #242424; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-weight: 300; +} +.header-main { + background-color: #fff; + border-bottom: 1px solid #eee; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .header-main { + padding: 10px 0; + } +} +.header-actions { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.header-actions > * + * { + margin-left: 18px; +} +@media only screen and (max-width: 575px) { + .header-actions > * + * { + margin-left: 15px; + } +} +@media only screen and (max-width: 479px) { + .header-actions > * + * { + margin-left: 8px; + } +} +.header-actions .header-action-btn { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + text-decoration: none; + color: #000; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.header-actions .header-action-btn:hover { + color: #036eb8; +} +.header-actions .header-action-btn i { + -webkit-transition: 0s; + transition: 0s; + font-size: 26px; +} +@media only screen and (max-width: 575px) { + .header-actions .header-action-btn i { + font-size: 25px; + } +} +@media only screen and (max-width: 479px) { + .header-actions .header-action-btn i { + font-size: 22px; + } +} +.header-actions .header-action-btn i:hover { + color: #036eb8; +} +.header-actions .header-action-btn .header-action-num { + font-size: 11px; + font-weight: 700; + position: absolute; + z-index: 2; + top: -10px; + right: -7px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + color: #fff; + border-radius: 50%; + background-color: #036eb8; + width: 21px; + height: 21px; +} +.header-actions .header-action-btn .cart-amount { + display: block; + font-size: 16px; + font-weight: 700; + text-align: center; + padding-left: 15px; + color: #0f0f0f; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.header-actions .header-action-btn:hover .cart-amount { + color: #036eb8; +} +.main-menu { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: right; + margin-right: 80px; + float: right; +} +.main-menu ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.main-menu ul li + li { + margin-left: 50px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .main-menu ul li + li { + margin-left: 30px; + } +} +.main-menu ul li a { + font-size: 14px; + font-weight: 400; + text-decoration: none; + text-transform: uppercase; + color: #2d2d2d; + display: block; + position: relative; + line-height: 80px; +} +.main-menu ul li.active > a, +.main-menu ul li:hover > a { + color: #036eb8 !important; +} +.main-menu ul li.dropdown { + position: relative; +} +.main-menu ul li.dropdown ul.sub-menu { + position: absolute; + z-index: 9; + text-align: left; + opacity: 0; + visibility: hidden; + -o-transform-origin: 0 0; + -ms-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -webkit-transform-origin: 0 0; + transform-style: preserve-3d; + -o-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + -webkit-transform-style: preserve-3d; + transform: rotateX(-75deg); + -o-transform: rotateX(-75deg); + -moz-transform: rotateX(-75deg); + -webkit-transform: rotateX(-75deg); + min-width: 120px; + left: auto !important; + background: #fff; + -webkit-box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + display: block; + -o-transition: -o-transform 0.3s, opacity 0.3s; + -ms-transition: -ms-transform 0.3s, opacity 0.3s; + -moz-transition: -moz-transform 0.3s, opacity 0.3s; + -webkit-transition: -webkit-transform 0.3s, opacity 0.3s; + padding: 10px 0; +} +.main-menu ul li.dropdown ul li { + padding: 0; + margin: 0; + display: block; +} +.main-menu ul li.dropdown ul li a { + display: block; + line-height: 20px; + padding: 12px 0 12px 20px; + font-weight: 400; + font-size: 12px; + color: #2d2d2d; + text-transform: capitalize; +} +.main-menu ul li.dropdown ul li a:hover { + padding-left: 25px; +} +.main-menu ul li.dropdown:hover .sub-menu { + opacity: 1; + visibility: visible; + transform: rotateX(0); + -o-transform: rotateX(0); + -moz-transform: rotateX(0); + -webkit-transform: rotateX(0); + -o-transition: -o-transform 0.3s, opacity 0.3s; + -ms-transition: -ms-transform 0.3s, opacity 0.3s; + -moz-transition: -moz-transform 0.3s, opacity 0.3s; + -webkit-transition: -webkit-transform 0.3s, opacity 0.3s; +} +.main-menu ul li.dropdown:hover .mega-menu { + opacity: 1; + visibility: visible; + transform: rotateX(0); + -o-transform: rotateX(0); + -moz-transform: rotateX(0); + -webkit-transform: rotateX(0); + -o-transition: -o-transform 0.3s, opacity 0.3s; + -ms-transition: -ms-transform 0.3s, opacity 0.3s; + -moz-transition: -moz-transform 0.3s, opacity 0.3s; + -webkit-transition: -webkit-transform 0.3s, opacity 0.3s; +} +.main-menu ul li .mega-menu { + position: absolute; + -webkit-box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + background: #fff; + padding: 30px 0 30px 30px; + opacity: 0; + visibility: hidden; + -o-transform-origin: 0 0; + -ms-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -webkit-transform-origin: 0 0; + transform-style: preserve-3d; + -o-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + -webkit-transform-style: preserve-3d; + transform: rotateX(-75deg); + -o-transform: rotateX(-75deg); + -moz-transform: rotateX(-75deg); + -webkit-transform: rotateX(-75deg); + left: 0; + width: 100%; + z-index: 2; + -o-transition: -o-transform 0.3s, opacity 0.3s; + -ms-transition: -ms-transform 0.3s, opacity 0.3s; + -moz-transition: -moz-transform 0.3s, opacity 0.3s; + -webkit-transition: -webkit-transform 0.3s, opacity 0.3s; + z-index: 15; +} +.main-menu ul li .mega-menu li ul { + width: 25%; + margin-right: 30px; + border-right: 1px solid #ebebeb; +} +.main-menu ul li .mega-menu li ul:last-child { + border-right: 0; +} +.main-menu ul li .mega-menu li ul li.title a { + color: #000; + font-size: 14px; + font-weight: 600; + display: block; + margin-bottom: 20px; + height: auto; + margin-top: 10px; +} +.main-menu ul li .mega-menu li ul li.title a:hover { + color: #036eb8; + padding-left: 0; +} +.main-menu ul li .mega-menu li ul li a { + color: #999; + text-transform: capitalize; + line-height: 20px; + font-weight: 400; + font-size: 12px; + display: block; + padding: 0; + border: 0; + height: auto; + margin-bottom: 8px; +} +.mega-menu span { + margin-right: 16px; + display: inline-block; +} +.mega-menu span img { + width: 96px; + height: 96px; + background: #f5f5f5; + padding: 12px; + border-radius: 8px; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + -ms-border-radius: 8px; + -o-border-radius: 8px; +} +.main-menu ul li .mega-menu li ul li a:hover { + color: #036eb8; + padding-left: 10px; +} +.main-menu ul li .mega-menu li ul li:last-child a { + margin: 0; +} +.header-bottom-set .dropdown-toggle { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + border: 0; + background-color: transparent; + padding: 0; +} +.header-bottom-set .dropdown-toggle::after { + display: none; +} +.header-bottom-set .dropdown-toggle i { + font-size: 29px; +} +.header-bottom-set .dropdown-menu { + margin: 0; + top: 40px !important; + left: auto !important; + right: 0; + min-width: 130px; + overflow: hidden; + padding: 0 15px; + background: #fff; + border-radius: 0; + border: 0; + -webkit-box-shadow: 0 3px 25.5px 4.5px rgba(0, 0, 0, 0.06); + box-shadow: 0 3px 25.5px 4.5px rgba(0, 0, 0, 0.06); + -webkit-transform: translate3d(0, 0, 0) !important; + transform: translate3d(0, 0, 0) !important; + inset: 40px 0 auto auto !important; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .header-bottom-set .dropdown-menu { + top: 48px !important; + inset: 48px 0 auto auto !important; + } +} +@media only screen and (max-width: 767px) { + .header-bottom-set .dropdown-menu { + top: 46px !important; + inset: 46px 0 auto auto !important; + } +} +.header-bottom-set .dropdown-menu li { + border-bottom: 1px solid #ebebeb; +} +.header-bottom-set .dropdown-menu li:last-child { + border: 0; +} +.header-bottom-set .dropdown-menu .dropdown-item { + padding: 10px; + color: #2d2d2d; + line-height: 25px; + font-size: 14px; + background: 0; +} +.header-bottom-set .dropdown-menu .dropdown-item:hover { + color: #036eb8; +} +.action-form { + position: relative; +} +.submit { + position: absolute; + top: 0; + left: auto; + right: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: 60px; + height: 100%; + background: #036eb8; + color: #fff; + font-size: 20px; + border-radius: 0 5px 5px 0; + -webkit-box-shadow: none; + box-shadow: none; + outline: 0; +} +body.offcanvas-open { + overflow: hidden; +} +.offcanvas { + font-size: 14px; + font-weight: 400; + position: fixed; + z-index: 1000; + top: 0; + right: 0; + left: auto; + display: block; + width: 400px; + height: 100%; + padding: 20px; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: translateX(100%); + transform: translateX(100%); + background-color: #fff; + -webkit-box-shadow: none; + box-shadow: none; + overflow: auto; + visibility: visible; +} +@media only screen and (max-width: 479px) { + .offcanvas { + width: 300px; + } +} +.offcanvas .inner { + position: relative; + z-index: 9; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + height: 100%; +} +.offcanvas .inner .head { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + width: 100%; + padding: 30px 20px; +} +.offcanvas .inner .head .title { + color: #000; + font-weight: 700; +} +.offcanvas .inner .head .offcanvas-close { + position: relative; + width: 20px; + height: 20px; + text-indent: -9999px; + border: 0; + background-color: transparent; +} +.offcanvas .inner .head .offcanvas-close::after { + position: absolute; + top: calc(50% - 1px); + left: 0; + width: 20px; + height: 2px; + content: ''; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + background-color: #036eb8; +} +.offcanvas .inner .head .offcanvas-close::before { + position: absolute; + top: calc(50% - 1px); + left: 0; + width: 20px; + height: 2px; + content: ''; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background-color: #036eb8; +} +.offcanvas .inner .head .offcanvas-close:hover:before { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} +.offcanvas .inner .head .offcanvas-close:hover:after { + -webkit-transform: rotate(0); + transform: rotate(0); +} +.offcanvas .inner .offcanvas-menu ul li { + position: relative; + display: block; + line-height: 28px; +} +.offcanvas .inner .offcanvas-menu ul li a { + display: block; + padding: 10px 0; + text-transform: capitalize; + color: #474747; + border-top: 1px solid #eee; + font-size: 16px; + font-weight: 600; +} +.offcanvas .inner .offcanvas-menu ul li .sub-menu { + position: static; + top: auto; + display: none; + visibility: visible; + width: 100%; + min-width: auto; + padding: 0; + -webkit-transition: none; + transition: none; + opacity: 1; + -webkit-box-shadow: none; + box-shadow: none; +} +.offcanvas .inner .offcanvas-menu ul li .sub-menu li { + line-height: inherit; + position: relative; +} +.offcanvas .inner .offcanvas-menu ul li .sub-menu li a { + text-transform: capitalize; + font-weight: 400; + padding-left: 10px; + padding-right: 0; + display: block; + border-top: 1px solid #eee; + font-size: 14px; + font-weight: 500; +} +.offcanvas .inner .offcanvas-menu ul li .sub-menu li:last-child { + border-bottom: 0 solid #eee; +} +.offcanvas .inner .offcanvas-menu ul li .menu-expand { + position: absolute; + z-index: 2; + top: 0; + right: 0; + width: 24px; + height: 49px; + cursor: pointer; + background-color: transparent; +} +.offcanvas .inner .offcanvas-menu ul li:hover > a { + color: #036eb8; +} +.offcanvas .inner .offcanvas-menu ul li:hover > span.menu-expand:before { + background: #036eb8; +} +.offcanvas .inner .offcanvas-menu ul li:hover > span.menu-expand:after { + background: #036eb8; +} +.offcanvas .inner .offcanvas-menu ul li:last-child { + border-bottom: 1px solid #eee; +} +.offcanvas .inner .offcanvas-social li { + display: inline-block; + margin: 0 10px 0 0; + line-height: 40px; + padding: 0; +} +@media only screen and (max-width: 479px) { + .offcanvas .inner .offcanvas-social li { + margin: 0 5px 0 0; + } +} +.offcanvas .inner .offcanvas-social li a { + position: relative; + display: inline-block; + vertical-align: middle; + color: #fff; + background: #036eb8; + font-size: 16px; + padding: 0; + line-height: 40px; + width: 40px; + height: 40px; + border-radius: 100%; + text-align: center; + border: 0; + z-index: 1; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; +} +.offcanvas .inner .offcanvas-social li a:hover { + background: #000; + color: #fff; +} +@media only screen and (max-width: 479px) { + .offcanvas .inner .offcanvas-social li a { + line-height: 35px; + width: 35px; + height: 35px; + font-size: 15px; + } +} +.offcanvas .inner .foot .buttons a { + display: block; + text-transform: capitalize; + font-weight: 500; + font-size: 16px; + border: 0; + color: #fff; + -webkit-box-shadow: none; + box-shadow: none; + padding: 10px 15px; + line-height: 26px; + border: 0; + background: #000; + border-radius: 0; + width: auto; + height: auto; +} +.offcanvas .inner .foot .buttons a:hover { + background-color: #036eb8; + color: #fff; +} +.offcanvas .inner .foot .buttons .current-btn { + background-color: #036eb8; + color: #fff; +} +.offcanvas .inner .foot .sub-total { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding-top: 15px; + padding-bottom: 15px; + border-top: 1px solid #eee; + margin: 30px 0 0 0; +} +.offcanvas .inner .foot .sub-total .table > :not(caption) > * > * { + padding: 0; + border: 0; +} +.offcanvas .inner .foot .sub-total .table > tbody > tr > td { + border: 0; + padding: 0; + color: #000; + text-transform: capitalize; + font-size: 20px; + vertical-align: middle; + font-weight: 500; + line-height: 30px; +} +.offcanvas .inner .foot .sub-total .table > tbody > tr > td.theme-color { + color: #036eb8; +} +.offcanvas .inner .foot .sub-total .amount { + color: #eb2606; + font-weight: 600; +} +.offcanvas .inner .foot .minicart-message { + margin-top: 30px; + margin-bottom: 30px; +} +.offcanvas-menu > ul > li .menu-expand { + position: absolute; + z-index: 2; + top: 0; + right: 0; + width: 24px; + height: 44px; + cursor: pointer; + background-color: transparent; +} +.offcanvas-menu > ul.sub-menu > li .menu-expand { + right: 15px; +} +.offcanvas.offcanvas-mobile-menu { + right: auto; + left: 0; + padding: 0; + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + width: 350px; + padding: 50px 30px; +} +@media only screen and (max-width: 479px) { + .offcanvas.offcanvas-mobile-menu { + width: 300px; + } +} +.offcanvas.offcanvas-mobile-menu .offcanvas-close { + position: absolute; + width: 40px; + height: 40px; + text-indent: -9999px; + border: 0; + left: 0; + top: 5px; + background-color: #036eb8; + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; + border-radius: 50%; +} +.offcanvas.offcanvas-mobile-menu .offcanvas-close::after { + position: absolute; + top: calc(50% - 1px); + left: 50%; + margin-left: -10px; + width: 20px; + height: 2px; + content: ''; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + background-color: #fff; +} +.offcanvas.offcanvas-mobile-menu .offcanvas-close::before { + position: absolute; + top: calc(50% - 1px); + left: 50%; + margin-left: -10px; + width: 20px; + height: 2px; + content: ''; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background-color: #fff; +} +.offcanvas.offcanvas-mobile-menu .offcanvas-close:hover:before { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} +.offcanvas.offcanvas-mobile-menu .offcanvas-close:hover:after { + -webkit-transform: rotate(0); + transform: rotate(0); +} +.offcanvas.offcanvas-cart .inner .head, +.offcanvas.offcanvas-wishlist .inner .head { + margin-bottom: 30px; + padding: 0; +} +.offcanvas.offcanvas-cart .inner .head .title, +.offcanvas.offcanvas-wishlist .inner .head .title { + font-size: 20px; +} +.offcanvas-menu > ul > li .menu-expand::after, +.offcanvas-menu > ul > li .menu-expand::before { + position: absolute; + top: calc(50% - 1px); + left: calc(50% - 7px); + width: 14px; + height: 2px; + content: ''; + -webkit-transition: all 0.5s ease 0s; + transition: all 0.5s ease 0s; + -webkit-transform: scale(0.75); + transform: scale(0.75); + background-color: #000; +} +.offcanvas-menu > ul > li .menu-expand::after { + -webkit-transform: rotate(90deg) scale(0.75); + transform: rotate(90deg) scale(0.75); +} +.offcanvas-menu > ul > li.active > .menu-expand::after { + -webkit-transform: rotate(0) scale(0.75); + transform: rotate(0) scale(0.75); +} +.offcanvas-menu > ul > li .sub-menu li.active > .menu-expand::after { + -webkit-transform: rotate(0) scale(0.75); + transform: rotate(0) scale(0.75); +} +.offcanvas.offcanvas-mobile-menu.offcanvas-open { + -webkit-transform: translateX(0); + transform: translateX(0); +} +.offcanvas.offcanvas-mobile-menu.offcanvas-open .offcanvas-close { + left: 80%; +} +.offcanvas-overlay { + position: fixed; + z-index: 999; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: none; + background-color: rgba(0, 0, 0, 0.5); +} +.offcanvas.offcanvas-open { + -webkit-transform: translateX(0); + transform: translateX(0); +} +.minicart-product-list { + margin: 0; + padding-left: 0; + list-style: none; +} +.minicart-product-list li { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-bottom: 30px; + padding-bottom: 30px; + border-bottom: 1px solid #ebebeb; +} +.minicart-product-list li .image { + -webkit-box-flex: 1; + -ms-flex: 1 0 75px; + flex: 1 0 75px; +} +.minicart-product-list li .image img { + max-width: 100%; + border: 1px solid #ebebeb; +} +@media only screen and (max-width: 575px) { + .minicart-product-list li .image { + -ms-flex: 1 0 50px; + -webkit-box-flex: 1; + flex: 1 0 50px; + } +} +.minicart-product-list li .content { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 0 calc(100% - 150px); + flex: 1 0 calc(100% - 150px); + padding-left: 15px; +} +.minicart-product-list li .content .title { + color: #000; + font-weight: 500; +} +.minicart-product-list li .content .title:hover { + color: #036eb8; +} +.minicart-product-list li .content .quantity-price { + font-size: 14px; + display: block; + margin-top: 10px; +} +.minicart-product-list li .content .quantity-price .amount { + color: #036eb8; + font-weight: 500; + font-size: 18px; +} +.minicart-product-list li .content .remove { + line-height: 1.5; + position: absolute; + top: 0; + right: 0; + padding: 0 3px; + color: #000; + font-size: 16px; +} +.minicart-product-list li .content .remove:hover { + color: #eb2606; +} +@media only screen and (max-width: 575px) { + .minicart-product-list li .content { + -ms-flex: 1 0 calc(100% - 75px); + -webkit-box-flex: 1; + flex: 1 0 calc(100% - 75px); + } +} +.minicart-product-list li:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: 0; +} +.bg-color1 { + background-color: #f5f5f5; +} +.bg-color2 { + background-color: #cebdb5; +} +.bg-color3 { + background-color: #cebdb5; +} +.slider-height { + height: 771px; +} +@media only screen and (min-width: 1200px) and (max-width: 1599px) { + .slider-height { + height: 700px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .slider-height { + height: 550px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-height { + height: 500px; + } +} +@media only screen and (max-width: 767px) { + .slider-height { + height: 450px; + } +} +@media only screen and (max-width: 575px) { + .slider-height { + height: 650px; + } +} +@media only screen and (max-width: 479px) { + .slider-height { + height: 600px; + } +} +.ptb-30px { + padding: 30px 0; +} +.pl-80px { + padding-left: 80px; +} +.slider-height-2 { + background-repeat: no-repeat; + background-size: cover; + background-position: center; + height: 513px; +} +@media only screen and (min-width: 1200px) and (max-width: 1599px) { + .slider-height-2 { + height: 500px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .slider-height-2 { + height: 500px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-height-2 { + height: 500px; + } +} +@media only screen and (max-width: 767px) { + .slider-height-2 { + height: 500px; + } +} +.hero-slide-image { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: end; + -ms-flex-align: end; + align-items: flex-end; +} +.hero-slide-image img { + max-width: 100%; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .hero-slide-image img { + width: 80%; + } +} +@media only screen and (max-width: 575px) { + .hero-slide-image img { + width: 60%; + margin: auto; + } +} +@media only screen and (max-width: 479px) { + .hero-slide-image img { + width: 70%; + margin: auto; + } +} +@media only screen and (max-width: 575px) { + .hero-slide-image { + margin-top: 50px; + text-align: center; + } +} +@media only screen and (max-width: 575px) { + .sm-center-view { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } +} +.swiper-slide-active .hero-slide-image img { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; + -webkit-animation-delay: 1s; + animation-delay: 1s; +} +.hero-slide-content { + position: relative; + z-index: 9; + text-transform: capitalize; + text-align: center; +} +.hero-slide-content .category { + display: block; + font-size: 36px; + color: #036eb8; + margin: 0; + font-weight: 400; +} +.hero-slide-content .title-1 { + font-size: 60px; + font-weight: 500; + margin-bottom: 22px; + color: #4a4a4a; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .hero-slide-content .title-1 { + font-size: 56px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .hero-slide-content .title-1 { + font-size: 42px; + } +} +@media only screen and (max-width: 767px) { + .hero-slide-content .title-1 { + font-size: 30px; + margin-bottom: 15px; + } +} +.hero-slide-content .price { + font-size: 36px; + font-weight: 500; + margin-bottom: 37px; + color: #4a4a4a; + display: block; +} +.hero-slide-content .price .new { + color: #036eb8; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .hero-slide-content .price { + font-size: 30px; + margin-bottom: 30px; + } +} +@media only screen and (max-width: 767px) { + .hero-slide-content .price { + font-size: 24px; + margin-bottom: 25px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .hero-slide-content .btn { + width: 150px; + height: 50px; + font-size: 14px; + } +} +.hero-slide-content .btn i { + font-size: 16px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .hero-slide-content .btn i { + font-size: 14px; + } +} +@media only screen and (max-width: 767px) { + .hero-slide-content.hero-slide-content-2.pl-80px { + padding-left: 30px; + } +} +@media only screen and (max-width: 767px) { + .hero-slide-content.hero-slide-content-2 .category { + font-size: 24px; + margin-bottom: 10px; + } +} +.hero-slide-content.hero-slide-content-2 .title-1 { + text-transform: capitalize; + font-weight: 400; + margin-bottom: 37px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .hero-slide-content.hero-slide-content-2 .title-1 { + font-size: 54px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .hero-slide-content.hero-slide-content-2 .title-1 { + font-size: 48px; + } +} +@media only screen and (max-width: 767px) { + .hero-slide-content.hero-slide-content-2 .title-1 { + font-size: 40px; + } +} +.hero-slide-content.hero-slide-content-2 .btn-primary { + width: 160px; + height: 55px; +} +@media only screen and (max-width: 575px) { + .show-case { + position: relative; + } +} +.newsletter-area { + background-color: #fff; + color: #fff; + line-height: 1; + padding: 48px 0; +} +@media only screen and (max-width: 1400px) { + .newsletter-area { + padding: 24px 0; + width: 94%; + } +} +.newsletter-area .newsletter-content { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .newsletter-area .newsletter-content { + margin: 0 0 30px; + } +} +.newsletter-area .newsletter-content i { + font-size: 60px; + color: #036eb8; + margin-right: 30px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .newsletter-area .newsletter-content i { + margin-bottom: 15px; + margin-right: 20px; + } +} +.newsletter-area .newsletter-content .newsletter-text .title { + font-size: 24px; + font-weight: 400; + color: #fff; + margin: 0 0 10px; +} +.newsletter-area .newsletter-content .newsletter-text p { + font-size: 16px; + color: #a1a1a1; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (max-width: 479px) { + .newsletter-area .newsletter-content .newsletter-text p { + font-size: 14px; + } +} +.newsletter-area .news-letter-form .subscribe-form { + position: relative; +} +.newsletter-area .news-letter-form .subscribe-form input { + height: 52px; + font-size: 14px; + border: 0; + background-color: #f5f5f5; + color: #B2B2B2f; + border-radius: 5px 5px 5px 5px; + padding-right: 130px; +} +@media only screen and (max-width: 479px) { + .newsletter-area .news-letter-form .subscribe-form input { + padding-right: 105px; + } +} +.newsletter-area .news-letter-form .subscribe-form input::-webkit-input-placeholder { + color: #a1a1a1; +} +.newsletter-area .news-letter-form .subscribe-form input::-moz-placeholder { + color: #a1a1a1; +} +.newsletter-area .news-letter-form .subscribe-form input:-ms-input-placeholder { + color: #a1a1a1; +} +.newsletter-area .news-letter-form .subscribe-form input::-ms-input-placeholder { + color: #a1a1a1; +} +.newsletter-area .news-letter-form .subscribe-form input::placeholder { + color: #a1a1a1; +} +.newsletter-area .news-letter-form .subscribe-form button { + height: 52px; + position: absolute; + top: 0; + right: 0; + width: 126px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + font-size: 14px; + color: #fff; + font-weight: 500; + text-transform: uppercase; + background-color: #036eb8; + border-radius: 0 5px 5px 0; + z-index: 1; + overflow: hidden; + -webkit-box-shadow: none; + box-shadow: none; +} +@media only screen and (max-width: 479px) { + .newsletter-area .news-letter-form .subscribe-form button { + width: 100px; + } +} +.newsletter-area .news-letter-form .subscribe-form button::before { + position: absolute; + content: ''; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: #000; + z-index: -1; + -webkit-transition: 0.3s linear; + transition: 0.3s linear; + -webkit-transform: scale(0); + transform: scale(0); + border-radius: 50%; + width: 100%; + height: 100%; +} +.newsletter-area .news-letter-form .subscribe-form button:hover::before { + -webkit-transform: scale(1.5); + transform: scale(1.5); +} +.line-shape-bottom { + position: relative; +} +.line-shape-bottom::after { + position: absolute; + top: auto; + left: 0; + width: 100%; + max-width: 1170px; + height: 1px; + content: ''; + background-color: #454545; + margin: auto; + bottom: -60px; + right: 0; +} +.line-shape { + position: relative; +} +.line-shape::after { + position: absolute; + top: 10px; + left: 20px; + height: 100%; + width: 1px; + content: ''; + background-color: #454545; + margin: auto; + bottom: 0; +} +.payment-img { + margin: 0 0 2em 10px; + padding: 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .line-shape::after { + left: 10px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .line-shape::after { + display: none; + } +} +.line-shape-top { + border-top: 1px solid #eee; + margin: 25px 0 25px 0; +} +.line-footer-top { + border-top: 1px solid #eee; + padding: 25px 0 25px 0; +} +.pl-120px { + padding-left: 120px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .pl-120px { + padding-left: 40px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .pl-120px { + padding-left: 12px; + } +} +@media only screen and (max-width: 575px) { + .pl-120px { + padding-left: 12px; + padding-top: 0; + padding-bottom: 20px; + } +} +.footer-area { + color: #333; + border-top: 1px solid #eee; +} +.footer-area .footer-top { + padding: 60px 0 55px 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .footer-area .footer-top { + padding: 60px 0 0 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .footer-area .footer-top { + padding: 60px 0 0 0; + } +} +@media only screen and (max-width: 767px) { + .footer-area .footer-top { + padding: 50px 0 0 0; + } +} +.img-weixin { + box-shadow: 0px 0px 20px #e8e9eb; + border-radius: 8px; + width: 60%; + padding: 12px; +} +.img-weixin p { + text-align: center; + line-height: 40px; +} +.footer-area .footer-top .single-wedge .footer-logo { + margin: 0 0 27px; +} +.footer-area .footer-top .single-wedge .footer-herading { + font-size: 14px; + text-transform: capitalize; + position: relative; + color: #333; +} +.footer-area .footer-top .single-wedge .footer-links li { + display: block; + margin: 0; + line-height: 1; + border: 0; + font-weight: 400; +} +.footer-area .footer-top .single-wedge .footer-links .single-link { + font-size: 12px; + line-height: 22px; + padding: 0; + display: inline-block; + text-transform: capitalize; + color: #999; + margin-bottom: 0; + display: inline-block; + position: relative; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; +} +.footer-area .footer-top .single-wedge .footer-links .single-link:hover { + padding-left: 10px; + color: #036eb8; +} +.footer-area .footer-top .single-wedge .footer-links p { + margin: 0 0 25px; + font-weight: 400; + color: #036eb8; + font-size: 24px; +} +@media only screen and (max-width: 767px) { + .footer-area .footer-top .single-wedge .footer-links p.mail br { + display: none; + } +} +@media only screen and (max-width: 767px) { + .footer-area .footer-top .single-wedge .footer-links p.mail a { + font-size: 24px; + } + .footer-area .footer-top .single-wedge .footer-links p { + font-size: 14px; + } +} +.footer-area .footer-top .single-wedge .footer-links p a { + color: #036eb8; + font-weight: 500; +} +.footer-area .footer-top .single-wedge .footer-links p a:hover { + color: #036eb8; +} +.footer-area .footer-top .single-wedge .footer-links p.address, +.footer-area .footer-top .single-wedge .footer-links p.phone { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.footer-area .footer-top .single-wedge .footer-links p.address i, +.footer-area .footer-top .single-wedge .footer-links p.phone i { + font-size: 36px; + color: #036eb8; + margin-right: 20px; +} +.footer-area .footer-top .single-wedge .footer-links p.address a, +.footer-area .footer-top .single-wedge .footer-links p.phone a { + font-weight: 600; + color: #036eb8; +} +.footer-area .footer-top .single-wedge .footer-links p.address a:hover, +.footer-area .footer-top .single-wedge .footer-links p.phone a:hover { + color: #036eb8; +} +.footer-bottom { + line-height: 1; +} +.footer-bottom .copy-text { + color: #a1a1a1; + font-size: 12px; + line-height: 22px; + text-align: center; +} +@media only screen and (max-width: 767px) { + .footer-bottom .copy-text { + margin-top: 15px; + } +} +.footer-bottom .copy-text .company-name { + color: #a1a1a1; +} +.footer-bottom .copy-text .company-name:hover { + color: #036eb8; +} +.footer-bottom .copy-text i { + color: red; + margin: 0 3px; + font-size: 16px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .mb-lg-30px { + margin-bottom: 30px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .mb-md-30px { + margin-bottom: 30px; + } + .mt-md-30px { + margin-top: 30px; + } + .mt-md-50px { + margin-top: 50px; + } + .mb-md-60px { + margin-bottom: 60px; + } +} +@media only screen and (max-width: 767px) { + .mb-lm-30px { + margin-bottom: 30px; + } + .mt-lm-50px { + margin-top: 50px; + } + .mt-lm-30px { + margin-top: 24px; + } + .mt-lm-20px { + margin-top: 20px; + } + .mb-lm-20px { + margin-bottom: 20px; + } + .mb-lm-60px { + margin-bottom: 60px; + } + .mb-lm-30px { + margin-bottom: 30px; + } + .mb-lm-10px { + margin-bottom: 10px; + } + .mb-lm-15px { + margin-bottom: 15px; + } + .mt-lm-15px { + margin-top: 15px; + } +} +@media only screen and (max-width: 575px) { + .mb-xs-30px { + margin-bottom: 30px; + } + .mb-xs-15px { + margin-bottom: 15px; + } +} +@media only screen and (max-width: 479px) { + .mb-es-30px { + margin-bottom: 30px; + } +} +.modal-dialog { + margin: 0 auto; + max-width: 960px; + width: 960px; + padding: 35px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .modal-dialog { + max-width: 720px; + width: 720px; + } +} +@media only screen and (max-width: 767px) { + .modal-dialog { + width: 98%; + max-width: 100%; + padding: 35px 0; + margin: auto 2%; + } +} +.modal-dialog .gallery-thumbs { + width: 100%; + margin: 20px auto; +} +.modal-dialog .gallery-thumbs .swiper-slide img { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + border: 1px solid transparent; + border-radius: 5px; +} +.modal-dialog .gallery-thumbs .swiper-slide:hover img { + border-color: #036eb8; +} +.modal-dialog .gallery-thumbs .swiper-slide.swiper-slide-thumb-active img { + border-color: #036eb8; +} +.modal-dialog .gallery-thumbs .swiper-slide .img-responsive { + width: auto; +} +.modal-dialog .social-info ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.modal.fade { + display: block !important; + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.modal.fade.show { + display: block !important; + opacity: 1; + visibility: visible; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.shop-category-area .shop-top-bar { + margin-bottom: 40px; + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + font-size: 16px; + border-radius: 10px; +} +@media only screen and (max-width: 767px) { + .shop-category-area .shop-top-bar > * { + margin-bottom: 20px; + } +} +.shop-category-area .shop-top-bar .compare-product { + color: #6c6c6c; + height: 40px; + width: 230px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border: 1px solid #d5d5d5; + border-radius: 5px; + background-color: #fff; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .shop-category-area .shop-top-bar .compare-product { + width: 190px; + } +} +.shop-category-area .shop-top-bar .compare-product span { + margin-left: 5px; + color: #036eb8; +} +@media only screen and (max-width: 767px) { + .shop-category-area .shop-top-bar.d-flex { + display: block !important; + } +} +@media only screen and (max-width: 767px) { + .desktop-tab { + display: none; + } +} +@media only screen and (max-width: 479px) { + .desktop-tab { + display: block; + } +} +.mobile-tab { + display: none; +} +@media only screen and (max-width: 767px) { + .mobile-tab { + display: block; + } +} +@media only screen and (max-width: 479px) { + .mobile-tab { + display: none; + } +} +.mobile-view { + display: none; +} +@media only screen and (max-width: 767px) { + .mobile-view { + display: block; + } +} +.shop-tab { + line-height: 1; +} +.shop-tab a + a { + margin-left: 15px; +} +.shop-tab a { + font-size: 18px; + color: #9e9e9e; + width: 40px; + height: 40px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border: 1px solid #d5d5d5; + border-radius: 5px; + background-color: #fff; +} +.shop-tab a.active { + background-color: #036eb8; + color: #fff; + border-color: #036eb8; +} +@media only screen and (max-width: 767px) { + .shop-tab { + margin-top: 15px; + margin-bottom: 5px; + } +} +.shot-product p { + color: #6c6c6c; +} +.shop-select { + border: 1px solid #d5d5d5; + margin-left: 10px; + border-radius: 5px; + height: 40px; +} +.shop-select.show { + height: 40px; +} +.shop-select.show .nice-select { + max-width: 64px; + width: 64px; + padding-right: 10px; +} +.shop-select.show .nice-select:after { + right: 10px; +} +.shop-select .nice-select { + -webkit-tap-highlight-color: transparent; + background-color: transparent; + border-radius: 0; + border: solid 1px transparent; + -webkit-box-sizing: border-box; + box-sizing: border-box; + clear: both; + cursor: pointer; + display: block; + float: left; + font-family: Rubik, sans-serif; + font-size: 16px; + font-weight: 400; + height: 40px; + line-height: 40px; + outline: 0; + padding-left: 10px; + padding-right: 30px; + position: relative; + text-align: left !important; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + max-width: 200px; + width: 200px; + color: #6c6c6c; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .shop-select .nice-select { + max-width: 170px; + width: 170px; + } +} +@media only screen and (max-width: 575px) { + .shop-select .nice-select { + max-width: 200px; + } +} +.shop-select .nice-select .current { + color: #090909; +} +.shop-select .nice-select:after { + border: 0; + content: ''; + display: inline-block; + font-family: FontAwesome; + height: auto; + margin-top: 0; + pointer-events: none; + position: absolute; + right: 20px; + top: auto; + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-transform: rotate(0); + transform: rotate(0); + -webkit-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; + width: auto; + color: #036eb8; + font-size: 16px; +} +.shop-select .nice-select .list { + background-color: #fff; + border-radius: 0; + -webkit-box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin-top: 5px; + opacity: 0; + overflow: hidden; + padding: 0; + pointer-events: none; + position: absolute; + top: 100%; + left: 0; + -webkit-transform-origin: 50% 0; + transform-origin: 50% 0; + -webkit-transform: scale(0.75) translate(-21px); + transform: scale(0.75) translate(-21px); + -webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + z-index: 15; + width: 100%; + color: #090909; + font-size: 16px; +} +.shop-select .nice-select.open .list { + opacity: 1; + pointer-events: auto; + -webkit-transform: scale(1) translate(0); + transform: scale(1) translate(0); +} +.shop-sidebar-wrap .sidebar-widget-search { + margin: 0 0 40px; + position: relative; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field { + border: 1px solid #cfcfcf; + background-color: #f9f9f9; + border-radius: 10px; + width: 100%; + height: 60px; + padding-left: 15px; + padding-right: 75px; + font-size: 16px; + font-style: italic; + color: #969696; + background-color: transparent; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field::-webkit-input-placeholder { + color: #969696; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field::-moz-placeholder { + color: #969696; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field:-ms-input-placeholder { + color: #969696; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field::-ms-input-placeholder { + color: #969696; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .input-field::placeholder { + color: #969696; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .widgets-searchbox-btn { + background-color: transparent; + border: 0; + border-left: 1px solid #cfcfcf; + position: absolute; + top: 50%; + right: 0; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + font-size: 18px; + padding-left: 15px; + padding-right: 15px; + color: #cfcfcf; + line-height: 1; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.shop-sidebar-wrap .sidebar-widget-search #widgets-searchbox .widgets-searchbox-btn:hover { + color: #036eb8; +} +.shop-sidebar-wrap .sidebar-widget-category, +.shop-sidebar-wrap .sidebar-widget-color, +.shop-sidebar-wrap .sidebar-widget-size { + padding-bottom: 23px; + padding-left: 30px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .shop-sidebar-wrap .sidebar-widget-category, + .shop-sidebar-wrap .sidebar-widget-color, + .shop-sidebar-wrap .sidebar-widget-size { + padding-left: 20px; + } +} +.shop-sidebar-wrap .sidebar-widget-category li a, +.shop-sidebar-wrap .sidebar-widget-color li a, +.shop-sidebar-wrap .sidebar-widget-size li a { + color: #6a6a6a; + font-size: 16px; + display: inline-block; + margin-top: 18px; +} +.shop-sidebar-wrap .sidebar-widget-category li a:hover, +.shop-sidebar-wrap .sidebar-widget-color li a:hover, +.shop-sidebar-wrap .sidebar-widget-size li a:hover { + color: #036eb8; +} +.shop-sidebar-wrap .sidebar-widget { + background-color: #fff; + border-radius: 10px; + margin: 0 0 40px; + border: 1px solid #f3f3f3; +} +.shop-sidebar-wrap .sidebar-widget h4 { + font-size: 24px; + display: block; + text-transform: capitalize; + font-weight: 400; + color: #6c6c6c; + margin: 0 0 24px; + padding: 14px 0 15px 28px; + background: #f3f3f3; +} +.shop-sidebar-wrap .sidebar-widget .price-slider-amount input { + color: #656565; + font-size: 16px; + border: 0; +} +.shop-sidebar-wrap .sidebar-widget .price-filter { + padding: 0 25px 37px 29px; +} +.shop-sidebar-wrap .sidebar-widget .ui-widget-content { + border: 1px solid #036eb8; +} +.shop-sidebar-wrap .sidebar-widget .ui-slider-horizontal { + height: 3px; + margin: 15px 0 0; +} +.shop-sidebar-wrap .sidebar-widget .ui-widget-header { + background: #036eb8; +} +.shop-sidebar-wrap .sidebar-widget .ui-slider-handle { + top: 50%; + width: 16px; + height: 16px; + background: #fff; + border-radius: 100%; + outline: 0; + margin-top: -8px; + border: 5px solid #036eb8; + cursor: pointer; + -webkit-transition: 0.3s; + transition: 0.3s; +} +.shop-sidebar-wrap .sidebar-widget .ui-slider-handle.ui-state-hover { + background: #036eb8; +} +.shop-sidebar-wrap .sidebar-widget-tag { + padding: 0 0 10px 15px; +} +.shop-sidebar-wrap .sidebar-widget-tag li { + line-height: 1; + display: inline-block; + margin: 8px 0; +} +.shop-sidebar-wrap .sidebar-widget-tag li a { + display: block; + float: left; + padding: 8px 17px; + font-size: 16px; + color: #7e7e7e; + font-weight: 400; + border: 1px solid #f3f3f3; + border-radius: 5px; + background: 0; + text-transform: capitalize; + margin-left: 15px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .shop-sidebar-wrap .sidebar-widget-tag li a { + padding: 8px 14px; + font-size: 14px; + margin-left: 5px; + } +} +.shop-sidebar-wrap .sidebar-widget-tag li a:hover { + background-color: #036eb8; + border-color: #036eb8; + color: #fff; +} +.sidebar-widget-image { + margin: 0 0 40px; +} +.sidebar-widget-image .single-banner { + position: relative; + display: block; + overflow: hidden; + border-radius: 10px; +} +.sidebar-widget-image .single-banner img { + width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.sidebar-widget-image .single-banner:hover img { + -webkit-transform: scale(1.1) rotate(1deg); + transform: scale(1.1) rotate(1deg); +} +.shop-list-wrapper .content-desc-wrap .content { + position: relative; + z-index: 10; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + padding: 24px 0 10px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + background-color: #fff; + border-bottom: 1px solid #eee; +} +.download-text { + padding: 24px 0; + font-size: 14px; +} +.download-text b { + position: relative; + width: 100%; + padding-left: 14px; +} +.download-text p { + padding-left: 14px; + color: #666; +} +.download-text b::before { + content: ''; + position: absolute; + background: #036eb8; + width: 6px; + height: 6px; + left: 0; + top: 5px; +} +@media only screen and (max-width: 767px) { + .shop-list-wrapper .content-desc-wrap .content { + margin-top: 0; + padding: 0 0 10px; + } +} +.shop-list-wrapper .content-desc-wrap .content .ratings { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + margin-bottom: 4px; +} +.shop-list-wrapper .content-desc-wrap .content .ratings .rating-wrap { + font-size: 14px; + line-height: 1; + position: relative; + color: #e4e4e4; + white-space: nowrap; +} +.shop-list-wrapper .content-desc-wrap .content .ratings .rating-wrap::before { + font-family: FontAwesome; + content: '    '; +} +.shop-list-wrapper .content-desc-wrap .content .ratings .rating-wrap .star { + position: absolute; + top: 0; + left: 0; + overflow: hidden; + color: #ffde00; +} +.shop-list-wrapper .content-desc-wrap .content .ratings .rating-wrap .star::before { + font-family: FontAwesome; + content: '    '; +} +.shop-list-wrapper .content-desc-wrap .content .ratings .rating-num { + font-size: 14px; + line-height: 1; + margin-left: 6px; + color: #9f9e9e; +} +.shop-list-wrapper .content-desc-wrap .content .title { + font-size: 18px; + margin: 10px 0 10px; +} +.shop-list-wrapper .content-desc-wrap .content .title a { + text-decoration: none; + color: #474747; + font-weight: 600; +} +.shop-list-wrapper .content-desc-wrap .content .title a:hover { + color: #036eb8; +} +.shop-list-wrapper .content-desc-wrap .content p { + font-size: 14px; + color: #6c6c6c; + line-height: 24px; +} +.shop-list-wrapper .content-desc-wrap .box-inner { + margin-top: 20px; +} +.shop-list-wrapper .content-desc-wrap .box-inner .price { + font-size: 16px; + line-height: 1; + display: block; + margin: 0 0 20px; +} +.shop-list-wrapper .content-desc-wrap .box-inner .price .new { + color: #1d1d1d; + font-weight: 500; +} +.shop-list-wrapper .content-desc-wrap .box-inner .price .old { + font-size: 14px; + margin-left: 10px; + text-decoration: line-through; + color: #9f9e9e; +} +.shop-list-wrapper .content-desc-wrap .box-inner .add-to-cart { + width: 170px; + height: 50px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background: #036eb8; + border: 0; + border-radius: 10px; + font-size: 14px; + z-index: 11; + font-weight: 400; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + color: #fff; + text-transform: uppercase; + margin-top: 30px; + position: relative; + overflow: hidden; +} +.shop-list-wrapper .content-desc-wrap .box-inner .add-to-cart::before { + position: absolute; + content: ''; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: #4a4a4a; + z-index: -1; + -webkit-transition: 0.3s linear; + transition: 0.3s linear; + -webkit-transform: scale(0); + transform: scale(0); + border-radius: 50%; + width: 100%; + height: 100%; +} +.shop-list-wrapper .content-desc-wrap .box-inner .add-to-cart:hover { + color: #fff; + -webkit-box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + background: 0; + -webkit-transform: translateY(-3px); + transform: translateY(-3px); +} +.shop-list-wrapper .content-desc-wrap .box-inner .add-to-cart:hover::before { + -webkit-transform: scale(1.5); + transform: scale(1.5); +} +.shop-list-wrapper .content-desc-wrap .box-inner .actions { + z-index: 9; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.shop-list-wrapper .content-desc-wrap .box-inner .actions .action + .action { + margin-left: 10px; +} +.shop-list-wrapper .content-desc-wrap .box-inner .actions .action { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + width: 40px; + height: 40px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + text-decoration: none; + color: #000; + border-radius: 50%; + background-color: #eaeaea; + font-size: 24px; +} +.shop-list-wrapper .content-desc-wrap .box-inner .actions .action:hover { + color: #fff; + background-color: #036eb8; +} +.shop-list-wrapper + .shop-list-wrapper { + margin-top: 24px; +} +.zoom-thumbs { + width: 100%; + margin: 18px auto 0 auto; +} +.zoom-thumbs .swiper-slide img { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + border: 1px solid transparent; + border-radius: 5px; +} +.zoom-thumbs .swiper-slide:hover img { + border-color: #036eb8; +} +.zoom-thumbs .swiper-slide.swiper-slide-thumb-active img { + border-color: #036eb8; +} +.zoom-thumbs .swiper-slide .img-responsive { + width: auto; +} +.zoom-top .swiper-slide { + border-radius: 5px; + border: 1px solid #eeeeee; +} +.product-details-content.ml-25px { + margin-left: 25px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .product-details-content.ml-25px { + margin-left: 0; + } +} +.product-details-content h2 { + color: #333; + font-size: 24px; + text-transform: capitalize; + line-height: 32px; + font-weight: 600; + margin: 0 0 18px 0; +} +@media only screen and (max-width: 767px) { + .product-details-content h2 { + font-size: 28px; + } +} +@media only screen and (max-width: 479px) { + .product-details-content h2 { + font-size: 24px; + } +} +.product-details-content .pricing-meta ul li + li { + margin-left: 10px; +} +.product-details-content .pricing-meta ul li { + font-size: 24px; + color: #d1d2d4; + line-height: 30px; + margin-bottom: 20px; + font-weight: 400; +} +@media only screen and (max-width: 479px) { + .product-details-content .pricing-meta ul li { + font-size: 20px; + } +} +.product-details-content .pricing-meta ul li.new-price { + color: #036eb8; +} +.product-details-content .pro-details-rating-wrap { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + line-height: 1; +} +.product-details-content .pro-details-rating-wrap .rating-product { + margin-right: 5px; +} +.product-details-content .pro-details-rating-wrap .rating-product i { + color: #ffde00; + font-size: 14px; +} +.product-details-content .pro-details-rating-wrap .rating-product i + i { + margin-left: 3px; +} +.product-details-content .pro-details-rating-wrap .read-review a { + text-decoration: none; + color: #424242; + position: relative; + margin-left: 8px; + padding: 0; + font-size: 16px; + display: inline-block; +} +.product-details-content .pro-details-rating-wrap .read-review a:hover { + color: #036eb8; +} +.product-details-content .stock { + line-height: 1; +} +.product-details-content .stock .avallabillty { + color: #090909; + font-weight: 500; +} +.product-details-content .stock .avallabillty .in-stock { + color: #036eb8; + font-weight: 400; +} +.product-details-content .stock .avallabillty .in-stock i { + margin: 0 5px; +} +.product-details-content .pro-details-list { + padding: 0 0 30px 0; + margin: 0 0 15px 0; + border-bottom: 1px solid #ebebeb; + display: inline-block; + width: 100%; + color: #474747; +} +.product-details-content .pro-details-list p { + font-weight: 400; + color: #474747; + line-height: 24px; + margin: 0; +} +.product-details-content .pro-details-list li { + display: block; + width: 100%; + line-height: 24px; +} +.product-details-content p { + color: #666; + line-height: 22px; + font-size: 14px; +} +.product-details-content .pro-details-quality { + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + margin: 30px 0; + width: 100%; +} +.product-details-content .pro-details-quality .cart-plus-minus { + border: 1px solid #ebebeb; + display: inline-block; + height: 50px; + overflow: hidden; + padding: 0; + position: relative; + width: 80px; + background: #505050; + border-radius: 5px; +} +.product-details-content .pro-details-quality .cart-plus-minus .qtybutton { + color: #fff; + cursor: pointer; + float: inherit; + font-size: 18px; + font-weight: 500; + line-height: 20px; + margin: 0; + position: absolute; + text-align: center; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + width: 30px; +} +.product-details-content .pro-details-quality .cart-plus-minus input.cart-plus-minus-box { + background: transparent none repeat scroll 0 0; + border: medium none; + color: #fff; + float: left; + font-size: 14px; + height: 50px; + margin: 0; + padding: 0; + text-align: center; + width: 80px; + outline: 0; +} +.product-details-content .pro-details-quality .cart-plus-minus .inc.qtybutton { + height: 50px; + padding-top: 14px; + right: 0; + top: 0; +} +.product-details-content .pro-details-quality .cart-plus-minus .dec.qtybutton { + height: 50px; + left: 0; + padding-top: 14px; + top: 0; +} +.product-details-content .pro-details-quality .pro-details-cart .add-cart { + position: relative; + padding: 0 35px; + height: 50px; + font-size: 14px; + font-weight: 500; + border: 0; + border-radius: 5px; + -webkit-box-shadow: none; + box-shadow: none; + text-transform: uppercase; + display: inline-block; + margin-left: 10px; + background: #505050; + color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + letter-spacing: 2px; +} +.product-details-content .pro-details-quality .pro-details-cart .add-cart.buy-button { + background: #036eb8; +} +.product-details-content .pro-details-quality .pro-details-cart .add-cart.buy-button:hover { + background-color: #000; +} +.product-details-content .pro-details-quality .pro-details-cart .add-cart:hover { + background-color: #000; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .product-details-content .pro-details-quality .pro-details-cart .add-cart { + padding: 0 15px; + } +} +@media only screen and (max-width: 767px) { + .product-details-content .pro-details-quality .pro-details-cart .add-cart { + padding: 0 12px; + letter-spacing: 0; + } +} +@media only screen and (max-width: 479px) { + .product-details-content .pro-details-quality .pro-details-cart .add-cart { + padding: 0 10px; + font-size: 12px; + margin-left: 5px; + } +} +.product-details-content .pro-details-compare-wishlist a { + padding: 0; + border: 0; + color: #fff; + font-size: 18px; + margin-left: 10px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 5px; + background-color: #3d3d3d; + width: 50px; + height: 50px; +} +@media only screen and (max-width: 479px) { + .product-details-content .pro-details-compare-wishlist a { + margin-left: 5px; + } +} +.product-details-content .pro-details-compare-wishlist a:hover { + background-color: #000; +} +.product-details-content .pro-details-same-style span { + font-weight: 500; + color: #b2b2b2; + display: inline-block; + margin-right: 5px; +} +.product-details-content .pro-details-same-style a { + font-weight: 400; + color: #9f9e9e; + margin-left: 3px; +} +.product-details-content .pro-details-same-style a:hover { + color: #036eb8; +} +.product-details-content .pro-details-same-style.pro-details-categories-info { + margin: 10px 0; + font-size: 14px; +} +.product-details-content .pro-details-same-style.pro-details-social-info { + margin-bottom: 40px; +} +.product-details-content .pro-details-same-style.pro-details-social-info a { + margin-left: 20px; +} +.description-review-topbar.nav { + border-bottom: 0; + position: relative; + margin-bottom: 0; + margin: auto; + text-align: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + height: 48px; + border: 0; + background-color: #f5f5f5; + border: 1px solid #f5f5f5; +} + +.description-review-topbar.nav a { + background: 0; + border: 0; + text-transform: capitalize; + line-height: 24px; + color: #363636; + padding: 12px 40px; + font-size: 16px; + font-weight: 500; + position: relative; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + display: inline-block; + font-family: 'Nunito Sans', sans-serif; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.description-review-topbar.nav a:hover { + color: #fff; + background-color: #036eb8; +} +.description-review-topbar.nav a.active { + color: #fff; + background-color: #036eb8; +} + +@media only screen and (max-width: 767px) { + .description-review-topbar.nav a { + margin: 0 15px; + } +} +@media only screen and (max-width: 575px) { + .description-review-topbar.nav a { + margin: 0 10px; + font-size: 16px; + } +} +@media only screen and (max-width: 479px) { + .description-review-topbar.nav a { + margin: 0 5px; + font-size: 14px; + padding: 12px 30px; + } +} +.description-review-bottom { + overflow: hidden; + font-size: 16px; + background: #fff; + padding: 44px 56px; + border-top: 1px solid #f4f4f4; + margin-top: 24px; +} +@media only screen and (max-width: 767px) { + .description-review-bottom { + padding: 40px 0 0 0; + border: 0; + border-top: 1px solid #f4f4f4; + } +} +.description-review-bottom .product-description-wrapper { + text-align: left; +} +.description-review-bottom .product-description-wrapper p { + margin: 0; + font-size: 16px; + line-height: 30px; + color: #000; + font-weight: 400; + text-align: center; +} +.description-review-bottom .product-description-wrapper img { + max-width: 100%; +} +.description-review-bottom .product-anotherinfo-wrapper li { + color: #3d3d3d; + font-size: 14px; + list-style: outside none none; + margin: 0 0 13px; + display: block; +} +.description-review-bottom .product-anotherinfo-wrapper li span { + color: #525252; + display: inline-block; + font-weight: 500; + margin: 0 24px 0 0; + min-width: 60px; +} +.description-review-bottom .product-anotherinfo-wrapper li em { + font-style: normal; + color: #999; +} +.description-review-bottom .single-review { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin: 0 0 50px; +} +.description-review-bottom .single-review .review-img { + -webkit-box-flex: 0; + -ms-flex: 0 0 90px; + flex: 0 0 90px; + margin: 0 15px 0 0; +} +@media only screen and (max-width: 767px) { + .description-review-bottom .single-review .review-img { + margin: 0 0 20px 0; + } +} +.description-review-bottom .single-review .review-top-wrap { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 0 0 10px; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.description-review-bottom .single-review .review-top-wrap .review-left { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.description-review-bottom .single-review .review-top-wrap .review-left .review-name { + margin-right: 15px; +} +.description-review-bottom .single-review .review-top-wrap .review-left .review-name h4 { + font-size: 20px; + margin: 0; + line-height: 1; + font-weight: 500; + color: #525252; +} +.description-review-bottom .single-review .review-top-wrap .review-left .rating-product { + line-height: 1; +} +.description-review-bottom .single-review .review-top-wrap .review-left .rating-product i { + overflow: hidden; + font-size: 14px; + color: #fdd835; +} +.description-review-bottom .single-review .review-top-wrap .review-left a { + color: #525252; +} +.description-review-bottom .single-review .review-top-wrap .review-left a:hover { + color: #036eb8; +} +.description-review-bottom .single-review .review-bottom p { + margin: 0; + width: 93%; + color: #6c788c; +} +.description-review-bottom .single-review.child-review { + margin-left: 70px; + margin-bottom: 0; +} +@media only screen and (max-width: 767px) { + .description-review-bottom .single-review.child-review { + margin-left: 0; + } +} +@media only screen and (max-width: 767px) { + .description-review-bottom .single-review { + display: block; + } +} +.description-review-bottom .ratting-form-wrapper { + padding-left: 50px; + line-height: 1; +} +.description-review-bottom .ratting-form-wrapper h3 { + margin: 0; + font-size: 18px; + font-weight: 500; + color: #525252; +} +.description-review-bottom .ratting-form-wrapper .star-box { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin: 10px 0 20px; +} +.description-review-bottom .ratting-form-wrapper .star-box span { + margin: 0 15px 0 0; + font-size: 18px; + color: #525252; + font-weight: 500; +} +.description-review-bottom .ratting-form-wrapper .star-box i { + overflow: hidden; + font-size: 14px; + color: #fdd835; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style { + margin-bottom: 10px; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style input { + height: 45px; + -webkit-box-shadow: none; + box-shadow: none; + padding-left: 10px; + font-size: 14px; + width: 100%; + margin-bottom: 15px; + outline: 0; + padding: 2px 10px 2px 20px; + background: 0; + border: 1px solid #ebebeb; + color: #474747; + padding: 2px 10px 2px 20px; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style input:focus { + border-color: #036eb8; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style textarea { + background: 0; + border: 1px solid #ebebeb; + color: #474747; + height: 180px; + padding: 20px 10px 2px 20px; + margin-bottom: 20px; + width: 100%; + outline: 0; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style textarea:focus { + border-color: #036eb8; +} +.description-review-bottom .ratting-form-wrapper .rating-form-style button { + width: 170px; + height: 50px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .description-review-bottom .ratting-form-wrapper { + margin-top: 50px; + padding: 0; + } +} +@media only screen and (max-width: 767px) { + .description-review-bottom .ratting-form-wrapper { + margin-top: 50px; + padding: 0; + } +} +.pro-details-color-size { + margin-top: 30px; + margin-bottom: 10px; +} +.pro-details-color-size p { + font-weight: 500; + color: #090909; +} +.pro-details-color-size .ml-30px { + margin-left: 30px; +} +@media only screen and (max-width: 575px) { + .pro-details-color-size .ml-30px { + margin-left: 20px; + } +} +.pro-details-color-size .shop-select { + border: 1px solid #d5d5d5; + margin-left: 10px; + border-radius: 5px; + height: 40px; +} +.pro-details-color-size .shop-select.show { + height: 40px; +} +.pro-details-color-size .shop-select.show .nice-select { + max-width: 79px; + width: 79px; + padding-right: 10px; +} +@media only screen and (max-width: 575px) { + .pro-details-color-size .shop-select.show .nice-select { + width: 70px; + } +} +.pro-details-color-size .shop-select.show .nice-select:after { + right: 10px; +} +.pro-details-color-size .shop-select .nice-select { + -webkit-tap-highlight-color: transparent; + background-color: transparent; + border-radius: 0; + border: solid 1px transparent; + -webkit-box-sizing: border-box; + box-sizing: border-box; + clear: both; + cursor: pointer; + display: block; + float: left; + font-family: Rubik, sans-serif; + font-size: 16px; + font-weight: 400; + height: 40px; + line-height: 40px; + outline: 0; + padding-left: 10px; + padding-right: 30px; + position: relative; + text-align: left !important; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + max-width: 162px; + width: 162px; + color: #090909; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (max-width: 575px) { + .pro-details-color-size .shop-select .nice-select { + width: 130px; + } +} +.pro-details-color-size .shop-select .nice-select .current { + color: #090909; +} +.pro-details-color-size .shop-select .nice-select:after { + border: 0; + content: ''; + display: inline-block; + font-family: FontAwesome; + height: auto; + margin-top: 0; + pointer-events: none; + position: absolute; + right: 20px; + top: auto; + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-transform: rotate(0); + transform: rotate(0); + -webkit-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; + width: auto; + color: #036eb8; + font-size: 18px; +} +.pro-details-color-size .shop-select .nice-select .list { + background-color: #fff; + border-radius: 0; + -webkit-box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin-top: 5px; + opacity: 0; + overflow: hidden; + padding: 0; + pointer-events: none; + position: absolute; + top: 100%; + left: 0; + -webkit-transform-origin: 50% 0; + transform-origin: 50% 0; + -webkit-transform: scale(0.75) translate(-21px); + transform: scale(0.75) translate(-21px); + -webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + z-index: 15; + width: 100%; + color: #090909; + font-size: 16px; +} +.pro-details-color-size .shop-select .nice-select.open .list { + opacity: 1; + pointer-events: auto; + -webkit-transform: scale(1) translate(0); + transform: scale(1) translate(0); +} +.product-details-table.pro-details-quality { + display: block; + margin: 30px 0 10px 0; +} +.product-details-table .table tbody tr td { + padding: 10px 15px; + width: 33.33%; + text-align: center; + border: 1px solid #ebebeb; + vertical-align: middle; + font-size: 16px; +} +.product-details-table .table tbody tr td a { + color: #090909; +} +.product-details-table .table tbody tr td a:hover { + color: #036eb8; +} +.product-details-img.product-details-tab.product-details-tab-2 { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + overflow: hidden; +} +.product-details-img.product-details-tab.product-details-tab-2.product-details-tab-3 { + -webkit-box-orient: horizontal; + -webkit-box-direction: reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; +} +.product-details-img.product-details-tab.product-details-tab-2 .zoom-thumbs-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 15%; + flex: 0 0 15%; + width: 15%; +} +.product-details-img.product-details-tab.product-details-tab-2 .zoom-top-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 85%; + flex: 0 0 85%; + width: 85%; +} +.zoom-thumbs-2 { + display: inline-block; + float: left; + text-align: center; +} +.zoom-thumbs-2 .swiper-slide { + text-align: center; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + outline: 0 none; +} +.zoom-thumbs-2 .swiper-slide + .swiper-slide { + margin-top: 10px; +} +.zoom-thumbs-2 .swiper-slide img { + margin: auto; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + border: 1px solid transparent; + border-radius: 5px; +} +.zoom-thumbs-2 .swiper-slide.swiper-slide-thumb-active img { + border-color: #036eb8; +} +.zoom-thumbs-2 .swiper-slide:hover img { + border-color: #036eb8; +} +.single-product-gallery .single-product-slider-item { + width: 50%; +} +.single-product-gallery img { + border: 1px solid #fff; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + margin: auto; + width: 100%; +} +.single-product-gallery img:hover { + border-color: #036eb8; +} +.single-product-sticky .single-product-slider-item { + width: 100%; + text-align: center; +} +.single-product-sticky img { + border: 1px solid #fff; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + width: 100%; +} +.single-product-sticky img:hover { + border-color: #036eb8; +} +.product-details-content.sticky { + position: sticky; + top: 140px; + left: 0; + width: 100%; +} +.cart-main-area .cart-page-title { + color: #000; + text-align: left; + font-size: 24px; + line-height: 16px; + font-style: normal; + text-transform: none; + margin: 0 0 30px; + font-weight: 500; +} +.cart-main-area .table-content table { + border: 1px solid #ebebeb; + width: 100%; +} +.cart-main-area .table-content table thead > tr { + background-color: #ebebeb; + border: 1px solid #ebebeb; +} +.cart-main-area .table-content table thead > tr > th { + border-top: medium none; + color: #000; + font-size: 16px; + font-weight: 500; + padding: 21px 45px 22px; + text-align: center; + text-transform: uppercase; + vertical-align: middle; + white-space: nowrap; +} +.cart-main-area .table-content table tbody > tr { + border-bottom: 1px solid #ebebeb; +} +.cart-main-area .table-content table tbody > tr td { + color: #474747; + font-size: 16px; + padding: 30px 0; + text-align: center; +} +.cart-main-area .table-content table tbody > tr td.product-thumbnail { + width: 150px; +} +.cart-main-area .table-content table tbody > tr td.product-name { + width: 435px; +} +.cart-main-area .table-content table tbody > tr td.product-name a { + color: #474747; + font-size: 16px; + font-weight: 500; +} +.cart-main-area .table-content table tbody > tr td.product-price-cart { + width: 435px; +} +.cart-main-area .table-content table tbody > tr td.product-quantity { + width: 435px; +} +.cart-main-area .table-content table tbody > tr td.product-quantity .cart-plus-minus { + display: inline-block; + height: 40px; + padding: 0; + position: relative; + width: 110px; +} +.cart-main-area .table-content table tbody > tr td.product-quantity .cart-plus-minus .dec.qtybutton { + border-right: 1px solid #e5e5e5; + height: 40px; + left: 0; + padding-top: 8px; + top: 0; +} +.cart-main-area .table-content table tbody > tr td.product-quantity .cart-plus-minus .inc.qtybutton { + border-left: 1px solid #e5e5e5; + height: 40px; + padding-top: 9px; + right: 0; + top: 0; +} +.cart-main-area .table-content table tbody > tr td.product-quantity .cart-plus-minus .qtybutton { + color: #474747; + cursor: pointer; + float: inherit; + font-size: 16px; + margin: 0; + position: absolute; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + width: 20px; + text-align: center; +} +.cart-main-area .table-content table tbody > tr td.product-quantity .cart-plus-minus input.cart-plus-minus-box { + color: #474747; + float: left; + font-size: 16px; + height: 40px; + margin: 0; + width: 110px; + background: transparent none repeat scroll 0 0; + border: 1px solid #e1e1e1; + padding: 0; + text-align: center; +} +.cart-main-area .table-content table tbody > tr td.product-remove { + width: 100px; +} +.cart-main-area .table-content table tbody > tr td.product-remove a { + color: #474747; + font-size: 16px; + margin: 0 10px; +} +.cart-main-area .table-content table tbody > tr td.product-remove a:hover { + color: #036eb8; +} +.cart-main-area .table-content table tbody > tr td.product-wishlist-cart > a { + background-color: #036eb8; + border-radius: 0; + color: #fff; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 10px 12px; + text-transform: uppercase; +} +.cart-main-area .table-content table tbody > tr td.product-wishlist-cart > a:hover { + background-color: #000; +} +.cart-main-area .cart-shiping-update-wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 30px 0 60px; +} +.cart-main-area .cart-shiping-update-wrapper .cart-clear > button { + border: medium none; + cursor: pointer; + margin-right: 27px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +@media only screen and (max-width: 767px) { + .cart-main-area .cart-shiping-update-wrapper { + display: block; + padding: 30px 0 15px; + } +} +.cart-shiping-update-wrapper .cart-clear > a, +.cart-shiping-update-wrapper .cart-clear > button, +.cart-shiping-update-wrapper .cart-shiping-update > a { + background-color: #f2f2f2; + border-radius: 0; + color: #000; + display: inline-block; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 18px 63px 17px; + text-transform: uppercase; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .cart-shiping-update-wrapper .cart-clear > a, + .cart-shiping-update-wrapper .cart-clear > button, + .cart-shiping-update-wrapper .cart-shiping-update > a { + padding: 18px 25px; + } +} +@media only screen and (max-width: 767px) { + .cart-shiping-update-wrapper .cart-clear > a, + .cart-shiping-update-wrapper .cart-clear > button, + .cart-shiping-update-wrapper .cart-shiping-update > a { + padding: 18px 25px; + margin: 0 0 15px; + } +} +.cart-shiping-update-wrapper .cart-clear > button:hover, +.cart-shiping-update-wrapper .cart-shiping-update > a:hover { + background-color: #036eb8; + color: #fff; +} +.cart-shiping-update-wrapper .cart-clear > a { + background-color: #036eb8; + color: #fff; +} +.cart-shiping-update-wrapper .cart-clear > a:hover { + background-color: #000; + color: #fff; +} +.cart-tax, +.discount-code-wrapper, +.grand-totall { + background-color: #ebebeb; + border: 1px solid #ebebeb; + border-radius: 0; + padding: 45px 30px 50px; +} +.cart-tax .title-wrap, +.discount-code-wrapper .title-wrap, +.grand-totall .title-wrap { + position: relative; +} +.cart-tax .title-wrap::before, +.discount-code-wrapper .title-wrap::before, +.grand-totall .title-wrap::before { + background-color: #e3e1e1; + content: ''; + height: 1px; + left: 0; + position: absolute; + top: 13px; + -webkit-transition: all 0.4s ease 0s; + transition: all 0.4s ease 0s; + width: 100%; + z-index: 1; +} +.cart-tax .title-wrap h4.cart-bottom-title, +.discount-code-wrapper .title-wrap h4.cart-bottom-title, +.grand-totall .title-wrap h4.cart-bottom-title { + display: inline-block; + font-size: 18px; + font-weight: 500; + margin: 0; + padding-right: 18px; + background-color: #ebebeb; + position: relative; + z-index: 1; + color: #000; +} +.cart-tax .tax-wrapper, +.discount-code-wrapper .tax-wrapper, +.grand-totall .tax-wrapper { + margin-top: 22px; +} +.tax-select-wrapper { + margin: 15px 0 0; +} +.tax-select-wrapper select { + width: 100%; + height: 42px; + line-height: 42px; + border: 1px solid #ebebeb; + background: #fff; + padding-left: 20px; + border-radius: 0; +} +.tax-select-wrapper input { + width: 100%; + height: 42px; + line-height: 42px; + border: 1px solid #ebebeb; + background: #fff; + padding-left: 20px; + border-radius: 0; +} +.tax-select-wrapper .tax-select { + margin-bottom: 20px; +} +.tax-select-wrapper .tax-select label { + color: #000; + font-size: 16px; + margin: 0 0 10px; +} +.tax-select-wrapper button.cart-btn-2 { + background: #036eb8; + border-radius: 0; + color: #fff; + display: inline-block; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 18px 58px; + text-transform: uppercase; +} +.tax-select-wrapper button.cart-btn-2:hover { + color: #fff; + background: #000; +} +.discount-code-wrapper .title-wrap { + margin-bottom: 22px; +} +.discount-code-wrapper .discount-code p { + margin: 0 0 15px; +} +.discount-code-wrapper .discount-code input { + background: #fff; + border: 1px solid #ebebeb; + height: 45px; + margin-bottom: 30px; + padding-left: 10px; + outline: 0; + width: 100%; + border-radius: 0; +} +.discount-code-wrapper .discount-code button.cart-btn-2 { + background: #036eb8; + border-radius: 0; + color: #fff; + display: inline-block; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 18px 58px; + text-transform: uppercase; +} +.discount-code-wrapper .discount-code button.cart-btn-2:hover { + color: #fff; + background: #000; +} +.grand-totall h5 { + font-size: 16px; + margin: 36px 0 27px; + font-weight: 400; +} +.grand-totall h5 span { + float: right; + font-size: 18px; + font-weight: 500; +} +.grand-totall .total-shipping { + border-bottom: 1px solid #ebebeb; + border-top: 1px solid #ebebeb; + margin: 0 0 27px; + padding: 28px 0; +} +.grand-totall .total-shipping h5 { + font-size: 16px; + margin: 0; +} +.grand-totall .total-shipping ul { + padding: 19px 0 0 0; +} +.grand-totall .total-shipping ul li { + color: #474747; + list-style: outside none none; + margin: 0 0 6px; + display: block; +} +.grand-totall .total-shipping ul li input { + background: #e9e9e9 none repeat scroll 0 0; + border: 1px solid #d7d7d7; + border-radius: 5px !important; + color: #474747; + cursor: pointer; + height: 13px; + margin-right: 10px; + padding: 0; + position: relative; + top: 2px; + width: 13px; +} +.grand-totall .total-shipping ul li span { + float: right; +} +.grand-totall .grand-totall-title { + color: #036eb8; + font-size: 20px; + font-weight: 500; + margin: 0 0 25px; +} +.grand-totall .grand-totall-title span { + float: right; +} +.grand-totall a { + background-color: #036eb8; + border-radius: 0; + color: #fff; + display: block; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 18px 10px 17px; + text-align: center; + text-transform: uppercase; + text-transform: uppercase; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.grand-totall a:hover { + background-color: #000; +} +.billing-info-wrap h3 { + font-weight: 500; + color: #000; + margin: 0 0 30px; + font-size: 24px; + line-height: 16px; +} +.billing-info-wrap .billing-info input { + background: transparent none repeat scroll 0 0; + border: 1px solid #ebebeb; + color: #474747; + font-size: 16px; + padding-left: 20px; + padding-right: 10px; + width: 100%; + outline: 0; + height: 45px; +} +.billing-info-wrap .billing-info input.billing-address { + margin-bottom: 10px; +} +.billing-info-wrap .billing-info .checkout-account label { + color: #474747; + font-weight: 400; + margin: 0 0 0 12px; +} +.billing-info-wrap .billing-info .checkout-account input { + border: 1px solid #ebebeb; + display: inline-block; + float: left; + height: 12px; + width: 12px; + margin-top: 7px; + cursor: pointer; +} +.billing-info-wrap .billing-select select { + background: transparent none repeat scroll 0 0; + border: 1px solid #ebebeb; + color: #474747; + font-size: 16px; + padding-left: 20px; + padding-right: 10px; + width: 100%; + outline: 0; + height: 45px; +} +.billing-info-wrap .checkout-account-toggle input { + background: transparent none repeat scroll 0 0; + border: 1px solid #ebebeb; + color: #474747; + font-size: 16px; + padding-left: 20px; + padding-right: 10px; + margin: 0 0 20px; + width: 100%; + height: 45px; + outline: 0; +} +.billing-info-wrap .checkout-account-toggle button.checkout-btn { + background-color: #036eb8; + border: medium none; + color: #fff; + cursor: pointer; + font-weight: 500; + padding: 10px 30px; + text-transform: uppercase; + border-radius: 0; + z-index: 9; +} +.billing-info-wrap .checkout-account-toggle button.checkout-btn:hover { + background-color: #000; +} +.billing-info-wrap .additional-info-wrap { + margin: 30px 0; +} +.billing-info-wrap .additional-info-wrap h4 { + font-size: 18px; + font-weight: 500; + color: #000; + margin: 0 0 10px; +} +.billing-info-wrap .additional-info-wrap textarea { + background: transparent none repeat scroll 0 0; + border: 1px solid #ebebeb; + color: #474747; + font-size: 16px; + height: 138px; + padding: 17px 20px; + width: 100%; + outline: 0; +} +.billing-info-wrap label { + margin-bottom: 10px; +} +.your-order-area h3 { + font-weight: 500; + color: #000; + margin: 0 0 30px; + font-size: 24px; + line-height: 16px; +} +.your-order-area .your-order-wrap { + padding: 38px 45px 44px; + background: #ebebeb; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-top ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + font-family: Rubik, sans-serif; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-top ul li { + font-size: 16px; + font-weight: 500; + list-style: outside none none; + color: #000; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-middle { + border-bottom: 1px solid #dee0e4; + border-top: 1px solid #dee0e4; + margin: 29px 0; + padding: 19px 0 18px; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-middle li { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 0 0 10px; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-bottom ul { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + font-family: Rubik, sans-serif; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-bottom ul li.your-order-shipping { + font-size: 16px; + color: #000; + font-weight: 500; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-total { + border-bottom: 1px solid #dee0e4; + border-top: 1px solid #dee0e4; + margin: 18px 0 33px; + padding: 17px 0 19px; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-total ul { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-total ul li { + font-weight: 500; + color: #036eb8; + font-size: 16px; + list-style: outside none none; + font-family: Rubik, sans-serif; +} +.your-order-area .your-order-wrap .your-order-product-info .your-order-total ul li.order-total { + font-weight: 500; + color: #000; + font-size: 18px; +} +@media only screen and (max-width: 767px) { + .your-order-area .your-order-wrap { + padding: 38px 30px 44px; + } +} +.your-order-area .payment-accordion { + margin: 0 0 16px; +} +.your-order-area .payment-accordion:last-child { + margin: 0; +} +.your-order-area .payment-accordion h4 a { + color: #000; + font-size: 16px; + margin: 0; + font-weight: 500; +} +.your-order-area .payment-accordion .panel-body { + padding: 5px 0 0 0; +} +.your-order-area .payment-accordion .panel-body p { + padding: 0 0 0 10px; + font-size: 14px; + color: #474747; + line-height: 24px; +} +.your-order-area .Place-order { + margin-top: 25px; +} +.your-order-area .Place-order a { + background-color: #036eb8; + color: #fff; + display: block; + font-weight: 500; + letter-spacing: 1px; + line-height: 1; + padding: 18px 20px; + text-align: center; + text-transform: uppercase; + border-radius: 0; + z-index: 9; +} +.your-order-area .Place-order a:hover { + background-color: #000; +} +.open-toggle, +.open-toggle2 { + display: none; +} +.compare-table .table tbody { + border-right: 1px solid #ebebeb; +} +.compare-table .table tbody tr:first-child { + border-top: 1px solid #ebebeb; +} +.compare-table .table tbody tr td { + text-align: center; + border: 0; + padding: 25px 30px; + vertical-align: middle; + border-bottom: 1px solid #ebebeb; + border-left: 1px solid #ebebeb; +} +.compare-table .table tbody tr td.first-column { + min-width: 180px; + font-size: 18px; + font-weight: 500; + color: #000; + margin: 0; + line-height: 1; +} +.compare-table .table tbody tr td.product-image-title { + min-width: 310px; + vertical-align: bottom; + padding-top: 70px; +} +.compare-table .table tbody tr td.product-image-title .image { + clear: both; + width: 100%; + margin-bottom: 40px; + display: block; +} +.compare-table .table tbody tr td.product-image-title .category { + float: left; + clear: both; + font-size: 13px; + line-height: 15px; + color: #000; + text-transform: capitalize; + letter-spacing: 0.5px; +} +.compare-table .table tbody tr td.product-image-title .title { + float: left; + clear: both; + font-size: 16px; + font-weight: 500; + color: #000; + line-height: 20px; + margin-bottom: 10px; +} +.compare-table .table tbody tr td.pro-desc p { + text-align: left; + margin: 0; + line-height: 24px; + font-size: 14px; +} +.compare-table .table tbody tr td.pro-color, +.compare-table .table tbody tr td.pro-price, +.compare-table .table tbody tr td.pro-stock { + font-size: 16px; + font-weight: 500; + color: #000; +} +.compare-table .table tbody tr td.pro-addtocart .add-to-cart { + position: relative; + background-color: #036eb8; + color: #fff; + border-radius: 0; + display: inline-block; + width: 170px; + padding: 14px 25px 14px 25px; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + outline: 0; + font-weight: 500; +} +.compare-table .table tbody tr td.pro-addtocart .add-to-cart:hover { + background-color: #000; +} +.compare-table .table tbody tr td.pro-remove button { + border: 0; + background-color: transparent; + padding: 0; + cursor: pointer; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + outline: 0; + color: #000; +} +.compare-table .table tbody tr td.pro-remove button i { + font-size: 22px; +} +.compare-table .table tbody tr td.pro-remove button:hover { + color: #036eb8; +} +.compare-table .table tbody tr td.pro-ratting i { + font-size: 20px; + color: #fdd835; +} +.single-my-account { + margin-bottom: 20px; + border: 1px solid #ebebeb; +} +.single-my-account .myaccount-info-wrapper { + padding: 30px 20px; + background-color: #fff; +} +.single-my-account .myaccount-info-wrapper .account-info-wrapper { + border-bottom: 1px solid #eaeaea; + margin-bottom: 28px; + padding-bottom: 30px; +} +.single-my-account .myaccount-info-wrapper .account-info-wrapper h4 { + font-size: 14px; + margin: 0; + text-transform: uppercase; + color: #000; + font-weight: 500; +} +.single-my-account .myaccount-info-wrapper .account-info-wrapper h5 { + font-size: 14px; + letter-spacing: 0.2px; + margin-top: 7px; + font-weight: 500; + color: #000; +} +.single-my-account .myaccount-info-wrapper .account-info-wrapper .account-info-wrapper { + border-bottom: 1px solid #eaeaea; + margin-bottom: 28px; + padding-bottom: 30px; +} +.single-my-account .myaccount-info-wrapper .billing-info { + margin-bottom: 20px; +} +.single-my-account .myaccount-info-wrapper .billing-info label { + color: #474747; + font-size: 14px; + text-transform: capitalize; + margin-bottom: 10px; +} +.single-my-account .myaccount-info-wrapper .billing-info input { + background: transparent none repeat scroll 0 0; + border: 1px solid #ebebeb; + color: #474747; + height: 40px; + padding: 0 15px; + width: 100%; + outline: 0; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin-top: 26px; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn .billing-back a { + color: #000; + display: inline-block; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn .billing-back a i { + font-size: 15px; + color: #036eb8; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn .billing-back a:hover { + color: #036eb8; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn .billing-btn button { + background-color: #f2f2f2; + border: medium none; + color: #000; + display: inline-block; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 16px 35px 17px; + text-transform: uppercase; + cursor: pointer; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + outline: 0; + border-radius: 0; +} +.single-my-account .myaccount-info-wrapper .billing-back-btn .billing-btn button:hover { + background-color: #036eb8; + color: #fff; +} +.single-my-account .myaccount-info-wrapper .entries-wrapper { + border: 1px solid #eaeaea; + position: relative; +} +@media only screen and (max-width: 767px) { + .single-my-account .myaccount-info-wrapper .entries-wrapper { + padding: 30px 10px; + } +} +.single-my-account .myaccount-info-wrapper .entries-wrapper:before { + position: absolute; + content: ''; + height: 100%; + width: 1px; + left: 50%; + top: 0; + background-color: #eaeaea; +} +@media only screen and (max-width: 767px) { + .single-my-account .myaccount-info-wrapper .entries-wrapper:before { + display: none; + } +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-info { + padding: 30px 20px; +} +@media only screen and (max-width: 767px) { + .single-my-account .myaccount-info-wrapper .entries-wrapper .entries-info { + padding: 0 10px 30px; + } +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-info p { + color: #474747; + font-size: 14px; + margin: 0; + text-transform: capitalize; + line-height: 24px; +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-edit-delete a { + background-color: #f32013; + color: #fff; + display: inline-block; + line-height: 1; + margin: 0 2px; + padding: 12px 15px; + text-transform: uppercase; + font-weight: 500; +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-edit-delete a:hover { + background-color: #036eb8; +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-edit-delete a.edit { + background-color: #000; + font-weight: 500; +} +.single-my-account .myaccount-info-wrapper .entries-wrapper .entries-edit-delete a.edit:hover { + background-color: #036eb8; +} +@media only screen and (max-width: 767px) { + .dashboard_tab_button { + margin-bottom: 50px; + } +} +.dashboard_tab_button li { + margin-bottom: 10px; +} +.dashboard_tab_button li:last-child { + margin-bottom: 0; +} +.dashboard_tab_button li .nav-link { + font-weight: 500; + color: #fff; + background-color: #000; + font-size: 16px; + text-transform: uppercase; + display: block; +} +.dashboard_tab_button li .nav-link.active { + background-color: #036eb8; +} +.dashboard_content h4 { + font-size: 24px; + text-transform: capitalize; + font-weight: 500; + margin-bottom: 15px; +} +.dashboard_content h5 { + font-size: 20px; + text-transform: capitalize; + font-weight: 500; + margin-bottom: 10px; + margin-top: 10px; +} +.dashboard_content p { + font-size: 16px; + line-height: 26px; +} +.dashboard_content p a { + color: #036eb8; + font-weight: 500; +} +.input-radio span { + font-weight: 500; + padding-right: 10px; +} +.account_login_form form span input[type='checkbox'], +.input-radio span input[type='radio'] { + width: 15px; + height: 15px; + margin-right: 2px; + position: relative; + top: 2px; +} +.checkbox-default-more-text em { + margin-top: 14px; + display: block; + line-height: 24px; +} +.table_page table { + width: 100%; + caption-side: bottom; + border-collapse: collapse; +} +.table_page table thead { + background: #f2f2f2; +} +.table_page table thead tr th { + color: #24262b; + border-bottom: 3px solid #036eb8; + border-right: 1px solid #ededed; + font-size: 16px; + font-weight: 500; + text-transform: capitalize; + padding: 10px; + text-align: center; +} +.table_page tbody tr td { + border-right: 1px solid #ededed; + font-weight: 500; + text-transform: capitalize; + font-size: 14px; + text-align: center; + min-width: 150px; +} +.table_page tbody tr td a:hover { + color: #036eb8; +} +.table_page table tbody tr td { + border-bottom: 1px solid #ededed; + border-right: 1px solid #ededed; + text-align: center; + padding: 10px; +} +.table_desc table tbody tr td:last-child, +.table_page table thead tr:last-child th { + border-right: 0; +} +.default-form-box { + margin-bottom: 20px; +} +.default-form-box label { + font-weight: 400; + font-size: 16px; + margin-bottom: 10px; + display: block; +} +.default-form-box input { + display: block; + width: 100%; + height: 45px; + padding: 0 10px 0 20px; + font-size: 16px; + font-weight: 400; + color: #474747; + border-radius: 3px; + background-color: #fff; + border: 1px solid #e2e2e2; + line-height: 45px; +} +.default-form-box input:focus { + border-color: #036eb8; +} +.checkbox-default { + line-height: 1; + display: inline-block; +} +.checkbox-default input { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + line-height: 0; + height: auto; +} +.checkbox-default input::after { + position: absolute; + content: ''; + width: 20px; + height: 20px; + border: 1px solid #dee2e6; + line-height: 20px; + text-align: center; + left: 0; +} +.checkbox-default span { + display: inline-block; + -webkit-transform: translateX(35px); + transform: translateX(35px); + text-transform: capitalize; + color: #777 !important; + font-size: 16px; + cursor: pointer; +} +.checkbox-default input:checked::after { + position: absolute; + content: ''; + background: #036eb8; + border-color: #036eb8; + font-family: FontAwesome; + color: #fff; +} +.save_button button { + background-color: #3b3b3b; + border-color: #3b3b3b; + color: #fff; + font-weight: 400; + font-size: 14px; + width: 130px; + height: 45px; + line-height: 45px; +} +.save_button button:hover { + border-color: #036eb8; + background-color: #036eb8; + color: #fff; +} +.login-register-wrapper .login-register-tab-list { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 40px; +} +.login-register-wrapper .login-register-tab-list a { + position: relative; +} +.login-register-wrapper .login-register-tab-list a:before { + background-color: #000; + bottom: 5px; + content: ''; + height: 18px; + margin: 0 auto; + position: absolute; + right: -2px; + -webkit-transition: all 0.4s ease 0s; + transition: all 0.4s ease 0s; + width: 1px; +} +.login-register-wrapper .login-register-tab-list a:hover h4 { + color: #036eb8 !important; +} +.login-register-wrapper .login-register-tab-list a h4 { + font-size: 25px; + font-weight: 500; + margin: 0 20px; + text-transform: capitalize; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + color: #000; +} +.login-register-wrapper .login-register-tab-list a:last-child:before { + display: none; +} +.login-register-wrapper .login-form-container { + background: transparent none repeat scroll 0 0; + -webkit-box-shadow: 0 0 6px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 6px rgba(0, 0, 0, 0.1); + padding: 80px; + text-align: left; +} +.login-register-wrapper .login-form-container .login-register-form input { + background-color: transparent; + border: 1px solid #ebebeb; + color: #474747; + font-size: 14px; + margin-bottom: 30px; + padding: 0 15px; + width: 100%; + outline: 0; +} +.login-register-wrapper .login-form-container .login-register-form input:focus { + border-color: #036eb8; +} +.login-register-wrapper .login-form-container .login-register-form .button-box .login-toggle-btn { + padding: 10px 0 19px; +} +.login-register-wrapper .login-form-container .login-register-form .button-box .login-toggle-btn input[type='checkbox'] { + height: 15px; + margin: 0; + position: relative; + top: 1px; + width: 17px; +} +.login-register-wrapper .login-form-container .login-register-form .button-box .login-toggle-btn a { + color: #000; + float: right; + font-size: 15px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.login-register-wrapper .login-form-container .login-register-form .button-box .login-toggle-btn a.flote-none { + float: none !important; +} +.login-register-wrapper .login-form-container .login-register-form .button-box .login-toggle-btn a:hover { + color: #036eb8; +} +.login-register-wrapper .login-form-container .login-register-form .button-box button { + background-color: #f2f2f2; + border: medium none; + color: #000; + cursor: pointer; + font-size: 14px; + font-weight: 500; + line-height: 1; + padding: 11px 30px; + text-transform: uppercase; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + outline: 0; + border-radius: 0; + font-family: Rubik, sans-serif; +} +.login-register-wrapper .login-form-container .login-register-form .button-box button:hover { + background-color: #036eb8; + color: #fff; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .login-register-wrapper .login-form-container { + padding: 80px 50px; + } +} +@media only screen and (max-width: 767px) { + .login-register-wrapper .login-form-container { + padding: 40px 15px; + } +} +.login-register-wrapper .login-register-tab-list a.active h4 { + color: #036eb8; +} +.cart-heading h2 { + color: #000; + text-align: left; + font-size: 24px; + line-height: 16px; + font-style: normal; + text-transform: none; + margin: 0 0 30px; + font-weight: 500; +} +.empty-text-contant i { + font-size: 60px; + color: #000; +} +.empty-text-contant h3 { + font-size: 20px; + color: #000; + margin: 20px 0 20px; + font-weight: 500; +} +@media only screen and (max-width: 575px) { + .empty-text-contant h3 { + font-size: 18px; + } +} +.empty-text-contant a.empty-cart-btn { + padding: 15px 25px; + display: inline-block; + background: #036eb8; + color: #fff; + font-size: 14px; + font-weight: 500; + border-radius: 30px; + -webkit-transition: 0.3s; + transition: 0.3s; + text-transform: uppercase; +} +.empty-text-contant a.empty-cart-btn:hover { + background-color: #000; +} +.empty-text-contant a.empty-cart-btn:hover i { + -webkit-transform: translate(-5px, 0); + transform: translate(-5px, 0); +} +.empty-text-contant a.empty-cart-btn i { + font-size: 14px !important; + color: #fff; + -webkit-transition: 0.3s; + transition: 0.3s; + display: inline-block; +} +.privacy_policy_main_area .privacy_content { + margin-bottom: 22px; +} +.privacy_policy_main_area .privacy_content h2 { + font-size: 22px; + line-height: 26px; + font-weight: 500; + margin-bottom: 7px; +} +@media only screen and (max-width: 767px) { + .privacy_policy_main_area .privacy_content h2 { + font-size: 20px; + } +} +.privacy_policy_main_area .privacy_content h3 { + font-size: 22px; + line-height: 26px; + font-weight: 500; + margin-bottom: 7px; +} +.privacy_policy_main_area .privacy_content p { + font-size: 16px; + line-height: 26px; + margin-bottom: 19px; +} +.privacy_policy_main_area .privacy_content p a { + color: #036eb8; +} +@media only screen and (max-width: 479px) { + .privacy_policy_main_area .privacy_content p a { + font-size: 12px; + } +} +.privacy_policy_main_area .privacy_content p a:hover { + color: #036eb8; +} +.privacy_policy_main_area .privacy_content.section_2 h2 { + margin-bottom: 24px; +} +.privacy_policy_main_area .privacy_content.section_3:last-child { + margin: 0; +} +.privacy_policy_main_area .privacy_content.section_3:last-child p { + margin: 0; +} +.coming_soon_area { + height: 100vh; + background-repeat: no-repeat; + background-attachment: scroll; + background-position: center center; + background-size: cover; + background-image: url(../images/coming-soon-bg/coming-soon.jpg); + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.coming_soon_area::before { + position: absolute; + content: ''; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: #000; + opacity: 0.15; +} +.coming_soon_title { + text-align: center; + margin-bottom: 40px; +} +@media only screen and (max-width: 767px) { + .coming_soon_title { + margin-bottom: 36px; + } +} +.coming_soon_title h2 { + font-size: 37px; + text-transform: capitalize; + color: #fff; + font-weight: 600; + margin-bottom: 15px; +} +@media only screen and (max-width: 767px) { + .coming_soon_title h2 { + font-size: 22px; + margin-bottom: 11px; + } +} +.coming_soon_title p { + color: #fff; + font-size: 16px; + max-width: 730px; + margin: 0 auto; + line-height: 26px; +} +@media only screen and (max-width: 575px) { + .coming_soon_title p { + font-size: 14px; + } +} +.coming_soon_timing { + text-align: center; + margin: 57px 0 42px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .coming_soon_timing { + margin: 50px 0 30px; + } +} +@media only screen and (max-width: 767px) { + .coming_soon_timing { + margin: 34px 0 22px; + } +} +.coming_soon_timing span.cdown { + display: inline-block; + margin-right: 35px; + background: inherit; + font-size: 26px; + font-weight: 600; + line-height: 1; + color: #fff; + margin-bottom: 8px; + width: 60px; + height: 40px; + line-height: 38px; + border: 1px solid #ebebeb; + border-radius: 4px; + padding-top: 0; + font-family: Rubik, sans-serif; +} +@media only screen and (max-width: 575px) { + .coming_soon_timing span.cdown { + margin-right: 20px; + width: 55px; + font-size: 20px; + } +} +.coming_soon_timing span.cdown:last-child { + margin-right: 0; +} +.coming_soon_timing span p { + font-size: 14px; + text-transform: capitalize; + color: #fff; +} +.coming_soon_newsletter { + text-align: center; +} +.coming_soon_newsletter .subscribe_form { + margin-top: 0; +} +.coming_soon_newsletter .subscribe_form form { + margin: 0 auto; + width: 600px; + background: inherit; + border: 1px solid #efefef; + border-radius: 50px; + position: relative; + text-align: left; +} +@media only screen and (max-width: 767px) { + .coming_soon_newsletter .subscribe_form form { + width: 100%; + } +} +.coming_soon_newsletter .subscribe_form form input::-webkit-input-placeholder { + color: #fff; +} +.coming_soon_newsletter .subscribe_form form input::-moz-placeholder { + color: #fff; +} +.coming_soon_newsletter .subscribe_form form input:-ms-input-placeholder { + color: #fff; +} +.coming_soon_newsletter .subscribe_form form input:-moz-placeholder { + color: #fff; +} +.coming_soon_newsletter .subscribe_form form input { + color: #fff; + font-size: 16px; + padding: 0 140px 0 28px; + background: inherit; + height: 48px; + border: 0; + width: 100%; +} +@media only screen and (max-width: 767px) { + .coming_soon_newsletter .subscribe_form form input { + padding: 0 106px 0 18px; + height: 45px; + } +} +.coming_soon_newsletter .subscribe_form form button { + font-size: 16px; + text-transform: uppercase; + font-weight: 700; + background: inherit; + color: #fff; + position: absolute; + right: 0; + top: 50%; + margin-top: -24px; + width: 120px; + height: 48px; +} +.coming_soon_newsletter .subscribe_form form button:hover { + color: #036eb8; +} +.coming_soon_newsletter .subscribe_form form button::before { + content: ''; + background: #fff; + width: 2px; + position: absolute; + bottom: 8px; + top: 8px; + left: 0; + height: 30px; +} +@media only screen and (max-width: 767px) { + .coming_soon_newsletter .subscribe_form form button { + font-size: 13px; + } +} +.coming_soon_newsletter h3 { + font-size: 16px; + color: #fff; + font-weight: 700; + margin-bottom: 15px; + letter-spacing: 2px; + text-transform: capitalize; +} +@media only screen and (max-width: 767px) { + .coming_soon_newsletter h3 { + letter-spacing: 1px; + } +} +.coming_soon_newsletter .mailchimp-error { + text-align: center; + color: #fff; +} +.coming_soon_newsletter .mailchimp-success { + text-align: center; + color: #fff; +} +.coming_soon_logo { + margin-bottom: 32px; +} +@media only screen and (max-width: 575px) { + .coming_soon_logo { + margin-bottom: 25px; + } +} +.coming_soon_container { + position: relative; +} +.faq-area .inner-descripe { + margin-bottom: 30px; +} +.faq-area .inner-descripe h4 { + color: #000; + font-size: 24px; + font-weight: 500; + margin: 0 0 15px; + line-height: 28px; +} +@media only screen and (max-width: 767px) { + .faq-area .inner-descripe h4 { + font-size: 20px; + } +} +.faq-area .inner-descripe p { + color: #474747; + line-height: 26px; +} +.faq-area .single-my-account h3.panel-title { + border-bottom: 0; + text-transform: capitalize; +} +.faq-area .single-my-account h3.panel-title a { + font-size: 16px; + color: #212121; + display: block; + padding: 16px 45px; + position: relative; + color: #000; +} +@media only screen and (max-width: 767px) { + .faq-area .single-my-account h3.panel-title a { + padding: 12px 38px; + font-size: 14px; + } +} +@media only screen and (max-width: 575px) { + .faq-area .single-my-account h3.panel-title a { + font-size: 13px; + } +} +.faq-area .single-my-account h3.panel-title a:before { + content: ''; + display: inline-block; + font-family: FontAwesome; + font-size: 14px; + position: absolute; + right: 20px; + top: 50%; + margin-top: -14px; +} +.faq-area .single-my-account h3.panel-title span { + color: #212121; + font-size: 14px; + left: 20px; + position: absolute; + top: 10px; + font-size: 16px; + top: 14px; +} +@media only screen and (max-width: 767px) { + .faq-area .single-my-account h3.panel-title span { + top: 10px; + font-size: 14px; + } +} +.faq-area .single-my-account h3.panel-title a[aria-expanded='true'] { + color: #036eb8; +} +.faq-area .single-my-account .panel-body { + padding: 20px; + line-height: 26px; +} +.single-my-account h3.panel-title { + background-color: #ebebeb; + border-bottom: 1px solid #ebebeb; + color: #212121; + font-size: 14px; + font-weight: 500; + margin: 0; + position: relative; + text-transform: uppercase; + line-height: 2; +} +.blank-page-area { + background-size: cover; + background-position: center; + background-repeat: no-repeat; + height: 770px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .blank-page-area { + height: 560px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .blank-page-area { + height: 550px; + } +} +@media only screen and (max-width: 767px) { + .blank-page-area { + height: 500px; + } +} +.blank-page-area .page-not-found { + margin-top: 310px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .blank-page-area .page-not-found { + margin-top: 200px; + } +} +@media only screen and (max-width: 767px) { + .blank-page-area .page-not-found { + margin-top: 150px; + } +} +.blank-page-area .page-not-found h2 { + font-size: 48px; + font-weight: 700; + font-style: italic; + color: #4e4e4e; + line-height: 61px; +} +@media only screen and (max-width: 767px) { + .blank-page-area .page-not-found h2 { + font-size: 36px; + line-height: 48px; + } +} +.blank-page-area .page-not-found p { + font-size: 36px; + font-weight: 400; + color: #4e4e4e; + line-height: 61px; + margin: 0 0 50px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .blank-page-area .page-not-found p { + margin: 0 0 30px; + } +} +@media only screen and (max-width: 767px) { + .blank-page-area .page-not-found p { + font-size: 28px; + line-height: 40px; + margin: 0 0 20px; + } +} +.blank-page-area .page-not-found a { + color: #fff; + font-weight: 500; + margin: 10px 0; + display: inline-block; + text-transform: capitalize; + width: 208px; + height: 63px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 5px; + background-color: #036eb8; + margin-top: 20px; + margin: auto; +} +.blank-page-area .page-not-found a i { + margin-left: 10px; + font-size: 20px; +} +.blank-page-area .page-not-found a:hover { + background-color: #000; +} +.inner_complated { + text-align: center; +} +.inner_complated img { + max-width: 100%; +} +.img_cmpted { + margin: 0 0 30px; +} +.dsc_cmpted { + margin: 0 0 30px; + line-height: 24px; +} +.btn_cmpted .shop-btn { + width: 210px; + background: #036eb8; + text-transform: capitalize; + height: 45px; + line-height: 45px; + text-align: center; + display: inline-block; + color: #fff; + font-weight: 500; + border-radius: 5px; + font-size: 16px; +} +.btn_cmpted .shop-btn:hover { + background-color: #1d1d1d; +} +.quick_order { + margin: 60px 0 60px; + text-align: center; +} +.quick_order .title { + font-size: 32px; +} +@media only screen and (max-width: 575px) { + .quick_order .title { + font-size: 26px; + } +} +.cntct.typewriter-effect a { + font-size: 20px; + color: #eb2606; + margin: 15px 0 0; + display: inline-block; + font-weight: 500; +} +.service-right-content { + padding-left: 84px; + width: 90%; +} +@media only screen and (max-width: 990px) { + .service-right-content { + padding-left: 12px; + width: 98%; + } +} +.service-left { + position: relative; + z-index: 1; +} +.service-left img { + max-width: 100%; +} +.service-left-image { + max-width: 100%; + display: block; + border-radius: 50%; +} +.pd-80 { + padding: 80px 0 0; +} +.pd-64 { + padding: 64px 0; +} +.about-bg { + background: #fff; +} +.p-0 { + padding: 0; +} +.service-area .service-right-content .title { + position: relative; +} +.service-area .service-right-content .eng-text { + position: absolute; + content: ''; + left: 0; + top: -50%; + opacity: 0.03; + font-weight: 600; + color: #036eb8; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .service-left-image { + margin: auto; + } +} +.service-left-image-2 { + position: absolute; + left: auto; + right: 25px; + z-index: -1; + top: 25px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .service-left-image-2 { + top: 0; + right: 0; + width: 85%; + max-width: 100%; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .service-left-image-2 { + top: 23px; + right: 15%; + max-width: 100%; + } +} +@media only screen and (max-width: 575px) { + .service-left-image-2 { + display: none; + } + .pd-64 { + padding: 32px 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .service-area .service-right-content { + margin-top: 80px; + } +} +@media only screen and (max-width: 575px) { + .service-area .service-right-content { + margin-top: 20px; + } +} +.service-area .service-right-content .title { + font-size: 40px; + color: #333; + font-weight: 600; + margin: 0 0 30px; + line-height: 50px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .service-area .service-right-content .title { + font-size: 24px; + line-height: 36px; + } +} +.service-area .service-right-content .para-1 { + color: #666; + font-weight: 500; + font-size: 16px; + line-height: 30px; + margin: 0 0 25px; +} +.service-area .service-right-content .para-2 { + color: #5e5e5e; + font-weight: 400; + font-size: 16px; + line-height: 28px; + margin: 0 0 45px; +} +.service-area .service-right-content .mision-vision .mision { + margin-bottom: 40px; +} +.service-area .service-right-content .mision-vision .mision, +.service-area .service-right-content .mision-vision .vision { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (max-width: 575px) { + .service-area .service-right-content .mision-vision .mision, + .service-area .service-right-content .mision-vision .vision { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + } +} +.service-area .service-right-content .mision-vision .mision .heading, +.service-area .service-right-content .mision-vision .vision .heading { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 235px; + font-size: 30px; + color: #4a4a4a; + padding-left: 20px; + position: relative; +} +.service-area .service-right-content .mision-vision .mision .heading::after, +.service-area .service-right-content .mision-vision .vision .heading::after { + position: absolute; + top: 50%; + left: 0; + width: 10px; + height: 4px; + content: ''; + background-color: #000; + margin-top: -2.5px; +} +.service-area .service-right-content .mision-vision .mision-desc, +.service-area .service-right-content .mision-vision .vision-desc { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: calc(100% - 235px); + color: #747474; + line-height: 30px; +} +@media only screen and (max-width: 575px) { + .service-area .service-right-content .mision-vision .mision-desc, + .service-area .service-right-content .mision-vision .vision-desc { + width: 100%; + } +} +.promo-video { + border-radius: 50%; + position: relative; +} +.promo-video .overlay-box { + width: 98px; + height: 98px; + transition: all 0.3s ease; + -moz-transition: all 0.3s ease; + -webkit-transition: all 0.3s ease; + -ms-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + position: absolute; + left: 40px; + top: -70px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .promo-video .overlay-box { + left: 35%; + } +} +.promo-video .overlay-box span { + position: absolute; + width: 98px; + height: 98px; + left: 50%; + top: 50%; + z-index: 10; + color: #fff; + font-weight: 400; + font-size: 38px; + border-radius: 50%; + margin-top: -49px; + margin-left: -49px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + transition: all 0.9s ease; + -moz-transition: all 0.9s ease; + -webkit-transition: all 0.9s ease; + -ms-transition: all 0.9s ease; + -o-transition: all 0.9s ease; + background-color: #036eb8; +} +@media only screen and (max-width: 479px) { + .promo-video .overlay-box span { + width: 60px; + height: 60px; + margin-top: -30px; + margin-left: -30px; + font-size: 14px; + } +} +.ripple, +.ripple:after, +.ripple:before { + position: absolute; + top: 50%; + left: 50%; + width: 98px; + height: 98px; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + border-radius: 50%; + -webkit-box-shadow: 0 0 0 0 rgba(230, 167, 131, 0.8); + -ms-box-shadow: 0 0 0 0 rgba(230, 167, 131, 0.8); + -o-box-shadow: 0 0 0 0 rgba(230, 167, 131, 0.8); + box-shadow: 0 0 0 0 rgba(230, 167, 131, 0.8); + -webkit-animation: ripple 3s infinite; + animation: ripple 3s infinite; +} +@media only screen and (max-width: 479px) { + .ripple, + .ripple:after, + .ripple:before { + width: 60px; + height: 60px; + } +} +.ripple:before { + -webkit-animation-delay: 0.9s; + animation-delay: 0.9s; + content: ''; + position: absolute; +} +.ripple:after { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; + content: ''; + position: absolute; +} +@-webkit-keyframes ripple { + 70% { + -webkit-box-shadow: 0 0 0 70px rgba(37, 24, 24, 0); + box-shadow: 0 0 0 70px rgba(37, 24, 24, 0); + } + 100% { + -webkit-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + } +} +@keyframes ripple { + 70% { + -webkit-box-shadow: 0 0 0 70px rgba(255, 255, 255, 0); + box-shadow: 0 0 0 70px rgba(255, 255, 255, 0); + } + 100% { + -webkit-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + } +} +.team-wrapper .team-image img { + max-width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + width: 100%; +} +.team-wrapper .team-inner { + margin-top: -30px; + padding: 20px 0 20px 30px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + background-color: #fff; + position: relative; +} +.team-wrapper .team-inner .team-content { + text-align: left; + line-height: 1; +} +.team-wrapper .team-inner .team-content .title { + font-size: 18px; + color: #393939; + font-weight: 500; + text-transform: uppercase; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.team-wrapper .team-inner .team-content .sub-title { + font-size: 16px; + font-weight: 400; + color: grey; + text-transform: uppercase; + margin: 9px 0 27px; + display: block; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.team-wrapper .team-inner .team-social { + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; +} +.team-wrapper .team-inner .team-social li + li { + margin-left: 10px; +} +.team-wrapper .team-inner .team-social li a { + width: 36px; + height: 36px; + background-color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + color: #fff; + font-size: 14px; + position: relative; + overflow: hidden; + z-index: 1; + margin-top: -1px; + border-radius: 5px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.team-wrapper:hover .team-image img { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); +} +.team-wrapper:hover .team-inner { + margin-left: 40px; + background-color: #036eb8; +} +@media only screen and (max-width: 767px) { + .team-wrapper:hover .team-inner { + margin-left: 30px; + } +} +.team-wrapper:hover .team-inner .title { + color: #fff; +} +.team-wrapper:hover .team-inner .sub-title { + color: #fff; +} +.team-wrapper:hover .team-inner .team-social li a { + background-color: #fff; + color: #036eb8; +} +.gmap_canvas { + line-height: 0; +} +.gmap_canvas iframe { + overflow: hidden; + background: 0 0 !important; + height: 600px; + width: 100%; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .gmap_canvas iframe { + height: 400px; + } +} +@media only screen and (max-width: 767px) { + .gmap_canvas iframe { + height: 350px; + } +} +.contact-wrapper .contact-info { + padding: 32px 40px 48px; + background: #fff; + margin: 0 14px; +} +@media only screen and (max-width: 575px) { + .contact-wrapper .contact-info { + padding: 0; + } +} +.contact-wrapper .contact-info .sub-title { + font-size: 18px; + font-weight: 500; + color: #036eb8; + margin: 0 0 5px; + display: block; +} +.contact-wrapper .contact-info .heading { + font-size: 36px; + color: #424242; + font-weight: 500; + margin: 0 0 35px; + line-height: 55px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .contact-wrapper .contact-info .heading { + font-size: 28px; + line-height: 45px; + } +} +@media only screen and (max-width: 575px) { + .contact-wrapper .contact-info .heading { + font-size: 24px; + line-height: 35px; + } +} +.contact-wrapper .contact-info .single-contact { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + /* justify-content: center; + align-items: center; */ + -webkit-box-align: center; + -ms-flex-align: center; + border-bottom: 1px solid #eee; + padding: 63px; + margin-left: 33%; +} +@media only screen and (max-width: 767px) { + .contact-wrapper .contact-info .single-contact { + padding: 24px 0; + margin-left: 0; + } +} +.contact-wrapper .contact-info .single-contact:last-child { + border-bottom: none; +} +.contact-wrapper .contact-info .single-contact .icon-box { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + /* justify-content: center; + align-items: center; */ + -webkit-box-align: center; + -ms-flex-align: center; + margin-right: 30px; + position: relative; + -webkit-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} +.contact-wrapper .contact-info .single-contact .icon-box i { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + font-size: 36px; + color: #fff; +} +@media only screen and (max-width: 575px) { + .contact-wrapper .contact-info .single-contact .icon-box { + margin-right: 0; + } + .icon-box img { + max-width: 50%; + margin-left: 10px; + } +} +.contact-wrapper .contact-info .single-contact .info-box { + width: calc(100% - 110px); +} +@media only screen and (max-width: 479px) { + .contact-wrapper .contact-info .single-contact .info-box { + width: calc(100% - 80px); + } +} +.contact-wrapper .contact-info .single-contact .info-box .title { + font-size: 40px; + color: #036eb8; + font-weight: 600; + margin: 0 0 24px; + word-wrap: break-word; +} +@media only screen and (max-width: 750px) { + .contact-wrapper .contact-info .single-contact .info-box .title { + font-size: 20px; + margin: 0 0 5px; + } +} +.contact-wrapper .contact-info .single-contact .info-box p { + font-size: 14px; + color: #999; + margin: 0; +} +.contact-wrapper .contact-info .single-contact .info-box a { + color: #848484; +} +.contact-wrapper .contact-info .single-contact .info-box a:hover { + color: #036eb8; +} +.contact-wrapper .contact-info .single-contact:hover i { + -webkit-transform: scale(0.95) rotate(0); + transform: scale(0.95) rotate(0); +} + +.contact-wrapper .contact-info .social { + margin-top: 60px; +} +.contact-wrapper .contact-info .social li { + display: inline-block; + margin-left: 10px; +} +.contact-wrapper .contact-info .social li a { + width: 36px; + height: 36px; + color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + font-size: 16px; + background-color: #000; + border-radius: 5px; +} +.contact-wrapper .contact-info .social li a:hover { + background-color: #036eb8; +} +.contact-form { + padding: 60px 40px 60px 40px; + -webkit-box-shadow: 0 8px 36px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 8px 36px 0 rgba(0, 0, 0, 0.1); + border-radius: 20px; +} +.contact-form .contact-title { + margin: 0 0 31px; +} +.contact-form .contact-title .title { + font-size: 36px; + color: #424242; + font-weight: 500; + margin: 0 0 14px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .contact-form .contact-title .title { + font-size: 28px; + } +} +@media only screen and (max-width: 575px) { + .contact-form .contact-title .title { + font-size: 24px; + } +} +.contact-form .contact-title p { + color: #747474; + line-height: 27px; +} +.contact-form .contact-form-style input, +.contact-form .contact-form-style textarea { + background: 0; + border: 1px solid #c1c1c1; + margin-bottom: 30px; + color: #474747; + font-size: 14px; +} +.contact-form .contact-form-style input::-webkit-input-placeholder, +.contact-form .contact-form-style textarea::-webkit-input-placeholder { + font-style: italic; + color: #999; +} +.contact-form .contact-form-style input::-moz-placeholder, +.contact-form .contact-form-style textarea::-moz-placeholder { + font-style: italic; + color: #999; +} +.contact-form .contact-form-style input:-ms-input-placeholder, +.contact-form .contact-form-style textarea:-ms-input-placeholder { + font-style: italic; + color: #999; +} +.contact-form .contact-form-style input::-ms-input-placeholder, +.contact-form .contact-form-style textarea::-ms-input-placeholder { + font-style: italic; + color: #999; +} +.contact-form .contact-form-style input::placeholder, +.contact-form .contact-form-style textarea::placeholder { + font-style: italic; + color: #999; +} +.contact-form .contact-form-style input:focus, +.contact-form .contact-form-style textarea:focus { + border-color: #036eb8; +} +.contact-form .contact-form-style textarea { + margin-bottom: 0; + height: 200px; +} +.contact-form p { + color: #474747; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .contact-form { + margin-top: 60px; + } +} +@media only screen and (max-width: 575px) { + .contact-form { + padding: 40px 20px; + } +} +.contact-form button { + font-size: 14px; + letter-spacing: 2px; + line-height: 1; + font-weight: 400; + text-transform: uppercase; +} +.contact-form button i { + font-size: 16px; + margin-left: 10px; +} +.btn { + padding: 0; + font-size: 16px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border: 0; + font-weight: 400; + line-height: 1; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; +} +.f-20 { + font-size: 30px; + font-weight: 600; +} +.btn-primary { + color: #fff; + border: 1px solid #036eb8; + background: #fff; + width: 216px; + height: 48px; + color: #036eb8; + z-index: 1; + position: relative; + overflow: hidden; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-primary::before { + position: absolute; + content: ''; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: #036eb8; + border: 1px solid #036eb8; + color: #fff; + z-index: -1; + -webkit-transition: 0.3s linear; + transition: 0.3s linear; + -webkit-transform: scale(0); + transform: scale(0); + border-radius: 50%; + width: 100%; + height: 100%; +} +.btn-primary:hover { + color: #fff; + -webkit-box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + box-shadow: -1px 10px 80px -15px rgba(0, 0, 0, 0.3); + background: 0; + -webkit-transform: translateY(-3px); + transform: translateY(-3px); +} +.btn-primary:hover::before { + -webkit-transform: scale(1.5); + transform: scale(1.5); +} +.btn-primary.blog-btn { + background: #036eb8; + width: 130px; + height: 40px; + font-size: 14px; + text-transform: uppercase; + font-weight: 400; +} +.btn-primary.blog-btn::before { + background: #036eb8; +} +.btn-check:focus + .btn, +.btn:focus { + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-check:focus + .btn-primary, +.btn-primary:focus { + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: 1px solid #036eb8; + color: #036eb8; +} +.btn-check:active + .btn-primary, +.btn-check:checked + .btn-primary, +.btn-primary.active, +.btn-primary:active, +.show > .btn-primary.dropdown-toggle { + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: 0; +} +.category-wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.category-wrapper .category-inner { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + width: 180px; + height: 180px; + border: 2px solid #474747; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + border-radius: 50%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + position: relative; + margin: auto; +} +@media only screen and (max-width: 479px) { + .category-wrapper .category-inner { + width: 140px; + height: 140px; + } +} +.category-wrapper .category-inner:after { + content: ''; + position: absolute; + top: -1px; + left: -1px; + right: -1px; + bottom: -1px; + border-radius: 100%; + z-index: -1; + border: 2px dashed #036eb8; + opacity: 0; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.category-wrapper .category-inner .category-single-item { + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + text-align: center; +} +.category-wrapper .category-inner .category-single-item img { + margin: auto; +} +@media only screen and (max-width: 479px) { + .category-wrapper .category-inner .category-single-item img { + max-width: 100%; + } +} +.category-wrapper .category-inner .category-single-item .title { + display: block; + font-family: Rubik, sans-serif; + font-weight: 600; + color: #474747; + margin: 12px 0 0; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +@media only screen and (max-width: 479px) { + .category-wrapper .category-inner .category-single-item .title { + font-size: 13px; + } +} +.category-wrapper .category-inner:hover { + border-color: transparent; +} +.category-wrapper .category-inner:hover:after { + opacity: 1; + -webkit-animation: spinAround 9s linear infinite; + animation: spinAround 9s linear infinite; +} +.category-wrapper .category-inner:hover .title { + color: #036eb8; +} +@-webkit-keyframes spinAround { + from { + -webkit-transform: rotate(0); + } + to { + -webkit-transform: rotate(360deg); + } +} +@keyframes spinAround { + from { + -webkit-transform: rotate(0); + transform: rotate(0); + } + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.nav-center .product-tab-nav .nav-item { + display: inline-block; + vertical-align: top; + font-size: 18px; + text-transform: capitalize; + padding: 0; + cursor: pointer; + font-weight: 500; + -webkit-transition: all 0.3s ease; + transition: all 0.3s ease; +} +@media only screen and (max-width: 479px) { + .nav-center .product-tab-nav .nav-item { + margin: 0 0 20px 5px; + font-size: 16px; + } +} +.nav-center .product-tab-nav .nav-item:last-child { + margin-right: 0; +} +.nav-center .product-tab-nav .nav-item .nav-link { + color: #767676; +} +.nav-center .product-tab-nav .nav-item .nav-link span { + width: 131px; + height: 44px; + margin: 0; +} +@media only screen and (max-width: 575px) { + .nav-center .product-tab-nav .nav-item .nav-link span { + width: 115px; + } +} +@media only screen and (max-width: 479px) { + .nav-center .product-tab-nav .nav-item .nav-link span { + width: 80px; + } +} +.nav-center .product-tab-nav .nav-item .nav-link span::after { + background-image: url(../images/icons/tab-bg-2.png); +} +@media only screen and (max-width: 479px) { + .nav-center .product-tab-nav .nav-item .nav-link span::after { + background-size: contain; + } +} +.nav-center .product-tab-nav .nav-item.active, +.nav-center .product-tab-nav .nav-item:hover { + color: #fff; +} +.nav-center .product-tab-nav .nav-item.active span::after, +.nav-center .product-tab-nav .nav-item:hover span::after { + opacity: 1; +} +@media only screen and (max-width: 575px) { + .nav-center.nav-center-2 .product-tab-nav { + -ms-flex-wrap: wrap; + flex-wrap: wrap; + } +} +@media only screen and (max-width: 479px) { + .nav-center.nav-center-2 .product-tab-nav .nav-item { + margin: 0 0 0 5px; + } +} +@media only screen and (max-width: 767px) { + .nav-center.nav-center-2 .product-tab-nav .nav-item .nav-link span { + width: 100px; + } +} +@media only screen and (max-width: 767px) { + .nav-center.nav-center-2 .product-tab-nav .nav-item .nav-link span::after { + background-size: contain; + } +} +.mb-n-30px { + margin-bottom: -30px; +} +.product-tab-nav.nav { + -ms-flex-wrap: inherit; + flex-wrap: inherit; +} +.product-tab-nav .nav-item { + display: inline-block; + vertical-align: top; + font-size: 18px; + text-transform: capitalize; + padding: 0; + cursor: pointer; + font-weight: 500; + -webkit-transition: all 0.3s ease; + transition: all 0.3s ease; +} +.product-tab-nav .nav-item .nav-link { + color: #393939; + padding: 0; + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.product-tab-nav .nav-item .nav-link span { + position: relative; + z-index: 1; + width: 100%; + height: 65px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: 5px 0 0; +} +.product-tab-nav .nav-item .nav-link span::after { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + content: ''; + background-image: url(../images/icons/tab-bg.png); + background-repeat: no-repeat; + background-position: center; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + width: 100%; + height: 100%; + z-index: -1; + opacity: 0; +} +.product-tab-nav .nav-item .nav-link.active, +.product-tab-nav .nav-item .nav-link:hover { + color: #fff; +} +.product-tab-nav .nav-item .nav-link.active span::after, +.product-tab-nav .nav-item .nav-link:hover span::after { + opacity: 1; +} +@media only screen and (max-width: 575px) { + .col-xs-6 { + width: 50%; + } +} +@media only screen and (max-width: 479px) { + .col-xs-6 { + width: 100%; + } +} +.mt-60px { + padding-top: 56px; +} +@media only screen and (max-width: 479px) { + .mt-60px { + padding-top: 24px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .grid-4-view .product .content .title a { + font-size: 14px; + } +} +.product { + position: relative; + background: #fff; + padding: 56px; +} +.updoanlod { + position: relative; + background: #fff; + padding: 24px; +} +.updoanlod img { + max-width: 100%; +} +.updoanlod-icon { + position: absolute; + padding: 80px; + margin-right: 2%; + text-align: center; +} +.contact { + padding: 48px; + background: #fff; + text-align: center; +} +.contact p { + text-align: center; + width: 100%; + padding-top: 40px; +} +.contact img { + max-width: 100%; +} +@media only screen and (max-width: 1000px) { + .contact { + padding: 24px; + background: none; + } + .contact img { + max-width: 50%; + } +} +@media only screen and (max-width: 750px) { + .content-desc-wrap { + padding: 0 24px; + margin-bottom: 2em; + font-size: 14px; + } + .updoanlod-icon { + position: absolute; + padding: 48px; + margin: 2%; + text-align: center; + } +} +.back-bg { + background: #f9f9f9; + position: relative; +} +.product .add-to-cart { + display: block; + width: 100%; + height: 64px; + line-height: 64px; + background: #036eb8; + text-align: center; + position: absolute; + bottom: 0; + left: 0; + font-size: 14px; + z-index: 11; + margin: auto; + font-weight: 400; + visibility: hidden; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-transform: translateY(0); + transform: translateY(0); + color: #fff; + opacity: 0; + text-transform: uppercase; + overflow: hidden; +} +@media only screen and (min-width: 320px) and (max-width: 1366px) { + .product { + position: relative; + background: #fff; + padding: 48px 12px; + } + .product .add-to-cart { + height: 32px; + line-height: 32px; + } +} +.product .add-to-cart:hover { + color: #fff; + -webkit-box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.2); +} +.contact-area { + padding: 64px 0; +} +.product-bg { + background: #f5f5f5; +} +@media only screen and (max-width: 1400px) { + .product-bg { + padding-top: 2em; + } +} +.product .thumb { + position: relative; + overflow: hidden; +} +.product .thumb .image { + position: relative; + display: block; + overflow: hidden; + text-align: center; +} +.product .thumb .image img { + z-index: 1; + max-width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.product .thumb .image img.hover-image { + position: absolute; + z-index: 2; + top: 0; + left: 20%; + opacity: 0; +} +.product .thumb .badges { + position: absolute; + z-index: 8; + top: 18px; + left: -2px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} +.product .thumb .badges span { + font-size: 12px; + line-height: 1.7; + display: block; + padding: 0 10px; + text-align: center; + text-transform: uppercase; + border-radius: 3px; + color: #fff; + font-weight: 500; +} +.product .thumb .badges span + span { + margin-top: 12px; +} +.product .thumb .badges span.new { + background-color: #000; +} +.product .thumb .badges span.sale { + background: #036eb8; +} +.product .thumb .actions { + position: absolute; + z-index: 9; + top: 18px; + right: 18px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.product .thumb .actions .action { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + width: 40px; + height: 40px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + text-decoration: none; + color: #000; + border-radius: 50%; + background-color: #eaeaea; + font-size: 24px; +} +.product .thumb .actions .action:hover { + color: #fff; + -webkit-box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.2); + -webkit-transform: translateY(-1px); + transform: translateY(-1px); + background: #036eb8; +} +.product .thumb .actions .action + .action { + margin-top: 15px; +} +.product .thumb .actions .action:not(.wishlist) { + visibility: hidden; + -webkit-transform: translateY(20px); + transform: translateY(20px); + opacity: 0; +} +.product .thumb .actions .action.active { + background: #036eb8; +} +.product .content { + position: relative; + z-index: 10; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #fff; +} +.product .content span { + color: #999; + font-size: 14px; + line-height: 18px; + height: 38px; + overflow: hidden; +} +.product .content .ratings { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + margin-bottom: 4px; +} +.product .content .ratings .rating-wrap { + font-size: 14px; + line-height: 1; + position: relative; + color: #e4e4e4; + white-space: nowrap; +} +.product .content .ratings .rating-wrap::before { + font-family: FontAwesome; + content: '    '; +} +.product .content .ratings .rating-wrap .star { + position: absolute; + top: 0; + left: 0; + overflow: hidden; + color: #ffde00; +} +.product .content .ratings .rating-wrap .star::before { + font-family: FontAwesome; + content: '    '; +} +.product .content .ratings .rating-num { + font-size: 14px; + line-height: 1; + margin-left: 6px; + color: #9f9e9e; + display: none; +} +.product .content .title { + font-size: 16px; + margin: 32px 0 15px; + font-family: Rubik, sans-serif; + max-height: 20px; + text-overflow: ellipsis; /*设置超出部分显示...*/ + -o-text-overflow: ellipsis; + overflow: hidden; +} +.product .content .title a { + text-decoration: none; + color: #333; + font-size: 16px; + font-weight: bold; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 575px) { + .product .content .title a { + font-size: 14px; + } +} +.product .content .price { + font-size: 16px; + font-family: Rubik, sans-serif; + line-height: 1; + font-weight: 500; +} +.product .content .price:not(:last-child) { + margin-bottom: 20px; +} +.product .content .price span.new { + color: #393939; + font-weight: 500; +} +.product .content .price span.old { + font-size: 14px; + margin-left: 10px; + text-decoration: line-through; + color: #747474; +} +.product .content .btn { + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; +} +.product:hover { + -webkit-transform: translateY(-10px); + -moz-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transition: all 0.5s; + -webkit-transition: all 0.5s; + -ms-transition: all 0.5s; + cursor: pointer; +} +.product:hover .thumb .image img:not(:last-child) { + opacity: 0; +} +.product:hover .thumb .image img.hover-image { + opacity: 1; +} +.product:hover .thumb .actions .action { + visibility: visible; + -webkit-transform: translateY(0); + transform: translateY(0); + opacity: 1; +} +.product:hover .content .title a { + color: #474747; +} +.product:hover .content .title a:hover { + color: #036eb8; +} +.product:hover .add-to-cart { + visibility: visible; + -webkit-transform: translateY(20px); + transform: translateY(20px); + opacity: 1; +} +.tab-content .tab-pane { + display: block; + overflow: hidden; + height: 0; + visibility: hidden; + max-width: 100%; + opacity: 0; +} +.tab-content .tab-pane.active { + height: auto; + visibility: visible; + opacity: 1; + overflow: visible; +} +.single-col { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 24.8%; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .single-col { + width: 100%; + } +} +.single-col .single-banner { + position: relative; + display: block; + overflow: hidden; + border-radius: 5px; +} +.single-col .single-banner img { + width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} + +.single-col .single-banner .banner-content { + position: absolute; + top: 0; + left: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + padding: 60px 30px; + width: 100%; + height: 100%; + line-height: 1; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (max-width: 767px) { + .single-col .single-banner .banner-content { + padding: 40px 30px; + } +} +@media only screen and (max-width: 479px) { + .single-col .single-banner .banner-content { + padding: 40px 20px; + } +} +.single-col .single-banner .banner-content .category { + display: block; + font-size: 16px; + color: #414141; + font-weight: 500; + margin: 0 0 12px; +} +@media only screen and (max-width: 479px) { + .single-col .single-banner .banner-content .category { + margin: 0 0 5px; + } +} +.single-col .single-banner .banner-content .title { + font-size: 30px; + color: #424242; + font-weight: 500; + text-transform: capitalize; + display: block; + margin: 0 0 28px; + line-height: 43px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .single-col .single-banner .banner-content .title { + font-size: 24px; + line-height: 36px; + margin: 0 0 20px; + } +} +@media only screen and (max-width: 479px) { + .single-col .single-banner .banner-content .title { + font-size: 24px; + margin: 0 0 15px; + line-height: 32px; + } +} +.single-col .single-banner .banner-content .shop-link { + width: 120px; + height: 40px; + font-size: 14px; +} +.single-col.center-col { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50.3%; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .single-col.center-col { + width: 100%; + margin: 30px 0; + } +} +@media only screen and (max-width: 479px) { + .single-col.center-col .banner-content { + padding: 12px 20px; + } +} +.plr-15px { + padding: 0 15px; +} +@media only screen and (max-width: 479px) { + .plr-15px { + padding: 0; + } +} +.banner-area-2 .single-banner { + position: relative; + overflow: hidden; + border-radius: 0; +} +.banner-area-2 .single-banner.nth-child-1 { + margin-right: 24px; +} +@media only screen and (max-width: 767px) { + .banner-area-2 .single-banner.nth-child-1 { + margin-right: 0; + } +} +.banner-area-2 .single-banner.nth-child-2 { + margin-bottom: 24px; +} + +.banner-area-2 .single-banner img { + max-width: 100%; + width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.banner-area-2 .single-banner .banner-content { + position: absolute; + top: 0; + /* bottom: 0; */ + left: 0; + right: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.banner-area-2 .single-banner .banner-content.nth-child-1 { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.banner-area-2 .single-banner .banner-content.nth-child-2 { + left: 0; +} + +.banner-area-2 .single-banner .banner-content.nth-child-2 .category { + color: #414141; +} +.banner-area-2 .single-banner .banner-content.nth-child-2 .title { + color: #fff; + font-size: 30px; + line-height: 43px; + font-weight: 600; + margin: 0 0 10px; + background: rgba(3, 110, 184, 0.6); + width: 100%; + text-align: center; + padding: 20px 0; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-2 .single-banner .banner-content.nth-child-2 .title { + font-size: 20px; + line-height: 30px; + margin: 0 0 5px; + } +} +@media only screen and (max-width: 479px) { + .banner-area-2 .single-banner .banner-content.nth-child-2 .title { + font-size: 20px; + line-height: 28px; + margin: 0; + } +} +.banner-area-2 .single-banner .banner-content.nth-child-3 { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; +} + +.banner-area-2 .single-banner .banner-content.nth-child-3 .category { + color: #414141; +} +.banner-area-2 .single-banner .banner-content.nth-child-3 .title { + color: #fff; + font-size: 30px; + line-height: 43px; + font-weight: 600; + margin: 0 0 10px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-2 .single-banner .banner-content.nth-child-3 .title { + font-size: 20px; + line-height: 30px; + margin: 0 0 5px; + } +} +@media only screen and (max-width: 479px) { + .banner-area-2 .single-banner .banner-content.nth-child-3 .title { + font-size: 20px; + line-height: 28px; + margin: 0; + } +} +.banner-area-2 .single-banner .banner-content .category { + display: block; + color: #fff; + font-size: 16px; + font-weight: 500; + margin: 0 0 3px; +} +.banner-area-2 .single-banner .banner-content .title { + color: #fff; + font-size: 36px; + line-height: 46px; + font-weight: 600; + margin: 0 0 10px; + background: rgba(3, 110, 184, 0.6); + width: 100%; + text-align: center; + padding: 20px 0; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-2 .single-banner .banner-content .title { + font-size: 24px; + line-height: 36px; + margin: 0 0 5px; + } +} +.banner-area-2 .single-banner .banner-content .shop-link { + font-size: 14px; + width: 120px; + height: 40px; + margin: 21px 0 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .banner-area-2 .single-banner .banner-content .shop-link { + margin: 15px 0 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-2 .single-banner .banner-content .shop-link { + margin: 10px 0 0; + } +} +@media only screen and (max-width: 479px) { + .banner-area-2 .single-banner .banner-content .shop-link { + margin: 15px 0 0; + font-size: 12px; + width: 100px; + height: 35px; + } + .banner-area-2 .single-banner .banner-content .title { + font-size: 20px; + } +} +.banner-area-2 .single-banner:hover img { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); +} +.banner-area-3 .single-banner { + position: relative; + overflow: hidden; + border-radius: 0; +} +.banner-area-3 .single-banner img { + max-width: 100%; + width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.banner-area-3 .single-banner .banner-content { + position: absolute; + top: 0; + bottom: 0; + left: auto; + right: 40px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.banner-area-3 .single-banner .banner-content .category { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + color: #fff; + font-size: 16px; + font-weight: 500; + margin: 0 0 15px; + background-image: url(/assets/images/banner/sticker-bg.png); + width: 80px; + height: 32px; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 12px; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.banner-area-3 .single-banner .banner-content .title { + color: #424242; + font-size: 30px; + line-height: 43px; + font-weight: 500; + margin: 0 0 10px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-3 .single-banner .banner-content .title { + font-size: 24px; + line-height: 36px; + margin: 0 0 5px; + } +} +@media only screen and (max-width: 575px) { + .banner-area-3 .single-banner .banner-content .title { + font-size: 20px; + line-height: 20px; + } + .banner-area-2 .single-banner .banner-content .title { + font-size: 20px; + line-height: 20px; + } +} +@media only screen and (max-width: 479px) { + .banner-area-3 .single-banner .banner-content .title { + font-size: 20px; + line-height: 28px; + margin: 0 0 5px; + } +} +.banner-area-3 .single-banner .banner-content .shop-link { + font-size: 14px; + width: 120px; + height: 40px; + margin: 21px 0 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .banner-area-3 .single-banner .banner-content .shop-link { + margin: 15px 0 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .banner-area-3 .single-banner .banner-content .shop-link { + margin: 10px 0 0; + } +} +@media only screen and (max-width: 479px) { + .banner-area-3 .single-banner .banner-content .shop-link { + margin: 15px 0 0; + font-size: 12px; + width: 100px; + height: 35px; + } +} +.banner-area-3 .single-banner:hover img { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); +} +.slider-banner .single-banner { + position: relative; + overflow: hidden; + border-radius: 0; +} +.slider-banner .single-banner img { + max-width: 100%; + width: 100%; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .slider-banner .single-banner img { + height: 237.5px; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; + } +} +.slider-banner .single-banner .banner-content { + position: absolute; + top: 0; + bottom: 0; + left: 40px; + right: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} +.slider-banner .single-banner .banner-content .category { + display: block; + color: #fff; + font-size: 16px; + font-weight: 400; + margin: 0 0 3px; +} +.slider-banner .single-banner .banner-content .title { + color: #424242; + font-size: 30px; + line-height: 38px; + font-weight: 400; + margin: 0; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-banner .single-banner .banner-content .title { + font-size: 24px; + line-height: 36px; + margin: 0 0 5px; + } +} +.slider-banner .single-banner .banner-content .shop-link { + font-size: 14px; + width: 120px; + height: 40px; + margin: 21px 0 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .slider-banner .single-banner .banner-content .shop-link { + margin: 15px 0 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-banner .single-banner .banner-content .shop-link { + margin: 10px 0 0; + } +} +@media only screen and (max-width: 479px) { + .slider-banner .single-banner .banner-content .shop-link { + margin: 15px 0 0; + font-size: 12px; + width: 100px; + height: 35px; + } +} +.slider-banner .single-banner:hover img { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-banner .responsive-flex { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .slider-banner .responsive-flex .single-banner { + margin-top: 30px; + padding: 0 15px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .slider-banner .responsive-flex .single-banner img { + -webkit-transform: none; + transform: none; + } +} +@media only screen and (max-width: 767px) { + .slider-banner .responsive-flex .single-banner { + margin-top: 30px; + } +} +.single-blog { + position: relative; +} +.single-blog .blog-image { + overflow: hidden; + border-radius: 20px; +} +.single-blog .blog-image img { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.single-blog:hover .blog-image img { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.single-blog .blog-text { + padding: 30px 0 0 0; +} +.single-blog .blog-text .blog-heading { + margin: 15px 0 21px 0; + font-size: 30px; + font-weight: 400; + line-height: 43px; +} +@media only screen and (min-width: 1200px) and (max-width: 1599px) { + .single-blog .blog-text .blog-heading { + font-size: 30px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .single-blog .blog-text .blog-heading { + font-size: 24px; + line-height: 36px; + } +} +@media only screen and (max-width: 575px) { + .single-blog .blog-text .blog-heading { + font-size: 21px; + line-height: 32px; + } +} +.single-blog .blog-text .blog-heading .blog-heading-link { + color: #424242; +} +.single-blog .blog-text .blog-heading .blog-heading-link:hover { + color: #036eb8; +} +.single-blog .blog-text .blog-detail-text { + margin: 10px 0; +} +.single-blog .blog-text p { + margin-bottom: 25px; +} +.single-blog .blog-athor-date span + span { + margin-left: 15px; +} +.single-blog .blog-athor-date span { + color: #adadad; +} +.single-blog .blog-athor-date span.blog-date { + color: #424242; +} +.single-blog .blog-athor-date a { + color: #036eb8; + font-weight: 400; + display: inline-block; + font-size: 16px; + position: relative; + padding: 0 5px; +} +.single-blog .blog-athor-date a::after { + position: absolute; + top: auto; + bottom: 6px; + right: -8px; + width: 6px; + height: 6px; + content: ''; + background-color: #3d3d3d; + border-radius: 50%; +} +.single-blog .blog-athor-date a:hover { + color: #036eb8; +} +.single-blog .blog-athor-date a i { + color: #036eb8; + margin-right: 5px; +} +.blog-post-content-inner .blog-title { + font-size: 36px; + font-weight: 500; + margin: 15px 0 35px; + line-height: 1.4; + color: #2d2d2d; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .blog-post-content-inner .blog-title { + font-size: 28px; + } +} +@media only screen and (max-width: 767px) { + .blog-post-content-inner .blog-title { + font-size: 24px; + } +} +.blog-post-content-inner .blog-athor-date span + span { + margin-left: 30px; +} +.blog-post-content-inner .blog-athor-date span { + color: #adadad; + font-size: 18px; + font-weight: 500; +} +.blog-post-content-inner .blog-athor-date span.blog-date { + color: #424242; +} +.blog-post-content-inner .blog-athor-date a { + color: #036eb8; + font-weight: 400; + display: inline-block; + font-size: 18px; + position: relative; + padding: 0 5px; +} +.blog-post-content-inner .blog-athor-date a::after { + position: absolute; + top: auto; + bottom: 9px; + right: -19px; + width: 9px; + height: 9px; + content: ''; + background-color: #3d3d3d; + border-radius: 50%; +} +.blog-post-content-inner .blog-athor-date a:hover { + color: #036eb8; +} +.blog-post-content-inner .blog-athor-date a i { + color: #036eb8; + margin-right: 5px; +} +.blog-post-content-inner .title { + font-size: 30px; + color: #2d2d2d; + margin: 20px 0 30px; + display: block; + font-weight: 400; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .blog-post-content-inner .title { + font-size: 28px; + } +} +@media only screen and (max-width: 767px) { + .blog-post-content-inner .title { + font-size: 24px; + } +} +.blog-post-content-inner P { + color: #525252; + line-height: 30px; + margin-bottom: 40px; +} +.blog-post-content-inner P + p { + margin-bottom: 40px; +} +.single-post-content .quate-speech-area { + position: relative; + min-height: 360px; + z-index: 2; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin: 0 0 50px; + z-index: 2; +} +.single-post-content .quate-speech-area .speecker-img { + position: absolute; + top: 0; + left: auto; + right: 0; + max-width: 100%; +} +@media only screen and (max-width: 575px) { + .single-post-content .quate-speech-area .speecker-img { + right: auto; + left: 50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + } +} +.single-post-content p.quate-speech { + padding: 40px 45px; + font-size: 24px; + line-height: 40px; + font-style: italic; + color: #fff; + background-color: #036eb8; + position: relative; + text-align: center; + margin: 40px 0; + font-weight: 300; + border-radius: 5px; + max-width: 585px; + overflow: hidden; + z-index: 1; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .single-post-content p.quate-speech { + font-size: 18px; + line-height: 32px; + padding: 35px 20px; + max-width: 370px; + } +} +@media only screen and (max-width: 767px) { + .single-post-content p.quate-speech { + font-size: 18px; + line-height: 32px; + padding: 30px 25px; + max-width: 300px; + } +} +@media only screen and (max-width: 575px) { + .single-post-content p.quate-speech { + padding: 30px 20px; + font-size: 18px; + line-height: 28px; + max-width: 100%; + } +} +.single-post-content p.quate-speech::after { + position: absolute; + top: auto; + left: auto; + right: -7px; + bottom: -7px; + content: ''; + background-image: url(../images/blog-image/quate-icon.png); + background-repeat: no-repeat; + background-position: bottom right; + width: 72px; + height: 64px; + opacity: 0.1; +} +.single-post-content .title { + font-size: 30px; + color: #2d2d2d; + margin: 20px 0 30px; + display: block; + font-weight: 400; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .single-post-content .title { + font-size: 28px; + } +} +@media only screen and (max-width: 767px) { + .single-post-content .title { + font-size: 24px; + } +} +.single-post-content ul li + li { + margin-top: 20px; +} +.single-post-content ul li { + color: #525252; + font-weight: 500; + line-height: 30px; +} +.single-post-content P { + color: #525252; + line-height: 30px; + margin-bottom: 30px; +} +.single-post-content P + p { + margin-bottom: 40px; +} +.blog-sidebar .sidebar-widget { + background-color: #fff; + border-radius: 10px; + margin: 0 0 40px; + border: 1px solid #f3f3f3; +} +.blog-sidebar .sidebar-widget .sidebar-title { + font-size: 24px; + display: block; + text-transform: capitalize; + font-weight: 400; + color: #6c6c6c; + margin: 0 0 24px; + padding: 14px 0 15px 18px; + background: #f3f3f3; +} +.blog-sidebar .sidebar-widget + .sidebar-widget { + margin-top: 40px; +} +.blog-sidebar .search-widget { + padding-bottom: 23px; + padding-left: 20px; + padding-right: 30px; +} +.blog-sidebar form { + position: relative; +} +.blog-sidebar form input { + border: 1px solid #cfcfcf; + padding-right: 0; + font-size: 16px; + border-radius: 20px; + height: 45px; + padding-right: 55px; +} +.blog-sidebar form input:focus { + border-color: #036eb8; +} +.blog-sidebar form input::-webkit-input-placeholder { + color: #969696; +} +.blog-sidebar form input::-moz-placeholder { + color: #969696; +} +.blog-sidebar form input:-ms-input-placeholder { + color: #969696; +} +.blog-sidebar form input::-ms-input-placeholder { + color: #969696; +} +.blog-sidebar form input::placeholder { + color: #969696; +} +.blog-sidebar form button { + position: absolute; + width: 50px; + height: 45px; + left: auto; + right: 0; + font-size: 16px; + text-align: center; + background: 0; + color: #969696; + padding: 0; + border: 0; +} +.blog-sidebar form button:hover { + color: #036eb8; +} +.blog-sidebar .category-post { + padding-bottom: 23px; + padding-left: 20px; + padding-right: 30px; +} +.blog-sidebar .category-post li a { + color: #6a6a6a; + font-size: 16px; + display: inline-block; + margin-top: 18px; +} +.blog-sidebar .category-post li a:hover { + color: #036eb8; +} +.blog-sidebar .recent-post-widget { + padding-bottom: 23px; + padding-left: 20px; + padding-right: 30px; +} +.blog-sidebar .recent-post-widget .recent-single-post .thumb-side img { + width: 70px; + height: 70px; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; + border-radius: 10px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .blog-sidebar .recent-post-widget .recent-single-post .thumb-side img { + width: 70px; + } +} +.blog-sidebar .recent-post-widget .recent-single-post .media-side { + margin: 0 0 0 18px; + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + line-height: 1; +} +.blog-sidebar .recent-post-widget .recent-single-post .media-side a { + font-size: 17px; + font-weight: 400; + color: #424242; + line-height: 26px; +} +.blog-sidebar .recent-post-widget .recent-single-post .media-side a:hover { + color: #036eb8; +} +.blog-sidebar .recent-post-widget .recent-single-post .media-side span { + font-size: 16px; + color: #036eb8; + display: block; + margin: 0 0 10px; +} +.blog-sidebar .recent-post-widget .recent-single-post .media-side span i { + color: #036eb8; + margin-right: 5px; +} +.blog-sidebar .recent-post-widget .recent-single-post + .recent-single-post { + margin-top: 30px; +} +.blog-sidebar .sidebar-widget-tag { + padding-bottom: 23px; + padding-left: 20px; + padding-right: 30px; +} +.blog-sidebar .sidebar-widget-tag ul li { + line-height: 1; + display: inline-block; + margin: 8px 5px; +} +.blog-sidebar .sidebar-widget-tag ul li a { + display: block; + float: left; + padding: 8px 18px; + font-size: 16px; + color: #7e7e7e; + font-weight: 400; + border: 1px solid #f3f3f3; + border-radius: 5px; + background: 0; + text-transform: capitalize; +} +.blog-sidebar .sidebar-widget-tag ul li a:hover { + background-color: #036eb8; + color: #fff; + border-color: #036eb8; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .blog-sidebar .sidebar-widget-tag ul li a { + font-size: 14px; + } +} +.blog-post-audio { + line-height: 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .blog-post-audio.sidebar iframe { + height: 200px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .blog-post-audio.sidebar iframe { + height: 228px; + } +} +.blog-image img { + height: 100%; + width: 100%; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; +} +.blog-post-media { + overflow: hidden; +} +.blog-post-media .blog-image img { + height: 100%; + width: 100%; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; +} +.blog-post-media iframe { + border-radius: 20px; + height: 250px; + width: 100%; + position: relative; + border: 0; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .blog-post-media iframe { + height: 308px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .blog-post-media iframe { + height: 228px; + } +} +.blog-post-media .blog-post-video .thumb-image { + height: 100%; + width: 100%; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; +} +.blog-post-media .blog-post-video .icon { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.blog-post-media .blog-gallery .swiper-slide img { + width: 100%; + height: 100%; + -o-object-fit: cover; + object-fit: cover; + -o-object-position: center; + object-position: center; +} +.blog-single-tags-share { + padding-bottom: 60px; + line-height: 24px; + border-bottom: 2px solid #f3f3f3; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding-top: 20px; +} +@media only screen and (max-width: 575px) { + .blog-single-tags-share { + padding: 20px 20px; + } +} +.blog-single-tags-share .blog-single-tags { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +@media only screen and (max-width: 767px) { + .blog-single-tags-share .blog-single-tags { + margin-bottom: 30px; + } +} +.blog-single-tags-share span.title { + color: #2e2e2e; + font-size: 30px; +} +@media only screen and (max-width: 479px) { + .blog-single-tags-share span.title { + font-size: 20px; + } +} +.blog-single-tags-share span.title i { + margin-right: 30px; +} +@media only screen and (max-width: 479px) { + .blog-single-tags-share span.title i { + margin-right: 10px; + } +} +.blog-single-tags-share .tag-list { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.blog-single-tags-share .tag-list li { + display: inline-block; + margin-right: 20px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .blog-single-tags-share .tag-list li { + margin-right: 10px; + } +} +@media only screen and (max-width: 479px) { + .blog-single-tags-share .tag-list li { + margin-right: 10px; + } +} +.blog-single-tags-share .tag-list li a { + display: block; + float: left; + padding: 4px 18px; + font-size: 16px; + color: #7e7e7e; + font-weight: 400; + border: 1px solid #f3f3f3; + border-radius: 5px; + background: 0; + text-transform: capitalize; +} +@media only screen and (max-width: 479px) { + .blog-single-tags-share .tag-list li a { + padding: 4px 10px; + } +} +.blog-single-tags-share .tag-list li a:hover { + background-color: #036eb8; + color: #fff; + border-color: #036eb8; +} +.blog-single-tags-share .social li { + display: inline-block; + margin-left: 10px; +} +.blog-single-tags-share .social li a { + width: 36px; + height: 36px; + color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + font-size: 16px; + background-color: #000; + border-radius: 5px; +} +.blog-single-tags-share .social li a:hover { + background-color: #036eb8; +} +.comment-area { + line-height: 24px; + margin-top: 100px; + background-color: #fff; + border-radius: 10px; + border: 1px solid #f3f3f3; +} +@media only screen and (max-width: 767px) { + .comment-area { + margin-top: 50px; + } +} +.comment-area .comment-heading { + font-size: 24px; + display: block; + text-transform: capitalize; + font-weight: 400; + color: #6c6c6c; + margin: 0 0 50px; + padding: 14px 0 15px 18px; + background: #f3f3f3; +} +@media only screen and (max-width: 575px) { + .comment-area .comment-heading { + font-size: 24px; + } +} +.comment-area .single-review { + padding-left: 30px; + padding-right: 30px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin: 0 0 60px; +} +@media only screen and (max-width: 767px) { + .comment-area .single-review { + display: block; + } +} +.comment-area .single-review .review-img { + -webkit-box-flex: 0; + -ms-flex: 0 0 90px; + flex: 0 0 90px; + margin: 0 15px 0 0; +} +.comment-area .single-review .review-img img { + border-radius: 10px; +} +@media only screen and (max-width: 767px) { + .comment-area .single-review .review-img { + margin: 0 0 20px 0; + } +} +.comment-area .single-review .review-content { + padding-left: 15px; +} +@media only screen and (max-width: 767px) { + .comment-area .single-review .review-content { + padding-left: 0; + } +} +.comment-area .single-review .review-content .review-top-wrap { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 0 0 20px; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.comment-area .single-review .review-content .review-top-wrap .review-left { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.comment-area .single-review .review-content .review-top-wrap .review-left .review-name .title { + font-size: 18px; + font-weight: 500; + color: #333; +} +@media only screen and (max-width: 767px) { + .comment-area .single-review .review-content .review-top-wrap .review-left .review-name .title { + font-size: 20px; + } +} +.comment-area .single-review .review-content .review-top-wrap .review-left .review-name span { + font-weight: 400; + color: #666; +} +.comment-area .single-review .review-content .review-top-wrap .review-left a { + color: #474747; +} +.comment-area .single-review .review-content .review-top-wrap .review-left a:hover { + color: #036eb8; +} +.comment-area .single-review .review-content p { + margin: 0; + line-height: 30px; + color: #525252; +} +.comment-area .single-review .review-content .review-left a { + font-size: 16px; + color: #343434; + text-transform: uppercase; + font-weight: 400; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + z-index: 1; + position: relative; + overflow: hidden; + -webkit-box-shadow: none; + box-shadow: none; + margin-top: 20px; +} +.comment-area .single-review .review-content .review-left a:hover { + color: #036eb8; +} +.comment-area .single-review .review-content .review-left a i { + font-size: 14px; + margin-right: 5px; +} +.comment-area .single-review.child-review { + margin-left: 70px; +} +@media only screen and (max-width: 767px) { + .comment-area .single-review.child-review { + margin-left: 0; + } +} +.blog-comment-form { + line-height: 24px; + margin-top: 100px; + background-color: #fff; + border-radius: 10px; + border: 1px solid #f3f3f3; +} +@media only screen and (max-width: 767px) { + .blog-comment-form { + margin-top: 50px; + } +} +.blog-comment-form .comment-heading { + font-size: 24px; + display: block; + text-transform: capitalize; + font-weight: 400; + color: #6c6c6c; + margin: 0 0 50px; + padding: 14px 0 15px 18px; + background: #f3f3f3; +} +@media only screen and (max-width: 575px) { + .blog-comment-form .comment-heading { + font-size: 24px; + } +} +.blog-comment-form .form-inner { + padding-left: 30px; + padding-right: 30px; + padding-bottom: 60px; +} +.blog-comment-form .single-form { + margin: 0 0 30px; +} +.blog-comment-form .single-form input { + border: 1px solid #d7d7d7; + font-size: 14px; + font-style: italic; +} +.blog-comment-form .single-form input::-webkit-input-placeholder { + color: #999; +} +.blog-comment-form .single-form input::-moz-placeholder { + color: #999; +} +.blog-comment-form .single-form input:-ms-input-placeholder { + color: #999; +} +.blog-comment-form .single-form input::-ms-input-placeholder { + color: #999; +} +.blog-comment-form .single-form input::placeholder { + color: #999; +} +.blog-comment-form .single-form input:focus { + border-color: #036eb8; +} +.blog-comment-form .single-form textarea { + height: 180px; + border: 1px solid #d7d7d7; +} +.blog-comment-form .single-form textarea:focus { + border-color: #036eb8; +} +.blog-comment-form .single-form button { + font-size: 14px; + letter-spacing: 2px; + line-height: 1; + font-weight: 400; + text-transform: uppercase; +} +.pro-pagination-style li { + display: inline-block; + height: 40px; + line-height: 40px; + background: #fff; + display: inline-block; + width: 40px; + border-radius: 5px; + text-align: center; + vertical-align: top; + font-size: 16px; +} +.pro-pagination-style li + li { + margin-left: 10px; +} +.pro-pagination-style a { + font-weight: 400; + color: #d5d5d5; + padding: 0; + height: 40px; + line-height: 40px; + background: #fff; + display: inline-block; + width: 40px; + border-radius: 5px; + text-align: center; + vertical-align: top; + font-size: 16px; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; + border-color: #d5d5d5; + font-weight: 500; +} +.pro-pagination-style a .fa { + font-size: 24px; +} +.pro-pagination-style li.active { + color: #fff; + background-color: #036eb8; + -webkit-box-shadow: 0 5px 15px 0 rgba(234, 170, 133, 0.5); + box-shadow: 0 5px 15px 0 rgba(234, 170, 133, 0.5); + -webkit-transform: translateY(-1px); + transform: translateY(-1px); + border-color: #036eb8; +} +.pro-pagination-style li:hover { + color: #fff; + background-color: #036eb8; + -webkit-box-shadow: 0 5px 15px 0 rgba(234, 170, 133, 0.5); + box-shadow: 0 5px 15px 0 rgba(234, 170, 133, 0.5); + -webkit-transform: translateY(-1px); + transform: translateY(-1px); + border-color: #036eb8; +} +.feature-area { + position: relative; + z-index: 1; + padding-bottom: 30px; +} +.feature-area.mt-n-65px { + margin-top: -65px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .feature-area.mt-n-65px { + margin-top: 65px; + } +} +@media only screen and (max-width: 767px) { + .feature-area.mt-n-65px { + margin-top: 65px; + } +} +.feature-wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + position: relative; + -webkit-box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.08); + box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.08); + border-radius: 10px; + z-index: 1; +} +.feature-wrapper::after { + position: absolute; + top: 15px; + left: 0; + width: 95%; + height: 100%; + -webkit-box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.04); + box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.04); + content: ''; + border-radius: 10px; + margin: auto; + right: 0; + z-index: -1; +} +.feature-wrapper::before { + position: absolute; + top: 30px; + left: 0; + width: 90%; + height: 100%; + -webkit-box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.02); + box-shadow: 0 24px 29px 0 rgba(0, 0, 0, 0.02); + content: ''; + border-radius: 10px; + margin: auto; + right: 0; + z-index: -2; +} +.feature-wrapper .single-feture-col { + padding-right: 15px; + padding-left: 15px; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333%; +} +@media only screen and (min-width: 1200px) and (max-width: 1599px), only screen and (min-width: 992px) and (max-width: 1199px) { + .feature-wrapper .single-feture-col { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333%; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .feature-wrapper .single-feture-col { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50%; + } +} +@media only screen and (max-width: 767px) { + .feature-wrapper .single-feture-col { + -ms-flex-negative: 0; + flex-shrink: 0; + width: 100%; + max-width: 100%; + } +} +.feature-wrapper .single-feture-col + .single-feture-col { + position: relative; +} +.feature-wrapper .single-feture-col + .single-feture-col::after { + position: absolute; + top: 50%; + left: -7.5px; + width: 2px; + height: 60px; + background-color: #e7e7e7; + content: ''; + margin-top: -30px; +} +@media only screen and (max-width: 767px) { + .feature-wrapper .single-feture-col + .single-feture-col::after { + display: none; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .feature-wrapper .single-feture-col + .single-feture-col + .single-feture-col::after { + display: none; + } +} +.single-feature { + padding: 30px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #fff; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .single-feature { + padding: 12px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .single-feature { + padding: 25px; + } +} +@media only screen and (max-width: 479px) { + .single-feature { + padding: 20px; + } +} +.single-feature .feature-icon { + width: 79px; + height: 70px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 50%; + margin-right: 20px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (max-width: 479px) { + .single-feature .feature-icon { + margin-right: 20px; + } +} +.single-feature .feature-content { + width: calc(100% - 99px); +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (max-width: 479px) { + .single-feature .feature-content { + width: calc(100% - 90px); + } +} +.single-feature .feature-content .title { + font-size: 24px; + color: #2e2e2e; + font-weight: 400; + margin: 0 0 3px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), + only screen and (min-width: 768px) and (max-width: 991px), + only screen and (max-width: 479px) { + .single-feature .feature-content .title { + font-size: 20px; + } +} +.single-feature .feature-content .sub-title { + font-size: 16px; + color: #848484; + font-weight: 400; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), + only screen and (min-width: 768px) and (max-width: 991px), + only screen and (max-width: 479px) { + .single-feature .feature-content .sub-title { + font-size: 14px; + } +} +.single-feature img { + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.single-feature:hover img { + -webkit-transform: scale(0.9) rotate(3deg); + transform: scale(0.9) rotate(3deg); +} +.slider-nav-style-1 { + position: relative; +} +.slider-nav-style-1 .swiper-button-next:after { + content: ''; +} +.slider-nav-style-1 .swiper-button-prev:after { + content: ''; +} +.slider-nav-style-1 .swiper-button-next:after, +.slider-nav-style-1 .swiper-button-prev:after { + font-family: Pe-icon-7-stroke; + font-size: 40px; + text-transform: none !important; + letter-spacing: 0; + text-transform: none; + font-variant: initial; + line-height: 1; + outline: 0; +} +@media only screen and (max-width: 575px) { + .slider-nav-style-1 .swiper-button-next:after, + .slider-nav-style-1 .swiper-button-prev:after { + font-size: 24px; + } +} +.slider-nav-style-1.small-nav .swiper-button-next:after, +.slider-nav-style-1.small-nav .swiper-button-prev:after { + font-size: 30px; +} +.small-nav.slider-nav-style-1.small-nav .swiper-button-next:after, +.small-nav.slider-nav-style-1.small-nav .swiper-button-prev:after { + font-size: 24px; +} +.slider-nav-style-1 .swiper-buttons .swiper-button-next, +.slider-nav-style-1 .swiper-buttons .swiper-button-prev { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + z-index: 9; + width: 50px; + height: 50px; + line-height: 50px; + opacity: 0; + visibility: hidden; + -webkit-transition: all 0.3s; + transition: all 0.3s; + margin: auto; + border-radius: 50%; + text-align: center; + -webkit-box-shadow: 0 3px 25.5px 4.5px rgba(0, 0, 0, 0.06); + box-shadow: 0 3px 25.5px 4.5px rgba(0, 0, 0, 0.06); + color: #000; + background-color: #fff; +} +@media only screen and (max-width: 575px) { + .slider-nav-style-1 .swiper-buttons .swiper-button-next, + .slider-nav-style-1 .swiper-buttons .swiper-button-prev { + width: 35px; + height: 35px; + line-height: 35px; + } +} +.slider-nav-style-1 .swiper-buttons .swiper-button-next:hover, +.slider-nav-style-1 .swiper-buttons .swiper-button-prev:hover { + background-color: #036eb8; + color: #fff; + -webkit-box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.3); + box-shadow: 0 5px 15px 0 rgba(0, 0, 0, 0.3); +} +.slider-nav-style-1.small-nav .swiper-buttons .swiper-button-next, +.slider-nav-style-1.small-nav .swiper-buttons .swiper-button-prev { + width: 40px; + height: 40px; + line-height: 40px; +} +.slider-nav-style-1.small-nav .swiper-buttons .swiper-button-next:hover, +.slider-nav-style-1.small-nav .swiper-buttons .swiper-button-prev:hover { + background-color: #036eb8; + color: #fff; +} +.slider-nav-style-1 .swiper-button-prev { + outline: 0; + right: auto; + left: 30px; +} +@media only screen and (max-width: 767px) { + .slider-nav-style-1 .swiper-button-prev { + left: 15px; + } +} +.slider-nav-style-1.small-nav .swiper-button-prev { + outline: 0; + right: auto; + left: 10px; +} +@media only screen and (max-width: 767px) { + .slider-nav-style-1.small-nav .swiper-button-prev { + left: 5px; + } +} +.slider-nav-style-1 .swiper-button-next { + outline: 0; + left: auto; + right: 30px; +} +@media only screen and (max-width: 767px) { + .slider-nav-style-1 .swiper-button-next { + right: 15px; + } +} +.slider-nav-style-1.small-nav .swiper-button-next { + outline: 0; + left: auto; + right: 10px; +} +@media only screen and (max-width: 767px) { + .slider-nav-style-1.small-nav .swiper-button-next { + right: 5px; + } +} +.slider-nav-style-1:hover .swiper-button-next, +.slider-nav-style-1:hover .swiper-button-prev { + opacity: 1; + visibility: visible; +} +.slider-nav-style-1:hover .swiper-button-next { + right: 50px; +} +@media only screen and (max-width: 575px) { + .slider-nav-style-1:hover .swiper-button-next { + right: 20px; + } +} +.slider-nav-style-1:hover .swiper-button-prev { + left: 50px; +} +@media only screen and (max-width: 575px) { + .slider-nav-style-1:hover .swiper-button-prev { + left: 20px; + } +} +.slider-nav-style-1.small-nav:hover .swiper-button-next { + right: 20px; +} +.slider-nav-style-1.small-nav:hover .swiper-button-prev { + left: 20px; +} + +.breadcrumb-area { + position: relative; +} +.breadcrumb-area img { + max-width: 100%; +} +.breadcrumb-title { + position: absolute; + left: 12.5%; + top: 25%; + font-weight: 700; + font-size: 64px; + color: #fff; + margin: 0; +} +@media only screen and (max-width: 1366px) { + .breadcrumb-title { + left: 12.5%; + top: 25%; + font-size: 48px; + } +} +@media only screen and (max-width: 750px) { + .breadcrumb-title { + left: 2.5%; + top: 10%; + font-size: 32px; + } + .md-blank { + display: none; + } +} +@media only screen and (max-width: 767px) { + .breadcrumb-area .breadcrumb-title { + font-size: 24px; + } +} +.breadcrumb-list li { + display: inline-block; + font-size: 14px; + font-weight: 500; + text-transform: capitalize; + margin: 24px 0 20px; +} +.breadcrumb-list span { + color: #b2b2b2; + padding: 0 8px; +} +.breadcrumb-list li a { + color: #4a4a4a; +} +.breadcrumb-list li a:hover { + color: #b2b2b2; +} +.breadcrumb-list li.active { + color: #b2b2b2; +} +.breadcrumb-item + .breadcrumb-item { + padding-left: 5px; +} + +.page-pagination li { + display: inline-block; +} +.page-pagination li a { + font-weight: 500; + padding: 0 10px; + display: block; + text-align: center; + line-height: 41px; + min-width: 41px; + height: 41px; + text-transform: uppercase; + color: #ababab; + letter-spacing: 2px; + border-radius: 5px; +} +.page-pagination li a.current { + background: #f6f5f9; + color: #036eb8; +} +.page-pagination li a:hover { + color: #036eb8; +} +.deal-bg { + position: relative; + background-color: #e7e7e7; + background-position: center; + background-size: cover; + background-repeat: no-repeat; +} +.deal-bg.ptb-80px { + padding: 66px 0 80px; +} +.deal-bg-2 { + border-radius: 10px; + margin: 0 30px; +} +@media only screen and (max-width: 479px) { + .deal-bg-2 { + margin: 0; + } +} +.deal-image { + position: absolute; + left: auto; + right: 168px; + bottom: 28px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .deal-image { + right: 100px; + bottom: 0; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .deal-image { + right: 0; + width: 50%; + bottom: 0; + } +} +@media only screen and (max-width: 767px) { + .deal-image { + margin: auto; + position: initial; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } +} +.deal-image .discount { + width: 103px; + height: 103px; + color: #fff; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + background: #036eb8; + border-radius: 50%; + position: absolute; + bottom: 60px; + right: -30px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .deal-image .discount { + right: 30px; + } +} +@media only screen and (max-width: 767px) { + .deal-image .discount { + bottom: 145px; + right: auto; + left: 68%; + } +} +.deal-image .discount h3 { + color: #fff; + font-weight: 500; +} +.deal-wrapper { + width: 1440px; + margin: auto; + line-height: 1; + position: absolute; + left: 12.5%; + color: #fff; + top: 15%; +} +.deal-inner img { + max-width: 100%; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .deal-wrapper { + width: 40%; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .deal-wrapper { + width: 50%; + padding-left: 40px; + } +} +@media only screen and (max-width: 767px) { + .deal-wrapper { + margin: auto; + width: 100%; + margin: 0 0 50px; + } +} +@media only screen and (max-width: 479px) { + .deal-wrapper { + padding-left: 30px; + } +} +.deal-wrapper p { + font-size: 32px; + color: #fff; +} +.deal-wrapper .title { + font-size: 64px; + color: #fff; + font-weight: 600; + margin: 0; + line-height: 82px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .deal-wrapper .title { + font-size: 48px; + line-height: 60px; + } +} +@media only screen and (max-width: 767px) { + .deal-wrapper .title { + font-size: 30px; + line-height: 40px; + } + .deal-wrapper p { + font-size: 20px; + } +} +@media only screen and (max-width: 479px) { + .deal-wrapper { + left: 3%; + } + .deal-wrapper .title { + font-size: 20px; + line-height: 30px; + } + .deal-wrapper p { + font-size: 16px; + } +} +.deal-wrapper .price { + font-size: 30px; + font-weight: 500; + margin-bottom: 55px; + margin-top: 22px; + color: #4a4a4a; + display: block; +} +@media only screen and (max-width: 575px) { + .deal-wrapper .price { + font-size: 24px; + margin-top: 15px; + margin-bottom: 40px; + } +} +@media only screen and (max-width: 479px) { + .deal-wrapper .price { + font-size: 20px; + margin-top: 10px; + margin-bottom: 30px; + } +} +.deal-wrapper .price .new { + color: #036eb8; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .deal-wrapper .price { + font-size: 24px; + margin-bottom: 40px; + margin-top: 15px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .deal-wrapper .price { + font-size: 20px; + margin-bottom: 40px; + margin-top: 20px; + } +} +.deal-wrapper a.btn-primary { + width: 140px; + height: 40px; + font-size: 14px; + text-transform: uppercase; + font-weight: 400; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (max-width: 767px) { + .testimonial-area.pb-40px { + padding-bottom: 0; + } +} +.testimonial-wrapper { + max-width: 570px; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: auto; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-content { + text-align: center; + margin-top: 45px; + position: relative; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-content::after { + position: absolute; + top: 50%; + left: 50%; + content: ''; + background-image: url(../images/testimonial-image/quate-1.png); + background-repeat: no-repeat; + background-position: center; + width: 136px; + height: 117px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-top: -58.5px; + margin-left: -68px; + z-index: -1; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-content p { + font-size: 30px; + line-height: 48px; + color: #565656; + font-style: italic; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-content p { + font-size: 24px; + line-height: 38px; + } +} +@media only screen and (max-width: 767px) { + .testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-content p { + font-size: 24px; + line-height: 38px; + } +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-author { + line-height: 1; + margin: 45px 0 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-author .author-img { + position: relative; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-author .author-name .name { + color: #393939; + font-size: 18px; + margin: 0 0 10px; + font-weight: 500; + text-transform: uppercase; +} +.testimonial-wrapper .swiper-wrapper .swiper-slide .testi-inner .testi-author .author-name .title { + color: grey; + font-size: 18px; + font-weight: 300; + text-transform: uppercase; +} +.testimonial-wrapper .swiper-button-next:after, +.testimonial-wrapper .swiper-button-prev:after { + font-family: FontAwesome; + font-size: 24px; + color: #424242; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.testimonial-wrapper .swiper-button-prev:after { + content: ''; +} +.testimonial-wrapper .swiper-button-next:after { + content: ''; +} +.testimonial-wrapper .swiper-button-prev { + left: 25%; +} +@media only screen and (max-width: 575px) { + .testimonial-wrapper .swiper-button-prev { + left: 15%; + } +} +.testimonial-wrapper .swiper-button-next { + right: 25%; +} +@media only screen and (max-width: 575px) { + .testimonial-wrapper .swiper-button-next { + right: 15%; + } +} +.testimonial-wrapper .swiper-button-next, +.testimonial-wrapper .swiper-button-prev { + top: 60px; +} +.testimonial-wrapper .swiper-button-next:hover:after, +.testimonial-wrapper .swiper-button-prev:hover:after { + color: #036eb8; +} +.brand-slider { + border: 1px solid #e1e1e1; +} +.brand-slider .brand-slider-item { + position: relative; +} +.brand-slider .brand-slider-item::after { + position: absolute; + top: -20px; + left: 0; + width: 1px; + height: 250px; + content: ''; + background-color: #e1e1e1; +} +.brand-slider .brand-slider-item a { + padding: 48px 0; + display: inline-block; +} +.brand-slider .brand-slider-item img { + filter: gray; + -webkit-filter: grayscale(1); + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; + margin: auto; + opacity: 0.5; +} +.brand-slider .brand-slider-item:hover img { + filter: none; + -webkit-filter: grayscale(0); + opacity: 1; +} +.brand-slider .brand-slider-item.swiper-slide-active::after { + display: none; +} +.modal-backdrop { + background-color: transparent; +} +.modal { + overflow: hidden !important; + padding-right: 0 !important; +} +.modal::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + background-color: rgba(28, 28, 28, 0.5); + width: 100%; + height: 0; + padding-bottom: 100%; + border-radius: 100%; + -webkit-transform: scale(0.04) translateY(9999px); + transform: scale(0.04) translateY(9999px); + overflow: hidden; + z-index: 9; +} +.modal .modal-overlay { + overflow: auto; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + width: 100%; + height: 100%; + position: relative; +} +.modal .modal-dialog { + top: 0 !important; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + -webkit-transition: all 0.55s ease, opacity 0.35s ease-in; + transition: all 0.55s ease, opacity 0.35s ease-in; + background-color: transparent; + width: 100%; + opacity: 0; + margin: auto; + z-index: 9999; +} +.modal.show::before { + -webkit-animation: menu-animation 0.8s ease-out forwards; + animation: menu-animation 0.8s ease-out forwards; + -webkit-transform: scale(2) translateY(0); + transform: scale(2) translateY(0); +} +.modal.show .modal-dialog { + -webkit-transform: translateY(0); + transform: translateY(0); + -webkit-transition-delay: 0.7s; + transition-delay: 0.7s; + opacity: 1; + top: 50%; +} +.modal.show .close-btn { + -webkit-transition-delay: 0.7s; + transition-delay: 0.7s; + opacity: 1; + top: 50px; +} +.modal.popup-login-style .modal-dialog, +.modal.popup-search-style .modal-dialog { + max-width: 400px; + border-radius: 10px; + -webkit-box-shadow: 0 0 41px 1px rgba(0, 0, 0, 0.46); + box-shadow: 0 0 41px 1px rgba(0, 0, 0, 0.46); +} +@media only screen and (max-width: 575px) { + .modal.popup-login-style .modal-dialog, + .modal.popup-search-style .modal-dialog { + max-width: 380px; + } +} +@media only screen and (max-width: 479px) { + .modal.popup-login-style .modal-dialog, + .modal.popup-search-style .modal-dialog { + max-width: 330px; + } +} +.modal.popup-login-style .modal-dialog .modal-content, +.modal.popup-search-style .modal-dialog .modal-content { + background: #fff; +} +.modal.popup-login-style .modal-dialog .modal-content .modal-body, +.modal.popup-search-style .modal-dialog .modal-content .modal-body { + padding: 40px 20px 45px; +} +.close-btn { + position: absolute; + top: 0; + right: 50px; + color: #fff; + z-index: 9; + width: 40px; + height: 40px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 30px; + background: 0; + border: 1px solid #fff; + opacity: 0; + -webkit-transition: 0.5s; + transition: 0.5s; + padding: 0; +} +.login-content h2 { + font-weight: 700; + color: #fff; + font-size: 30px; + text-align: center; + margin: 0 0 48px; +} +.login-content h3 { + font-weight: 600; + color: #fff; + font-size: 14px; + text-transform: uppercase; + margin: 0 0 29px; +} +.login-content form > input { + width: 100%; + background-color: #fff; + padding: 1px 20px; + color: #000; + line-height: 47px; + border: 0; + border-radius: 5px; + margin-bottom: 25px; +} +.login-content form > input::-webkit-input-placeholder { + color: #000; + opacity: 1; +} +.login-content form > input::-moz-input-placeholder { + color: #000; + opacity: 1; +} +.login-content form .remember-forget-wrap { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 0 0 32px; +} +.login-content form .remember-forget-wrap .remember-wrap { + position: relative; +} +.login-content form .remember-forget-wrap .remember-wrap input { + position: absolute; + cursor: pointer; + z-index: 999; + width: 20px; + height: 20px; +} +.login-content form .remember-forget-wrap .remember-wrap p { + margin: 0 0 0 30px; + color: #fff; + font-size: 14px; +} +.login-content form .remember-forget-wrap .remember-wrap p a { + color: #036eb8; +} +.login-content form .remember-forget-wrap .forget-wrap a { + font-size: 14px; + color: #036eb8; +} +.login-content form button { + color: #fff; + font-weight: 600; + -webkit-transition: all 0.5s; + transition: all 0.5s; + background-color: #036eb8; + border-radius: 5px; + padding: 16px 20px; + border: 0; + text-transform: uppercase; + line-height: 1; +} +.login-content form button:hover { + background-color: #000; +} +.login-content form .member-register { + margin: 27px 0 0; +} +.login-content form .member-register p { + color: #999; + text-transform: uppercase; + font-weight: 600; + margin: 0; + font-size: 14px; +} +.login-content form .member-register p a { + color: #fff; + display: inline-block; + margin-left: 5px; + line-height: 1; + padding: 0 0 1px; + border-bottom: 1px solid #fff; +} +.modal .submit-btn { + position: absolute; + top: 0; + right: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + width: 60px; + height: 50px; + background: #036eb8; + color: #fff; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + border: 0; + outline: 0; + font-size: 20px; + border-radius: 0 5px 5px 0; + -webkit-transition: all 0.3s ease 0s; + transition: all 0.3s ease 0s; +} +.modal .submit-btn:hover { + background-color: #000; +} +.modal h2 { + font-size: 24px; + font-weight: 700; + color: #333; + margin: 0 0 30px; +} +.modal.fade .modal-dialog { + -webkit-transition-delay: 0.7s; + transition-delay: 0.7s; +} +.modal-2.fade .modal-dialog { + -webkit-transition-delay: 0.7s; + transition-delay: 0.7s; + -webkit-transition: opacity 0.7s; + transition: opacity 0.7s; +} +.modal-2.fade.show::before { + -webkit-animation: menu-animation 0.8s ease-out forwards; + animation: menu-animation 0.8s ease-out forwards; + -webkit-transform: scale(2) translateY(0); + transform: scale(2) translateY(0); +} +.modal-2.fade.show .modal-dialog { + -webkit-transform: translateY(0); + transform: translateY(0); + -webkit-transition-delay: 0.7s; + transition-delay: 0.7s; + opacity: 1; + top: 50%; +} +.modal-2 h2 { + color: #747474; + font-size: 30px; + text-transform: capitalize; + line-height: 1; + font-weight: 500; + margin: 0 0 18px 0; +} +@media only screen and (max-width: 479px) { + .modal-2 h2 { + font-size: 24px; + } +} +@media only screen and (max-width: 479px) { + .modal-2 .product-details-content .pro-details-quality .pro-details-cart .add-cart { + font-size: 12px; + } +} +.modal-open .modal-2 { + overflow-x: hidden !important; + overflow-y: auto !important; +} +@-webkit-keyframes menu-animation { + 0% { + opacity: 0; + -webkit-transform: scale(0.04) translateY(300%); + transform: scale(0.04) translateY(300%); + } + 40% { + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + -webkit-transition: ease-out; + transition: ease-out; + } + 40% { + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + } + 60% { + opacity: 1; + -webkit-transform: scale(0.02) translateY(0); + transform: scale(0.02) translateY(0); + } + 61% { + opacity: 1; + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + } + 99.9% { + opacity: 1; + height: 0; + padding-bottom: 100%; + border-radius: 100%; + } + 100% { + opacity: 1; + -webkit-transform: scale(2) translateY(0); + transform: scale(2) translateY(0); + height: 100%; + padding-bottom: 0; + border-radius: 0; + } +} +@keyframes menu-animation { + 0% { + opacity: 0; + -webkit-transform: scale(0.04) translateY(300%); + transform: scale(0.04) translateY(300%); + } + 40% { + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + -webkit-transition: ease-out; + transition: ease-out; + } + 40% { + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + } + 60% { + opacity: 1; + -webkit-transform: scale(0.02) translateY(0); + transform: scale(0.02) translateY(0); + } + 61% { + opacity: 1; + -webkit-transform: scale(0.04) translateY(0); + transform: scale(0.04) translateY(0); + } + 99.9% { + opacity: 1; + height: 0; + padding-bottom: 100%; + border-radius: 100%; + } + 100% { + opacity: 1; + -webkit-transform: scale(2) translateY(0); + transform: scale(2) translateY(0); + height: 100%; + padding-bottom: 0; + border-radius: 0; + } +} +/*list列表*/ +/* 必要布局样式css */ +.cation-bg { + background: #f5f5f5; +} +.cation-content { + margin: 0 auto; + padding: 32px 0 24px; +} +@media only screen and (max-width: 750px) { + .cation-bg { + display: none; + } +} + +.cation-middle { + line-height: 48px; + background: #fff; + padding: 10px 20px 10px 30px; + font-size: 14px; + border: 1px solid #eee; +} + +.cation-list { + overflow: hidden; +} + +.cation-list dt { + float: left; + width: 64px; + font-weight: 100; + line-height: 48px; + position: relative; + color: #999; + text-align: center; +} + +.cation-list dd { + border-bottom: 1px dotted #e0e0e0; + margin-left: 64px; + overflow: hidden; +} + +.cation-list dd a { + color: #333; + font-size: 14px; + line-height: 14px; + height: 14px; + float: left; + border-right: 1px solid #e0e0e0; + padding: 0 18px; + margin: 17px 0; +} +.cation-all dd a.on, +.cation-list dd a.on, +.cation-list a:hover, +.cation-all a:hover { + color: #036eb8; +} + +.cation-list dd a:last-child { + border-right: 0 none; +} + +.cation-list:last-of-type dd { + border-bottom: 0 none; +} + +.cation-all { + overflow: hidden; + background: #fff; + border-bottom: 1px solid #eee; +} + +.cation-all dt { + float: left; + width: 64px; + font-weight: 100; + line-height: 48px; + position: relative; + color: #999; + text-align: center; + border-bottom: 1px dotted #e0e0e0; +} + +.cation-all dd { + overflow: hidden; +} + +.cation-all dd a { + color: #333; + font-size: 14px; + line-height: 14px; + height: 14px; + float: left; + border-right: 1px solid #e0e0e0; + padding: 0 18px; + margin: 17px 0; +} +.list-bg-non { + background: #fff; +} +.list-non { + padding: 100px 0; + font-size: 20px; + text-align: center; +} +/*07/27修改*/ +@media only screen and (max-width: 767px) { + .header-logo img { + width: 80%; + } +} +/*07/29修改*/ +@media only screen and (max-width: 575px) { + .img-none { + display: none; + } + .row { + --bs-gutter-x: 0; + } +} diff --git a/public/assets/css/vendor/vendor.min.css b/public/assets/css/vendor/vendor.min.css new file mode 100644 index 0000000..9b56973 --- /dev/null +++ b/public/assets/css/vendor/vendor.min.css @@ -0,0 +1,12348 @@ +@charset "UTF-8"; /*! + * Bootstrap v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +:root { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-primary: #0d6efd; + --bs-secondary: #6c757d; + --bs-success: #198754; + --bs-info: #0dcaf0; + --bs-warning: #ffc107; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-font-sans-serif: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', 'Liberation Sans', sans-serif, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); +} +*, +::after, +::before { + box-sizing: border-box; +} +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: none; + } +} +body { + margin: 0; + font-family: var(--bs-font-sans-serif); + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: transparent; +} +hr { + margin: 1rem 0; + color: inherit; + background-color: currentColor; + border: 0; + opacity: 0.25; +} +hr:not([size]) { + height: 1px; +} +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; +} +.h1, +h1 { + font-size: calc(1.375rem+1.5vw); +} +@media (min-width: 1200px) { + .h1, + h1 { + font-size: 2.5rem; + } +} +.h2, +h2 { + font-size: calc(1.325rem+0.9vw); +} +@media (min-width: 1200px) { + .h2, + h2 { + font-size: 2rem; + } +} +.h3, +h3 { + font-size: calc(1.3rem+0.6vw); +} +@media (min-width: 1200px) { + .h3, + h3 { + font-size: 1.75rem; + } +} +.h4, +h4 { + font-size: calc(1.275rem+0.3vw); +} +@media (min-width: 1200px) { + .h4, + h4 { + font-size: 1.5rem; + } +} +.h5, +h5 { + font-size: 1.25rem; +} +.h6, +h6 { + font-size: 1rem; +} +p { + margin-top: 0; + margin-bottom: 1rem; +} +abbr[data-bs-original-title], +abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} +ol, +ul { + padding-left: 2rem; +} +dl, +ol, +ul { + margin-top: 0; + margin-bottom: 1rem; +} +ol ol, +ol ul, +ul ol, +ul ul { + margin-bottom: 0; +} +b, +strong { + font-weight: bolder; +} +.small, +small { + font-size: 0.875em; +} +.mark, +mark { + padding: 0.2em; + background-color: #fcf8e3; +} +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +a { + color: #0d6efd; + text-decoration: underline; +} +a:hover { + color: #0a58ca; +} +a:not([href]):not([class]), +a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none; +} +code, +kbd, +pre, +samp { + font-family: var(--bs-font-monospace); + font-size: 1em; + direction: ltr; + unicode-bidi: bidi-override; +} +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: 0.875em; +} +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} +code { + font-size: 0.875em; + color: #d63384; + word-wrap: break-word; +} +a > code { + color: inherit; +} +kbd { + padding: 0.2rem 0.4rem; + font-size: 0.875em; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} +kbd kbd { + padding: 0; + font-size: 1em; + font-weight: 700; +} +figure { + margin: 0 0 1rem; +} +img, +svg { + vertical-align: middle; +} +table { + caption-side: bottom; + border-collapse: collapse; +} +caption { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: #6c757d; + text-align: left; +} +th { + text-align: inherit; + text-align: -webkit-match-parent; +} +tbody, +td, +tfoot, +th, +thead, +tr { + border-color: inherit; + border-style: solid; + border-width: 0; +} +label { + display: inline-block; +} +button { + border-radius: 0; +} +button:focus:not(:focus-visible) { + outline: 0; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +button, +select { + text-transform: none; +} +[role='button'] { + cursor: pointer; +} +select { + word-wrap: normal; +} +select:disabled { + opacity: 1; +} +[list]::-webkit-calendar-picker-indicator { + display: none; +} +[type='button'], +[type='reset'], +[type='submit'], +button { + -webkit-appearance: button; +} +[type='button']:not(:disabled), +[type='reset']:not(:disabled), +[type='submit']:not(:disabled), +button:not(:disabled) { + cursor: pointer; +} +::-moz-focus-inner { + padding: 0; + border-style: none; +} +textarea { + resize: vertical; +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: calc(1.275rem+0.3vw); + line-height: inherit; +} +@media (min-width: 1200px) { + legend { + font-size: 1.5rem; + } +} +legend + * { + clear: left; +} +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-fields-wrapper, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-minute, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-text, +::-webkit-datetime-edit-year-field { + padding: 0; +} +::-webkit-inner-spin-button { + height: auto; +} +[type='search'] { + outline-offset: -2px; + -webkit-appearance: textfield; +} +::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-color-swatch-wrapper { + padding: 0; +} +::file-selector-button { + font: inherit; +} +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} +output { + display: inline-block; +} +iframe { + border: 0; +} +summary { + display: list-item; + cursor: pointer; +} +progress { + vertical-align: baseline; +} +[hidden] { + display: none !important; +} +.lead { + font-size: 1.25rem; + font-weight: 300; +} +.display-1 { + font-size: calc(1.625rem+4.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem; + } +} +.display-2 { + font-size: calc(1.575rem+3.9vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem; + } +} +.display-3 { + font-size: calc(1.525rem+3.3vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem; + } +} +.display-4 { + font-size: calc(1.475rem+2.7vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem; + } +} +.display-5 { + font-size: calc(1.425rem+2.1vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem; + } +} +.display-6 { + font-size: calc(1.375rem+1.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem; + } +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; +} +.list-inline-item { + display: inline-block; +} +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} +.initialism { + font-size: 0.875em; + text-transform: uppercase; +} +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} +.blockquote > :last-child { + margin-bottom: 0; +} +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: 0.875em; + color: #6c757d; +} +.blockquote-footer::before { + content: '— '; +} +.img-fluid { + max-width: 100%; + height: auto; +} +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} +.figure { + display: inline-block; +} +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} +.figure-caption { + font-size: 0.875em; + color: #6c757d; +} +.container, +.container-fluid, +.container-lg, +.container-md, +.container-sm, +.container-xl, +.container-xxl { + width: 100%; + padding-right: var(--bs-gutter-x, 0.75rem); + padding-left: var(--bs-gutter-x, 0.75rem); + margin-right: auto; + margin-left: auto; + padding: 0 12px; +} +@media (min-width: 576px) { + .container, + .container-sm { + max-width: 100%; + } +} +@media (min-width: 768px) { + .container, + .container-md, + .container-sm { + max-width: 720px; + } +} +@media (min-width: 992px) { + .container, + .container-lg, + .container-md, + .container-sm { + max-width: 960px; + } +} +@media (min-width: 1200px) { + .container, + .container-lg, + .container-md, + .container-sm, + .container-xl { + max-width: 1200px; + } +} +@media (min-width: 1440px) { + .container, + .container-lg, + .container-md, + .container-sm, + .container-xl, + .container-xxl { + max-width: 1440px; + padding: 0; + } +} +.cate-list { + width: 70%; + margin: auto; +} +.cate-list li { + width: 31.5%; + display: inline-block; + text-align: center; + padding: 36px 0 0; +} +.cate-list li img { + max-width: 50%; +} +.cate-list li p { + color: #333; + font-size: 14px; + padding-top: 12px; +} +@media (min-width: 400px) and (max-width: 1000px) { + .cate-list { + width: 98%; + margin: auto; + } + .cate-list li { + width: 24%; + padding: 16px 0 0; + } +} +@media (min-width: 320px) and (max-width: 399px) { + .cate-list { + width: 98%; + margin: auto; + } + .cate-list li { + width: 31.8%; + padding: 16px 0 0; + } +} +.cate-list li p:hover { + color: #036eb8; +} +.cate-list li:hover { + -webkit-transform: translateY(-10px); + -moz-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transition: all 0.5s; + -webkit-transition: all 0.5s; + -ms-transition: all 0.5s; +} +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(var(--bs-gutter-y) * -1); + margin-right: calc(var(--bs-gutter-x) / -2); + margin-left: calc(var(--bs-gutter-x) / -2); +} +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) / 2); + padding-left: calc(var(--bs-gutter-x) / 2); + margin-top: var(--bs-gutter-y); +} +.col { + flex: 1 0 0; +} +.row-cols-auto > * { + flex: 0 0 auto; + width: auto; +} +.row-cols-1 > * { + flex: 0 0 auto; + width: 100%; +} +.row-cols-2 > * { + flex: 0 0 auto; + width: 50%; +} +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; +} +.row-cols-4 > * { + flex: 0 0 auto; + width: 25%; +} +.row-cols-5 > * { + flex: 0 0 auto; + width: 20%; +} +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; +} +.col-auto { + flex: 0 0 auto; + width: auto; +} +.col-1 { + flex: 0 0 auto; + width: 8.3333333333%; +} +.col-2 { + flex: 0 0 auto; + width: 16.6666666667%; +} +.col-3 { + flex: 0 0 auto; + width: 25%; +} +.col-4 { + flex: 0 0 auto; + width: 33.3333333333%; +} +.col-5 { + flex: 0 0 auto; + width: 41.6666666667%; +} +.col-6 { + flex: 0 0 auto; + width: 50%; +} +.col-7 { + flex: 0 0 auto; + width: 58.3333333333%; +} +.col-8 { + flex: 0 0 auto; + width: 66.6666666667%; +} +.col-9 { + flex: 0 0 auto; + width: 75%; +} +.col-10 { + flex: 0 0 auto; + width: 83.3333333333%; +} +.col-11 { + flex: 0 0 auto; + width: 91.6666666667%; +} +.col-12 { + flex: 0 0 auto; + width: 100%; +} +.offset-1 { + margin-left: 8.3333333333%; +} +.offset-2 { + margin-left: 16.6666666667%; +} +.offset-3 { + margin-left: 25%; +} +.offset-4 { + margin-left: 33.3333333333%; +} +.offset-5 { + margin-left: 41.6666666667%; +} +.offset-6 { + margin-left: 50%; +} +.offset-7 { + margin-left: 58.3333333333%; +} +.offset-8 { + margin-left: 66.6666666667%; +} +.offset-9 { + margin-left: 75%; +} +.offset-10 { + margin-left: 83.3333333333%; +} +.offset-11 { + margin-left: 91.6666666667%; +} +.g-0, +.gx-0 { + --bs-gutter-x: 0; +} +.g-0, +.gy-0 { + --bs-gutter-y: 0; +} +.g-1, +.gx-1 { + --bs-gutter-x: 0.25rem; +} +.g-1, +.gy-1 { + --bs-gutter-y: 0.25rem; +} +.g-2, +.gx-2 { + --bs-gutter-x: 0.5rem; +} +.g-2, +.gy-2 { + --bs-gutter-y: 0.5rem; +} +.g-3, +.gx-3 { + --bs-gutter-x: 1rem; +} +.g-3, +.gy-3 { + --bs-gutter-y: 1rem; +} +.g-4, +.gx-4 { + --bs-gutter-x: 1.5rem; +} +.g-4, +.gy-4 { + --bs-gutter-y: 1.5rem; +} +.g-5, +.gx-5 { + --bs-gutter-x: 3rem; +} +.g-5, +.gy-5 { + --bs-gutter-y: 3rem; +} +@media (min-width: 320px) { + .col-sm { + flex: 1 0 0; + } + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + .col-sm-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + .col-sm-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-sm-3 { + flex: 0 0 auto; + width: 25%; + } + .col-sm-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + .col-sm-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + .col-sm-6 { + flex: 0 0 auto; + width: 50%; + } + .col-sm-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + .col-sm-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + .col-sm-9 { + flex: 0 0 auto; + width: 75%; + } + .col-sm-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + .col-sm-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + .col-sm-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.3333333333%; + } + .offset-sm-2 { + margin-left: 16.6666666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.3333333333%; + } + .offset-sm-5 { + margin-left: 41.6666666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.3333333333%; + } + .offset-sm-8 { + margin-left: 66.6666666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.3333333333%; + } + .offset-sm-11 { + margin-left: 91.6666666667%; + } + .g-sm-0, + .gx-sm-0 { + --bs-gutter-x: 0; + } + .g-sm-0, + .gy-sm-0 { + --bs-gutter-y: 0; + } + .g-sm-1, + .gx-sm-1 { + --bs-gutter-x: 0.25rem; + } + .g-sm-1, + .gy-sm-1 { + --bs-gutter-y: 0.25rem; + } + .g-sm-2, + .gx-sm-2 { + --bs-gutter-x: 0.5rem; + } + .g-sm-2, + .gy-sm-2 { + --bs-gutter-y: 0.5rem; + } + .g-sm-3, + .gx-sm-3 { + --bs-gutter-x: 1rem; + } + .g-sm-3, + .gy-sm-3 { + --bs-gutter-y: 1rem; + } + .g-sm-4, + .gx-sm-4 { + --bs-gutter-x: 1.5rem; + } + .g-sm-4, + .gy-sm-4 { + --bs-gutter-y: 1.5rem; + } + .g-sm-5, + .gx-sm-5 { + --bs-gutter-x: 3rem; + } + .g-sm-5, + .gy-sm-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 768px) { + .col-md { + flex: 1 0 0; + } + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + .col-md-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + .col-md-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-md-3 { + flex: 0 0 auto; + width: 25%; + } + .col-md-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + .col-md-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + .col-md-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + .col-md-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + .col-md-9 { + flex: 0 0 auto; + width: 75%; + } + .col-md-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + .col-md-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + .col-md-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.3333333333%; + } + .offset-md-2 { + margin-left: 16.6666666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.3333333333%; + } + .offset-md-5 { + margin-left: 41.6666666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.3333333333%; + } + .offset-md-8 { + margin-left: 66.6666666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.3333333333%; + } + .offset-md-11 { + margin-left: 91.6666666667%; + } + .g-md-0, + .gx-md-0 { + --bs-gutter-x: 0; + } + .g-md-0, + .gy-md-0 { + --bs-gutter-y: 0; + } + .g-md-1, + .gx-md-1 { + --bs-gutter-x: 0.25rem; + } + .g-md-1, + .gy-md-1 { + --bs-gutter-y: 0.25rem; + } + .g-md-2, + .gx-md-2 { + --bs-gutter-x: 0.5rem; + } + .g-md-2, + .gy-md-2 { + --bs-gutter-y: 0.5rem; + } + .g-md-3, + .gx-md-3 { + --bs-gutter-x: 1rem; + } + .g-md-3, + .gy-md-3 { + --bs-gutter-y: 1rem; + } + .g-md-4, + .gx-md-4 { + --bs-gutter-x: 1.5rem; + } + .g-md-4, + .gy-md-4 { + --bs-gutter-y: 1.5rem; + } + .g-md-5, + .gx-md-5 { + --bs-gutter-x: 3rem; + } + .g-md-5, + .gy-md-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0; + } + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + .col-lg-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + .col-lg-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-lg-3 { + flex: 0 0 auto; + width: 25%; + } + .col-lg-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + .col-lg-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + .col-lg-6 { + flex: 0 0 auto; + width: 50%; + } + .col-lg-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + .col-lg-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + .col-lg-9 { + flex: 0 0 auto; + width: 75%; + } + .col-lg-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + .col-lg-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + .col-lg-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.3333333333%; + } + .offset-lg-2 { + margin-left: 16.6666666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.3333333333%; + } + .offset-lg-5 { + margin-left: 41.6666666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.3333333333%; + } + .offset-lg-8 { + margin-left: 66.6666666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.3333333333%; + } + .offset-lg-11 { + margin-left: 91.6666666667%; + } + .g-lg-0, + .gx-lg-0 { + --bs-gutter-x: 0; + } + .g-lg-0, + .gy-lg-0 { + --bs-gutter-y: 0; + } + .g-lg-1, + .gx-lg-1 { + --bs-gutter-x: 0.25rem; + } + .g-lg-1, + .gy-lg-1 { + --bs-gutter-y: 0.25rem; + } + .g-lg-2, + .gx-lg-2 { + --bs-gutter-x: 0.5rem; + } + .g-lg-2, + .gy-lg-2 { + --bs-gutter-y: 0.5rem; + } + .g-lg-3, + .gx-lg-3 { + --bs-gutter-x: 1rem; + } + .g-lg-3, + .gy-lg-3 { + --bs-gutter-y: 1rem; + } + .g-lg-4, + .gx-lg-4 { + --bs-gutter-x: 1.5rem; + } + .g-lg-4, + .gy-lg-4 { + --bs-gutter-y: 1.5rem; + } + .g-lg-5, + .gx-lg-5 { + --bs-gutter-x: 3rem; + } + .g-lg-5, + .gy-lg-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0; + } + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xl-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + .col-xl-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xl-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + .col-xl-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + .col-xl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xl-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + .col-xl-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + .col-xl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xl-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + .col-xl-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + .col-xl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.3333333333%; + } + .offset-xl-2 { + margin-left: 16.6666666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.3333333333%; + } + .offset-xl-5 { + margin-left: 41.6666666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.3333333333%; + } + .offset-xl-8 { + margin-left: 66.6666666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.3333333333%; + } + .offset-xl-11 { + margin-left: 91.6666666667%; + } + .g-xl-0, + .gx-xl-0 { + --bs-gutter-x: 0; + } + .g-xl-0, + .gy-xl-0 { + --bs-gutter-y: 0; + } + .g-xl-1, + .gx-xl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xl-1, + .gy-xl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xl-2, + .gx-xl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xl-2, + .gy-xl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xl-3, + .gx-xl-3 { + --bs-gutter-x: 1rem; + } + .g-xl-3, + .gy-xl-3 { + --bs-gutter-y: 1rem; + } + .g-xl-4, + .gx-xl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xl-4, + .gy-xl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xl-5, + .gx-xl-5 { + --bs-gutter-x: 3rem; + } + .g-xl-5, + .gy-xl-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0; + } + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xxl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xxl-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + .col-xxl-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xxl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xxl-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + .col-xxl-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + .col-xxl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xxl-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + .col-xxl-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + .col-xxl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xxl-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + .col-xxl-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + .col-xxl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xxl-0 { + margin-left: 0; + } + .offset-xxl-1 { + margin-left: 8.3333333333%; + } + .offset-xxl-2 { + margin-left: 16.6666666667%; + } + .offset-xxl-3 { + margin-left: 25%; + } + .offset-xxl-4 { + margin-left: 33.3333333333%; + } + .offset-xxl-5 { + margin-left: 41.6666666667%; + } + .offset-xxl-6 { + margin-left: 50%; + } + .offset-xxl-7 { + margin-left: 58.3333333333%; + } + .offset-xxl-8 { + margin-left: 66.6666666667%; + } + .offset-xxl-9 { + margin-left: 75%; + } + .offset-xxl-10 { + margin-left: 83.3333333333%; + } + .offset-xxl-11 { + margin-left: 91.6666666667%; + } + .g-xxl-0, + .gx-xxl-0 { + --bs-gutter-x: 0; + } + .g-xxl-0, + .gy-xxl-0 { + --bs-gutter-y: 0; + } + .g-xxl-1, + .gx-xxl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xxl-1, + .gy-xxl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xxl-2, + .gx-xxl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xxl-2, + .gy-xxl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xxl-3, + .gx-xxl-3 { + --bs-gutter-x: 1rem; + } + .g-xxl-3, + .gy-xxl-3 { + --bs-gutter-y: 1rem; + } + .g-xxl-4, + .gx-xxl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xxl-4, + .gy-xxl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xxl-5, + .gx-xxl-5 { + --bs-gutter-x: 3rem; + } + .g-xxl-5, + .gy-xxl-5 { + --bs-gutter-y: 3rem; + } +} +.table { + --bs-table-bg: transparent; + --bs-table-striped-color: #212529; + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: #212529; + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: #212529; + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: #212529; + vertical-align: top; + border-color: #dee2e6; +} +.table > :not(caption) > * > * { + padding: 0.5rem 0.5rem; + background-color: var(--bs-table-bg); + border-bottom-width: 1px; + box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); +} +.table > tbody { + vertical-align: inherit; +} +.table > thead { + vertical-align: bottom; +} +.table > :not(:last-child) > :last-child > * { + border-bottom-color: currentColor; +} +.caption-top { + caption-side: top; +} +.table-sm > :not(caption) > * > * { + padding: 0.25rem 0.25rem; +} +.table-bordered > :not(caption) > * { + border-width: 1px 0; +} +.table-bordered > :not(caption) > * > * { + border-width: 0 1px; +} +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0; +} +.table-striped > tbody > tr:nth-of-type(odd) { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color); +} +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color); +} +.table-hover > tbody > tr:hover { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color); +} +.table-primary { + --bs-table-bg: #cfe2ff; + --bs-table-striped-bg: #c5d7f2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bacbe6; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfd1ec; + --bs-table-hover-color: #000; + color: #000; + border-color: #bacbe6; +} +.table-secondary { + --bs-table-bg: #e2e3e5; + --bs-table-striped-bg: #d7d8da; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbccce; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d2d4; + --bs-table-hover-color: #000; + color: #000; + border-color: #cbccce; +} +.table-success { + --bs-table-bg: #d1e7dd; + --bs-table-striped-bg: #c7dbd2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bcd0c7; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c1d6cc; + --bs-table-hover-color: #000; + color: #000; + border-color: #bcd0c7; +} +.table-info { + --bs-table-bg: #cff4fc; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: #000; + border-color: #badce3; +} +.table-warning { + --bs-table-bg: #fff3cd; + --bs-table-striped-bg: #f2e7c3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dbb9; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece1be; + --bs-table-hover-color: #000; + color: #000; + border-color: #e6dbb9; +} +.table-danger { + --bs-table-bg: #f8d7da; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfc2c4; +} +.table-light { + --bs-table-bg: #f8f9fa; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfe0e1; +} +.table-dark { + --bs-table-bg: #212529; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: #fff; + border-color: #373b3e; +} +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +.form-label { + margin-bottom: 0.5rem; +} +.col-form-label { + padding-top: calc(0.375rem+1px); + padding-bottom: calc(0.375rem+1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} +.col-form-label-lg { + padding-top: calc(0.5rem+1px); + padding-bottom: calc(0.5rem+1px); + font-size: 1.25rem; +} +.col-form-label-sm { + padding-top: calc(0.25rem+1px); + padding-bottom: calc(0.25rem+1px); + font-size: 0.875rem; +} +.form-text { + margin-top: 0.25rem; + font-size: 0.875em; + color: #6c757d; +} +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} +.form-control[type='file'] { + overflow: hidden; +} +.form-control[type='file']:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control:focus { + color: #212529; + background-color: #fff; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-control::-webkit-date-and-time-value { + height: 1.5em; +} +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1; +} +.form-control::placeholder { + color: #6c757d; + opacity: 1; +} +.form-control:disabled, +.form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} +.form-control::file-selector-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::file-selector-button { + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: #dde0e3; +} +.form-control::-webkit-file-upload-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: #dde0e3; +} +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.375rem 0; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} +.form-control-plaintext.form-control-lg, +.form-control-plaintext.form-control-sm { + padding-right: 0; + padding-left: 0; +} +.form-control-sm { + min-height: calc(1.5em+0.5rem+2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} +.form-control-sm::file-selector-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} +.form-control-sm::-webkit-file-upload-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} +.form-control-lg { + min-height: calc(1.5em+1rem+2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} +.form-control-lg::file-selector-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} +.form-control-lg::-webkit-file-upload-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} +textarea.form-control { + min-height: calc(1.5em+0.75rem+2px); +} +textarea.form-control-sm { + min-height: calc(1.5em+0.5rem+2px); +} +textarea.form-control-lg { + min-height: calc(1.5em+1rem+2px); +} +.form-control-color { + max-width: 3rem; + height: auto; + padding: 0.375rem; +} +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control-color::-moz-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} +.form-control-color::-webkit-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} +.form-select { + display: block; + width: 100%; + padding: 0.375rem 2.25rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-select[multiple], +.form-select[size]:not([size='1']) { + padding-right: 0.75rem; + background-image: none; +} +.form-select:disabled { + background-color: #e9ecef; +} +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #212529; +} +.form-select-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; +} +.form-select-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; +} +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: 0.125rem; +} +.form-check .form-check-input { + float: left; + margin-left: -1.5em; +} +.form-check-input { + width: 1em; + height: 1em; + margin-top: 0.25em; + vertical-align: top; + background-color: #fff; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: 1px solid rgba(0, 0, 0, 0.25); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-print-color-adjust: exact; + color-adjust: exact; +} +.form-check-input[type='checkbox'] { + border-radius: 0.25em; +} +.form-check-input[type='radio'] { + border-radius: 50%; +} +.form-check-input:active { + filter: brightness(90%); +} +.form-check-input:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd; +} +.form-check-input:checked[type='checkbox'] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); +} +.form-check-input:checked[type='radio'] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-check-input[type='checkbox']:indeterminate { + background-color: #0d6efd; + border-color: #0d6efd; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); +} +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: 0.5; +} +.form-check-input:disabled ~ .form-check-label, +.form-check-input[disabled] ~ .form-check-label { + opacity: 0.5; +} +.form-switch { + padding-left: 2.5em; +} +.form-switch .form-check-input { + width: 2em; + margin-left: -2.5em; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + background-position: left center; + border-radius: 2em; + transition: background-position 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none; + } +} +.form-switch .form-check-input:focus { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); +} +.form-switch .form-check-input:checked { + background-position: right center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-check-inline { + display: inline-block; + margin-right: 1rem; +} +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.btn-check:disabled + .btn, +.btn-check[disabled] + .btn { + pointer-events: none; + filter: none; + opacity: 0.65; +} +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.form-range:focus { + outline: 0; +} +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range::-moz-focus-outer { + border: 0; +} +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none; + } +} +.form-range::-webkit-slider-thumb:active { + background-color: #b6d4fe; +} +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none; + } +} +.form-range::-moz-range-thumb:active { + background-color: #b6d4fe; +} +.form-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} +.form-range:disabled { + pointer-events: none; +} +.form-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} +.form-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} +.form-floating { + position: relative; +} +.form-floating > .form-control, +.form-floating > .form-select { + height: calc(3.5rem+2px); + padding: 1rem 0.75rem; +} +.form-floating > label { + position: absolute; + top: 0; + left: 0; + height: 100%; + padding: 1rem 0.75rem; + pointer-events: none; + border: 1px solid transparent; + transform-origin: 0 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none; + } +} +.form-floating > .form-control::-moz-placeholder { + color: transparent; +} +.form-floating > .form-control::placeholder { + color: transparent; +} +.form-floating > .form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:focus, +.form-floating > .form-control:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:focus ~ label, +.form-floating > .form-control:not(:placeholder-shown) ~ label, +.form-floating > .form-select ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:-webkit-autofill ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} +.input-group > .form-control, +.input-group > .form-select { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .form-control:focus, +.input-group > .form-select:focus { + z-index: 3; +} +.input-group .btn { + position: relative; + z-index: 2; +} +.input-group .btn:focus { + z-index: 3; +} +.input-group-text { + display: flex; + align-items: center; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} +.input-group-lg > .btn, +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} +.input-group-sm > .btn, +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: 3rem; +} +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n + 3), +.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group.has-validation > .dropdown-toggle:nth-last-child(n + 4), +.input-group.has-validation > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group + > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #198754; +} +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(25, 135, 84, 0.9); + border-radius: 0.25rem; +} +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip, +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip { + display: block; +} +.form-control.is-valid, +.was-validated .form-control:valid { + border-color: #198754; + padding-right: calc(1.5em+0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em+0.1875rem) center; + background-size: calc(0.75em+0.375rem) calc(0.75em+0.375rem); +} +.form-control.is-valid:focus, +.was-validated .form-control:valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} +.was-validated textarea.form-control:valid, +textarea.form-control.is-valid { + padding-right: calc(1.5em+0.75rem); + background-position: top calc(0.375em+0.1875rem) right calc(0.375em+0.1875rem); +} +.form-select.is-valid, +.was-validated .form-select:valid { + border-color: #198754; + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), + url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em+0.375rem) calc(0.75em+0.375rem); +} +.form-select.is-valid:focus, +.was-validated .form-select:valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} +.form-check-input.is-valid, +.was-validated .form-check-input:valid { + border-color: #198754; +} +.form-check-input.is-valid:checked, +.was-validated .form-check-input:valid:checked { + background-color: #198754; +} +.form-check-input.is-valid:focus, +.was-validated .form-check-input:valid:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} +.form-check-input.is-valid ~ .form-check-label, +.was-validated .form-check-input:valid ~ .form-check-label { + color: #198754; +} +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: 0.5em; +} +.input-group .form-control.is-valid, +.input-group .form-select.is-valid, +.was-validated .input-group .form-control:valid, +.was-validated .input-group .form-select:valid { + z-index: 3; +} +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #dc3545; +} +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip, +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip { + display: block; +} +.form-control.is-invalid, +.was-validated .form-control:invalid { + border-color: #dc3545; + padding-right: calc(1.5em+0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em+0.1875rem) center; + background-size: calc(0.75em+0.375rem) calc(0.75em+0.375rem); +} +.form-control.is-invalid:focus, +.was-validated .form-control:invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} +.was-validated textarea.form-control:invalid, +textarea.form-control.is-invalid { + padding-right: calc(1.5em+0.75rem); + background-position: top calc(0.375em+0.1875rem) right calc(0.375em+0.1875rem); +} +.form-select.is-invalid, +.was-validated .form-select:invalid { + border-color: #dc3545; + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), + url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em+0.375rem) calc(0.75em+0.375rem); +} +.form-select.is-invalid:focus, +.was-validated .form-select:invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} +.form-check-input.is-invalid, +.was-validated .form-check-input:invalid { + border-color: #dc3545; +} +.form-check-input.is-invalid:checked, +.was-validated .form-check-input:invalid:checked { + background-color: #dc3545; +} +.form-check-input.is-invalid:focus, +.was-validated .form-check-input:invalid:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} +.form-check-input.is-invalid ~ .form-check-label, +.was-validated .form-check-input:invalid ~ .form-check-label { + color: #dc3545; +} +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: 0.5em; +} +.input-group .form-control.is-invalid, +.input-group .form-select.is-invalid, +.was-validated .input-group .form-control:invalid, +.was-validated .input-group .form-select:invalid { + z-index: 3; +} +.btn { + display: inline-block; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} +.btn:hover { + color: #212529; +} +.btn-check:focus + .btn, +.btn:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.btn.disabled, +.btn:disabled, +fieldset:disabled .btn { + pointer-events: none; + opacity: 0.65; +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-secondary:hover { + color: #fff; + background-color: #5c636a; + border-color: #565e64; +} +.btn-check:focus + .btn-secondary, +.btn-secondary:focus { + color: #fff; + background-color: #5c636a; + border-color: #565e64; + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} +.btn-check:active + .btn-secondary, +.btn-check:checked + .btn-secondary, +.btn-secondary.active, +.btn-secondary:active, +.show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #565e64; + border-color: #51585e; +} +.btn-check:active + .btn-secondary:focus, +.btn-check:checked + .btn-secondary:focus, +.btn-secondary.active:focus, +.btn-secondary:active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} +.btn-secondary.disabled, +.btn-secondary:disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-success { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-success:hover { + color: #fff; + background-color: #157347; + border-color: #146c43; +} +.btn-check:focus + .btn-success, +.btn-success:focus { + color: #fff; + background-color: #157347; + border-color: #146c43; + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} +.btn-check:active + .btn-success, +.btn-check:checked + .btn-success, +.btn-success.active, +.btn-success:active, +.show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #146c43; + border-color: #13653f; +} +.btn-check:active + .btn-success:focus, +.btn-check:checked + .btn-success:focus, +.btn-success.active:focus, +.btn-success:active:focus, +.show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} +.btn-success.disabled, +.btn-success:disabled { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-info { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-info:hover { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; +} +.btn-check:focus + .btn-info, +.btn-info:focus { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} +.btn-check:active + .btn-info, +.btn-check:checked + .btn-info, +.btn-info.active, +.btn-info:active, +.show > .btn-info.dropdown-toggle { + color: #000; + background-color: #3dd5f3; + border-color: #25cff2; +} +.btn-check:active + .btn-info:focus, +.btn-check:checked + .btn-info:focus, +.btn-info.active:focus, +.btn-info:active:focus, +.show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} +.btn-info.disabled, +.btn-info:disabled { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-warning { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-warning:hover { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; +} +.btn-check:focus + .btn-warning, +.btn-warning:focus { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} +.btn-check:active + .btn-warning, +.btn-check:checked + .btn-warning, +.btn-warning.active, +.btn-warning:active, +.show > .btn-warning.dropdown-toggle { + color: #000; + background-color: #ffcd39; + border-color: #ffc720; +} +.btn-check:active + .btn-warning:focus, +.btn-check:checked + .btn-warning:focus, +.btn-warning.active:focus, +.btn-warning:active:focus, +.show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} +.btn-warning.disabled, +.btn-warning:disabled { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-danger:hover { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; +} +.btn-check:focus + .btn-danger, +.btn-danger:focus { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} +.btn-check:active + .btn-danger, +.btn-check:checked + .btn-danger, +.btn-danger.active, +.btn-danger:active, +.show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #b02a37; + border-color: #a52834; +} +.btn-check:active + .btn-danger:focus, +.btn-check:checked + .btn-danger:focus, +.btn-danger.active:focus, +.btn-danger:active:focus, +.show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} +.btn-danger.disabled, +.btn-danger:disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-light { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-light:hover { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} +.btn-check:focus + .btn-light, +.btn-light:focus { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} +.btn-check:active + .btn-light, +.btn-check:checked + .btn-light, +.btn-light.active, +.btn-light:active, +.show > .btn-light.dropdown-toggle { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} +.btn-check:active + .btn-light:focus, +.btn-check:checked + .btn-light:focus, +.btn-light.active:focus, +.btn-light:active:focus, +.show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} +.btn-light.disabled, +.btn-light:disabled { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-dark { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-dark:hover { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; +} +.btn-check:focus + .btn-dark, +.btn-dark:focus { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} +.btn-check:active + .btn-dark, +.btn-check:checked + .btn-dark, +.btn-dark.active, +.btn-dark:active, +.show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1a1e21; + border-color: #191c1f; +} +.btn-check:active + .btn-dark:focus, +.btn-check:checked + .btn-dark:focus, +.btn-dark.active:focus, +.btn-dark:active:focus, +.show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} +.btn-dark.disabled, +.btn-dark:disabled { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-outline-primary { + color: #0d6efd; + border-color: #0d6efd; +} +.btn-outline-primary:hover { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.btn-check:focus + .btn-outline-primary, +.btn-outline-primary:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} +.btn-check:active + .btn-outline-primary, +.btn-check:checked + .btn-outline-primary, +.btn-outline-primary.active, +.btn-outline-primary.dropdown-toggle.show, +.btn-outline-primary:active { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.btn-check:active + .btn-outline-primary:focus, +.btn-check:checked + .btn-outline-primary:focus, +.btn-outline-primary.active:focus, +.btn-outline-primary.dropdown-toggle.show:focus, +.btn-outline-primary:active:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} +.btn-outline-primary.disabled, +.btn-outline-primary:disabled { + color: #0d6efd; + background-color: transparent; +} +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; +} +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-check:focus + .btn-outline-secondary, +.btn-outline-secondary:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} +.btn-check:active + .btn-outline-secondary, +.btn-check:checked + .btn-outline-secondary, +.btn-outline-secondary.active, +.btn-outline-secondary.dropdown-toggle.show, +.btn-outline-secondary:active { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-check:active + .btn-outline-secondary:focus, +.btn-check:checked + .btn-outline-secondary:focus, +.btn-outline-secondary.active:focus, +.btn-outline-secondary.dropdown-toggle.show:focus, +.btn-outline-secondary:active:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} +.btn-outline-secondary.disabled, +.btn-outline-secondary:disabled { + color: #6c757d; + background-color: transparent; +} +.btn-outline-success { + color: #198754; + border-color: #198754; +} +.btn-outline-success:hover { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-check:focus + .btn-outline-success, +.btn-outline-success:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} +.btn-check:active + .btn-outline-success, +.btn-check:checked + .btn-outline-success, +.btn-outline-success.active, +.btn-outline-success.dropdown-toggle.show, +.btn-outline-success:active { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-check:active + .btn-outline-success:focus, +.btn-check:checked + .btn-outline-success:focus, +.btn-outline-success.active:focus, +.btn-outline-success.dropdown-toggle.show:focus, +.btn-outline-success:active:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} +.btn-outline-success.disabled, +.btn-outline-success:disabled { + color: #198754; + background-color: transparent; +} +.btn-outline-info { + color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-outline-info:hover { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-check:focus + .btn-outline-info, +.btn-outline-info:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} +.btn-check:active + .btn-outline-info, +.btn-check:checked + .btn-outline-info, +.btn-outline-info.active, +.btn-outline-info.dropdown-toggle.show, +.btn-outline-info:active { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-check:active + .btn-outline-info:focus, +.btn-check:checked + .btn-outline-info:focus, +.btn-outline-info.active:focus, +.btn-outline-info.dropdown-toggle.show:focus, +.btn-outline-info:active:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} +.btn-outline-info.disabled, +.btn-outline-info:disabled { + color: #0dcaf0; + background-color: transparent; +} +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107; +} +.btn-outline-warning:hover { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-check:focus + .btn-outline-warning, +.btn-outline-warning:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} +.btn-check:active + .btn-outline-warning, +.btn-check:checked + .btn-outline-warning, +.btn-outline-warning.active, +.btn-outline-warning.dropdown-toggle.show, +.btn-outline-warning:active { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-check:active + .btn-outline-warning:focus, +.btn-check:checked + .btn-outline-warning:focus, +.btn-outline-warning.active:focus, +.btn-outline-warning.dropdown-toggle.show:focus, +.btn-outline-warning:active:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} +.btn-outline-warning.disabled, +.btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545; +} +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-check:focus + .btn-outline-danger, +.btn-outline-danger:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} +.btn-check:active + .btn-outline-danger, +.btn-check:checked + .btn-outline-danger, +.btn-outline-danger.active, +.btn-outline-danger.dropdown-toggle.show, +.btn-outline-danger:active { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-check:active + .btn-outline-danger:focus, +.btn-check:checked + .btn-outline-danger:focus, +.btn-outline-danger.active:focus, +.btn-outline-danger.dropdown-toggle.show:focus, +.btn-outline-danger:active:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} +.btn-outline-danger.disabled, +.btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-outline-light:hover { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-check:focus + .btn-outline-light, +.btn-outline-light:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} +.btn-check:active + .btn-outline-light, +.btn-check:checked + .btn-outline-light, +.btn-outline-light.active, +.btn-outline-light.dropdown-toggle.show, +.btn-outline-light:active { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-check:active + .btn-outline-light:focus, +.btn-check:checked + .btn-outline-light:focus, +.btn-outline-light.active:focus, +.btn-outline-light.dropdown-toggle.show:focus, +.btn-outline-light:active:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} +.btn-outline-light.disabled, +.btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} +.btn-outline-dark { + color: #212529; + border-color: #212529; +} +.btn-outline-dark:hover { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-check:focus + .btn-outline-dark, +.btn-outline-dark:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} +.btn-check:active + .btn-outline-dark, +.btn-check:checked + .btn-outline-dark, +.btn-outline-dark.active, +.btn-outline-dark.dropdown-toggle.show, +.btn-outline-dark:active { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-check:active + .btn-outline-dark:focus, +.btn-check:checked + .btn-outline-dark:focus, +.btn-outline-dark.active:focus, +.btn-outline-dark.dropdown-toggle.show:focus, +.btn-outline-dark:active:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} +.btn-outline-dark.disabled, +.btn-outline-dark:disabled { + color: #212529; + background-color: transparent; +} +.btn-link { + font-weight: 400; + color: #0d6efd; + text-decoration: underline; +} +.btn-link:hover { + color: #0a58ca; +} +.btn-link.disabled, +.btn-link:disabled { + color: #6c757d; +} +.btn-group-lg > .btn, +.btn-lg { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} +.btn-group-sm > .btn, +.btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} +.fade { + transition: opacity 0.15s linear; +} +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} +.fade:not(.show) { + opacity: 0; +} +.collapse:not(.show) { + display: none; +} +.collapsing { + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} +.dropdown, +.dropend, +.dropstart, +.dropup { + position: relative; +} +.dropdown-toggle { + white-space: nowrap; +} +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} +.dropdown-toggle:empty::after { + margin-left: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + z-index: 1000; + display: none; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} +.dropdown-menu[data-bs-popper] { + left: 0; + margin-top: 0.125rem; +} +.dropdown-menu-start { + --bs-position: start; +} +.dropdown-menu-start[data-bs-popper] { + right: auto; + left: 0; +} +.dropdown-menu-end { + --bs-position: end; +} +.dropdown-menu-end[data-bs-popper] { + right: 0; + left: auto; +} +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start; + } + .dropdown-menu-sm-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-sm-end { + --bs-position: end; + } + .dropdown-menu-sm-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start; + } + .dropdown-menu-md-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-md-end { + --bs-position: end; + } + .dropdown-menu-md-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start; + } + .dropdown-menu-lg-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-lg-end { + --bs-position: end; + } + .dropdown-menu-lg-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start; + } + .dropdown-menu-xl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xl-end { + --bs-position: end; + } + .dropdown-menu-xl-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start; + } + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xxl-end { + --bs-position: end; + } + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0; + left: auto; + } +} +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropend .dropdown-menu { + top: 0; + right: auto; + left: 100%; +} +.dropend .dropdown-menu[data-bs-popper] { + margin-top: 0; + margin-left: 0.125rem; +} +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} +.dropend .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropend .dropdown-toggle::after { + vertical-align: 0; +} +.dropstart .dropdown-menu { + top: 0; + right: 100%; + left: auto; +} +.dropstart .dropdown-menu[data-bs-popper] { + margin-top: 0; + margin-right: 0.125rem; +} +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ''; +} +.dropstart .dropdown-toggle::after { + display: none; +} +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ''; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} +.dropstart .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropstart .dropdown-toggle::before { + vertical-align: 0; +} +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid rgba(0, 0, 0, 0.15); +} +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border: 0; +} +.dropdown-item:focus, +.dropdown-item:hover { + color: #1e2125; + background-color: #e9ecef; +} +.dropdown-item.active, +.dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #0d6efd; +} +.dropdown-item.disabled, +.dropdown-item:disabled { + color: #adb5bd; + pointer-events: none; + background-color: transparent; +} +.dropdown-menu.show { + display: block; +} +.dropdown-header { + display: block; + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} +.dropdown-item-text { + display: block; + padding: 0.25rem 1rem; + color: #212529; +} +.dropdown-menu-dark { + color: #dee2e6; + background-color: #343a40; + border-color: rgba(0, 0, 0, 0.15); +} +.dropdown-menu-dark .dropdown-item { + color: #dee2e6; +} +.dropdown-menu-dark .dropdown-item:focus, +.dropdown-menu-dark .dropdown-item:hover { + color: #fff; + background-color: rgba(255, 255, 255, 0.15); +} +.dropdown-menu-dark .dropdown-item.active, +.dropdown-menu-dark .dropdown-item:active { + color: #fff; + background-color: #0d6efd; +} +.dropdown-menu-dark .dropdown-item.disabled, +.dropdown-menu-dark .dropdown-item:disabled { + color: #adb5bd; +} +.dropdown-menu-dark .dropdown-divider { + border-color: rgba(0, 0, 0, 0.15); +} +.dropdown-menu-dark .dropdown-item-text { + color: #dee2e6; +} +.dropdown-menu-dark .dropdown-header { + color: #adb5bd; +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} +.btn-group-vertical > .btn, +.btn-group > .btn { + position: relative; + flex: 1 1 auto; +} +.btn-group-vertical > .btn-check:checked + .btn, +.btn-group-vertical > .btn-check:focus + .btn, +.btn-group-vertical > .btn.active, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:hover, +.btn-group > .btn-check:checked + .btn, +.btn-group > .btn-check:focus + .btn, +.btn-group > .btn.active, +.btn-group > .btn:active, +.btn-group > .btn:focus, +.btn-group > .btn:hover { + z-index: 1; +} +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} +.btn-toolbar .input-group { + width: auto; +} +.btn-group > .btn-group:not(:first-child), +.btn-group > .btn:not(:first-child) { + margin-left: -1px; +} +.btn-group > .btn-group:not(:last-child) > .btn, +.btn-group > .btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:not(:first-child) > .btn, +.btn-group > .btn:nth-child(n + 3), +.btn-group > :not(.btn-check) + .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} +.dropdown-toggle-split::after, +.dropend .dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after { + margin-left: 0; +} +.dropstart .dropdown-toggle-split::before { + margin-right: 0; +} +.btn-group-sm > .btn + .dropdown-toggle-split, +.btn-sm + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} +.btn-group-lg > .btn + .dropdown-toggle-split, +.btn-lg + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} +.btn-group-vertical > .btn-group:not(:first-child), +.btn-group-vertical > .btn:not(:first-child) { + margin-top: -1px; +} +.btn-group-vertical > .btn-group:not(:last-child) > .btn, +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child) > .btn, +.btn-group-vertical > .btn ~ .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav-link { + display: block; + padding: 0.5rem 1rem; + text-decoration: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none; + } +} +.nav-link.disabled { + color: #6c757d; + pointer-events: none; + cursor: default; +} +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} +.nav-tabs .nav-link { + margin-bottom: -1px; + background: 0; + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.nav-tabs .nav-link:focus, +.nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #dee2e6; + isolation: isolate; +} +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent; +} +.nav-tabs .nav-item.show .nav-link, +.nav-tabs .nav-link.active { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.nav-pills .nav-link { + background: 0; + border: 0; + border-radius: 0.25rem; +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #0d6efd; +} +.nav-fill .nav-item, +.nav-fill > .nav-link { + flex: 1 1 auto; + text-align: center; +} +.nav-justified .nav-item, +.nav-justified > .nav-link { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} +.nav-fill .nav-item .nav-link, +.nav-justified .nav-item .nav-link { + width: 100%; +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.navbar > .container, +.navbar > .container-fluid, +.navbar > .container-lg, +.navbar > .container-md, +.navbar > .container-sm, +.navbar > .container-xl, +.navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between; +} +.navbar-brand { + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + text-decoration: none; + white-space: nowrap; +} +.navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} +.navbar-nav .dropdown-menu { + position: static; +} +.navbar-text { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; + transition: box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none; + } +} +.navbar-toggler:hover { + text-decoration: none; +} +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 0.25rem; +} +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto; +} +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } +} +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } +} +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } +} +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } +} +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xxl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xxl .navbar-toggler { + display: none; + } +} +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start; +} +.navbar-expand .navbar-nav { + flex-direction: row; +} +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} +.navbar-expand .navbar-nav-scroll { + overflow: visible; +} +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} +.navbar-expand .navbar-toggler { + display: none; +} +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-brand:focus, +.navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.55); +} +.navbar-light .navbar-nav .nav-link:focus, +.navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, 0.7); +} +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} +.navbar-light .navbar-nav .nav-link.active, +.navbar-light .navbar-nav .show > .nav-link { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.55); + border-color: rgba(0, 0, 0, 0.1); +} +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.55); +} +.navbar-light .navbar-text a, +.navbar-light .navbar-text a:focus, +.navbar-light .navbar-text a:hover { + color: rgba(0, 0, 0, 0.9); +} +.navbar-dark .navbar-brand { + color: #fff; +} +.navbar-dark .navbar-brand:focus, +.navbar-dark .navbar-brand:hover { + color: #fff; +} +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.55); +} +.navbar-dark .navbar-nav .nav-link:focus, +.navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, 0.75); +} +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} +.navbar-dark .navbar-nav .nav-link.active, +.navbar-dark .navbar-nav .show > .nav-link { + color: #fff; +} +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.55); + border-color: rgba(255, 255, 255, 0.1); +} +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.55); +} +.navbar-dark .navbar-text a, +.navbar-dark .navbar-text a:focus, +.navbar-dark .navbar-text a:hover { + color: #fff; +} +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} +.card > hr { + margin-right: 0; + margin-left: 0; +} +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} +.card > .card-header + .list-group, +.card > .list-group + .card-footer { + border-top: 0; +} +.card-body { + flex: 1 1 auto; + padding: 1rem 1rem; +} +.card-title { + margin-bottom: 0.5rem; +} +.card-subtitle { + margin-top: -0.25rem; + margin-bottom: 0; +} +.card-text:last-child { + margin-bottom: 0; +} +.card-link:hover { + text-decoration: none; +} +.card-link + .card-link { + margin-left: 1rem; +} +.card-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} +.card-footer { + padding: 0.5rem 1rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} +.card-header-tabs { + margin-right: -0.5rem; + margin-bottom: -0.5rem; + margin-left: -0.5rem; + border-bottom: 0; +} +.card-header-pills { + margin-right: -0.5rem; + margin-left: -0.5rem; +} +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1rem; + border-radius: calc(0.25rem - 1px); +} +.card-img, +.card-img-bottom, +.card-img-top { + width: 100%; +} +.card-img, +.card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.card-img, +.card-img-bottom { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} +.card-group > .card { + margin-bottom: 0.75rem; +} +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + .card-group > .card { + flex: 1 0 0; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-header, + .card-group > .card:not(:last-child) .card-img-top { + border-top-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-footer, + .card-group > .card:not(:last-child) .card-img-bottom { + border-bottom-right-radius: 0; + } + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-header, + .card-group > .card:not(:first-child) .card-img-top { + border-top-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-footer, + .card-group > .card:not(:first-child) .card-img-bottom { + border-bottom-left-radius: 0; + } +} +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: 1rem 1.25rem; + font-size: 1rem; + color: #212529; + text-align: left; + background-color: #fff; + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, + border-radius 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none; + } +} +.accordion-button:not(.collapsed) { + color: #0c63e4; + background-color: #e7f1ff; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125); +} +.accordion-button:not(.collapsed)::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + transform: rotate(180deg); +} +.accordion-button::after { + flex-shrink: 0; + width: 1.25rem; + height: 1.25rem; + margin-left: auto; + content: ''; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-size: 1.25rem; + transition: transform 0.2s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none; + } +} +.accordion-button:hover { + z-index: 2; +} +.accordion-button:focus { + z-index: 3; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.accordion-header { + margin-bottom: 0; +} +.accordion-item { + margin-bottom: -1px; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} +.accordion-item:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.accordion-item:last-of-type { + margin-bottom: 0; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.accordion-body { + padding: 1rem 1.25rem; +} +.accordion-flush .accordion-collapse { + border-width: 0; +} +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} +.accordion-flush .accordion-item:first-child { + border-top: 0; +} +.accordion-flush .accordion-item:last-child { + border-bottom: 0; +} +.accordion-flush .accordion-item .accordion-button { + border-radius: 0; +} +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: 0; + margin-bottom: 1rem; + list-style: none; +} +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item.active { + color: #6c757d; +} +.pagination { + /* display: flex; */ + padding-left: 0; + list-style: none; +} +.page-link { + position: relative; + display: block; + color: #0d6efd; + text-decoration: none; + background-color: #fff; + border: 1px solid #dee2e6; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none; + } +} +.page-link:hover { + z-index: 2; + color: #0a58ca; + background-color: #e9ecef; + border-color: #dee2e6; +} +.page-link:focus { + z-index: 3; + color: #0a58ca; + background-color: #e9ecef; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.page-item:not(:first-child) .page-link { + margin-left: -1px; +} +.page-item.active .page-link { + z-index: 3; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + background-color: #fff; + border-color: #dee2e6; +} +.page-link { + padding: 0.375rem 0.75rem; +} +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; +} +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; +} +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} +.badge { + display: inline-block; + padding: 0.35em 0.65em; + font-size: 0.75em; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.alert { + position: relative; + padding: 1rem 1rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} +.alert-heading { + color: inherit; +} +.alert-link { + font-weight: 700; +} +.alert-dismissible { + padding-right: 3rem; +} +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem; +} +.alert-primary { + color: #084298; + background-color: #cfe2ff; + border-color: #b6d4fe; +} +.alert-primary .alert-link { + color: #06357a; +} +.alert-secondary { + color: #41464b; + background-color: #e2e3e5; + border-color: #d3d6d8; +} +.alert-secondary .alert-link { + color: #34383c; +} +.alert-success { + color: #0f5132; + background-color: #d1e7dd; + border-color: #badbcc; +} +.alert-success .alert-link { + color: #0c4128; +} +.alert-info { + color: #055160; + background-color: #cff4fc; + border-color: #b6effb; +} +.alert-info .alert-link { + color: #04414d; +} +.alert-warning { + color: #664d03; + background-color: #fff3cd; + border-color: #ffecb5; +} +.alert-warning .alert-link { + color: #523e02; +} +.alert-danger { + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7; +} +.alert-danger .alert-link { + color: #6a1a21; +} +.alert-light { + color: #636464; + background-color: #fefefe; + border-color: #fdfdfe; +} +.alert-light .alert-link { + color: #4f5050; +} +.alert-dark { + color: #141619; + background-color: #d3d3d4; + border-color: #bcbebf; +} +.alert-dark .alert-link { + color: #101214; +} +@-webkit-keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} +.progress { + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #0d6efd; + transition: width 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} +.progress-bar-striped { + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-size: 1rem 1rem; +} +.progress-bar-animated { + -webkit-animation: 1s linear infinite progress-bar-stripes; + animation: 1s linear infinite progress-bar-stripes; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none; + } +} +.list-group { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: 0.25rem; +} +.list-group-numbered { + list-style-type: none; + counter-reset: section; +} +.list-group-numbered > li::before { + content: counters(section, '.') '. '; + counter-increment: section; +} +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} +.list-group-item-action:focus, +.list-group-item-action:hover { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} +.list-group-item { + position: relative; + display: block; + padding: 0.5rem 1rem; + color: #212529; + text-decoration: none; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} +.list-group-item.disabled, +.list-group-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: #fff; +} +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.list-group-item + .list-group-item { + border-top-width: 0; +} +.list-group-item + .list-group-item.active { + margin-top: -1px; + border-top-width: 1px; +} +.list-group-horizontal { + flex-direction: row; +} +.list-group-horizontal > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} +.list-group-horizontal > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; +} +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + .list-group-horizontal-sm > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-sm > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + .list-group-horizontal-md > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-md > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + .list-group-horizontal-lg > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-lg > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + .list-group-horizontal-xl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row; + } + .list-group-horizontal-xxl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +.list-group-flush { + border-radius: 0; +} +.list-group-flush > .list-group-item { + border-width: 0 0 1px; +} +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} +.list-group-item-primary { + color: #084298; + background-color: #cfe2ff; +} +.list-group-item-primary.list-group-item-action:focus, +.list-group-item-primary.list-group-item-action:hover { + color: #084298; + background-color: #bacbe6; +} +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #084298; + border-color: #084298; +} +.list-group-item-secondary { + color: #41464b; + background-color: #e2e3e5; +} +.list-group-item-secondary.list-group-item-action:focus, +.list-group-item-secondary.list-group-item-action:hover { + color: #41464b; + background-color: #cbccce; +} +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #41464b; + border-color: #41464b; +} +.list-group-item-success { + color: #0f5132; + background-color: #d1e7dd; +} +.list-group-item-success.list-group-item-action:focus, +.list-group-item-success.list-group-item-action:hover { + color: #0f5132; + background-color: #bcd0c7; +} +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #0f5132; + border-color: #0f5132; +} +.list-group-item-info { + color: #055160; + background-color: #cff4fc; +} +.list-group-item-info.list-group-item-action:focus, +.list-group-item-info.list-group-item-action:hover { + color: #055160; + background-color: #badce3; +} +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #055160; + border-color: #055160; +} +.list-group-item-warning { + color: #664d03; + background-color: #fff3cd; +} +.list-group-item-warning.list-group-item-action:focus, +.list-group-item-warning.list-group-item-action:hover { + color: #664d03; + background-color: #e6dbb9; +} +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #664d03; + border-color: #664d03; +} +.list-group-item-danger { + color: #842029; + background-color: #f8d7da; +} +.list-group-item-danger.list-group-item-action:focus, +.list-group-item-danger.list-group-item-action:hover { + color: #842029; + background-color: #dfc2c4; +} +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #842029; + border-color: #842029; +} +.list-group-item-light { + color: #636464; + background-color: #fefefe; +} +.list-group-item-light.list-group-item-action:focus, +.list-group-item-light.list-group-item-action:hover { + color: #636464; + background-color: #e5e5e5; +} +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #636464; + border-color: #636464; +} +.list-group-item-dark { + color: #141619; + background-color: #d3d3d4; +} +.list-group-item-dark.list-group-item-action:focus, +.list-group-item-dark.list-group-item-action:hover { + color: #141619; + background-color: #bebebf; +} +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #141619; + border-color: #141619; +} +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: 0.25em 0.25em; + color: #000; + background: transparent + url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") + center/1em auto no-repeat; + border: 0; + border-radius: 0.25rem; + opacity: 0.5; +} +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: 0.75; +} +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + opacity: 1; +} +.btn-close.disabled, +.btn-close:disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: 0.25; +} +.btn-close-white { + filter: invert(1) grayscale(100%) brightness(200%); +} +.toast { + width: 350px; + max-width: 100%; + font-size: 0.875rem; + pointer-events: auto; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} +.toast:not(.showing):not(.show) { + opacity: 0; +} +.toast.hide { + display: none; +} +.toast-container { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none; +} +.toast-container > :not(:last-child) { + margin-bottom: 0.75rem; +} +.toast-header { + display: flex; + align-items: center; + padding: 0.5rem 0.75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.toast-header .btn-close { + margin-right: -0.375rem; + margin-left: 0.75rem; +} +.toast-body { + padding: 0.75rem; + word-wrap: break-word; +} +.modal-open { + overflow: hidden; +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1060; + display: none; + width: 100%; + height: 100%; + overflow: hidden; + outline: 0; +} +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} +.modal.show .modal-dialog { + transform: none; +} +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} +.modal-dialog-scrollable { + height: calc(100% - 1rem); +} +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden; +} +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - 1rem); +} +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + width: 100vw; + height: 100vh; + background-color: #000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop.show { + opacity: 0.5; +} +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} +.modal-header .btn-close { + padding: 0.5rem 0.5rem; + margin: -0.5rem -0.5rem -0.5rem auto; +} +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} +.modal-body { + position: relative; + flex: 1 1 auto; + padding: 1rem; +} +.modal-footer { + display: flex; + flex-wrap: wrap; + flex-shrink: 0; + align-items: center; + justify-content: flex-end; + padding: 0.75rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: calc(0.3rem - 1px); + border-bottom-left-radius: calc(0.3rem - 1px); +} +.modal-footer > * { + margin: 0.25rem; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + .modal-dialog-scrollable { + height: calc(100% - 3.5rem); + } + .modal-dialog-centered { + min-height: calc(100% - 3.5rem); + } + .modal-sm { + max-width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + max-width: 800px; + } +} +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; +} +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0; +} +.modal-fullscreen .modal-header { + border-radius: 0; +} +.modal-fullscreen .modal-body { + overflow-y: auto; +} +.modal-fullscreen .modal-footer { + border-radius: 0; +} +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-md-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-md-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-md-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0; + } +} +.tooltip { + position: absolute; + z-index: 1080; + display: block; + margin: 0; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} +.tooltip.show { + opacity: 0.9; +} +.tooltip .tooltip-arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} +.tooltip .tooltip-arrow::before { + position: absolute; + content: ''; + border-color: transparent; + border-style: solid; +} +.bs-tooltip-auto[data-popper-placement^='top'], +.bs-tooltip-top { + padding: 0.4rem 0; +} +.bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow, +.bs-tooltip-top .tooltip-arrow { + bottom: 0; +} +.bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow::before, +.bs-tooltip-top .tooltip-arrow::before { + top: -1px; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} +.bs-tooltip-auto[data-popper-placement^='right'], +.bs-tooltip-end { + padding: 0 0.4rem; +} +.bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow, +.bs-tooltip-end .tooltip-arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow::before, +.bs-tooltip-end .tooltip-arrow::before { + right: -1px; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} +.bs-tooltip-auto[data-popper-placement^='bottom'], +.bs-tooltip-bottom { + padding: 0.4rem 0; +} +.bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow, +.bs-tooltip-bottom .tooltip-arrow { + top: 0; +} +.bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow::before, +.bs-tooltip-bottom .tooltip-arrow::before { + bottom: -1px; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} +.bs-tooltip-auto[data-popper-placement^='left'], +.bs-tooltip-start { + padding: 0 0.4rem; +} +.bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow, +.bs-tooltip-start .tooltip-arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow::before, +.bs-tooltip-start .tooltip-arrow::before { + left: -1px; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1070; + display: block; + max-width: 276px; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} +.popover .popover-arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; +} +.popover .popover-arrow::after, +.popover .popover-arrow::before { + position: absolute; + display: block; + content: ''; + border-color: transparent; + border-style: solid; +} +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow, +.bs-popover-top > .popover-arrow { + bottom: calc(-0.5rem - 1px); +} +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::before, +.bs-popover-top > .popover-arrow::before { + bottom: 0; + border-width: 0.5rem 0.5rem 0; + border-top-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-auto[data-popper-placement^='top'] > .popover-arrow::after, +.bs-popover-top > .popover-arrow::after { + bottom: 1px; + border-width: 0.5rem 0.5rem 0; + border-top-color: #fff; +} +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow, +.bs-popover-end > .popover-arrow { + left: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::before, +.bs-popover-end > .popover-arrow::before { + left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-auto[data-popper-placement^='right'] > .popover-arrow::after, +.bs-popover-end > .popover-arrow::after { + left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: #fff; +} +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow, +.bs-popover-bottom > .popover-arrow { + top: calc(-0.5rem - 1px); +} +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::before, +.bs-popover-bottom > .popover-arrow::before { + top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-auto[data-popper-placement^='bottom'] > .popover-arrow::after, +.bs-popover-bottom > .popover-arrow::after { + top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: #fff; +} +.bs-popover-auto[data-popper-placement^='bottom'] .popover-header::before, +.bs-popover-bottom .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ''; + border-bottom: 1px solid #f0f0f0; +} +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow, +.bs-popover-start > .popover-arrow { + right: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::before, +.bs-popover-start > .popover-arrow::before { + right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-auto[data-popper-placement^='left'] > .popover-arrow::after, +.bs-popover-start > .popover-arrow::after { + right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: #fff; +} +.popover-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f0f0f0; + border-bottom: 1px solid #d8d8d8; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} +.popover-header:empty { + display: none; +} +.popover-body { + padding: 1rem 1rem; + color: #212529; +} +.carousel { + position: relative; +} +.carousel.pointer-event { + touch-action: pan-y; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner::after { + display: block; + clear: both; + content: ''; +} +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} +.carousel-item-next, +.carousel-item-prev, +.carousel-item.active { + display: block; +} +.active.carousel-item-end, +.carousel-item-next:not(.carousel-item-start) { + transform: translateX(100%); +} +.active.carousel-item-start, +.carousel-item-prev:not(.carousel-item-end) { + transform: translateX(-100%); +} +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} +.carousel-fade .carousel-item-next.carousel-item-start, +.carousel-fade .carousel-item-prev.carousel-item-end, +.carousel-fade .carousel-item.active { + z-index: 1; + opacity: 1; +} +.carousel-fade .active.carousel-item-end, +.carousel-fade .active.carousel-item-start { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-end, + .carousel-fade .active.carousel-item-start { + transition: none; + } +} +.carousel-control-next, +.carousel-control-prev { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: 0; + border: 0; + opacity: 0.5; + transition: opacity 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-control-next, + .carousel-control-prev { + transition: none; + } +} +.carousel-control-next:focus, +.carousel-control-next:hover, +.carousel-control-prev:focus, +.carousel-control-prev:hover { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} +.carousel-control-prev { + left: 0; +} +.carousel-control-next { + right: 0; +} +.carousel-control-next-icon, +.carousel-control-prev-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); +} +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; + list-style: none; +} +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none; + } +} +.carousel-indicators .active { + opacity: 1; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center; +} +.carousel-dark .carousel-control-next-icon, +.carousel-dark .carousel-control-prev-icon { + filter: invert(1) grayscale(100); +} +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000; +} +.carousel-dark .carousel-caption { + color: #000; +} +@-webkit-keyframes spinner-border { + to { + transform: rotate(360deg); + } +} +@keyframes spinner-border { + to { + transform: rotate(360deg); + } +} +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: 0.75s linear infinite spinner-border; + animation: 0.75s linear infinite spinner-border; +} +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} +@-webkit-keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: 0.75s linear infinite spinner-grow; + animation: 0.75s linear infinite spinner-grow; +} +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} +@media (prefers-reduced-motion: reduce) { + .spinner-border, + .spinner-grow { + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s; + } +} +.offcanvas { + position: fixed; + bottom: 0; + z-index: 1040; + display: flex; + flex-direction: column; + max-width: 100%; + visibility: hidden; + background-color: #fff; + background-clip: padding-box; + outline: 0; + transition: transform 0.3s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none; + } +} +.offcanvas-header { + display: flex; + justify-content: space-between; + padding: 1rem 1rem; +} +.offcanvas-header .btn-close { + padding: 0.5rem 0.5rem; + margin: -0.5rem -0.5rem -0.5rem auto; +} +.offcanvas-title { + margin-bottom: 0; + line-height: 1.5; +} +.offcanvas-body { + flex-grow: 1; + padding: 1rem 1rem; + overflow-y: auto; +} +.offcanvas-start { + top: 0; + left: 0; + width: 400px; + border-right: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(-100%); +} +.offcanvas-end { + top: 0; + right: 0; + width: 400px; + border-left: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(100%); +} +.offcanvas-bottom { + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-top: 1px solid rgba(0, 0, 0, 0.2); + transform: translateY(100%); +} +.offcanvas.show { + transform: none; +} +.offcanvas-backdrop::before { + position: fixed; + top: 0; + left: 0; + z-index: 1039; + width: 100vw; + height: 100vh; + content: ''; + background-color: rgba(0, 0, 0, 0.5); +} +.clearfix::after { + display: block; + clear: both; + content: ''; +} +.link-primary { + color: #0d6efd; +} +.link-primary:focus, +.link-primary:hover { + color: #0a58ca; +} +.link-secondary { + color: #6c757d; +} +.link-secondary:focus, +.link-secondary:hover { + color: #565e64; +} +.link-success { + color: #198754; +} +.link-success:focus, +.link-success:hover { + color: #146c43; +} +.link-info { + color: #0dcaf0; +} +.link-info:focus, +.link-info:hover { + color: #3dd5f3; +} +.link-warning { + color: #ffc107; +} +.link-warning:focus, +.link-warning:hover { + color: #ffcd39; +} +.link-danger { + color: #dc3545; +} +.link-danger:focus, +.link-danger:hover { + color: #b02a37; +} +.link-light { + color: #f8f9fa; +} +.link-light:focus, +.link-light:hover { + color: #f9fafb; +} +.link-dark { + color: #212529; +} +.link-dark:focus, +.link-dark:hover { + color: #1a1e21; +} +.ratio { + position: relative; + width: 100%; +} +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: ''; +} +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ratio-1x1 { + --bs-aspect-ratio: 100%; +} +.ratio-4x3 { + --bs-aspect-ratio: calc(3 / 4 * 100%); +} +.ratio-16x9 { + --bs-aspect-ratio: calc(9 / 16 * 100%); +} +.ratio-21x9 { + --bs-aspect-ratio: calc(9 / 21 * 100%); +} +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} +.sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; +} +@media (min-width: 576px) { + .sticky-sm-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 768px) { + .sticky-md-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 992px) { + .sticky-lg-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 1200px) { + .sticky-xl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 1400px) { + .sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: ''; +} +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.align-baseline { + vertical-align: baseline !important; +} +.align-top { + vertical-align: top !important; +} +.align-middle { + vertical-align: middle !important; +} +.align-bottom { + vertical-align: bottom !important; +} +.align-text-bottom { + vertical-align: text-bottom !important; +} +.align-text-top { + vertical-align: text-top !important; +} +.float-start { + float: left !important; +} +.float-end { + float: right !important; +} +.float-none { + float: none !important; +} +.overflow-auto { + overflow: auto !important; +} +.overflow-hidden { + overflow: hidden !important; +} +.overflow-visible { + overflow: visible !important; +} +.overflow-scroll { + overflow: scroll !important; +} +.d-inline { + display: inline !important; +} +.d-inline-block { + display: inline-block !important; +} +.d-block { + display: block !important; +} +.d-grid { + display: grid !important; +} +.d-table { + display: table !important; +} +.d-table-row { + display: table-row !important; +} +.d-table-cell { + display: table-cell !important; +} +.d-flex { + display: flex !important; +} +.d-inline-flex { + display: inline-flex !important; +} +.d-none { + display: none !important; +} +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} +.shadow-none { + box-shadow: none !important; +} +.position-static { + position: static !important; +} +.position-relative { + position: relative !important; +} +.position-absolute { + position: absolute !important; +} +.position-fixed { + position: fixed !important; +} +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} +.top-0 { + top: 0 !important; +} +.top-50 { + top: 50% !important; +} +.top-100 { + top: 100% !important; +} +.bottom-0 { + bottom: 0 !important; +} +.bottom-50 { + bottom: 50% !important; +} +.bottom-100 { + bottom: 100% !important; +} +.start-0 { + left: 0 !important; +} +.start-50 { + left: 50% !important; +} +.start-100 { + left: 100% !important; +} +.end-0 { + right: 0 !important; +} +.end-50 { + right: 50% !important; +} +.end-100 { + right: 100% !important; +} +.translate-middle { + transform: translate(-50%, -50%) !important; +} +.translate-middle-x { + transform: translateX(-50%) !important; +} +.translate-middle-y { + transform: translateY(-50%) !important; +} +.border { + border: 1px solid #dee2e6 !important; +} +.border-0 { + border: 0 !important; +} +.border-top { + border-top: 1px solid #dee2e6 !important; +} +.border-top-0 { + border-top: 0 !important; +} +.border-end { + border-right: 1px solid #dee2e6 !important; +} +.border-end-0 { + border-right: 0 !important; +} +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} +.border-bottom-0 { + border-bottom: 0 !important; +} +.border-start { + border-left: 1px solid #dee2e6 !important; +} +.border-start-0 { + border-left: 0 !important; +} +.border-primary { + border-color: #0d6efd !important; +} +.border-secondary { + border-color: #6c757d !important; +} +.border-success { + border-color: #198754 !important; +} +.border-info { + border-color: #0dcaf0 !important; +} +.border-warning { + border-color: #ffc107 !important; +} +.border-danger { + border-color: #dc3545 !important; +} +.border-light { + border-color: #f8f9fa !important; +} +.border-dark { + border-color: #212529 !important; +} +.border-white { + border-color: #fff !important; +} +.border-1 { + border-width: 1px !important; +} +.border-2 { + border-width: 2px !important; +} +.border-3 { + border-width: 3px !important; +} +.border-4 { + border-width: 4px !important; +} +.border-5 { + border-width: 5px !important; +} +.w-25 { + width: 25% !important; +} +.w-50 { + width: 50% !important; +} +.w-75 { + width: 75% !important; +} +.w-100 { + width: 100% !important; +} +.w-auto { + width: auto !important; +} +.mw-100 { + max-width: 100% !important; +} +.vw-100 { + width: 100vw !important; +} +.min-vw-100 { + min-width: 100vw !important; +} +.h-25 { + height: 25% !important; +} +.h-50 { + height: 50% !important; +} +.h-75 { + height: 75% !important; +} +.h-100 { + height: 100% !important; +} +.h-auto { + height: auto !important; +} +.mh-100 { + max-height: 100% !important; +} +.vh-100 { + height: 100vh !important; +} +.min-vh-100 { + min-height: 100vh !important; +} +.flex-fill { + flex: 1 1 auto !important; +} +.flex-row { + flex-direction: row !important; +} +.flex-column { + flex-direction: column !important; +} +.flex-row-reverse { + flex-direction: row-reverse !important; +} +.flex-column-reverse { + flex-direction: column-reverse !important; +} +.flex-grow-0 { + flex-grow: 0 !important; +} +.flex-grow-1 { + flex-grow: 1 !important; +} +.flex-shrink-0 { + flex-shrink: 0 !important; +} +.flex-shrink-1 { + flex-shrink: 1 !important; +} +.flex-wrap { + flex-wrap: wrap !important; +} +.flex-nowrap { + flex-wrap: nowrap !important; +} +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} +.gap-0 { + gap: 0 !important; +} +.gap-1 { + gap: 0.25rem !important; +} +.gap-2 { + gap: 0.5rem !important; +} +.gap-3 { + gap: 1rem !important; +} +.gap-4 { + gap: 1.5rem !important; +} +.gap-5 { + gap: 3rem !important; +} +.justify-content-start { + justify-content: flex-start !important; +} +.justify-content-end { + justify-content: flex-end !important; +} +.justify-content-center { + justify-content: center !important; +} +.justify-content-between { + justify-content: space-between !important; +} +.justify-content-around { + justify-content: space-around !important; +} +.justify-content-evenly { + justify-content: space-evenly !important; +} +.align-items-start { + align-items: flex-start !important; +} +.align-items-end { + align-items: flex-end !important; +} +.align-items-center { + align-items: center !important; +} +.align-items-baseline { + align-items: baseline !important; +} +.align-items-stretch { + align-items: stretch !important; +} +.align-content-start { + align-content: flex-start !important; +} +.align-content-end { + align-content: flex-end !important; +} +.align-content-center { + align-content: center !important; +} +.align-content-between { + align-content: space-between !important; +} +.align-content-around { + align-content: space-around !important; +} +.align-content-stretch { + align-content: stretch !important; +} +.align-self-auto { + align-self: auto !important; +} +.align-self-start { + align-self: flex-start !important; +} +.align-self-end { + align-self: flex-end !important; +} +.align-self-center { + align-self: center !important; +} +.align-self-baseline { + align-self: baseline !important; +} +.align-self-stretch { + align-self: stretch !important; +} +.order-first { + order: -1 !important; +} +.order-0 { + order: 0 !important; +} +.order-1 { + order: 1 !important; +} +.order-2 { + order: 2 !important; +} +.order-3 { + order: 3 !important; +} +.order-4 { + order: 4 !important; +} +.order-5 { + order: 5 !important; +} +.order-last { + order: 6 !important; +} +.m-0 { + margin: 0 !important; +} +.m-1 { + margin: 0.25rem !important; +} +.m-2 { + margin: 0.5rem !important; +} +.m-3 { + margin: 1rem !important; +} +.m-4 { + margin: 1.5rem !important; +} +.m-5 { + margin: 3rem !important; +} +.m-auto { + margin: auto !important; +} +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important; +} +.mx-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; +} +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; +} +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; +} +.mx-auto { + margin-right: auto !important; + margin-left: auto !important; +} +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; +} +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; +} +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} +.mt-0 { + margin-top: 0 !important; +} +.mt-1 { + margin-top: 0.25rem !important; +} +.mt-2 { + margin-top: 0.5rem !important; +} +.mt-3 { + margin-top: 1rem !important; +} +.mt-4 { + margin-top: 1.5rem !important; +} +.mt-5 { + margin-top: 3rem !important; +} +.mt-auto { + margin-top: auto !important; +} +.me-0 { + margin-right: 0 !important; +} +.me-1 { + margin-right: 0.25rem !important; +} +.me-2 { + margin-right: 0.5rem !important; +} +.me-3 { + margin-right: 1rem !important; +} +.me-4 { + margin-right: 1.5rem !important; +} +.me-5 { + margin-right: 3rem !important; +} +.me-auto { + margin-right: auto !important; +} +.mb-0 { + margin-bottom: 0 !important; +} +.mb-1 { + margin-bottom: 0.25rem !important; +} +.mb-2 { + margin-bottom: 0.5rem !important; +} +.mb-3 { + margin-bottom: 1rem !important; +} +.mb-4 { + margin-bottom: 1.5rem !important; +} +.mb-5 { + margin-bottom: 3rem !important; +} +.mb-auto { + margin-bottom: auto !important; +} +.ms-0 { + margin-left: 0 !important; +} +.ms-1 { + margin-left: 0.25rem !important; +} +.ms-2 { + margin-left: 0.5rem !important; +} +.ms-3 { + margin-left: 1rem !important; +} +.ms-4 { + margin-left: 1.5rem !important; +} +.ms-5 { + margin-left: 3rem !important; +} +.ms-auto { + margin-left: auto !important; +} +.p-0 { + padding: 0 !important; +} +.p-1 { + padding: 0.25rem !important; +} +.p-2 { + padding: 0.5rem !important; +} +.p-3 { + padding: 1rem !important; +} +.p-4 { + padding: 1.5rem !important; +} +.p-5 { + padding: 3rem !important; +} +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important; +} +.px-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; +} +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; +} +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; +} +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; +} +.pt-0 { + padding-top: 0 !important; +} +.pt-1 { + padding-top: 0.25rem !important; +} +.pt-2 { + padding-top: 0.5rem !important; +} +.pt-3 { + padding-top: 1rem !important; +} +.pt-4 { + padding-top: 1.5rem !important; +} +.pt-5 { + padding-top: 3rem !important; +} +.pe-0 { + padding-right: 0 !important; +} +.pe-1 { + padding-right: 0.25rem !important; +} +.pe-2 { + padding-right: 0.5rem !important; +} +.pe-3 { + padding-right: 1rem !important; +} +.pe-4 { + padding-right: 1.5rem !important; +} +.pe-5 { + padding-right: 3rem !important; +} +.pb-0 { + padding-bottom: 0 !important; +} +.pb-1 { + padding-bottom: 0.25rem !important; +} +.pb-2 { + padding-bottom: 0.5rem !important; +} +.pb-3 { + padding-bottom: 1rem !important; +} +.pb-4 { + padding-bottom: 1.5rem !important; +} +.pb-5 { + padding-bottom: 3rem !important; +} +.ps-0 { + padding-left: 0 !important; +} +.ps-1 { + padding-left: 0.25rem !important; +} +.ps-2 { + padding-left: 0.5rem !important; +} +.ps-3 { + padding-left: 1rem !important; +} +.ps-4 { + padding-left: 1.5rem !important; +} +.ps-5 { + padding-left: 3rem !important; +} +.font-monospace { + font-family: var(--bs-font-monospace) !important; +} +.fs-1 { + font-size: calc(1.375rem+1.5vw) !important; +} +.fs-2 { + font-size: calc(1.325rem+0.9vw) !important; +} +.fs-3 { + font-size: calc(1.3rem+0.6vw) !important; +} +.fs-4 { + font-size: calc(1.275rem+0.3vw) !important; +} +.fs-5 { + font-size: 1.25rem !important; +} +.fs-6 { + font-size: 1rem !important; +} +.fst-italic { + font-style: italic !important; +} +.fst-normal { + font-style: normal !important; +} +.fw-light { + font-weight: 300 !important; +} +.fw-lighter { + font-weight: lighter !important; +} +.fw-normal { + font-weight: 400 !important; +} +.fw-bold { + font-weight: 700 !important; +} +.fw-bolder { + font-weight: bolder !important; +} +.lh-1 { + line-height: 1 !important; +} +.lh-sm { + line-height: 1.25 !important; +} +.lh-base { + line-height: 1.5 !important; +} +.lh-lg { + line-height: 2 !important; +} +.text-start { + text-align: left !important; +} +.text-end { + text-align: right !important; +} +.text-center { + text-align: center !important; +} +.text-decoration-none { + text-decoration: none !important; +} +.text-decoration-underline { + text-decoration: underline !important; +} +.text-decoration-line-through { + text-decoration: line-through !important; +} +.text-lowercase { + text-transform: lowercase !important; +} +.text-uppercase { + text-transform: uppercase !important; +} +.text-capitalize { + text-transform: capitalize !important; +} +.text-wrap { + white-space: normal !important; +} +.text-nowrap { + white-space: nowrap !important; +} +.text-break { + word-wrap: break-word !important; + word-break: break-word !important; +} +.text-primary { + color: #0d6efd !important; +} +.text-secondary { + color: #6c757d !important; +} +.text-success { + color: #198754 !important; +} +.text-info { + color: #0dcaf0 !important; +} +.text-warning { + color: #ffc107 !important; +} +.text-danger { + color: #dc3545 !important; +} +.text-light { + color: #f8f9fa !important; +} +.text-dark { + color: #212529 !important; +} +.text-white { + color: #fff !important; +} +.text-body { + color: #212529 !important; +} +.text-muted { + color: #6c757d !important; +} +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} +.text-reset { + color: inherit !important; +} +.bg-primary { + background-color: #0d6efd !important; +} +.bg-secondary { + background-color: #6c757d !important; +} +.bg-success { + background-color: #198754 !important; +} +.bg-info { + background-color: #0dcaf0 !important; +} +.bg-warning { + background-color: #ffc107 !important; +} +.bg-danger { + background-color: #dc3545 !important; +} +.bg-light { + background-color: #f8f9fa !important; +} +.bg-dark { + background-color: #212529 !important; +} +.bg-body { + background-color: #fff !important; +} +.bg-white { + background-color: #fff !important; +} +.bg-transparent { + background-color: transparent !important; +} +.bg-gradient { + background-image: var(--bs-gradient) !important; +} +.user-select-all { + -webkit-user-select: all !important; + -moz-user-select: all !important; + user-select: all !important; +} +.user-select-auto { + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + user-select: auto !important; +} +.user-select-none { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important; +} +.pe-none { + pointer-events: none !important; +} +.pe-auto { + pointer-events: auto !important; +} +.rounded { + border-radius: 0.25rem !important; +} +.rounded-0 { + border-radius: 0 !important; +} +.rounded-1 { + border-radius: 0.2rem !important; +} +.rounded-2 { + border-radius: 0.25rem !important; +} +.rounded-3 { + border-radius: 0.3rem !important; +} +.rounded-circle { + border-radius: 50% !important; +} +.rounded-pill { + border-radius: 50rem !important; +} +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} +.rounded-end { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} +.rounded-start { + border-bottom-left-radius: 0.25rem !important; + border-top-left-radius: 0.25rem !important; +} +.visible { + visibility: visible !important; +} +.invisible { + visibility: hidden !important; +} +@media (min-width: 576px) { + .float-sm-start { + float: left !important; + } + .float-sm-end { + float: right !important; + } + .float-sm-none { + float: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-grid { + display: grid !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: flex !important; + } + .d-sm-inline-flex { + display: inline-flex !important; + } + .d-sm-none { + display: none !important; + } + .flex-sm-fill { + flex: 1 1 auto !important; + } + .flex-sm-row { + flex-direction: row !important; + } + .flex-sm-column { + flex-direction: column !important; + } + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + .flex-sm-wrap { + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .gap-sm-0 { + gap: 0 !important; + } + .gap-sm-1 { + gap: 0.25rem !important; + } + .gap-sm-2 { + gap: 0.5rem !important; + } + .gap-sm-3 { + gap: 1rem !important; + } + .gap-sm-4 { + gap: 1.5rem !important; + } + .gap-sm-5 { + gap: 3rem !important; + } + .justify-content-sm-start { + justify-content: flex-start !important; + } + .justify-content-sm-end { + justify-content: flex-end !important; + } + .justify-content-sm-center { + justify-content: center !important; + } + .justify-content-sm-between { + justify-content: space-between !important; + } + .justify-content-sm-around { + justify-content: space-around !important; + } + .justify-content-sm-evenly { + justify-content: space-evenly !important; + } + .align-items-sm-start { + align-items: flex-start !important; + } + .align-items-sm-end { + align-items: flex-end !important; + } + .align-items-sm-center { + align-items: center !important; + } + .align-items-sm-baseline { + align-items: baseline !important; + } + .align-items-sm-stretch { + align-items: stretch !important; + } + .align-content-sm-start { + align-content: flex-start !important; + } + .align-content-sm-end { + align-content: flex-end !important; + } + .align-content-sm-center { + align-content: center !important; + } + .align-content-sm-between { + align-content: space-between !important; + } + .align-content-sm-around { + align-content: space-around !important; + } + .align-content-sm-stretch { + align-content: stretch !important; + } + .align-self-sm-auto { + align-self: auto !important; + } + .align-self-sm-start { + align-self: flex-start !important; + } + .align-self-sm-end { + align-self: flex-end !important; + } + .align-self-sm-center { + align-self: center !important; + } + .align-self-sm-baseline { + align-self: baseline !important; + } + .align-self-sm-stretch { + align-self: stretch !important; + } + .order-sm-first { + order: -1 !important; + } + .order-sm-0 { + order: 0 !important; + } + .order-sm-1 { + order: 1 !important; + } + .order-sm-2 { + order: 2 !important; + } + .order-sm-3 { + order: 3 !important; + } + .order-sm-4 { + order: 4 !important; + } + .order-sm-5 { + order: 5 !important; + } + .order-sm-last { + order: 6 !important; + } + .m-sm-0 { + margin: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-sm-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-sm-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-sm-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-sm-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-sm-0 { + margin-top: 0 !important; + } + .mt-sm-1 { + margin-top: 0.25rem !important; + } + .mt-sm-2 { + margin-top: 0.5rem !important; + } + .mt-sm-3 { + margin-top: 1rem !important; + } + .mt-sm-4 { + margin-top: 1.5rem !important; + } + .mt-sm-5 { + margin-top: 3rem !important; + } + .mt-sm-auto { + margin-top: auto !important; + } + .me-sm-0 { + margin-right: 0 !important; + } + .me-sm-1 { + margin-right: 0.25rem !important; + } + .me-sm-2 { + margin-right: 0.5rem !important; + } + .me-sm-3 { + margin-right: 1rem !important; + } + .me-sm-4 { + margin-right: 1.5rem !important; + } + .me-sm-5 { + margin-right: 3rem !important; + } + .me-sm-auto { + margin-right: auto !important; + } + .mb-sm-0 { + margin-bottom: 0 !important; + } + .mb-sm-1 { + margin-bottom: 0.25rem !important; + } + .mb-sm-2 { + margin-bottom: 0.5rem !important; + } + .mb-sm-3 { + margin-bottom: 1rem !important; + } + .mb-sm-4 { + margin-bottom: 1.5rem !important; + } + .mb-sm-5 { + margin-bottom: 3rem !important; + } + .mb-sm-auto { + margin-bottom: auto !important; + } + .ms-sm-0 { + margin-left: 0 !important; + } + .ms-sm-1 { + margin-left: 0.25rem !important; + } + .ms-sm-2 { + margin-left: 0.5rem !important; + } + .ms-sm-3 { + margin-left: 1rem !important; + } + .ms-sm-4 { + margin-left: 1.5rem !important; + } + .ms-sm-5 { + margin-left: 3rem !important; + } + .ms-sm-auto { + margin-left: auto !important; + } + .p-sm-0 { + padding: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-sm-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-sm-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-sm-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-sm-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-sm-0 { + padding-top: 0 !important; + } + .pt-sm-1 { + padding-top: 0.25rem !important; + } + .pt-sm-2 { + padding-top: 0.5rem !important; + } + .pt-sm-3 { + padding-top: 1rem !important; + } + .pt-sm-4 { + padding-top: 1.5rem !important; + } + .pt-sm-5 { + padding-top: 3rem !important; + } + .pe-sm-0 { + padding-right: 0 !important; + } + .pe-sm-1 { + padding-right: 0.25rem !important; + } + .pe-sm-2 { + padding-right: 0.5rem !important; + } + .pe-sm-3 { + padding-right: 1rem !important; + } + .pe-sm-4 { + padding-right: 1.5rem !important; + } + .pe-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-0 { + padding-bottom: 0 !important; + } + .pb-sm-1 { + padding-bottom: 0.25rem !important; + } + .pb-sm-2 { + padding-bottom: 0.5rem !important; + } + .pb-sm-3 { + padding-bottom: 1rem !important; + } + .pb-sm-4 { + padding-bottom: 1.5rem !important; + } + .pb-sm-5 { + padding-bottom: 3rem !important; + } + .ps-sm-0 { + padding-left: 0 !important; + } + .ps-sm-1 { + padding-left: 0.25rem !important; + } + .ps-sm-2 { + padding-left: 0.5rem !important; + } + .ps-sm-3 { + padding-left: 1rem !important; + } + .ps-sm-4 { + padding-left: 1.5rem !important; + } + .ps-sm-5 { + padding-left: 3rem !important; + } + .text-sm-start { + text-align: left !important; + } + .text-sm-end { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} +@media (min-width: 768px) { + .float-md-start { + float: left !important; + } + .float-md-end { + float: right !important; + } + .float-md-none { + float: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-grid { + display: grid !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: flex !important; + } + .d-md-inline-flex { + display: inline-flex !important; + } + .d-md-none { + display: none !important; + } + .flex-md-fill { + flex: 1 1 auto !important; + } + .flex-md-row { + flex-direction: row !important; + } + .flex-md-column { + flex-direction: column !important; + } + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + .flex-md-grow-0 { + flex-grow: 0 !important; + } + .flex-md-grow-1 { + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + .flex-md-wrap { + flex-wrap: wrap !important; + } + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .gap-md-0 { + gap: 0 !important; + } + .gap-md-1 { + gap: 0.25rem !important; + } + .gap-md-2 { + gap: 0.5rem !important; + } + .gap-md-3 { + gap: 1rem !important; + } + .gap-md-4 { + gap: 1.5rem !important; + } + .gap-md-5 { + gap: 3rem !important; + } + .justify-content-md-start { + justify-content: flex-start !important; + } + .justify-content-md-end { + justify-content: flex-end !important; + } + .justify-content-md-center { + justify-content: center !important; + } + .justify-content-md-between { + justify-content: space-between !important; + } + .justify-content-md-around { + justify-content: space-around !important; + } + .justify-content-md-evenly { + justify-content: space-evenly !important; + } + .align-items-md-start { + align-items: flex-start !important; + } + .align-items-md-end { + align-items: flex-end !important; + } + .align-items-md-center { + align-items: center !important; + } + .align-items-md-baseline { + align-items: baseline !important; + } + .align-items-md-stretch { + align-items: stretch !important; + } + .align-content-md-start { + align-content: flex-start !important; + } + .align-content-md-end { + align-content: flex-end !important; + } + .align-content-md-center { + align-content: center !important; + } + .align-content-md-between { + align-content: space-between !important; + } + .align-content-md-around { + align-content: space-around !important; + } + .align-content-md-stretch { + align-content: stretch !important; + } + .align-self-md-auto { + align-self: auto !important; + } + .align-self-md-start { + align-self: flex-start !important; + } + .align-self-md-end { + align-self: flex-end !important; + } + .align-self-md-center { + align-self: center !important; + } + .align-self-md-baseline { + align-self: baseline !important; + } + .align-self-md-stretch { + align-self: stretch !important; + } + .order-md-first { + order: -1 !important; + } + .order-md-0 { + order: 0 !important; + } + .order-md-1 { + order: 1 !important; + } + .order-md-2 { + order: 2 !important; + } + .order-md-3 { + order: 3 !important; + } + .order-md-4 { + order: 4 !important; + } + .order-md-5 { + order: 5 !important; + } + .order-md-last { + order: 6 !important; + } + .m-md-0 { + margin: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-md-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-md-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-md-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-md-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-md-0 { + margin-top: 0 !important; + } + .mt-md-1 { + margin-top: 0.25rem !important; + } + .mt-md-2 { + margin-top: 0.5rem !important; + } + .mt-md-3 { + margin-top: 1rem !important; + } + .mt-md-4 { + margin-top: 1.5rem !important; + } + .mt-md-5 { + margin-top: 3rem !important; + } + .mt-md-auto { + margin-top: auto !important; + } + .me-md-0 { + margin-right: 0 !important; + } + .me-md-1 { + margin-right: 0.25rem !important; + } + .me-md-2 { + margin-right: 0.5rem !important; + } + .me-md-3 { + margin-right: 1rem !important; + } + .me-md-4 { + margin-right: 1.5rem !important; + } + .me-md-5 { + margin-right: 3rem !important; + } + .me-md-auto { + margin-right: auto !important; + } + .mb-md-0 { + margin-bottom: 0 !important; + } + .mb-md-1 { + margin-bottom: 0.25rem !important; + } + .mb-md-2 { + margin-bottom: 0.5rem !important; + } + .mb-md-3 { + margin-bottom: 1rem !important; + } + .mb-md-4 { + margin-bottom: 1.5rem !important; + } + .mb-md-5 { + margin-bottom: 3rem !important; + } + .mb-md-auto { + margin-bottom: auto !important; + } + .ms-md-0 { + margin-left: 0 !important; + } + .ms-md-1 { + margin-left: 0.25rem !important; + } + .ms-md-2 { + margin-left: 0.5rem !important; + } + .ms-md-3 { + margin-left: 1rem !important; + } + .ms-md-4 { + margin-left: 1.5rem !important; + } + .ms-md-5 { + margin-left: 3rem !important; + } + .ms-md-auto { + margin-left: auto !important; + } + .p-md-0 { + padding: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-md-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-md-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-md-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-md-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-md-0 { + padding-top: 0 !important; + } + .pt-md-1 { + padding-top: 0.25rem !important; + } + .pt-md-2 { + padding-top: 0.5rem !important; + } + .pt-md-3 { + padding-top: 1rem !important; + } + .pt-md-4 { + padding-top: 1.5rem !important; + } + .pt-md-5 { + padding-top: 3rem !important; + } + .pe-md-0 { + padding-right: 0 !important; + } + .pe-md-1 { + padding-right: 0.25rem !important; + } + .pe-md-2 { + padding-right: 0.5rem !important; + } + .pe-md-3 { + padding-right: 1rem !important; + } + .pe-md-4 { + padding-right: 1.5rem !important; + } + .pe-md-5 { + padding-right: 3rem !important; + } + .pb-md-0 { + padding-bottom: 0 !important; + } + .pb-md-1 { + padding-bottom: 0.25rem !important; + } + .pb-md-2 { + padding-bottom: 0.5rem !important; + } + .pb-md-3 { + padding-bottom: 1rem !important; + } + .pb-md-4 { + padding-bottom: 1.5rem !important; + } + .pb-md-5 { + padding-bottom: 3rem !important; + } + .ps-md-0 { + padding-left: 0 !important; + } + .ps-md-1 { + padding-left: 0.25rem !important; + } + .ps-md-2 { + padding-left: 0.5rem !important; + } + .ps-md-3 { + padding-left: 1rem !important; + } + .ps-md-4 { + padding-left: 1.5rem !important; + } + .ps-md-5 { + padding-left: 3rem !important; + } + .text-md-start { + text-align: left !important; + } + .text-md-end { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} +@media (min-width: 992px) { + .float-lg-start { + float: left !important; + } + .float-lg-end { + float: right !important; + } + .float-lg-none { + float: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-grid { + display: grid !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: flex !important; + } + .d-lg-inline-flex { + display: inline-flex !important; + } + .d-lg-none { + display: none !important; + } + .flex-lg-fill { + flex: 1 1 auto !important; + } + .flex-lg-row { + flex-direction: row !important; + } + .flex-lg-column { + flex-direction: column !important; + } + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + .flex-lg-wrap { + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .gap-lg-0 { + gap: 0 !important; + } + .gap-lg-1 { + gap: 0.25rem !important; + } + .gap-lg-2 { + gap: 0.5rem !important; + } + .gap-lg-3 { + gap: 1rem !important; + } + .gap-lg-4 { + gap: 1.5rem !important; + } + .gap-lg-5 { + gap: 3rem !important; + } + .justify-content-lg-start { + justify-content: flex-start !important; + } + .justify-content-lg-end { + justify-content: flex-end !important; + } + .justify-content-lg-center { + justify-content: center !important; + } + .justify-content-lg-between { + justify-content: space-between !important; + } + .justify-content-lg-around { + justify-content: space-around !important; + } + .justify-content-lg-evenly { + justify-content: space-evenly !important; + } + .align-items-lg-start { + align-items: flex-start !important; + } + .align-items-lg-end { + align-items: flex-end !important; + } + .align-items-lg-center { + align-items: center !important; + } + .align-items-lg-baseline { + align-items: baseline !important; + } + .align-items-lg-stretch { + align-items: stretch !important; + } + .align-content-lg-start { + align-content: flex-start !important; + } + .align-content-lg-end { + align-content: flex-end !important; + } + .align-content-lg-center { + align-content: center !important; + } + .align-content-lg-between { + align-content: space-between !important; + } + .align-content-lg-around { + align-content: space-around !important; + } + .align-content-lg-stretch { + align-content: stretch !important; + } + .align-self-lg-auto { + align-self: auto !important; + } + .align-self-lg-start { + align-self: flex-start !important; + } + .align-self-lg-end { + align-self: flex-end !important; + } + .align-self-lg-center { + align-self: center !important; + } + .align-self-lg-baseline { + align-self: baseline !important; + } + .align-self-lg-stretch { + align-self: stretch !important; + } + .order-lg-first { + order: -1 !important; + } + .order-lg-0 { + order: 0 !important; + } + .order-lg-1 { + order: 1 !important; + } + .order-lg-2 { + order: 2 !important; + } + .order-lg-3 { + order: 3 !important; + } + .order-lg-4 { + order: 4 !important; + } + .order-lg-5 { + order: 5 !important; + } + .order-lg-last { + order: 6 !important; + } + .m-lg-0 { + margin: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-lg-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-lg-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-lg-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-lg-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-lg-0 { + margin-top: 0 !important; + } + .mt-lg-1 { + margin-top: 0.25rem !important; + } + .mt-lg-2 { + margin-top: 0.5rem !important; + } + .mt-lg-3 { + margin-top: 1rem !important; + } + .mt-lg-4 { + margin-top: 1.5rem !important; + } + .mt-lg-5 { + margin-top: 3rem !important; + } + .mt-lg-auto { + margin-top: auto !important; + } + .me-lg-0 { + margin-right: 0 !important; + } + .me-lg-1 { + margin-right: 0.25rem !important; + } + .me-lg-2 { + margin-right: 0.5rem !important; + } + .me-lg-3 { + margin-right: 1rem !important; + } + .me-lg-4 { + margin-right: 1.5rem !important; + } + .me-lg-5 { + margin-right: 3rem !important; + } + .me-lg-auto { + margin-right: auto !important; + } + .mb-lg-0 { + margin-bottom: 0 !important; + } + .mb-lg-1 { + margin-bottom: 0.25rem !important; + } + .mb-lg-2 { + margin-bottom: 0.5rem !important; + } + .mb-lg-3 { + margin-bottom: 1rem !important; + } + .mb-lg-4 { + margin-bottom: 1.5rem !important; + } + .mb-lg-5 { + margin-bottom: 3rem !important; + } + .mb-lg-auto { + margin-bottom: auto !important; + } + .ms-lg-0 { + margin-left: 0 !important; + } + .ms-lg-1 { + margin-left: 0.25rem !important; + } + .ms-lg-2 { + margin-left: 0.5rem !important; + } + .ms-lg-3 { + margin-left: 1rem !important; + } + .ms-lg-4 { + margin-left: 1.5rem !important; + } + .ms-lg-5 { + margin-left: 3rem !important; + } + .ms-lg-auto { + margin-left: auto !important; + } + .p-lg-0 { + padding: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-lg-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-lg-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-lg-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-lg-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-lg-0 { + padding-top: 0 !important; + } + .pt-lg-1 { + padding-top: 0.25rem !important; + } + .pt-lg-2 { + padding-top: 0.5rem !important; + } + .pt-lg-3 { + padding-top: 1rem !important; + } + .pt-lg-4 { + padding-top: 1.5rem !important; + } + .pt-lg-5 { + padding-top: 3rem !important; + } + .pe-lg-0 { + padding-right: 0 !important; + } + .pe-lg-1 { + padding-right: 0.25rem !important; + } + .pe-lg-2 { + padding-right: 0.5rem !important; + } + .pe-lg-3 { + padding-right: 1rem !important; + } + .pe-lg-4 { + padding-right: 1.5rem !important; + } + .pe-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-0 { + padding-bottom: 0 !important; + } + .pb-lg-1 { + padding-bottom: 0.25rem !important; + } + .pb-lg-2 { + padding-bottom: 0.5rem !important; + } + .pb-lg-3 { + padding-bottom: 1rem !important; + } + .pb-lg-4 { + padding-bottom: 1.5rem !important; + } + .pb-lg-5 { + padding-bottom: 3rem !important; + } + .ps-lg-0 { + padding-left: 0 !important; + } + .ps-lg-1 { + padding-left: 0.25rem !important; + } + .ps-lg-2 { + padding-left: 0.5rem !important; + } + .ps-lg-3 { + padding-left: 1rem !important; + } + .ps-lg-4 { + padding-left: 1.5rem !important; + } + .ps-lg-5 { + padding-left: 3rem !important; + } + .text-lg-start { + text-align: left !important; + } + .text-lg-end { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .float-xl-start { + float: left !important; + } + .float-xl-end { + float: right !important; + } + .float-xl-none { + float: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-grid { + display: grid !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: flex !important; + } + .d-xl-inline-flex { + display: inline-flex !important; + } + .d-xl-none { + display: none !important; + } + .flex-xl-fill { + flex: 1 1 auto !important; + } + .flex-xl-row { + flex-direction: row !important; + } + .flex-xl-column { + flex-direction: column !important; + } + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xl-wrap { + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .gap-xl-0 { + gap: 0 !important; + } + .gap-xl-1 { + gap: 0.25rem !important; + } + .gap-xl-2 { + gap: 0.5rem !important; + } + .gap-xl-3 { + gap: 1rem !important; + } + .gap-xl-4 { + gap: 1.5rem !important; + } + .gap-xl-5 { + gap: 3rem !important; + } + .justify-content-xl-start { + justify-content: flex-start !important; + } + .justify-content-xl-end { + justify-content: flex-end !important; + } + .justify-content-xl-center { + justify-content: center !important; + } + .justify-content-xl-between { + justify-content: space-between !important; + } + .justify-content-xl-around { + justify-content: space-around !important; + } + .justify-content-xl-evenly { + justify-content: space-evenly !important; + } + .align-items-xl-start { + align-items: flex-start !important; + } + .align-items-xl-end { + align-items: flex-end !important; + } + .align-items-xl-center { + align-items: center !important; + } + .align-items-xl-baseline { + align-items: baseline !important; + } + .align-items-xl-stretch { + align-items: stretch !important; + } + .align-content-xl-start { + align-content: flex-start !important; + } + .align-content-xl-end { + align-content: flex-end !important; + } + .align-content-xl-center { + align-content: center !important; + } + .align-content-xl-between { + align-content: space-between !important; + } + .align-content-xl-around { + align-content: space-around !important; + } + .align-content-xl-stretch { + align-content: stretch !important; + } + .align-self-xl-auto { + align-self: auto !important; + } + .align-self-xl-start { + align-self: flex-start !important; + } + .align-self-xl-end { + align-self: flex-end !important; + } + .align-self-xl-center { + align-self: center !important; + } + .align-self-xl-baseline { + align-self: baseline !important; + } + .align-self-xl-stretch { + align-self: stretch !important; + } + .order-xl-first { + order: -1 !important; + } + .order-xl-0 { + order: 0 !important; + } + .order-xl-1 { + order: 1 !important; + } + .order-xl-2 { + order: 2 !important; + } + .order-xl-3 { + order: 3 !important; + } + .order-xl-4 { + order: 4 !important; + } + .order-xl-5 { + order: 5 !important; + } + .order-xl-last { + order: 6 !important; + } + .m-xl-0 { + margin: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xl-0 { + margin-top: 0 !important; + } + .mt-xl-1 { + margin-top: 0.25rem !important; + } + .mt-xl-2 { + margin-top: 0.5rem !important; + } + .mt-xl-3 { + margin-top: 1rem !important; + } + .mt-xl-4 { + margin-top: 1.5rem !important; + } + .mt-xl-5 { + margin-top: 3rem !important; + } + .mt-xl-auto { + margin-top: auto !important; + } + .me-xl-0 { + margin-right: 0 !important; + } + .me-xl-1 { + margin-right: 0.25rem !important; + } + .me-xl-2 { + margin-right: 0.5rem !important; + } + .me-xl-3 { + margin-right: 1rem !important; + } + .me-xl-4 { + margin-right: 1.5rem !important; + } + .me-xl-5 { + margin-right: 3rem !important; + } + .me-xl-auto { + margin-right: auto !important; + } + .mb-xl-0 { + margin-bottom: 0 !important; + } + .mb-xl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xl-3 { + margin-bottom: 1rem !important; + } + .mb-xl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xl-5 { + margin-bottom: 3rem !important; + } + .mb-xl-auto { + margin-bottom: auto !important; + } + .ms-xl-0 { + margin-left: 0 !important; + } + .ms-xl-1 { + margin-left: 0.25rem !important; + } + .ms-xl-2 { + margin-left: 0.5rem !important; + } + .ms-xl-3 { + margin-left: 1rem !important; + } + .ms-xl-4 { + margin-left: 1.5rem !important; + } + .ms-xl-5 { + margin-left: 3rem !important; + } + .ms-xl-auto { + margin-left: auto !important; + } + .p-xl-0 { + padding: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xl-0 { + padding-top: 0 !important; + } + .pt-xl-1 { + padding-top: 0.25rem !important; + } + .pt-xl-2 { + padding-top: 0.5rem !important; + } + .pt-xl-3 { + padding-top: 1rem !important; + } + .pt-xl-4 { + padding-top: 1.5rem !important; + } + .pt-xl-5 { + padding-top: 3rem !important; + } + .pe-xl-0 { + padding-right: 0 !important; + } + .pe-xl-1 { + padding-right: 0.25rem !important; + } + .pe-xl-2 { + padding-right: 0.5rem !important; + } + .pe-xl-3 { + padding-right: 1rem !important; + } + .pe-xl-4 { + padding-right: 1.5rem !important; + } + .pe-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-0 { + padding-bottom: 0 !important; + } + .pb-xl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xl-3 { + padding-bottom: 1rem !important; + } + .pb-xl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xl-5 { + padding-bottom: 3rem !important; + } + .ps-xl-0 { + padding-left: 0 !important; + } + .ps-xl-1 { + padding-left: 0.25rem !important; + } + .ps-xl-2 { + padding-left: 0.5rem !important; + } + .ps-xl-3 { + padding-left: 1rem !important; + } + .ps-xl-4 { + padding-left: 1.5rem !important; + } + .ps-xl-5 { + padding-left: 3rem !important; + } + .text-xl-start { + text-align: left !important; + } + .text-xl-end { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important; + } + .float-xxl-end { + float: right !important; + } + .float-xxl-none { + float: none !important; + } + .d-xxl-inline { + display: inline !important; + } + .d-xxl-inline-block { + display: inline-block !important; + } + .d-xxl-block { + display: block !important; + } + .d-xxl-grid { + display: grid !important; + } + .d-xxl-table { + display: table !important; + } + .d-xxl-table-row { + display: table-row !important; + } + .d-xxl-table-cell { + display: table-cell !important; + } + .d-xxl-flex { + display: flex !important; + } + .d-xxl-inline-flex { + display: inline-flex !important; + } + .d-xxl-none { + display: none !important; + } + .flex-xxl-fill { + flex: 1 1 auto !important; + } + .flex-xxl-row { + flex-direction: row !important; + } + .flex-xxl-column { + flex-direction: column !important; + } + .flex-xxl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xxl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xxl-grow-0 { + flex-grow: 0 !important; + } + .flex-xxl-grow-1 { + flex-grow: 1 !important; + } + .flex-xxl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xxl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xxl-wrap { + flex-wrap: wrap !important; + } + .flex-xxl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .gap-xxl-0 { + gap: 0 !important; + } + .gap-xxl-1 { + gap: 0.25rem !important; + } + .gap-xxl-2 { + gap: 0.5rem !important; + } + .gap-xxl-3 { + gap: 1rem !important; + } + .gap-xxl-4 { + gap: 1.5rem !important; + } + .gap-xxl-5 { + gap: 3rem !important; + } + .justify-content-xxl-start { + justify-content: flex-start !important; + } + .justify-content-xxl-end { + justify-content: flex-end !important; + } + .justify-content-xxl-center { + justify-content: center !important; + } + .justify-content-xxl-between { + justify-content: space-between !important; + } + .justify-content-xxl-around { + justify-content: space-around !important; + } + .justify-content-xxl-evenly { + justify-content: space-evenly !important; + } + .align-items-xxl-start { + align-items: flex-start !important; + } + .align-items-xxl-end { + align-items: flex-end !important; + } + .align-items-xxl-center { + align-items: center !important; + } + .align-items-xxl-baseline { + align-items: baseline !important; + } + .align-items-xxl-stretch { + align-items: stretch !important; + } + .align-content-xxl-start { + align-content: flex-start !important; + } + .align-content-xxl-end { + align-content: flex-end !important; + } + .align-content-xxl-center { + align-content: center !important; + } + .align-content-xxl-between { + align-content: space-between !important; + } + .align-content-xxl-around { + align-content: space-around !important; + } + .align-content-xxl-stretch { + align-content: stretch !important; + } + .align-self-xxl-auto { + align-self: auto !important; + } + .align-self-xxl-start { + align-self: flex-start !important; + } + .align-self-xxl-end { + align-self: flex-end !important; + } + .align-self-xxl-center { + align-self: center !important; + } + .align-self-xxl-baseline { + align-self: baseline !important; + } + .align-self-xxl-stretch { + align-self: stretch !important; + } + .order-xxl-first { + order: -1 !important; + } + .order-xxl-0 { + order: 0 !important; + } + .order-xxl-1 { + order: 1 !important; + } + .order-xxl-2 { + order: 2 !important; + } + .order-xxl-3 { + order: 3 !important; + } + .order-xxl-4 { + order: 4 !important; + } + .order-xxl-5 { + order: 5 !important; + } + .order-xxl-last { + order: 6 !important; + } + .m-xxl-0 { + margin: 0 !important; + } + .m-xxl-1 { + margin: 0.25rem !important; + } + .m-xxl-2 { + margin: 0.5rem !important; + } + .m-xxl-3 { + margin: 1rem !important; + } + .m-xxl-4 { + margin: 1.5rem !important; + } + .m-xxl-5 { + margin: 3rem !important; + } + .m-xxl-auto { + margin: auto !important; + } + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xxl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xxl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xxl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xxl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xxl-0 { + margin-top: 0 !important; + } + .mt-xxl-1 { + margin-top: 0.25rem !important; + } + .mt-xxl-2 { + margin-top: 0.5rem !important; + } + .mt-xxl-3 { + margin-top: 1rem !important; + } + .mt-xxl-4 { + margin-top: 1.5rem !important; + } + .mt-xxl-5 { + margin-top: 3rem !important; + } + .mt-xxl-auto { + margin-top: auto !important; + } + .me-xxl-0 { + margin-right: 0 !important; + } + .me-xxl-1 { + margin-right: 0.25rem !important; + } + .me-xxl-2 { + margin-right: 0.5rem !important; + } + .me-xxl-3 { + margin-right: 1rem !important; + } + .me-xxl-4 { + margin-right: 1.5rem !important; + } + .me-xxl-5 { + margin-right: 3rem !important; + } + .me-xxl-auto { + margin-right: auto !important; + } + .mb-xxl-0 { + margin-bottom: 0 !important; + } + .mb-xxl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xxl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xxl-3 { + margin-bottom: 1rem !important; + } + .mb-xxl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xxl-5 { + margin-bottom: 3rem !important; + } + .mb-xxl-auto { + margin-bottom: auto !important; + } + .ms-xxl-0 { + margin-left: 0 !important; + } + .ms-xxl-1 { + margin-left: 0.25rem !important; + } + .ms-xxl-2 { + margin-left: 0.5rem !important; + } + .ms-xxl-3 { + margin-left: 1rem !important; + } + .ms-xxl-4 { + margin-left: 1.5rem !important; + } + .ms-xxl-5 { + margin-left: 3rem !important; + } + .ms-xxl-auto { + margin-left: auto !important; + } + .p-xxl-0 { + padding: 0 !important; + } + .p-xxl-1 { + padding: 0.25rem !important; + } + .p-xxl-2 { + padding: 0.5rem !important; + } + .p-xxl-3 { + padding: 1rem !important; + } + .p-xxl-4 { + padding: 1.5rem !important; + } + .p-xxl-5 { + padding: 3rem !important; + } + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xxl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xxl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xxl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xxl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xxl-0 { + padding-top: 0 !important; + } + .pt-xxl-1 { + padding-top: 0.25rem !important; + } + .pt-xxl-2 { + padding-top: 0.5rem !important; + } + .pt-xxl-3 { + padding-top: 1rem !important; + } + .pt-xxl-4 { + padding-top: 1.5rem !important; + } + .pt-xxl-5 { + padding-top: 3rem !important; + } + .pe-xxl-0 { + padding-right: 0 !important; + } + .pe-xxl-1 { + padding-right: 0.25rem !important; + } + .pe-xxl-2 { + padding-right: 0.5rem !important; + } + .pe-xxl-3 { + padding-right: 1rem !important; + } + .pe-xxl-4 { + padding-right: 1.5rem !important; + } + .pe-xxl-5 { + padding-right: 3rem !important; + } + .pb-xxl-0 { + padding-bottom: 0 !important; + } + .pb-xxl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xxl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xxl-3 { + padding-bottom: 1rem !important; + } + .pb-xxl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xxl-5 { + padding-bottom: 3rem !important; + } + .ps-xxl-0 { + padding-left: 0 !important; + } + .ps-xxl-1 { + padding-left: 0.25rem !important; + } + .ps-xxl-2 { + padding-left: 0.5rem !important; + } + .ps-xxl-3 { + padding-left: 1rem !important; + } + .ps-xxl-4 { + padding-left: 1.5rem !important; + } + .ps-xxl-5 { + padding-left: 3rem !important; + } + .text-xxl-start { + text-align: left !important; + } + .text-xxl-end { + text-align: right !important; + } + .text-xxl-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important; + } + .fs-2 { + font-size: 2rem !important; + } + .fs-3 { + font-size: 1.75rem !important; + } + .fs-4 { + font-size: 1.5rem !important; + } +} +@media print { + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-grid { + display: grid !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: flex !important; + } + .d-print-inline-flex { + display: inline-flex !important; + } + .d-print-none { + display: none !important; + } +} +@font-face { + font-family: Pe-icon-7-stroke; + src: url(../../fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.eot?d7yf1v); + src: url(../../fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.eot?#iefixd7yf1v) format('embedded-opentype'), + url(../../fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.woff?d7yf1v) format('woff'), + url(../../fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.ttf?d7yf1v) format('truetype'), + url(../../fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.svg?d7yf1v#Pe-icon-7-stroke) format('svg'); + font-weight: 400; + font-style: normal; +} +[class*=' pe-7s-'], +[class^='pe-7s-'] { + display: inline-block; + font-family: Pe-icon-7-stroke; + speak: none; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.pe-7s-album:before { + content: '\e6aa'; +} +.pe-7s-arc:before { + content: '\e6ab'; +} +.pe-7s-back-2:before { + content: '\e6ac'; +} +.pe-7s-bandaid:before { + content: '\e6ad'; +} +.pe-7s-car:before { + content: '\e6ae'; +} +.pe-7s-diamond:before { + content: '\e6af'; +} +.pe-7s-door-lock:before { + content: '\e6b0'; +} +.pe-7s-eyedropper:before { + content: '\e6b1'; +} +.pe-7s-female:before { + content: '\e6b2'; +} +.pe-7s-gym:before { + content: '\e6b3'; +} +.pe-7s-hammer:before { + content: '\e6b4'; +} +.pe-7s-headphones:before { + content: '\e6b5'; +} +.pe-7s-helm:before { + content: '\e6b6'; +} +.pe-7s-hourglass:before { + content: '\e6b7'; +} +.pe-7s-leaf:before { + content: '\e6b8'; +} +.pe-7s-magic-wand:before { + content: '\e6b9'; +} +.pe-7s-male:before { + content: '\e6ba'; +} +.pe-7s-map-2:before { + content: '\e6bb'; +} +.pe-7s-next-2:before { + content: '\e6bc'; +} +.pe-7s-paint-bucket:before { + content: '\e6bd'; +} +.pe-7s-pendrive:before { + content: '\e6be'; +} +.pe-7s-photo:before { + content: '\e6bf'; +} +.pe-7s-piggy:before { + content: '\e6c0'; +} +.pe-7s-plugin:before { + content: '\e6c1'; +} +.pe-7s-refresh-2:before { + content: '\e6c2'; +} +.pe-7s-rocket:before { + content: '\e6c3'; +} +.pe-7s-settings:before { + content: '\e6c4'; +} +.pe-7s-shield:before { + content: '\e6c5'; +} +.pe-7s-smile:before { + content: '\e6c6'; +} +.pe-7s-usb:before { + content: '\e6c7'; +} +.pe-7s-vector:before { + content: '\e6c8'; +} +.pe-7s-wine:before { + content: '\e6c9'; +} +.pe-7s-cloud-upload:before { + content: '\e68a'; +} +.pe-7s-cash:before { + content: '\e68c'; +} +.pe-7s-close:before { + content: '\e680'; +} +.pe-7s-bluetooth:before { + content: '\e68d'; +} +.pe-7s-cloud-download:before { + content: '\e68b'; +} +.pe-7s-way:before { + content: '\e68e'; +} +.pe-7s-close-circle:before { + content: '\e681'; +} +.pe-7s-id:before { + content: '\e68f'; +} +.pe-7s-angle-up:before { + content: '\e682'; +} +.pe-7s-wristwatch:before { + content: '\e690'; +} +.pe-7s-angle-up-circle:before { + content: '\e683'; +} +.pe-7s-world:before { + content: '\e691'; +} +.pe-7s-angle-right:before { + content: '\e684'; +} +.pe-7s-volume:before { + content: '\e692'; +} +.pe-7s-angle-right-circle:before { + content: '\e685'; +} +.pe-7s-users:before { + content: '\e693'; +} +.pe-7s-angle-left:before { + content: '\e686'; +} +.pe-7s-user-female:before { + content: '\e694'; +} +.pe-7s-angle-left-circle:before { + content: '\e687'; +} +.pe-7s-up-arrow:before { + content: '\e695'; +} +.pe-7s-angle-down:before { + content: '\e688'; +} +.pe-7s-switch:before { + content: '\e696'; +} +.pe-7s-angle-down-circle:before { + content: '\e689'; +} +.pe-7s-scissors:before { + content: '\e697'; +} +.pe-7s-wallet:before { + content: '\e600'; +} +.pe-7s-safe:before { + content: '\e698'; +} +.pe-7s-volume2:before { + content: '\e601'; +} +.pe-7s-volume1:before { + content: '\e602'; +} +.pe-7s-voicemail:before { + content: '\e603'; +} +.pe-7s-video:before { + content: '\e604'; +} +.pe-7s-user:before { + content: '\e605'; +} +.pe-7s-upload:before { + content: '\e606'; +} +.pe-7s-unlock:before { + content: '\e607'; +} +.pe-7s-umbrella:before { + content: '\e608'; +} +.pe-7s-trash:before { + content: '\e609'; +} +.pe-7s-tools:before { + content: '\e60a'; +} +.pe-7s-timer:before { + content: '\e60b'; +} +.pe-7s-ticket:before { + content: '\e60c'; +} +.pe-7s-target:before { + content: '\e60d'; +} +.pe-7s-sun:before { + content: '\e60e'; +} +.pe-7s-study:before { + content: '\e60f'; +} +.pe-7s-stopwatch:before { + content: '\e610'; +} +.pe-7s-star:before { + content: '\e611'; +} +.pe-7s-speaker:before { + content: '\e612'; +} +.pe-7s-signal:before { + content: '\e613'; +} +.pe-7s-shuffle:before { + content: '\e614'; +} +.pe-7s-shopbag:before { + content: '\e615'; +} +.pe-7s-share:before { + content: '\e616'; +} +.pe-7s-server:before { + content: '\e617'; +} +.pe-7s-search:before { + content: '\e618'; +} +.pe-7s-film:before { + content: '\e6a5'; +} +.pe-7s-science:before { + content: '\e619'; +} +.pe-7s-disk:before { + content: '\e6a6'; +} +.pe-7s-ribbon:before { + content: '\e61a'; +} +.pe-7s-repeat:before { + content: '\e61b'; +} +.pe-7s-refresh:before { + content: '\e61c'; +} +.pe-7s-add-user:before { + content: '\e6a9'; +} +.pe-7s-refresh-cloud:before { + content: '\e61d'; +} +.pe-7s-paperclip:before { + content: '\e69c'; +} +.pe-7s-radio:before { + content: '\e61e'; +} +.pe-7s-note2:before { + content: '\e69d'; +} +.pe-7s-print:before { + content: '\e61f'; +} +.pe-7s-network:before { + content: '\e69e'; +} +.pe-7s-prev:before { + content: '\e620'; +} +.pe-7s-mute:before { + content: '\e69f'; +} +.pe-7s-power:before { + content: '\e621'; +} +.pe-7s-medal:before { + content: '\e6a0'; +} +.pe-7s-portfolio:before { + content: '\e622'; +} +.pe-7s-like2:before { + content: '\e6a1'; +} +.pe-7s-plus:before { + content: '\e623'; +} +.pe-7s-left-arrow:before { + content: '\e6a2'; +} +.pe-7s-play:before { + content: '\e624'; +} +.pe-7s-key:before { + content: '\e6a3'; +} +.pe-7s-plane:before { + content: '\e625'; +} +.pe-7s-joy:before { + content: '\e6a4'; +} +.pe-7s-photo-gallery:before { + content: '\e626'; +} +.pe-7s-pin:before { + content: '\e69b'; +} +.pe-7s-phone:before { + content: '\e627'; +} +.pe-7s-plug:before { + content: '\e69a'; +} +.pe-7s-pen:before { + content: '\e628'; +} +.pe-7s-right-arrow:before { + content: '\e699'; +} +.pe-7s-paper-plane:before { + content: '\e629'; +} +.pe-7s-delete-user:before { + content: '\e6a7'; +} +.pe-7s-paint:before { + content: '\e62a'; +} +.pe-7s-bottom-arrow:before { + content: '\e6a8'; +} +.pe-7s-notebook:before { + content: '\e62b'; +} +.pe-7s-note:before { + content: '\e62c'; +} +.pe-7s-next:before { + content: '\e62d'; +} +.pe-7s-news-paper:before { + content: '\e62e'; +} +.pe-7s-musiclist:before { + content: '\e62f'; +} +.pe-7s-music:before { + content: '\e630'; +} +.pe-7s-mouse:before { + content: '\e631'; +} +.pe-7s-more:before { + content: '\e632'; +} +.pe-7s-moon:before { + content: '\e633'; +} +.pe-7s-monitor:before { + content: '\e634'; +} +.pe-7s-micro:before { + content: '\e635'; +} +.pe-7s-menu:before { + content: '\e636'; +} +.pe-7s-map:before { + content: '\e637'; +} +.pe-7s-map-marker:before { + content: '\e638'; +} +.pe-7s-mail:before { + content: '\e639'; +} +.pe-7s-mail-open:before { + content: '\e63a'; +} +.pe-7s-mail-open-file:before { + content: '\e63b'; +} +.pe-7s-magnet:before { + content: '\e63c'; +} +.pe-7s-loop:before { + content: '\e63d'; +} +.pe-7s-look:before { + content: '\e63e'; +} +.pe-7s-lock:before { + content: '\e63f'; +} +.pe-7s-lintern:before { + content: '\e640'; +} +.pe-7s-link:before { + content: '\e641'; +} +.pe-7s-like:before { + content: '\e642'; +} +.pe-7s-light:before { + content: '\e643'; +} +.pe-7s-less:before { + content: '\e644'; +} +.pe-7s-keypad:before { + content: '\e645'; +} +.pe-7s-junk:before { + content: '\e646'; +} +.pe-7s-info:before { + content: '\e647'; +} +.pe-7s-home:before { + content: '\e648'; +} +.pe-7s-help2:before { + content: '\e649'; +} +.pe-7s-help1:before { + content: '\e64a'; +} +.pe-7s-graph3:before { + content: '\e64b'; +} +.pe-7s-graph2:before { + content: '\e64c'; +} +.pe-7s-graph1:before { + content: '\e64d'; +} +.pe-7s-graph:before { + content: '\e64e'; +} +.pe-7s-global:before { + content: '\e64f'; +} +.pe-7s-gleam:before { + content: '\e650'; +} +.pe-7s-glasses:before { + content: '\e651'; +} +.pe-7s-gift:before { + content: '\e652'; +} +.pe-7s-folder:before { + content: '\e653'; +} +.pe-7s-flag:before { + content: '\e654'; +} +.pe-7s-filter:before { + content: '\e655'; +} +.pe-7s-file:before { + content: '\e656'; +} +.pe-7s-expand1:before { + content: '\e657'; +} +.pe-7s-exapnd2:before { + content: '\e658'; +} +.pe-7s-edit:before { + content: '\e659'; +} +.pe-7s-drop:before { + content: '\e65a'; +} +.pe-7s-drawer:before { + content: '\e65b'; +} +.pe-7s-download:before { + content: '\e65c'; +} +.pe-7s-display2:before { + content: '\e65d'; +} +.pe-7s-display1:before { + content: '\e65e'; +} +.pe-7s-diskette:before { + content: '\e65f'; +} +.pe-7s-date:before { + content: '\e660'; +} +.pe-7s-cup:before { + content: '\e661'; +} +.pe-7s-culture:before { + content: '\e662'; +} +.pe-7s-crop:before { + content: '\e663'; +} +.pe-7s-credit:before { + content: '\e664'; +} +.pe-7s-copy-file:before { + content: '\e665'; +} +.pe-7s-config:before { + content: '\e666'; +} +.pe-7s-compass:before { + content: '\e667'; +} +.pe-7s-comment:before { + content: '\e668'; +} +.pe-7s-coffee:before { + content: '\e669'; +} +.pe-7s-cloud:before { + content: '\e66a'; +} +.pe-7s-clock:before { + content: '\e66b'; +} +.pe-7s-check:before { + content: '\e66c'; +} +.pe-7s-chat:before { + content: '\e66d'; +} +.pe-7s-cart:before { + content: '\e66e'; +} +.pe-7s-camera:before { + content: '\e66f'; +} +.pe-7s-call:before { + content: '\e670'; +} +.pe-7s-calculator:before { + content: '\e671'; +} +.pe-7s-browser:before { + content: '\e672'; +} +.pe-7s-box2:before { + content: '\e673'; +} +.pe-7s-box1:before { + content: '\e674'; +} +.pe-7s-bookmarks:before { + content: '\e675'; +} +.pe-7s-bicycle:before { + content: '\e676'; +} +.pe-7s-bell:before { + content: '\e677'; +} +.pe-7s-battery:before { + content: '\e678'; +} +.pe-7s-ball:before { + content: '\e679'; +} +.pe-7s-back:before { + content: '\e67a'; +} +.pe-7s-attention:before { + content: '\e67b'; +} +.pe-7s-anchor:before { + content: '\e67c'; +} +.pe-7s-albums:before { + content: '\e67d'; +} +.pe-7s-alarm:before { + content: '\e67e'; +} +.pe-7s-airplay:before { + content: '\e67f'; +} /*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +@font-face { + font-family: 'FontAwesome'; + src: url('../../fonts/FontAwesome/fontawesome-webfont.eot?v=4.7.0'); + src: url('../../fonts/FontAwesome/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), + url('../../fonts/FontAwesome/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), + url('../../fonts/FontAwesome/fontawesome-webfont.woff?v=4.7.0') format('woff'), + url('../../fonts/FontAwesome/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), + url('../../fonts/FontAwesome/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: 0.2em 0.25em 0.15em; + border: solid 0.08em #eee; + border-radius: 0.1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: 0.3em; +} +.fa.fa-pull-right { + margin-left: 0.3em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: 0.3em; +} +.fa.pull-right { + margin-left: 0.3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2)'; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)'; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)'; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)'; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + -webkit-filter: none; + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #fff; +} +.fa-glass:before { + content: '\f000'; +} +.fa-music:before { + content: '\f001'; +} +.fa-search:before { + content: '\f002'; +} +.fa-envelope-o:before { + content: '\f003'; +} +.fa-heart:before { + content: '\f004'; +} +.fa-star:before { + content: '\f005'; +} +.fa-star-o:before { + content: '\f006'; +} +.fa-user:before { + content: '\f007'; +} +.fa-film:before { + content: '\f008'; +} +.fa-th-large:before { + content: '\f009'; +} +.fa-th:before { + content: '\f00a'; +} +.fa-th-list:before { + content: '\f00b'; +} +.fa-check:before { + content: '\f00c'; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: '\f00d'; +} +.fa-search-plus:before { + content: '\f00e'; +} +.fa-search-minus:before { + content: '\f010'; +} +.fa-power-off:before { + content: '\f011'; +} +.fa-signal:before { + content: '\f012'; +} +.fa-gear:before, +.fa-cog:before { + content: '\f013'; +} +.fa-trash-o:before { + content: '\f014'; +} +.fa-home:before { + content: '\f015'; +} +.fa-file-o:before { + content: '\f016'; +} +.fa-clock-o:before { + content: '\f017'; +} +.fa-road:before { + content: '\f018'; +} +.fa-download:before { + content: '\f019'; +} +.fa-arrow-circle-o-down:before { + content: '\f01a'; +} +.fa-arrow-circle-o-up:before { + content: '\f01b'; +} +.fa-inbox:before { + content: '\f01c'; +} +.fa-play-circle-o:before { + content: '\f01d'; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: '\f01e'; +} +.fa-refresh:before { + content: '\f021'; +} +.fa-list-alt:before { + content: '\f022'; +} +.fa-lock:before { + content: '\f023'; +} +.fa-flag:before { + content: '\f024'; +} +.fa-headphones:before { + content: '\f025'; +} +.fa-volume-off:before { + content: '\f026'; +} +.fa-volume-down:before { + content: '\f027'; +} +.fa-volume-up:before { + content: '\f028'; +} +.fa-qrcode:before { + content: '\f029'; +} +.fa-barcode:before { + content: '\f02a'; +} +.fa-tag:before { + content: '\f02b'; +} +.fa-tags:before { + content: '\f02c'; +} +.fa-book:before { + content: '\f02d'; +} +.fa-bookmark:before { + content: '\f02e'; +} +.fa-print:before { + content: '\f02f'; +} +.fa-camera:before { + content: '\f030'; +} +.fa-font:before { + content: '\f031'; +} +.fa-bold:before { + content: '\f032'; +} +.fa-italic:before { + content: '\f033'; +} +.fa-text-height:before { + content: '\f034'; +} +.fa-text-width:before { + content: '\f035'; +} +.fa-align-left:before { + content: '\f036'; +} +.fa-align-center:before { + content: '\f037'; +} +.fa-align-right:before { + content: '\f038'; +} +.fa-align-justify:before { + content: '\f039'; +} +.fa-list:before { + content: '\f03a'; +} +.fa-dedent:before, +.fa-outdent:before { + content: '\f03b'; +} +.fa-indent:before { + content: '\f03c'; +} +.fa-video-camera:before { + content: '\f03d'; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: '\f03e'; +} +.fa-pencil:before { + content: '\f040'; +} +.fa-map-marker:before { + content: '\f041'; +} +.fa-adjust:before { + content: '\f042'; +} +.fa-tint:before { + content: '\f043'; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: '\f044'; +} +.fa-share-square-o:before { + content: '\f045'; +} +.fa-check-square-o:before { + content: '\f046'; +} +.fa-arrows:before { + content: '\f047'; +} +.fa-step-backward:before { + content: '\f048'; +} +.fa-fast-backward:before { + content: '\f049'; +} +.fa-backward:before { + content: '\f04a'; +} +.fa-play:before { + content: '\f04b'; +} +.fa-pause:before { + content: '\f04c'; +} +.fa-stop:before { + content: '\f04d'; +} +.fa-forward:before { + content: '\f04e'; +} +.fa-fast-forward:before { + content: '\f050'; +} +.fa-step-forward:before { + content: '\f051'; +} +.fa-eject:before { + content: '\f052'; +} +.fa-chevron-left:before { + content: '\f053'; +} +.fa-chevron-right:before { + content: '\f054'; +} +.fa-plus-circle:before { + content: '\f055'; +} +.fa-minus-circle:before { + content: '\f056'; +} +.fa-times-circle:before { + content: '\f057'; +} +.fa-check-circle:before { + content: '\f058'; +} +.fa-question-circle:before { + content: '\f059'; +} +.fa-info-circle:before { + content: '\f05a'; +} +.fa-crosshairs:before { + content: '\f05b'; +} +.fa-times-circle-o:before { + content: '\f05c'; +} +.fa-check-circle-o:before { + content: '\f05d'; +} +.fa-ban:before { + content: '\f05e'; +} +.fa-arrow-left:before { + content: '\f060'; +} +.fa-arrow-right:before { + content: '\f061'; +} +.fa-arrow-up:before { + content: '\f062'; +} +.fa-arrow-down:before { + content: '\f063'; +} +.fa-mail-forward:before, +.fa-share:before { + content: '\f064'; +} +.fa-expand:before { + content: '\f065'; +} +.fa-compress:before { + content: '\f066'; +} +.fa-plus:before { + content: '\f067'; +} +.fa-minus:before { + content: '\f068'; +} +.fa-asterisk:before { + content: '\f069'; +} +.fa-exclamation-circle:before { + content: '\f06a'; +} +.fa-gift:before { + content: '\f06b'; +} +.fa-leaf:before { + content: '\f06c'; +} +.fa-fire:before { + content: '\f06d'; +} +.fa-eye:before { + content: '\f06e'; +} +.fa-eye-slash:before { + content: '\f070'; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: '\f071'; +} +.fa-plane:before { + content: '\f072'; +} +.fa-calendar:before { + content: '\f073'; +} +.fa-random:before { + content: '\f074'; +} +.fa-comment:before { + content: '\f075'; +} +.fa-magnet:before { + content: '\f076'; +} +.fa-chevron-up:before { + content: '\f077'; +} +.fa-chevron-down:before { + content: '\f078'; +} +.fa-retweet:before { + content: '\f079'; +} +.fa-shopping-cart:before { + content: '\f07a'; +} +.fa-folder:before { + content: '\f07b'; +} +.fa-folder-open:before { + content: '\f07c'; +} +.fa-arrows-v:before { + content: '\f07d'; +} +.fa-arrows-h:before { + content: '\f07e'; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: '\f080'; +} +.fa-twitter-square:before { + content: '\f081'; +} +.fa-facebook-square:before { + content: '\f082'; +} +.fa-camera-retro:before { + content: '\f083'; +} +.fa-key:before { + content: '\f084'; +} +.fa-gears:before, +.fa-cogs:before { + content: '\f085'; +} +.fa-comments:before { + content: '\f086'; +} +.fa-thumbs-o-up:before { + content: '\f087'; +} +.fa-thumbs-o-down:before { + content: '\f088'; +} +.fa-star-half:before { + content: '\f089'; +} +.fa-heart-o:before { + content: '\f08a'; +} +.fa-sign-out:before { + content: '\f08b'; +} +.fa-linkedin-square:before { + content: '\f08c'; +} +.fa-thumb-tack:before { + content: '\f08d'; +} +.fa-external-link:before { + content: '\f08e'; +} +.fa-sign-in:before { + content: '\f090'; +} +.fa-trophy:before { + content: '\f091'; +} +.fa-github-square:before { + content: '\f092'; +} +.fa-upload:before { + content: '\f093'; +} +.fa-lemon-o:before { + content: '\f094'; +} +.fa-phone:before { + content: '\f095'; +} +.fa-square-o:before { + content: '\f096'; +} +.fa-bookmark-o:before { + content: '\f097'; +} +.fa-phone-square:before { + content: '\f098'; +} +.fa-twitter:before { + content: '\f099'; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: '\f09a'; +} +.fa-github:before { + content: '\f09b'; +} +.fa-unlock:before { + content: '\f09c'; +} +.fa-credit-card:before { + content: '\f09d'; +} +.fa-feed:before, +.fa-rss:before { + content: '\f09e'; +} +.fa-hdd-o:before { + content: '\f0a0'; +} +.fa-bullhorn:before { + content: '\f0a1'; +} +.fa-bell:before { + content: '\f0f3'; +} +.fa-certificate:before { + content: '\f0a3'; +} +.fa-hand-o-right:before { + content: '\f0a4'; +} +.fa-hand-o-left:before { + content: '\f0a5'; +} +.fa-hand-o-up:before { + content: '\f0a6'; +} +.fa-hand-o-down:before { + content: '\f0a7'; +} +.fa-arrow-circle-left:before { + content: '\f0a8'; +} +.fa-arrow-circle-right:before { + content: '\f0a9'; +} +.fa-arrow-circle-up:before { + content: '\f0aa'; +} +.fa-arrow-circle-down:before { + content: '\f0ab'; +} +.fa-globe:before { + content: '\f0ac'; +} +.fa-wrench:before { + content: '\f0ad'; +} +.fa-tasks:before { + content: '\f0ae'; +} +.fa-filter:before { + content: '\f0b0'; +} +.fa-briefcase:before { + content: '\f0b1'; +} +.fa-arrows-alt:before { + content: '\f0b2'; +} +.fa-group:before, +.fa-users:before { + content: '\f0c0'; +} +.fa-chain:before, +.fa-link:before { + content: '\f0c1'; +} +.fa-cloud:before { + content: '\f0c2'; +} +.fa-flask:before { + content: '\f0c3'; +} +.fa-cut:before, +.fa-scissors:before { + content: '\f0c4'; +} +.fa-copy:before, +.fa-files-o:before { + content: '\f0c5'; +} +.fa-paperclip:before { + content: '\f0c6'; +} +.fa-save:before, +.fa-floppy-o:before { + content: '\f0c7'; +} +.fa-square:before { + content: '\f0c8'; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: '\f0c9'; +} +.fa-list-ul:before { + content: '\f0ca'; +} +.fa-list-ol:before { + content: '\f0cb'; +} +.fa-strikethrough:before { + content: '\f0cc'; +} +.fa-underline:before { + content: '\f0cd'; +} +.fa-table:before { + content: '\f0ce'; +} +.fa-magic:before { + content: '\f0d0'; +} +.fa-truck:before { + content: '\f0d1'; +} +.fa-pinterest:before { + content: '\f0d2'; +} +.fa-pinterest-square:before { + content: '\f0d3'; +} +.fa-google-plus-square:before { + content: '\f0d4'; +} +.fa-google-plus:before { + content: '\f0d5'; +} +.fa-money:before { + content: '\f0d6'; +} +.fa-caret-down:before { + content: '\f0d7'; +} +.fa-caret-up:before { + content: '\f0d8'; +} +.fa-caret-left:before { + content: '\f0d9'; +} +.fa-caret-right:before { + content: '\f0da'; +} +.fa-columns:before { + content: '\f0db'; +} +.fa-unsorted:before, +.fa-sort:before { + content: '\f0dc'; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: '\f0dd'; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: '\f0de'; +} +.fa-envelope:before { + content: '\f0e0'; +} +.fa-linkedin:before { + content: '\f0e1'; +} +.fa-rotate-left:before, +.fa-undo:before { + content: '\f0e2'; +} +.fa-legal:before, +.fa-gavel:before { + content: '\f0e3'; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: '\f0e4'; +} +.fa-comment-o:before { + content: '\f0e5'; +} +.fa-comments-o:before { + content: '\f0e6'; +} +.fa-flash:before, +.fa-bolt:before { + content: '\f0e7'; +} +.fa-sitemap:before { + content: '\f0e8'; +} +.fa-umbrella:before { + content: '\f0e9'; +} +.fa-paste:before, +.fa-clipboard:before { + content: '\f0ea'; +} +.fa-lightbulb-o:before { + content: '\f0eb'; +} +.fa-exchange:before { + content: '\f0ec'; +} +.fa-cloud-download:before { + content: '\f0ed'; +} +.fa-cloud-upload:before { + content: '\f0ee'; +} +.fa-user-md:before { + content: '\f0f0'; +} +.fa-stethoscope:before { + content: '\f0f1'; +} +.fa-suitcase:before { + content: '\f0f2'; +} +.fa-bell-o:before { + content: '\f0a2'; +} +.fa-coffee:before { + content: '\f0f4'; +} +.fa-cutlery:before { + content: '\f0f5'; +} +.fa-file-text-o:before { + content: '\f0f6'; +} +.fa-building-o:before { + content: '\f0f7'; +} +.fa-hospital-o:before { + content: '\f0f8'; +} +.fa-ambulance:before { + content: '\f0f9'; +} +.fa-medkit:before { + content: '\f0fa'; +} +.fa-fighter-jet:before { + content: '\f0fb'; +} +.fa-beer:before { + content: '\f0fc'; +} +.fa-h-square:before { + content: '\f0fd'; +} +.fa-plus-square:before { + content: '\f0fe'; +} +.fa-angle-double-left:before { + content: '\f100'; +} +.fa-angle-double-right:before { + content: '\f101'; +} +.fa-angle-double-up:before { + content: '\f102'; +} +.fa-angle-double-down:before { + content: '\f103'; +} +.fa-angle-left:before { + content: '\f104'; +} +.fa-angle-right:before { + content: '\f105'; +} +.fa-angle-up:before { + content: '\f106'; +} +.fa-angle-down:before { + content: '\f107'; +} +.fa-desktop:before { + content: '\f108'; +} +.fa-laptop:before { + content: '\f109'; +} +.fa-tablet:before { + content: '\f10a'; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: '\f10b'; +} +.fa-circle-o:before { + content: '\f10c'; +} +.fa-quote-left:before { + content: '\f10d'; +} +.fa-quote-right:before { + content: '\f10e'; +} +.fa-spinner:before { + content: '\f110'; +} +.fa-circle:before { + content: '\f111'; +} +.fa-mail-reply:before, +.fa-reply:before { + content: '\f112'; +} +.fa-github-alt:before { + content: '\f113'; +} +.fa-folder-o:before { + content: '\f114'; +} +.fa-folder-open-o:before { + content: '\f115'; +} +.fa-smile-o:before { + content: '\f118'; +} +.fa-frown-o:before { + content: '\f119'; +} +.fa-meh-o:before { + content: '\f11a'; +} +.fa-gamepad:before { + content: '\f11b'; +} +.fa-keyboard-o:before { + content: '\f11c'; +} +.fa-flag-o:before { + content: '\f11d'; +} +.fa-flag-checkered:before { + content: '\f11e'; +} +.fa-terminal:before { + content: '\f120'; +} +.fa-code:before { + content: '\f121'; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: '\f122'; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: '\f123'; +} +.fa-location-arrow:before { + content: '\f124'; +} +.fa-crop:before { + content: '\f125'; +} +.fa-code-fork:before { + content: '\f126'; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: '\f127'; +} +.fa-question:before { + content: '\f128'; +} +.fa-info:before { + content: '\f129'; +} +.fa-exclamation:before { + content: '\f12a'; +} +.fa-superscript:before { + content: '\f12b'; +} +.fa-subscript:before { + content: '\f12c'; +} +.fa-eraser:before { + content: '\f12d'; +} +.fa-puzzle-piece:before { + content: '\f12e'; +} +.fa-microphone:before { + content: '\f130'; +} +.fa-microphone-slash:before { + content: '\f131'; +} +.fa-shield:before { + content: '\f132'; +} +.fa-calendar-o:before { + content: '\f133'; +} +.fa-fire-extinguisher:before { + content: '\f134'; +} +.fa-rocket:before { + content: '\f135'; +} +.fa-maxcdn:before { + content: '\f136'; +} +.fa-chevron-circle-left:before { + content: '\f137'; +} +.fa-chevron-circle-right:before { + content: '\f138'; +} +.fa-chevron-circle-up:before { + content: '\f139'; +} +.fa-chevron-circle-down:before { + content: '\f13a'; +} +.fa-html5:before { + content: '\f13b'; +} +.fa-css3:before { + content: '\f13c'; +} +.fa-anchor:before { + content: '\f13d'; +} +.fa-unlock-alt:before { + content: '\f13e'; +} +.fa-bullseye:before { + content: '\f140'; +} +.fa-ellipsis-h:before { + content: '\f141'; +} +.fa-ellipsis-v:before { + content: '\f142'; +} +.fa-rss-square:before { + content: '\f143'; +} +.fa-play-circle:before { + content: '\f144'; +} +.fa-ticket:before { + content: '\f145'; +} +.fa-minus-square:before { + content: '\f146'; +} +.fa-minus-square-o:before { + content: '\f147'; +} +.fa-level-up:before { + content: '\f148'; +} +.fa-level-down:before { + content: '\f149'; +} +.fa-check-square:before { + content: '\f14a'; +} +.fa-pencil-square:before { + content: '\f14b'; +} +.fa-external-link-square:before { + content: '\f14c'; +} +.fa-share-square:before { + content: '\f14d'; +} +.fa-compass:before { + content: '\f14e'; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: '\f150'; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: '\f151'; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: '\f152'; +} +.fa-euro:before, +.fa-eur:before { + content: '\f153'; +} +.fa-gbp:before { + content: '\f154'; +} +.fa-dollar:before, +.fa-usd:before { + content: '\f155'; +} +.fa-rupee:before, +.fa-inr:before { + content: '\f156'; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: '\f157'; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: '\f158'; +} +.fa-won:before, +.fa-krw:before { + content: '\f159'; +} +.fa-bitcoin:before, +.fa-btc:before { + content: '\f15a'; +} +.fa-file:before { + content: '\f15b'; +} +.fa-file-text:before { + content: '\f15c'; +} +.fa-sort-alpha-asc:before { + content: '\f15d'; +} +.fa-sort-alpha-desc:before { + content: '\f15e'; +} +.fa-sort-amount-asc:before { + content: '\f160'; +} +.fa-sort-amount-desc:before { + content: '\f161'; +} +.fa-sort-numeric-asc:before { + content: '\f162'; +} +.fa-sort-numeric-desc:before { + content: '\f163'; +} +.fa-thumbs-up:before { + content: '\f164'; +} +.fa-thumbs-down:before { + content: '\f165'; +} +.fa-youtube-square:before { + content: '\f166'; +} +.fa-youtube:before { + content: '\f167'; +} +.fa-xing:before { + content: '\f168'; +} +.fa-xing-square:before { + content: '\f169'; +} +.fa-youtube-play:before { + content: '\f16a'; +} +.fa-dropbox:before { + content: '\f16b'; +} +.fa-stack-overflow:before { + content: '\f16c'; +} +.fa-instagram:before { + content: '\f16d'; +} +.fa-flickr:before { + content: '\f16e'; +} +.fa-adn:before { + content: '\f170'; +} +.fa-bitbucket:before { + content: '\f171'; +} +.fa-bitbucket-square:before { + content: '\f172'; +} +.fa-tumblr:before { + content: '\f173'; +} +.fa-tumblr-square:before { + content: '\f174'; +} +.fa-long-arrow-down:before { + content: '\f175'; +} +.fa-long-arrow-up:before { + content: '\f176'; +} +.fa-long-arrow-left:before { + content: '\f177'; +} +.fa-long-arrow-right:before { + content: '\f178'; +} +.fa-apple:before { + content: '\f179'; +} +.fa-windows:before { + content: '\f17a'; +} +.fa-android:before { + content: '\f17b'; +} +.fa-linux:before { + content: '\f17c'; +} +.fa-dribbble:before { + content: '\f17d'; +} +.fa-skype:before { + content: '\f17e'; +} +.fa-foursquare:before { + content: '\f180'; +} +.fa-trello:before { + content: '\f181'; +} +.fa-female:before { + content: '\f182'; +} +.fa-male:before { + content: '\f183'; +} +.fa-gittip:before, +.fa-gratipay:before { + content: '\f184'; +} +.fa-sun-o:before { + content: '\f185'; +} +.fa-moon-o:before { + content: '\f186'; +} +.fa-archive:before { + content: '\f187'; +} +.fa-bug:before { + content: '\f188'; +} +.fa-vk:before { + content: '\f189'; +} +.fa-weibo:before { + content: '\f18a'; +} +.fa-renren:before { + content: '\f18b'; +} +.fa-pagelines:before { + content: '\f18c'; +} +.fa-stack-exchange:before { + content: '\f18d'; +} +.fa-arrow-circle-o-right:before { + content: '\f18e'; +} +.fa-arrow-circle-o-left:before { + content: '\f190'; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: '\f191'; +} +.fa-dot-circle-o:before { + content: '\f192'; +} +.fa-wheelchair:before { + content: '\f193'; +} +.fa-vimeo-square:before { + content: '\f194'; +} +.fa-turkish-lira:before, +.fa-try:before { + content: '\f195'; +} +.fa-plus-square-o:before { + content: '\f196'; +} +.fa-space-shuttle:before { + content: '\f197'; +} +.fa-slack:before { + content: '\f198'; +} +.fa-envelope-square:before { + content: '\f199'; +} +.fa-wordpress:before { + content: '\f19a'; +} +.fa-openid:before { + content: '\f19b'; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: '\f19c'; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: '\f19d'; +} +.fa-yahoo:before { + content: '\f19e'; +} +.fa-google:before { + content: '\f1a0'; +} +.fa-reddit:before { + content: '\f1a1'; +} +.fa-reddit-square:before { + content: '\f1a2'; +} +.fa-stumbleupon-circle:before { + content: '\f1a3'; +} +.fa-stumbleupon:before { + content: '\f1a4'; +} +.fa-delicious:before { + content: '\f1a5'; +} +.fa-digg:before { + content: '\f1a6'; +} +.fa-pied-piper-pp:before { + content: '\f1a7'; +} +.fa-pied-piper-alt:before { + content: '\f1a8'; +} +.fa-drupal:before { + content: '\f1a9'; +} +.fa-joomla:before { + content: '\f1aa'; +} +.fa-language:before { + content: '\f1ab'; +} +.fa-fax:before { + content: '\f1ac'; +} +.fa-building:before { + content: '\f1ad'; +} +.fa-child:before { + content: '\f1ae'; +} +.fa-paw:before { + content: '\f1b0'; +} +.fa-spoon:before { + content: '\f1b1'; +} +.fa-cube:before { + content: '\f1b2'; +} +.fa-cubes:before { + content: '\f1b3'; +} +.fa-behance:before { + content: '\f1b4'; +} +.fa-behance-square:before { + content: '\f1b5'; +} +.fa-steam:before { + content: '\f1b6'; +} +.fa-steam-square:before { + content: '\f1b7'; +} +.fa-recycle:before { + content: '\f1b8'; +} +.fa-automobile:before, +.fa-car:before { + content: '\f1b9'; +} +.fa-cab:before, +.fa-taxi:before { + content: '\f1ba'; +} +.fa-tree:before { + content: '\f1bb'; +} +.fa-spotify:before { + content: '\f1bc'; +} +.fa-deviantart:before { + content: '\f1bd'; +} +.fa-soundcloud:before { + content: '\f1be'; +} +.fa-database:before { + content: '\f1c0'; +} +.fa-file-pdf-o:before { + content: '\f1c1'; +} +.fa-file-word-o:before { + content: '\f1c2'; +} +.fa-file-excel-o:before { + content: '\f1c3'; +} +.fa-file-powerpoint-o:before { + content: '\f1c4'; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: '\f1c5'; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: '\f1c6'; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: '\f1c7'; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: '\f1c8'; +} +.fa-file-code-o:before { + content: '\f1c9'; +} +.fa-vine:before { + content: '\f1ca'; +} +.fa-codepen:before { + content: '\f1cb'; +} +.fa-jsfiddle:before { + content: '\f1cc'; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: '\f1cd'; +} +.fa-circle-o-notch:before { + content: '\f1ce'; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: '\f1d0'; +} +.fa-ge:before, +.fa-empire:before { + content: '\f1d1'; +} +.fa-git-square:before { + content: '\f1d2'; +} +.fa-git:before { + content: '\f1d3'; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: '\f1d4'; +} +.fa-tencent-weibo:before { + content: '\f1d5'; +} +.fa-qq:before { + content: '\f1d6'; +} +.fa-wechat:before, +.fa-weixin:before { + content: '\f1d7'; +} +.fa-send:before, +.fa-paper-plane:before { + content: '\f1d8'; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: '\f1d9'; +} +.fa-history:before { + content: '\f1da'; +} +.fa-circle-thin:before { + content: '\f1db'; +} +.fa-header:before { + content: '\f1dc'; +} +.fa-paragraph:before { + content: '\f1dd'; +} +.fa-sliders:before { + content: '\f1de'; +} +.fa-share-alt:before { + content: '\f1e0'; +} +.fa-share-alt-square:before { + content: '\f1e1'; +} +.fa-bomb:before { + content: '\f1e2'; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: '\f1e3'; +} +.fa-tty:before { + content: '\f1e4'; +} +.fa-binoculars:before { + content: '\f1e5'; +} +.fa-plug:before { + content: '\f1e6'; +} +.fa-slideshare:before { + content: '\f1e7'; +} +.fa-twitch:before { + content: '\f1e8'; +} +.fa-yelp:before { + content: '\f1e9'; +} +.fa-newspaper-o:before { + content: '\f1ea'; +} +.fa-wifi:before { + content: '\f1eb'; +} +.fa-calculator:before { + content: '\f1ec'; +} +.fa-paypal:before { + content: '\f1ed'; +} +.fa-google-wallet:before { + content: '\f1ee'; +} +.fa-cc-visa:before { + content: '\f1f0'; +} +.fa-cc-mastercard:before { + content: '\f1f1'; +} +.fa-cc-discover:before { + content: '\f1f2'; +} +.fa-cc-amex:before { + content: '\f1f3'; +} +.fa-cc-paypal:before { + content: '\f1f4'; +} +.fa-cc-stripe:before { + content: '\f1f5'; +} +.fa-bell-slash:before { + content: '\f1f6'; +} +.fa-bell-slash-o:before { + content: '\f1f7'; +} +.fa-trash:before { + content: '\f1f8'; +} +.fa-copyright:before { + content: '\f1f9'; +} +.fa-at:before { + content: '\f1fa'; +} +.fa-eyedropper:before { + content: '\f1fb'; +} +.fa-paint-brush:before { + content: '\f1fc'; +} +.fa-birthday-cake:before { + content: '\f1fd'; +} +.fa-area-chart:before { + content: '\f1fe'; +} +.fa-pie-chart:before { + content: '\f200'; +} +.fa-line-chart:before { + content: '\f201'; +} +.fa-lastfm:before { + content: '\f202'; +} +.fa-lastfm-square:before { + content: '\f203'; +} +.fa-toggle-off:before { + content: '\f204'; +} +.fa-toggle-on:before { + content: '\f205'; +} +.fa-bicycle:before { + content: '\f206'; +} +.fa-bus:before { + content: '\f207'; +} +.fa-ioxhost:before { + content: '\f208'; +} +.fa-angellist:before { + content: '\f209'; +} +.fa-cc:before { + content: '\f20a'; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: '\f20b'; +} +.fa-meanpath:before { + content: '\f20c'; +} +.fa-buysellads:before { + content: '\f20d'; +} +.fa-connectdevelop:before { + content: '\f20e'; +} +.fa-dashcube:before { + content: '\f210'; +} +.fa-forumbee:before { + content: '\f211'; +} +.fa-leanpub:before { + content: '\f212'; +} +.fa-sellsy:before { + content: '\f213'; +} +.fa-shirtsinbulk:before { + content: '\f214'; +} +.fa-simplybuilt:before { + content: '\f215'; +} +.fa-skyatlas:before { + content: '\f216'; +} +.fa-cart-plus:before { + content: '\f217'; +} +.fa-cart-arrow-down:before { + content: '\f218'; +} +.fa-diamond:before { + content: '\f219'; +} +.fa-ship:before { + content: '\f21a'; +} +.fa-user-secret:before { + content: '\f21b'; +} +.fa-motorcycle:before { + content: '\f21c'; +} +.fa-street-view:before { + content: '\f21d'; +} +.fa-heartbeat:before { + content: '\f21e'; +} +.fa-venus:before { + content: '\f221'; +} +.fa-mars:before { + content: '\f222'; +} +.fa-mercury:before { + content: '\f223'; +} +.fa-intersex:before, +.fa-transgender:before { + content: '\f224'; +} +.fa-transgender-alt:before { + content: '\f225'; +} +.fa-venus-double:before { + content: '\f226'; +} +.fa-mars-double:before { + content: '\f227'; +} +.fa-venus-mars:before { + content: '\f228'; +} +.fa-mars-stroke:before { + content: '\f229'; +} +.fa-mars-stroke-v:before { + content: '\f22a'; +} +.fa-mars-stroke-h:before { + content: '\f22b'; +} +.fa-neuter:before { + content: '\f22c'; +} +.fa-genderless:before { + content: '\f22d'; +} +.fa-facebook-official:before { + content: '\f230'; +} +.fa-pinterest-p:before { + content: '\f231'; +} +.fa-whatsapp:before { + content: '\f232'; +} +.fa-server:before { + content: '\f233'; +} +.fa-user-plus:before { + content: '\f234'; +} +.fa-user-times:before { + content: '\f235'; +} +.fa-hotel:before, +.fa-bed:before { + content: '\f236'; +} +.fa-viacoin:before { + content: '\f237'; +} +.fa-train:before { + content: '\f238'; +} +.fa-subway:before { + content: '\f239'; +} +.fa-medium:before { + content: '\f23a'; +} +.fa-yc:before, +.fa-y-combinator:before { + content: '\f23b'; +} +.fa-optin-monster:before { + content: '\f23c'; +} +.fa-opencart:before { + content: '\f23d'; +} +.fa-expeditedssl:before { + content: '\f23e'; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: '\f240'; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: '\f241'; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: '\f242'; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: '\f243'; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: '\f244'; +} +.fa-mouse-pointer:before { + content: '\f245'; +} +.fa-i-cursor:before { + content: '\f246'; +} +.fa-object-group:before { + content: '\f247'; +} +.fa-object-ungroup:before { + content: '\f248'; +} +.fa-sticky-note:before { + content: '\f249'; +} +.fa-sticky-note-o:before { + content: '\f24a'; +} +.fa-cc-jcb:before { + content: '\f24b'; +} +.fa-cc-diners-club:before { + content: '\f24c'; +} +.fa-clone:before { + content: '\f24d'; +} +.fa-balance-scale:before { + content: '\f24e'; +} +.fa-hourglass-o:before { + content: '\f250'; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: '\f251'; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: '\f252'; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: '\f253'; +} +.fa-hourglass:before { + content: '\f254'; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: '\f255'; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: '\f256'; +} +.fa-hand-scissors-o:before { + content: '\f257'; +} +.fa-hand-lizard-o:before { + content: '\f258'; +} +.fa-hand-spock-o:before { + content: '\f259'; +} +.fa-hand-pointer-o:before { + content: '\f25a'; +} +.fa-hand-peace-o:before { + content: '\f25b'; +} +.fa-trademark:before { + content: '\f25c'; +} +.fa-registered:before { + content: '\f25d'; +} +.fa-creative-commons:before { + content: '\f25e'; +} +.fa-gg:before { + content: '\f260'; +} +.fa-gg-circle:before { + content: '\f261'; +} +.fa-tripadvisor:before { + content: '\f262'; +} +.fa-odnoklassniki:before { + content: '\f263'; +} +.fa-odnoklassniki-square:before { + content: '\f264'; +} +.fa-get-pocket:before { + content: '\f265'; +} +.fa-wikipedia-w:before { + content: '\f266'; +} +.fa-safari:before { + content: '\f267'; +} +.fa-chrome:before { + content: '\f268'; +} +.fa-firefox:before { + content: '\f269'; +} +.fa-opera:before { + content: '\f26a'; +} +.fa-internet-explorer:before { + content: '\f26b'; +} +.fa-tv:before, +.fa-television:before { + content: '\f26c'; +} +.fa-contao:before { + content: '\f26d'; +} +.fa-500px:before { + content: '\f26e'; +} +.fa-amazon:before { + content: '\f270'; +} +.fa-calendar-plus-o:before { + content: '\f271'; +} +.fa-calendar-minus-o:before { + content: '\f272'; +} +.fa-calendar-times-o:before { + content: '\f273'; +} +.fa-calendar-check-o:before { + content: '\f274'; +} +.fa-industry:before { + content: '\f275'; +} +.fa-map-pin:before { + content: '\f276'; +} +.fa-map-signs:before { + content: '\f277'; +} +.fa-map-o:before { + content: '\f278'; +} +.fa-map:before { + content: '\f279'; +} +.fa-commenting:before { + content: '\f27a'; +} +.fa-commenting-o:before { + content: '\f27b'; +} +.fa-houzz:before { + content: '\f27c'; +} +.fa-vimeo:before { + content: '\f27d'; +} +.fa-black-tie:before { + content: '\f27e'; +} +.fa-fonticons:before { + content: '\f280'; +} +.fa-reddit-alien:before { + content: '\f281'; +} +.fa-edge:before { + content: '\f282'; +} +.fa-credit-card-alt:before { + content: '\f283'; +} +.fa-codiepie:before { + content: '\f284'; +} +.fa-modx:before { + content: '\f285'; +} +.fa-fort-awesome:before { + content: '\f286'; +} +.fa-usb:before { + content: '\f287'; +} +.fa-product-hunt:before { + content: '\f288'; +} +.fa-mixcloud:before { + content: '\f289'; +} +.fa-scribd:before { + content: '\f28a'; +} +.fa-pause-circle:before { + content: '\f28b'; +} +.fa-pause-circle-o:before { + content: '\f28c'; +} +.fa-stop-circle:before { + content: '\f28d'; +} +.fa-stop-circle-o:before { + content: '\f28e'; +} +.fa-shopping-bag:before { + content: '\f290'; +} +.fa-shopping-basket:before { + content: '\f291'; +} +.fa-hashtag:before { + content: '\f292'; +} +.fa-bluetooth:before { + content: '\f293'; +} +.fa-bluetooth-b:before { + content: '\f294'; +} +.fa-percent:before { + content: '\f295'; +} +.fa-gitlab:before { + content: '\f296'; +} +.fa-wpbeginner:before { + content: '\f297'; +} +.fa-wpforms:before { + content: '\f298'; +} +.fa-envira:before { + content: '\f299'; +} +.fa-universal-access:before { + content: '\f29a'; +} +.fa-wheelchair-alt:before { + content: '\f29b'; +} +.fa-question-circle-o:before { + content: '\f29c'; +} +.fa-blind:before { + content: '\f29d'; +} +.fa-audio-description:before { + content: '\f29e'; +} +.fa-volume-control-phone:before { + content: '\f2a0'; +} +.fa-braille:before { + content: '\f2a1'; +} +.fa-assistive-listening-systems:before { + content: '\f2a2'; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: '\f2a3'; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: '\f2a4'; +} +.fa-glide:before { + content: '\f2a5'; +} +.fa-glide-g:before { + content: '\f2a6'; +} +.fa-signing:before, +.fa-sign-language:before { + content: '\f2a7'; +} +.fa-low-vision:before { + content: '\f2a8'; +} +.fa-viadeo:before { + content: '\f2a9'; +} +.fa-viadeo-square:before { + content: '\f2aa'; +} +.fa-snapchat:before { + content: '\f2ab'; +} +.fa-snapchat-ghost:before { + content: '\f2ac'; +} +.fa-snapchat-square:before { + content: '\f2ad'; +} +.fa-pied-piper:before { + content: '\f2ae'; +} +.fa-first-order:before { + content: '\f2b0'; +} +.fa-yoast:before { + content: '\f2b1'; +} +.fa-themeisle:before { + content: '\f2b2'; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: '\f2b3'; +} +.fa-fa:before, +.fa-font-awesome:before { + content: '\f2b4'; +} +.fa-handshake-o:before { + content: '\f2b5'; +} +.fa-envelope-open:before { + content: '\f2b6'; +} +.fa-envelope-open-o:before { + content: '\f2b7'; +} +.fa-linode:before { + content: '\f2b8'; +} +.fa-address-book:before { + content: '\f2b9'; +} +.fa-address-book-o:before { + content: '\f2ba'; +} +.fa-vcard:before, +.fa-address-card:before { + content: '\f2bb'; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: '\f2bc'; +} +.fa-user-circle:before { + content: '\f2bd'; +} +.fa-user-circle-o:before { + content: '\f2be'; +} +.fa-user-o:before { + content: '\f2c0'; +} +.fa-id-badge:before { + content: '\f2c1'; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: '\f2c2'; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: '\f2c3'; +} +.fa-quora:before { + content: '\f2c4'; +} +.fa-free-code-camp:before { + content: '\f2c5'; +} +.fa-telegram:before { + content: '\f2c6'; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: '\f2c7'; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: '\f2c8'; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: '\f2c9'; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: '\f2ca'; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: '\f2cb'; +} +.fa-shower:before { + content: '\f2cc'; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: '\f2cd'; +} +.fa-podcast:before { + content: '\f2ce'; +} +.fa-window-maximize:before { + content: '\f2d0'; +} +.fa-window-minimize:before { + content: '\f2d1'; +} +.fa-window-restore:before { + content: '\f2d2'; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: '\f2d3'; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: '\f2d4'; +} +.fa-bandcamp:before { + content: '\f2d5'; +} +.fa-grav:before { + content: '\f2d6'; +} +.fa-etsy:before { + content: '\f2d7'; +} +.fa-imdb:before { + content: '\f2d8'; +} +.fa-ravelry:before { + content: '\f2d9'; +} +.fa-eercast:before { + content: '\f2da'; +} +.fa-microchip:before { + content: '\f2db'; +} +.fa-snowflake-o:before { + content: '\f2dc'; +} +.fa-superpowers:before { + content: '\f2dd'; +} +.fa-wpexplorer:before { + content: '\f2de'; +} +.fa-meetup:before { + content: '\f2e0'; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/public/assets/fonts/FontAwesome/fontawesome-webfont.woff2 b/public/assets/fonts/FontAwesome/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/public/assets/fonts/FontAwesome/fontawesome-webfont.woff2 differ diff --git a/public/assets/fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.woff b/public/assets/fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.woff new file mode 100644 index 0000000..c205e6f Binary files /dev/null and b/public/assets/fonts/Pe-icon-7-stroke/Pe-icon-7-stroke.woff differ diff --git a/public/assets/images/Youtube.png b/public/assets/images/Youtube.png new file mode 100644 index 0000000..83b57aa Binary files /dev/null and b/public/assets/images/Youtube.png differ diff --git a/public/assets/images/about-banner.jpg b/public/assets/images/about-banner.jpg new file mode 100644 index 0000000..a15b9c5 Binary files /dev/null and b/public/assets/images/about-banner.jpg differ diff --git a/public/assets/images/about-img01.jpg b/public/assets/images/about-img01.jpg new file mode 100644 index 0000000..f4d238e Binary files /dev/null and b/public/assets/images/about-img01.jpg differ diff --git a/public/assets/images/about-img02.jpg b/public/assets/images/about-img02.jpg new file mode 100644 index 0000000..19c8d2a Binary files /dev/null and b/public/assets/images/about-img02.jpg differ diff --git a/public/assets/images/about-img03.jpg b/public/assets/images/about-img03.jpg new file mode 100644 index 0000000..5cfdb54 Binary files /dev/null and b/public/assets/images/about-img03.jpg differ diff --git a/public/assets/images/about-img04.jpg b/public/assets/images/about-img04.jpg new file mode 100644 index 0000000..01ff9b7 Binary files /dev/null and b/public/assets/images/about-img04.jpg differ diff --git a/public/assets/images/banner-01.jpg b/public/assets/images/banner-01.jpg new file mode 100644 index 0000000..027b883 Binary files /dev/null and b/public/assets/images/banner-01.jpg differ diff --git a/public/assets/images/banner-02.jpg b/public/assets/images/banner-02.jpg new file mode 100644 index 0000000..fb97232 Binary files /dev/null and b/public/assets/images/banner-02.jpg differ diff --git a/public/assets/images/banner-03.jpg b/public/assets/images/banner-03.jpg new file mode 100644 index 0000000..fb61c71 Binary files /dev/null and b/public/assets/images/banner-03.jpg differ diff --git a/public/assets/images/bx_loader.gif b/public/assets/images/bx_loader.gif new file mode 100644 index 0000000..f4ff40e Binary files /dev/null and b/public/assets/images/bx_loader.gif differ diff --git a/public/assets/images/cate-01.png b/public/assets/images/cate-01.png new file mode 100644 index 0000000..bb9deb6 Binary files /dev/null and b/public/assets/images/cate-01.png differ diff --git a/public/assets/images/cate-02.png b/public/assets/images/cate-02.png new file mode 100644 index 0000000..bd6207b Binary files /dev/null and b/public/assets/images/cate-02.png differ diff --git a/public/assets/images/cate-03.png b/public/assets/images/cate-03.png new file mode 100644 index 0000000..25d178c Binary files /dev/null and b/public/assets/images/cate-03.png differ diff --git a/public/assets/images/controls.png b/public/assets/images/controls.png new file mode 100644 index 0000000..28918dd Binary files /dev/null and b/public/assets/images/controls.png differ diff --git a/public/assets/images/down-icon.png b/public/assets/images/down-icon.png new file mode 100644 index 0000000..9b121a8 Binary files /dev/null and b/public/assets/images/down-icon.png differ diff --git a/public/assets/images/download-bg.jpg b/public/assets/images/download-bg.jpg new file mode 100644 index 0000000..39da9a7 Binary files /dev/null and b/public/assets/images/download-bg.jpg differ diff --git a/public/assets/images/download-img.jpg b/public/assets/images/download-img.jpg new file mode 100644 index 0000000..4dcd1e4 Binary files /dev/null and b/public/assets/images/download-img.jpg differ diff --git a/public/assets/images/facebook.png b/public/assets/images/facebook.png new file mode 100644 index 0000000..854e1f6 Binary files /dev/null and b/public/assets/images/facebook.png differ diff --git a/public/assets/images/greyline.png b/public/assets/images/greyline.png new file mode 100644 index 0000000..08fd503 Binary files /dev/null and b/public/assets/images/greyline.png differ diff --git a/public/assets/images/greyyuandian.png b/public/assets/images/greyyuandian.png new file mode 100644 index 0000000..0300cf9 Binary files /dev/null and b/public/assets/images/greyyuandian.png differ diff --git a/public/assets/images/gywm1.jpg b/public/assets/images/gywm1.jpg new file mode 100644 index 0000000..34d0a91 Binary files /dev/null and b/public/assets/images/gywm1.jpg differ diff --git a/public/assets/images/gywm2.jpg b/public/assets/images/gywm2.jpg new file mode 100644 index 0000000..d208f5f Binary files /dev/null and b/public/assets/images/gywm2.jpg differ diff --git a/public/assets/images/img-01.jpg b/public/assets/images/img-01.jpg new file mode 100644 index 0000000..af2b3e9 Binary files /dev/null and b/public/assets/images/img-01.jpg differ diff --git a/public/assets/images/img-02.jpg b/public/assets/images/img-02.jpg new file mode 100644 index 0000000..fcd66f1 Binary files /dev/null and b/public/assets/images/img-02.jpg differ diff --git a/public/assets/images/img-03.jpg b/public/assets/images/img-03.jpg new file mode 100644 index 0000000..51d5f96 Binary files /dev/null and b/public/assets/images/img-03.jpg differ diff --git a/public/assets/images/lichengbei.png b/public/assets/images/lichengbei.png new file mode 100644 index 0000000..4a7d8b4 Binary files /dev/null and b/public/assets/images/lichengbei.png differ diff --git a/public/assets/images/logo.svg b/public/assets/images/logo.svg new file mode 100644 index 0000000..fbf025b --- /dev/null +++ b/public/assets/images/logo.svg @@ -0,0 +1 @@ +ntonpower(浏览器icon) \ No newline at end of file diff --git a/public/assets/images/logo/logo.png b/public/assets/images/logo/logo.png new file mode 100644 index 0000000..9cdb4f9 Binary files /dev/null and b/public/assets/images/logo/logo.png differ diff --git a/public/assets/images/mail.png b/public/assets/images/mail.png new file mode 100644 index 0000000..6424a84 Binary files /dev/null and b/public/assets/images/mail.png differ diff --git a/public/assets/images/product-banner.jpg b/public/assets/images/product-banner.jpg new file mode 100644 index 0000000..f3471ce Binary files /dev/null and b/public/assets/images/product-banner.jpg differ diff --git a/public/assets/images/tel.png b/public/assets/images/tel.png new file mode 100644 index 0000000..0905943 Binary files /dev/null and b/public/assets/images/tel.png differ diff --git a/public/assets/images/weibo.png b/public/assets/images/weibo.png new file mode 100644 index 0000000..7b6bc75 Binary files /dev/null and b/public/assets/images/weibo.png differ diff --git a/public/assets/images/yaundian.png b/public/assets/images/yaundian.png new file mode 100644 index 0000000..740c12c Binary files /dev/null and b/public/assets/images/yaundian.png differ diff --git a/public/assets/images/zhihu.png b/public/assets/images/zhihu.png new file mode 100644 index 0000000..a59e10f Binary files /dev/null and b/public/assets/images/zhihu.png differ diff --git a/public/assets/js/action.js b/public/assets/js/action.js new file mode 100644 index 0000000..8f3d1d7 --- /dev/null +++ b/public/assets/js/action.js @@ -0,0 +1,83 @@ +/** + * 获取访问者IP + */ +getVisitorIp = function () { + let ip = '127.0.0.1' + $.ajax({ + type: 'get', + url: 'https://get.geojs.io/v1/ip.json', + data: {}, + dataType: 'json', + async:false, + }).done(function (responseData) { + // console.log(responseData) + if (responseData.ip) { + ip = responseData.ip + } else { + ip = '127.0.0.1' + } + }); + return ip; +} + +const visitIp = getVisitorIp() + +/** + * 请求开始 + */ +const RequestUrl = "/index/base/submitActionLog" + +// 图片选择器,记录图片点击的 +const imgAction = $("[log='img']"); +const aAction = $("[log='a']"); + +imgAction.click(function ($this){ + // console.log('click-img',$this) + // console.log(window.location.href) + const content = $this.target.outerHTML + // console.log(content) + actionSub($this,1,content,visitIp) +}); + +imgAction.dblclick(function ($this){ + const content = $this.target.outerHTML + actionSub($this,2,content,visitIp) +}); +// a标签行为监控 +aAction.click(function ($this){ + const content = $this.target.parentElement.outerHTML + actionSub($this,1,content,visitIp) +}); + +// a标签行为监控 +aAction.dblclick(function ($this){ + const content = $this.target.parentElement.outerHTML + actionSub($this,2,content,visitIp) +}); + +/** + * 日志请求提交 + */ +function actionSub(obj,clickNum,content,visitIp) { + $.ajax({ + type: 'POST', + url: RequestUrl, + data: { + 'url' : window.location.href, /*访问页*/ + 'refer' : obj.src, /*访问来源*/ + 'click' : clickNum, /*点击次数*/ + 'content' : content, /*访问内容*/ + 'ip' : visitIp, /*访客IP*/ + 'start_time' : obj.timeStamp, /*点击时间*/ + 'drive' : window.navigator.userAgent.toLowerCase(), /*PC OR 移动端*/ + // 'system' : window.navigator.userAgent.toLowerCase(), /*设备系统*/ + // 'brower' : window.navigator.userAgent.toLowerCase(), /*浏览器*/ + // 'models' : window.navigator.userAgent.toLowerCase(), /*设备型号*/ + 'date_time' : (new Date()).valueOf() /*生成时间*/ + }, + dataType: 'json', + // success: function (json) { + // console.log(json); + // } + }); +} diff --git a/public/assets/js/current.js b/public/assets/js/current.js new file mode 100644 index 0000000..d5f4f42 --- /dev/null +++ b/public/assets/js/current.js @@ -0,0 +1,73 @@ +function SelectTag(t) { + this.child = t.child || ".default", + this.over = t.over || "on", + this.all = t.all || ".all", + this.init() +} +$.extend(SelectTag.prototype, { + init: function() { + var t = this; + t._bindEvent(), + t._select() + }, + _bindEvent: function() { + var t = this; + $(t.child).click(function(e) { + e.preventDefault(); + var i = window.location.href + , n = $(this).attr("rel") + , r = $(this).attr("name"); + $(this).hasClass(t.over) || (window.location.href = t._changeURLPar(i, r, n)) + }), + $(t.all).click(function(e) { + e.preventDefault(); + var i = window.location.href + , n = $(this).attr("name"); + $("[name=" + n + "]").removeClass(t.over), + $(this).addClass(t.over), + window.location.href = t._delUrlPar(i, n) + }) + }, + _delUrlPar: function(t, e) { + var n = ""; + if (t.indexOf("?") == -1) + return t; + n = t.substr(t.indexOf("?") + 1); + var r = "" + , a = ""; + if (n.indexOf("&") != -1) { + r = n.split("&"); + for (i in r) + r[i].split("=")[0] != e && (a = a + r[i].split("=")[0] + "=" + r[i].split("=")[1] + "&"); + return t.substr(0, t.indexOf("?")) + "?" + a.substr(0, a.length - 1) + } + return r = n.split("="), + r[0] == e ? t.substr(0, t.indexOf("?")) : t + }, + _changeURLPar: function(t, e, i) { + var n = this + , r = e + "=([^&]*)" + , a = e + "=" + i + , s = encodeURI(n._getQueryString(e)); + return t.match(r) ? t = t.replace(s, i) : t.match("[?]") ? t + "&" + a : t + "?" + a + }, + _getQueryString: function(t) { + var e = new RegExp("(^|&)" + t + "=([^&]*)(&|$)","i") + , i = window.location.search.substr(1).match(e); + return null != i ? decodeURI(i[2]) : null + }, + _select: function() { + var t = this + , e = window.location.href; + $(t.child).each(function() { + var i = $(this).attr("name") + "=" + $(this).attr("rel") + , n = new RegExp(encodeURI(i),"g"); + if (n.test(e)) { + $(this).addClass(t.over); + var r = $(this).attr("name"); + $("[name=" + r + "]").eq(0).removeClass(t.over) + } else + $(this).removeClass(t.over) + }) + } +}); diff --git a/public/assets/js/jquery.bxslider.js b/public/assets/js/jquery.bxslider.js new file mode 100644 index 0000000..c8243e6 --- /dev/null +++ b/public/assets/js/jquery.bxslider.js @@ -0,0 +1,1343 @@ +/** + * BxSlider v4.1.2 - Fully loaded, responsive content slider + * http://bxslider.com + * + * Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com + * Written while drinking Belgian ales and listening to jazz + * + * Released under the MIT license - http://opensource.org/licenses/MIT + */ + +;(function($){ + + var plugin = {}; + + var defaults = { + + // GENERAL + mode: 'horizontal', + slideSelector: '', + infiniteLoop: true, + hideControlOnEnd: false, + speed: 500, + easing: null, + slideMargin: 0, + startSlide: 0, + randomStart: false, + captions: false, + ticker: false, + tickerHover: false, + adaptiveHeight: false, + adaptiveHeightSpeed: 500, + video: false, + useCSS: true, + preloadImages: 'visible', + responsive: true, + slideZIndex: 50, + wrapperClass: 'bx-wrapper', + + // TOUCH + touchEnabled: true, + swipeThreshold: 50, + oneToOneTouch: true, + preventDefaultSwipeX: true, + preventDefaultSwipeY: false, + + // PAGER + pager: true, + pagerType: 'full', + pagerShortSeparator: ' / ', + pagerSelector: null, + buildPager: null, + pagerCustom: null, + + // CONTROLS + controls: true, + nextText: 'Next', + prevText: 'Prev', + nextSelector: null, + prevSelector: null, + autoControls: false, + startText: 'Start', + stopText: 'Stop', + autoControlsCombine: false, + autoControlsSelector: null, + + // AUTO + auto: false, + pause: 4000, + autoStart: true, + autoDirection: 'next', + autoHover: false, + autoDelay: 0, + autoSlideForOnePage: false, + + // CAROUSEL + minSlides: 1, + maxSlides: 1, + moveSlides: 0, + slideWidth: 0, + + // CALLBACKS + onSliderLoad: function() {}, + onSlideBefore: function() {}, + onSlideAfter: function() {}, + onSlideNext: function() {}, + onSlidePrev: function() {}, + onSliderResize: function() {} + } + + $.fn.bxSlider = function(options){ + + if(this.length == 0) return this; + + // support mutltiple elements + if(this.length > 1){ + this.each(function(){$(this).bxSlider(options)}); + return this; + } + + // create a namespace to be used throughout the plugin + var slider = {}; + // set a reference to our slider element + var el = this; + plugin.el = this; + + /** + * Makes slideshow responsive + */ + // first get the original window dimens (thanks alot IE) + var windowWidth = $(window).width(); + var windowHeight = $(window).height(); + + + + /** + * =================================================================================== + * = PRIVATE FUNCTIONS + * =================================================================================== + */ + + /** + * Initializes namespace settings to be used throughout plugin + */ + var init = function(){ + // merge user-supplied options with the defaults + slider.settings = $.extend({}, defaults, options); + // parse slideWidth setting + slider.settings.slideWidth = parseInt(slider.settings.slideWidth); + // store the original children + slider.children = el.children(slider.settings.slideSelector); + // check if actual number of slides is less than minSlides / maxSlides + if(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length; + if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length; + // if random start, set the startSlide setting to random number + if(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); + // store active slide information + slider.active = { index: slider.settings.startSlide } + // store if the slider is in carousel mode (displaying / moving multiple slides) + slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1; + // if carousel, force preloadImages = 'all' + if(slider.carousel) slider.settings.preloadImages = 'all'; + // calculate the min / max width thresholds based on min / max number of slides + // used to setup and update carousel slides dimensions + slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); + slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); + // store the current state of the slider (if currently animating, working is true) + slider.working = false; + // initialize the controls object + slider.controls = {}; + // initialize an auto interval + slider.interval = null; + // determine which property to use for transitions + slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left'; + // determine if hardware acceleration can be used + slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){ + // create our test div element + var div = document.createElement('div'); + // css transition properties + var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; + // test for each property + for(var i in props){ + if(div.style[props[i]] !== undefined){ + slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase(); + slider.animProp = '-' + slider.cssPrefix + '-transform'; + return true; + } + } + return false; + }()); + // if vertical mode always make maxSlides and minSlides equal + if(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides; + // save original style data + el.data("origStyle", el.attr("style")); + el.children(slider.settings.slideSelector).each(function() { + $(this).data("origStyle", $(this).attr("style")); + }); + // perform all DOM / CSS modifications + setup(); + } + + /** + * Performs all DOM and CSS modifications + */ + var setup = function(){ + // wrap el in a wrapper + el.wrap('
    '); + // store a namspace reference to .bx-viewport + slider.viewport = el.parent(); + // add a loading div to display while images are loading + slider.loader = $('
    '); + slider.viewport.prepend(slider.loader); + // set el to a massive width, to hold any needed slides + // also strip any margin and padding from el + el.css({ + width: slider.settings.mode == 'horizontal' ? (slider.children.length * 100 + 215) + '%' : 'auto', + position: 'relative' + }); + // if using CSS, add the easing property + if(slider.usingCSS && slider.settings.easing){ + el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing); + // if not using CSS and no easing value was supplied, use the default JS animation easing (swing) + }else if(!slider.settings.easing){ + slider.settings.easing = 'swing'; + } + var slidesShowing = getNumberSlidesShowing(); + // make modifications to the viewport (.bx-viewport) + slider.viewport.css({ + width: '100%', + overflow: 'hidden', + position: 'relative' + }); + slider.viewport.parent().css({ + maxWidth: getViewportMaxWidth() + }); + // make modification to the wrapper (.bx-wrapper) + if(!slider.settings.pager) { + slider.viewport.parent().css({ + margin: '0 auto 0px' + }); + } + // apply css to all slider children + slider.children.css({ + 'float': slider.settings.mode == 'horizontal' ? 'left' : 'none', + listStyle: 'none', + position: 'relative' + }); + // apply the calculated width after the float is applied to prevent scrollbar interference + slider.children.css('width', getSlideWidth()); + // if slideMargin is supplied, add the css + if(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin); + if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin); + // if "fade" mode, add positioning and z-index CSS + if(slider.settings.mode == 'fade'){ + slider.children.css({ + position: 'absolute', + zIndex: 0, + display: 'none' + }); + // prepare the z-index on the showing element + slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'}); + } + // create an element to contain all slider controls (pager, start / stop, etc) + slider.controls.el = $('
    '); + // if captions are requested, add them + if(slider.settings.captions) appendCaptions(); + // check if startSlide is last slide + slider.active.last = slider.settings.startSlide == getPagerQty() - 1; + // if video is true, set up the fitVids plugin + if(slider.settings.video) el.fitVids(); + // set the default preload selector (visible) + var preloadSelector = slider.children.eq(slider.settings.startSlide); + if (slider.settings.preloadImages == "all") preloadSelector = slider.children; + // only check for control addition if not in "ticker" mode + if(!slider.settings.ticker){ + // if pager is requested, add it + if(slider.settings.pager) appendPager(); + // if controls are requested, add them + if(slider.settings.controls) appendControls(); + // if auto is true, and auto controls are requested, add them + if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto(); + // if any control option is requested, add the controls wrapper + if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el); + // if ticker mode, do not allow a pager + }else{ + slider.settings.pager = false; + } + // preload all images, then perform final DOM / CSS modifications that depend on images being loaded + loadElements(preloadSelector, start); + } + + var loadElements = function(selector, callback){ + var total = selector.find('img, iframe').length; + if (total == 0){ + callback(); + return; + } + var count = 0; + selector.find('img, iframe').each(function(){ + $(this).one('load', function() { + if(++count == total) callback(); + }).each(function() { + if(this.complete) $(this).load(); + }); + }); + } + + /** + * Start the slider + */ + var start = function(){ + // if infinite loop, prepare additional slides + if(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){ + var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides; + var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone'); + var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone'); + el.append(sliceAppend).prepend(slicePrepend); + } + // remove the loading DOM element + slider.loader.remove(); + // set the left / top position of "el" + setSlidePosition(); + // if "vertical" mode, always use adaptiveHeight to prevent odd behavior + if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true; + // set the viewport height + slider.viewport.height(getViewportHeight()); + // make sure everything is positioned just right (same as a window resize) + el.redrawSlider(); + // onSliderLoad callback + slider.settings.onSliderLoad(slider.active.index); + // slider has been fully initialized + slider.initialized = true; + // bind the resize call to the window + if (slider.settings.responsive) $(window).bind('resize', resizeWindow); + // if auto is true and has more than 1 page, start the show + if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) initAuto(); + // if ticker is true, start the ticker + if (slider.settings.ticker) initTicker(); + // if pager is requested, make the appropriate pager link active + if (slider.settings.pager) updatePagerActive(slider.settings.startSlide); + // check for any updates to the controls (like hideControlOnEnd updates) + if (slider.settings.controls) updateDirectionControls(); + // if touchEnabled is true, setup the touch events + if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch(); + } + + /** + * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value + */ + var getViewportHeight = function(){ + var height = 0; + // first determine which children (slides) should be used in our height calculation + var children = $(); + // if mode is not "vertical" and adaptiveHeight is false, include all children + if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){ + children = slider.children; + }else{ + // if not carousel, return the single active child + if(!slider.carousel){ + children = slider.children.eq(slider.active.index); + // if carousel, return a slice of children + }else{ + // get the individual slide index + var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy(); + // add the current slide to the children + children = slider.children.eq(currentIndex); + // cycle through the remaining "showing" slides + for (i = 1; i <= slider.settings.maxSlides - 1; i++){ + // if looped back to the start + if(currentIndex + i >= slider.children.length){ + children = children.add(slider.children.eq(i - 1)); + }else{ + children = children.add(slider.children.eq(currentIndex + i)); + } + } + } + } + // if "vertical" mode, calculate the sum of the heights of the children + if(slider.settings.mode == 'vertical'){ + children.each(function(index) { + height += $(this).outerHeight(); + }); + // add user-supplied margins + if(slider.settings.slideMargin > 0){ + height += slider.settings.slideMargin * (slider.settings.minSlides - 1); + } + // if not "vertical" mode, calculate the max height of the children + }else{ + height = Math.max.apply(Math, children.map(function(){ + return $(this).outerHeight(false); + }).get()); + } + + if(slider.viewport.css('box-sizing') == 'border-box'){ + height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) + + parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width')); + }else if(slider.viewport.css('box-sizing') == 'padding-box'){ + height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')); + } + + return height; + } + + /** + * Returns the calculated width to be used for the outer wrapper / viewport + */ + var getViewportMaxWidth = function(){ + var width = '100%'; + if(slider.settings.slideWidth > 0){ + if(slider.settings.mode == 'horizontal'){ + width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); + }else{ + width = slider.settings.slideWidth; + } + } + return width; + } + + /** + * Returns the calculated width to be applied to each slide + */ + var getSlideWidth = function(){ + // start with any user-supplied slide width + var newElWidth = slider.settings.slideWidth; + // get the current viewport width + var wrapWidth = slider.viewport.width(); + // if slide width was not supplied, or is larger than the viewport use the viewport width + if(slider.settings.slideWidth == 0 || + (slider.settings.slideWidth > wrapWidth && !slider.carousel) || + slider.settings.mode == 'vertical'){ + newElWidth = wrapWidth; + // if carousel, use the thresholds to determine the width + }else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){ + if(wrapWidth > slider.maxThreshold){ + // newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides; + }else if(wrapWidth < slider.minThreshold){ + newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; + } + } + return newElWidth; + } + + /** + * Returns the number of slides currently visible in the viewport (includes partially visible slides) + */ + var getNumberSlidesShowing = function(){ + var slidesShowing = 1; + if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){ + // if viewport is smaller than minThreshold, return minSlides + if(slider.viewport.width() < slider.minThreshold){ + slidesShowing = slider.settings.minSlides; + // if viewport is larger than minThreshold, return maxSlides + }else if(slider.viewport.width() > slider.maxThreshold){ + slidesShowing = slider.settings.maxSlides; + // if viewport is between min / max thresholds, divide viewport width by first child width + }else{ + var childWidth = slider.children.first().width() + slider.settings.slideMargin; + slidesShowing = Math.floor((slider.viewport.width() + + slider.settings.slideMargin) / childWidth); + } + // if "vertical" mode, slides showing will always be minSlides + }else if(slider.settings.mode == 'vertical'){ + slidesShowing = slider.settings.minSlides; + } + return slidesShowing; + } + + /** + * Returns the number of pages (one full viewport of slides is one "page") + */ + var getPagerQty = function(){ + var pagerQty = 0; + // if moveSlides is specified by the user + if(slider.settings.moveSlides > 0){ + if(slider.settings.infiniteLoop){ + pagerQty = Math.ceil(slider.children.length / getMoveBy()); + }else{ + // use a while loop to determine pages + var breakPoint = 0; + var counter = 0 + // when breakpoint goes above children length, counter is the number of pages + while (breakPoint < slider.children.length){ + ++pagerQty; + breakPoint = counter + getNumberSlidesShowing(); + counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); + } + } + // if moveSlides is 0 (auto) divide children length by sides showing, then round up + }else{ + pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); + } + return pagerQty; + } + + /** + * Returns the number of indivual slides by which to shift the slider + */ + var getMoveBy = function(){ + // if moveSlides was set by the user and moveSlides is less than number of slides showing + if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){ + return slider.settings.moveSlides; + } + // if moveSlides is 0 (auto) + return getNumberSlidesShowing(); + } + + /** + * Sets the slider's (el) left or top position + */ + var setSlidePosition = function(){ + // if last slide, not infinite loop, and number of children is larger than specified maxSlides + if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){ + if (slider.settings.mode == 'horizontal'){ + // get the last child's position + var lastChild = slider.children.last(); + var position = lastChild.position(); + // set the left position + setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0); + }else if(slider.settings.mode == 'vertical'){ + // get the last showing index's position + var lastShowingIndex = slider.children.length - slider.settings.minSlides; + var position = slider.children.eq(lastShowingIndex).position(); + // set the top position + setPositionProperty(-position.top, 'reset', 0); + } + // if not last slide + }else{ + // get the position of the first showing slide + var position = slider.children.eq(slider.active.index * getMoveBy()).position(); + // check for last slide + if (slider.active.index == getPagerQty() - 1) slider.active.last = true; + // set the repective position + if (position != undefined){ + if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0); + else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0); + } + } + } + + /** + * Sets the el's animating property position (which in turn will sometimes animate el). + * If using CSS, sets the transform property. If not using CSS, sets the top / left property. + * + * @param value (int) + * - the animating property's value + * + * @param type (string) 'slider', 'reset', 'ticker' + * - the type of instance for which the function is being + * + * @param duration (int) + * - the amount of time (in ms) the transition should occupy + * + * @param params (array) optional + * - an optional parameter containing any variables that need to be passed in + */ + var setPositionProperty = function(value, type, duration, params){ + // use CSS transform + if(slider.usingCSS){ + // determine the translate3d value + var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; + // add the CSS transition-duration + el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); + if(type == 'slide'){ + // set the property value + el.css(slider.animProp, propValue); + // bind a callback method - executes when CSS transition completes + el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ + // unbind the callback + el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); + updateAfterSlideTransition(); + }); + }else if(type == 'reset'){ + el.css(slider.animProp, propValue); + }else if(type == 'ticker'){ + // make the transition use 'linear' + el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); + el.css(slider.animProp, propValue); + // bind a callback method - executes when CSS transition completes + el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ + // unbind the callback + el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); + // reset the position + setPositionProperty(params['resetValue'], 'reset', 0); + // start the loop again + tickerLoop(); + }); + } + // use JS animate + }else{ + var animateObj = {}; + animateObj[slider.animProp] = value; + if(type == 'slide'){ + el.animate(animateObj, duration, slider.settings.easing, function(){ + updateAfterSlideTransition(); + }); + }else if(type == 'reset'){ + el.css(slider.animProp, value) + }else if(type == 'ticker'){ + el.animate(animateObj, speed, 'linear', function(){ + setPositionProperty(params['resetValue'], 'reset', 0); + // run the recursive loop after animation + tickerLoop(); + }); + } + } + } + + /** + * Populates the pager with proper amount of pages + */ + var populatePager = function(){ + var pagerHtml = ''; + var pagerQty = getPagerQty(); + // loop through each pager item + for(var i=0; i < pagerQty; i++){ + var linkContent = ''; + // if a buildPager function is supplied, use it to get pager link value, else use index + 1 + if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){ + linkContent = slider.settings.buildPager(i); + slider.pagerEl.addClass('bx-custom-pager'); + }else{ + linkContent = i + 1; + slider.pagerEl.addClass('bx-default-pager'); + } + // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; + // add the markup to the string + pagerHtml += ''; + }; + // populate the pager element with pager links + slider.pagerEl.html(pagerHtml); + } + + /** + * Appends the pager to the controls element + */ + var appendPager = function(){ + if(!slider.settings.pagerCustom){ + // create the pager DOM element + slider.pagerEl = $('
    '); + // if a pager selector was supplied, populate it with the pager + if(slider.settings.pagerSelector){ + $(slider.settings.pagerSelector).html(slider.pagerEl); + // if no pager selector was supplied, add it after the wrapper + }else{ + slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); + } + // populate the pager + populatePager(); + }else{ + slider.pagerEl = $(slider.settings.pagerCustom); + } + // assign the pager click binding + slider.pagerEl.on('click', 'a', clickPagerBind); + } + + /** + * Appends prev / next controls to the controls element + */ + var appendControls = function(){ + slider.controls.next = $('' + slider.settings.nextText + ''); + slider.controls.prev = $('' + slider.settings.prevText + ''); + // bind click actions to the controls + slider.controls.next.bind('click', clickNextBind); + slider.controls.prev.bind('click', clickPrevBind); + // if nextSlector was supplied, populate it + if(slider.settings.nextSelector){ + $(slider.settings.nextSelector).append(slider.controls.next); + } + // if prevSlector was supplied, populate it + if(slider.settings.prevSelector){ + $(slider.settings.prevSelector).append(slider.controls.prev); + } + // if no custom selectors were supplied + if(!slider.settings.nextSelector && !slider.settings.prevSelector){ + // add the controls to the DOM + slider.controls.directionEl = $('
    '); + // add the control elements to the directionEl + slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); + // slider.viewport.append(slider.controls.directionEl); + slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); + } + } + + /** + * Appends start / stop auto controls to the controls element + */ + var appendControlsAuto = function(){ + slider.controls.start = $(''); + slider.controls.stop = $(''); + // add the controls to the DOM + slider.controls.autoEl = $('
    '); + // bind click actions to the controls + slider.controls.autoEl.on('click', '.bx-start', clickStartBind); + slider.controls.autoEl.on('click', '.bx-stop', clickStopBind); + // if autoControlsCombine, insert only the "start" control + if(slider.settings.autoControlsCombine){ + slider.controls.autoEl.append(slider.controls.start); + // if autoControlsCombine is false, insert both controls + }else{ + slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); + } + // if auto controls selector was supplied, populate it with the controls + if(slider.settings.autoControlsSelector){ + $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); + // if auto controls selector was not supplied, add it after the wrapper + }else{ + slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); + } + // update the auto controls + updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); + } + + /** + * Appends image captions to the DOM + */ + var appendCaptions = function(){ + // cycle through each child + slider.children.each(function(index){ + // get the image title attribute + var title = $(this).find('img:first').attr('title'); + // append the caption + if (title != undefined && ('' + title).length) { + $(this).append('
    ' + title + '
    '); + } + }); + } + + /** + * Click next binding + * + * @param e (event) + * - DOM event object + */ + var clickNextBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + el.goToNextSlide(); + e.preventDefault(); + } + + /** + * Click prev binding + * + * @param e (event) + * - DOM event object + */ + var clickPrevBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + el.goToPrevSlide(); + e.preventDefault(); + } + + /** + * Click start binding + * + * @param e (event) + * - DOM event object + */ + var clickStartBind = function(e){ + el.startAuto(); + e.preventDefault(); + } + + /** + * Click stop binding + * + * @param e (event) + * - DOM event object + */ + var clickStopBind = function(e){ + el.stopAuto(); + e.preventDefault(); + } + + /** + * Click pager binding + * + * @param e (event) + * - DOM event object + */ + var clickPagerBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + var pagerLink = $(e.currentTarget); + if(pagerLink.attr('data-slide-index') !== undefined){ + var pagerIndex = parseInt(pagerLink.attr('data-slide-index')); + // if clicked pager link is not active, continue with the goToSlide call + if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex); + e.preventDefault(); + } + } + + /** + * Updates the pager links with an active class + * + * @param slideIndex (int) + * - index of slide to make active + */ + var updatePagerActive = function(slideIndex){ + // if "short" pager type + var len = slider.children.length; // nb of children + if(slider.settings.pagerType == 'short'){ + if(slider.settings.maxSlides > 1) { + len = Math.ceil(slider.children.length/slider.settings.maxSlides); + } + slider.pagerEl.html( (slideIndex + 1) + slider.settings.pagerShortSeparator + len); + return; + } + // remove all pager active classes + slider.pagerEl.find('a').removeClass('active'); + // apply the active class for all pagers + slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); + } + + /** + * Performs needed actions after a slide transition + */ + var updateAfterSlideTransition = function(){ + // if infinte loop is true + if(slider.settings.infiniteLoop){ + var position = ''; + // first slide + if(slider.active.index == 0){ + // set the new position + position = slider.children.eq(0).position(); + // carousel, last slide + }else if(slider.active.index == getPagerQty() - 1 && slider.carousel){ + position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); + // last slide + }else if(slider.active.index == slider.children.length - 1){ + position = slider.children.eq(slider.children.length - 1).position(); + } + if(position){ + if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } + else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0); } + } + } + // declare that the transition is complete + slider.working = false; + // onSlideAfter callback + slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + } + + /** + * Updates the auto controls state (either active, or combined switch) + * + * @param state (string) "start", "stop" + * - the new state of the auto show + */ + var updateAutoControls = function(state){ + // if autoControlsCombine is true, replace the current control with the new state + if(slider.settings.autoControlsCombine){ + slider.controls.autoEl.html(slider.controls[state]); + // if autoControlsCombine is false, apply the "active" class to the appropriate control + }else{ + slider.controls.autoEl.find('a').removeClass('active'); + slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); + } + } + + /** + * Updates the direction controls (checks if either should be hidden) + */ + var updateDirectionControls = function(){ + if(getPagerQty() == 1){ + slider.controls.prev.addClass('disabled'); + slider.controls.next.addClass('disabled'); + }else if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){ + // if first slide + if (slider.active.index == 0){ + slider.controls.prev.addClass('disabled'); + slider.controls.next.removeClass('disabled'); + // if last slide + }else if(slider.active.index == getPagerQty() - 1){ + slider.controls.next.addClass('disabled'); + slider.controls.prev.removeClass('disabled'); + // if any slide in the middle + }else{ + slider.controls.prev.removeClass('disabled'); + slider.controls.next.removeClass('disabled'); + } + } + } + + /** + * Initialzes the auto process + */ + var initAuto = function(){ + // if autoDelay was supplied, launch the auto show using a setTimeout() call + if(slider.settings.autoDelay > 0){ + var timeout = setTimeout(el.startAuto, slider.settings.autoDelay); + // if autoDelay was not supplied, start the auto show normally + }else{ + el.startAuto(); + } + // if autoHover is requested + if(slider.settings.autoHover){ + // on el hover + el.hover(function(){ + // if the auto show is currently playing (has an active interval) + if(slider.interval){ + // stop the auto show and pass true agument which will prevent control update + el.stopAuto(true); + // create a new autoPaused value which will be used by the relative "mouseout" event + slider.autoPaused = true; + } + }, function(){ + // if the autoPaused value was created be the prior "mouseover" event + if(slider.autoPaused){ + // start the auto show and pass true agument which will prevent control update + el.startAuto(true); + // reset the autoPaused value + slider.autoPaused = null; + } + }); + } + } + + /** + * Initialzes the ticker process + */ + var initTicker = function(){ + var startPosition = 0; + // if autoDirection is "next", append a clone of the entire slider + if(slider.settings.autoDirection == 'next'){ + el.append(slider.children.clone().addClass('bx-clone')); + // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position + }else{ + el.prepend(slider.children.clone().addClass('bx-clone')); + var position = slider.children.first().position(); + startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top; + } + setPositionProperty(startPosition, 'reset', 0); + // do not allow controls in ticker mode + slider.settings.pager = false; + slider.settings.controls = false; + slider.settings.autoControls = false; + // if autoHover is requested + if(slider.settings.tickerHover && !slider.usingCSS){ + // on el hover + slider.viewport.hover(function(){ + el.stop(); + }, function(){ + // calculate the total width of children (used to calculate the speed ratio) + var totalDimens = 0; + slider.children.each(function(index){ + totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); + }); + // calculate the speed ratio (used to determine the new speed to finish the paused animation) + var ratio = slider.settings.speed / totalDimens; + // determine which property to use + var property = slider.settings.mode == 'horizontal' ? 'left' : 'top'; + // calculate the new speed + var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); + tickerLoop(newSpeed); + }); + } + // start the ticker loop + tickerLoop(); + } + + /** + * Runs a continuous loop, news ticker-style + */ + var tickerLoop = function(resumeSpeed){ + speed = resumeSpeed ? resumeSpeed : slider.settings.speed; + var position = {left: 0, top: 0}; + var reset = {left: 0, top: 0}; + // if "next" animate left position to last child, then reset left to 0 + if(slider.settings.autoDirection == 'next'){ + position = el.find('.bx-clone').first().position(); + // if "prev" animate left position to 0, then reset left to first non-clone child + }else{ + reset = slider.children.first().position(); + } + var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top; + var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top; + var params = {resetValue: resetValue}; + setPositionProperty(animateProperty, 'ticker', speed, params); + } + + /** + * Initializes touch events + */ + var initTouch = function(){ + // initialize object to contain all touch values + slider.touch = { + start: {x: 0, y: 0}, + end: {x: 0, y: 0} + } + slider.viewport.bind('touchstart', onTouchStart); + } + + /** + * Event handler for "touchstart" + * + * @param e (event) + * - DOM event object + */ + var onTouchStart = function(e){ + if(slider.working){ + e.preventDefault(); + }else{ + // record the original position when touch starts + slider.touch.originalPos = el.position(); + var orig = e.originalEvent; + // record the starting touch x, y coordinates + slider.touch.start.x = orig.changedTouches[0].pageX; + slider.touch.start.y = orig.changedTouches[0].pageY; + // bind a "touchmove" event to the viewport + slider.viewport.bind('touchmove', onTouchMove); + // bind a "touchend" event to the viewport + slider.viewport.bind('touchend', onTouchEnd); + } + } + + /** + * Event handler for "touchmove" + * + * @param e (event) + * - DOM event object + */ + var onTouchMove = function(e){ + var orig = e.originalEvent; + // if scrolling on y axis, do not prevent default + var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x); + var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y); + // x axis swipe + if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){ + e.preventDefault(); + // y axis swipe + }else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){ + e.preventDefault(); + } + if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){ + var value = 0; + // if horizontal, drag along x axis + if(slider.settings.mode == 'horizontal'){ + var change = orig.changedTouches[0].pageX - slider.touch.start.x; + value = slider.touch.originalPos.left + change; + // if vertical, drag along y axis + }else{ + var change = orig.changedTouches[0].pageY - slider.touch.start.y; + value = slider.touch.originalPos.top + change; + } + setPositionProperty(value, 'reset', 0); + } + } + + /** + * Event handler for "touchend" + * + * @param e (event) + * - DOM event object + */ + var onTouchEnd = function(e){ + slider.viewport.unbind('touchmove', onTouchMove); + var orig = e.originalEvent; + var value = 0; + // record end x, y positions + slider.touch.end.x = orig.changedTouches[0].pageX; + slider.touch.end.y = orig.changedTouches[0].pageY; + // if fade mode, check if absolute x distance clears the threshold + if(slider.settings.mode == 'fade'){ + var distance = Math.abs(slider.touch.start.x - slider.touch.end.x); + if(distance >= slider.settings.swipeThreshold){ + slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide(); + el.stopAuto(); + } + // not fade mode + }else{ + var distance = 0; + // calculate distance and el's animate property + if(slider.settings.mode == 'horizontal'){ + distance = slider.touch.end.x - slider.touch.start.x; + value = slider.touch.originalPos.left; + }else{ + distance = slider.touch.end.y - slider.touch.start.y; + value = slider.touch.originalPos.top; + } + // if not infinite loop and first / last slide, do not attempt a slide transition + if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){ + setPositionProperty(value, 'reset', 200); + }else{ + // check if distance clears threshold + if(Math.abs(distance) >= slider.settings.swipeThreshold){ + distance < 0 ? el.goToNextSlide() : el.goToPrevSlide(); + el.stopAuto(); + }else{ + // el.animate(property, 200); + setPositionProperty(value, 'reset', 200); + } + } + } + slider.viewport.unbind('touchend', onTouchEnd); + } + + /** + * Window resize event callback + */ + var resizeWindow = function(e){ + // don't do anything if slider isn't initialized. + if(!slider.initialized) return; + // get the new window dimens (again, thank you IE) + var windowWidthNew = $(window).width(); + var windowHeightNew = $(window).height(); + // make sure that it is a true window resize + // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements + // are resized. Can you just die already?* + if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){ + // set the new window dimens + windowWidth = windowWidthNew; + windowHeight = windowHeightNew; + // update all dynamic elements + el.redrawSlider(); + // Call user resize handler + slider.settings.onSliderResize.call(el, slider.active.index); + } + } + + /** + * =================================================================================== + * = PUBLIC FUNCTIONS + * =================================================================================== + */ + + /** + * Performs slide transition to the specified slide + * + * @param slideIndex (int) + * - the destination slide's index (zero-based) + * + * @param direction (string) + * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") + */ + el.goToSlide = function(slideIndex, direction){ + // if plugin is currently in motion, ignore request + if(slider.working || slider.active.index == slideIndex) return; + // declare that plugin is in motion + slider.working = true; + // store the old index + slider.oldIndex = slider.active.index; + // if slideIndex is less than zero, set active index to last child (this happens during infinite loop) + if(slideIndex < 0){ + slider.active.index = getPagerQty() - 1; + // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) + }else if(slideIndex >= getPagerQty()){ + slider.active.index = 0; + // set active index to requested slide + }else{ + slider.active.index = slideIndex; + } + // onSlideBefore, onSlideNext, onSlidePrev callbacks + slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + if(direction == 'next'){ + slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + }else if(direction == 'prev'){ + slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + } + // check if last slide + slider.active.last = slider.active.index >= getPagerQty() - 1; + // update the pager with active class + if(slider.settings.pager) updatePagerActive(slider.active.index); + // // check for direction control update + if(slider.settings.controls) updateDirectionControls(); + // if slider is set to mode: "fade" + if(slider.settings.mode == 'fade'){ + // if adaptiveHeight is true and next height is different from current height, animate to the new height + if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ + slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); + } + // fade out the visible child and reset its z-index value + slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0}); + // fade in the newly requested slide + slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex+1).fadeIn(slider.settings.speed, function(){ + $(this).css('zIndex', slider.settings.slideZIndex); + updateAfterSlideTransition(); + }); + // slider mode is not "fade" + }else{ + // if adaptiveHeight is true and next height is different from current height, animate to the new height + if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ + slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); + } + var moveBy = 0; + var position = {left: 0, top: 0}; + // if carousel and not infinite loop + if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){ + if(slider.settings.mode == 'horizontal'){ + // get the last child position + var lastChild = slider.children.eq(slider.children.length - 1); + position = lastChild.position(); + // calculate the position of the last slide + moveBy = slider.viewport.width() - lastChild.outerWidth(); + }else{ + // get last showing index position + var lastShowingIndex = slider.children.length - slider.settings.minSlides; + position = slider.children.eq(lastShowingIndex).position(); + } + // horizontal carousel, going previous while on first slide (infiniteLoop mode) + }else if(slider.carousel && slider.active.last && direction == 'prev'){ + // get the last child position + var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides); + var lastChild = el.children('.bx-clone').eq(eq); + position = lastChild.position(); + // if infinite loop and "Next" is clicked on the last slide + }else if(direction == 'next' && slider.active.index == 0){ + // get the last clone position + position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position(); + slider.active.last = false; + // normal non-zero requests + }else if(slideIndex >= 0){ + var requestEl = slideIndex * getMoveBy(); + position = slider.children.eq(requestEl).position(); + } + + /* If the position doesn't exist + * (e.g. if you destroy the slider on a next click), + * it doesn't throw an error. + */ + if ("undefined" !== typeof(position)) { + var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top; + // plugin values to be animated + setPositionProperty(value, 'slide', slider.settings.speed); + } + } + } + + /** + * Transitions to the next slide in the show + */ + el.goToNextSlide = function(){ + // if infiniteLoop is false and last page is showing, disregard call + if (!slider.settings.infiniteLoop && slider.active.last) return; + var pagerIndex = parseInt(slider.active.index) + 1; + el.goToSlide(pagerIndex, 'next'); + } + + /** + * Transitions to the prev slide in the show + */ + el.goToPrevSlide = function(){ + // if infiniteLoop is false and last page is showing, disregard call + if (!slider.settings.infiniteLoop && slider.active.index == 0) return; + var pagerIndex = parseInt(slider.active.index) - 1; + el.goToSlide(pagerIndex, 'prev'); + } + + /** + * Starts the auto show + * + * @param preventControlUpdate (boolean) + * - if true, auto controls state will not be updated + */ + el.startAuto = function(preventControlUpdate){ + // if an interval already exists, disregard call + if(slider.interval) return; + // create an interval + slider.interval = setInterval(function(){ + slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide(); + }, slider.settings.pause); + // if auto controls are displayed and preventControlUpdate is not true + if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop'); + } + + /** + * Stops the auto show + * + * @param preventControlUpdate (boolean) + * - if true, auto controls state will not be updated + */ + el.stopAuto = function(preventControlUpdate){ + // if no interval exists, disregard call + if(!slider.interval) return; + // clear the interval + clearInterval(slider.interval); + slider.interval = null; + // if auto controls are displayed and preventControlUpdate is not true + if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start'); + } + + /** + * Returns current slide index (zero-based) + */ + el.getCurrentSlide = function(){ + return slider.active.index; + } + + /** + * Returns current slide element + */ + el.getCurrentSlideElement = function(){ + return slider.children.eq(slider.active.index); + } + + /** + * Returns number of slides in show + */ + el.getSlideCount = function(){ + return slider.children.length; + } + + /** + * Update all dynamic slider elements + */ + el.redrawSlider = function(){ + // resize all children in ratio to new screen size + slider.children.add(el.find('.bx-clone')).width(getSlideWidth()); + // adjust the height + slider.viewport.css('height', getViewportHeight()); + // update the slide position + if(!slider.settings.ticker) setSlidePosition(); + // if active.last was true before the screen resize, we want + // to keep it last no matter what screen size we end on + if (slider.active.last) slider.active.index = getPagerQty() - 1; + // if the active index (page) no longer exists due to the resize, simply set the index as last + if (slider.active.index >= getPagerQty()) slider.active.last = true; + // if a pager is being displayed and a custom pager is not being used, update it + if(slider.settings.pager && !slider.settings.pagerCustom){ + populatePager(); + updatePagerActive(slider.active.index); + } + } + + /** + * Destroy the current instance of the slider (revert everything back to original state) + */ + el.destroySlider = function(){ + // don't do anything if slider has already been destroyed + if(!slider.initialized) return; + slider.initialized = false; + $('.bx-clone', this).remove(); + slider.children.each(function() { + $(this).data("origStyle") != undefined ? $(this).attr("style", $(this).data("origStyle")) : $(this).removeAttr('style'); + }); + $(this).data("origStyle") != undefined ? this.attr("style", $(this).data("origStyle")) : $(this).removeAttr('style'); + $(this).unwrap().unwrap(); + if(slider.controls.el) slider.controls.el.remove(); + if(slider.controls.next) slider.controls.next.remove(); + if(slider.controls.prev) slider.controls.prev.remove(); + if(slider.pagerEl && slider.settings.controls) slider.pagerEl.remove(); + $('.bx-caption', this).remove(); + if(slider.controls.autoEl) slider.controls.autoEl.remove(); + clearInterval(slider.interval); + if(slider.settings.responsive) $(window).unbind('resize', resizeWindow); + } + + /** + * Reload the slider (revert all DOM changes, and re-initialize) + */ + el.reloadSlider = function(settings){ + if (settings != undefined) options = settings; + el.destroySlider(); + init(); + } + + init(); + + // returns the current jQuery object + return this; + } + +})(jQuery); diff --git a/public/assets/js/main.js b/public/assets/js/main.js new file mode 100644 index 0000000..947b327 --- /dev/null +++ b/public/assets/js/main.js @@ -0,0 +1 @@ +(function(a){var c=a(window),b=a("body");a("[data-bg-image]").each(function(){var q=a(this),p=q.data("bg-image");q.css("background-image","url("+p+")")});a(window).on("scroll",function(p){var q=a(window).scrollTop()+1;if(q>250){a(".sticky-nav").addClass("menu_fixed animated fadeInDown")}else{a(".sticky-nav").removeClass("menu_fixed animated fadeInDown")}});a(".dropdown").on("show.bs.dropdown",function(){a(this).find(".dropdown-menu").first().stop(true,true).slideDown()});a(".dropdown").on("hide.bs.dropdown",function(){a(this).find(".dropdown-menu").first().stop(true,true).slideUp()});a(".color a").on("click",function(){a(".sidebar-widget-list a").removeClass("active");a(this).addClass("active")});a(".size a").on("click",function(){a(".sidebar-widget-list a").removeClass("active-2");a(this).addClass("active-2")});a(".pro-details-color a").on("click",function(){a(".pro-details-color a").removeClass("active-color");a(this).addClass("active-color")});a(".pro-details-size a").on("click",function(){a(".pro-details-size a").removeClass("active-size");a(this).addClass("active-size")});(function(){var s=a(".offcanvas-toggle"),q=a(".offcanvas"),r=a(".offcanvas-overlay"),p=a(".mobile-menu-toggle");s.on("click",function(v){v.preventDefault();var u=a(this),t=u.attr("href");b.addClass("offcanvas-open");a(t).addClass("offcanvas-open");r.fadeIn();if(u.parent().hasClass("mobile-menu-toggle")){u.addClass("close")}});a(".offcanvas-close, .offcanvas-overlay").on("click",function(t){t.preventDefault();b.removeClass("offcanvas-open");q.removeClass("offcanvas-open");r.fadeOut();p.find("a").removeClass("close")})})();function j(){var p=a(".offcanvas-menu, .overlay-menu"),q=p.find(".sub-menu");q.parent().prepend('');p.on("click","li a, .menu-expand",function(s){var r=a(this);if(r.attr("href")==="#"||r.hasClass("menu-expand")){s.preventDefault();if(r.siblings("ul:visible").length){r.parent("li").removeClass("active");r.siblings("ul").slideUp();r.parent("li").find("li").removeClass("active");r.parent("li").find("ul:visible").slideUp()}else{r.parent("li").addClass("active");r.closest("li").siblings("li").removeClass("active").find("li").removeClass("active");r.closest("li").siblings("li").find("ul:visible").slideUp();r.siblings("ul").slideDown()}}})}j();function k(){var p=a(".offcanvas-userpanel"),q=p.find(".user-sub-menu");q.parent().prepend('');p.on("click","li a, .offcanvas__user-expand",function(s){var r=a(this);if(r.attr("href")==="#"||r.hasClass("offcanvas__user-expand")){s.preventDefault();if(r.siblings("ul:visible").length){r.parent("li").removeClass("active");r.siblings("ul").slideUp();r.parent("li").find("li").removeClass("active");r.parent("li").find("ul:visible").slideUp()}else{r.parent("li").addClass("active");r.closest("li").siblings("li").removeClass("active").find("li").removeClass("active");r.closest("li").siblings("li").find("ul:visible").slideUp();r.siblings("ul").slideDown()}}})}k();var i=new Swiper(".hero-slider.swiper-container",{loop:true,speed:2000,effect:"fade",autoplay:{delay:7000,disableOnInteraction:false,},navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",}});var e=new Swiper(".tab-slider.swiper-container",{loop:true,slidesPerView:6,spaceBetween:30,speed:1500,navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",},breakpoints:{0:{slidesPerView:2,},478:{slidesPerView:2,},576:{slidesPerView:3,},768:{slidesPerView:4,},992:{slidesPerView:5,},1200:{slidesPerView:6,},},});var e=new Swiper(".testimonial-wrapper.swiper-container",{loop:true,slidesPerView:1,spaceBetween:30,speed:1500,navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",},breakpoints:{0:{slidesPerView:1,},478:{slidesPerView:1,},576:{slidesPerView:1,},768:{slidesPerView:1,},992:{slidesPerView:1,},1200:{slidesPerView:1,},},});var l=new Swiper(".new-product-slider.swiper-container",{slidesPerView:4,spaceBetween:30,speed:1500,loop:true,navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",},breakpoints:{0:{slidesPerView:1,},478:{slidesPerView:1,},576:{slidesPerView:2,},768:{slidesPerView:2,},992:{slidesPerView:3,},1200:{slidesPerView:4,},},});var g=new Swiper(".gallery-thumbs",{spaceBetween:10,slidesPerView:5,freeMode:true,watchSlidesVisibility:true,watchSlidesProgress:true,});var h=new Swiper(".gallery-top",{spaceBetween:0,loop:true,thumbs:{swiper:g}});var n=new Swiper(".zoom-thumbs",{spaceBetween:18,slidesPerView:5,freeMode:true,watchSlidesVisibility:true,watchSlidesProgress:true,});var o=new Swiper(".zoom-top",{spaceBetween:0,slidesPerView:1,thumbs:{swiper:n}});var n=new Swiper(".zoom-thumbs-2",{spaceBetween:15,slidesPerView:5,direction:"vertical",freeMode:true,watchSlidesVisibility:true,watchSlidesProgress:true,});var o=new Swiper(".zoom-top-2",{spaceBetween:0,loop:true,thumbs:{swiper:n}});var d=a(".cart-plus-minus");d.prepend('
    -
    ');d.append('
    +
    ');a(".qtybutton").on("click",function(){var p=a(this);var r=p.parent().find("input").val();if(p.text()==="+"){var q=parseFloat(r)+1}else{if(r>1){var q=parseFloat(r)-1}else{q=1}}p.parent().find("input").val(q)});var m=new Swiper(".single-product-slider",{slidesPerView:4,spaceBetween:20,speed:1500,loop:true,navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",},breakpoints:{0:{slidesPerView:1,},478:{slidesPerView:1,},576:{slidesPerView:2,},768:{slidesPerView:3,},992:{slidesPerView:3,},1024:{slidesPerView:4,},1200:{slidesPerView:4,},},});a(".checkout-toggle2").on("click",function(){a(".open-toggle2").slideToggle(1000)});a(".checkout-toggle").on("click",function(){a(".open-toggle").slideToggle(1000)});a.scrollUp({scrollText:'',easingType:"linear",scrollSpeed:900,animation:"fade",});a("[data-countdown]").each(function(){var p=a(this),q=a(this).data("countdown");p.countdown(q,function(r){p.html(r.strftime('%-D

    Days

    %-H

    Hours

    %M

    Mins

    %S

    Sec

    '))})});var m=new Swiper(".blog-post-media.swiper-container",{slidesPerView:1,spaceBetween:0,loop:true,autoplay:{delay:2000,disableOnInteraction:false,},navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev",},});var f=new Swiper(".brand-slider.swiper-container",{slidesPerView:5,speed:1500,loop:true,autoplay:{delay:2000,disableOnInteraction:false,},breakpoints:{0:{slidesPerView:2,},480:{slidesPerView:3,},768:{slidesPerView:3,},992:{slidesPerView:4,},1200:{slidesPerView:5,},}});a(".shop-sort").niceSelect();a(".zoom-image-hover").zoom();a(".venobox").venobox()})(jQuery); \ No newline at end of file diff --git a/public/assets/js/plugins/plugins.min.js b/public/assets/js/plugins/plugins.min.js new file mode 100644 index 0000000..ca9f4b3 --- /dev/null +++ b/public/assets/js/plugins/plugins.min.js @@ -0,0 +1,117 @@ +/* + * + * scrollup + * Url: http://markgoodyear.com/labs/scrollup/ + * v2.4.1 + * + */ +!function(l,o,e){"use strict";l.fn.scrollUp=function(o){l.data(e.body,"scrollUp")||(l.data(e.body,"scrollUp",!0),l.fn.scrollUp.init(o))},l.fn.scrollUp.init=function(r){var s,t,c,i,n,a,d=l.fn.scrollUp.Settings=l.extend({},l.fn.scrollUp.defaults,r),p=!1;switch(a=d.scrollTrigger?l(d.scrollTrigger):l("",{id:d.scrollName,href:"#top"}),d.scrollTitle&&a.attr("title",d.scrollTitle),a.appendTo("body"),d.scrollImg||d.scrollTrigger||a.html(d.scrollText),a.css({display:"none",position:"fixed",zIndex:d.zIndex}),d.activeOverlay&&l("
    ",{id:d.scrollName+"-active"}).css({position:"absolute",top:d.scrollDistance+"px",width:"100%",borderTop:"1px dotted"+d.activeOverlay,zIndex:d.zIndex}).appendTo("body"),d.animation){case"fade":s="fadeIn",t="fadeOut",c=d.animationSpeed;break;case"slide":s="slideDown",t="slideUp",c=d.animationSpeed;break;default:s="show",t="hide",c=0}i="top"===d.scrollFrom?d.scrollDistance:l(e).height()-l(o).height()-d.scrollDistance,l(o).scroll(function(){l(o).scrollTop()>i?p||(a[s](c),p=!0):p&&(a[t](c),p=!1)}),d.scrollTarget?"number"==typeof d.scrollTarget?n=d.scrollTarget:"string"==typeof d.scrollTarget&&(n=Math.floor(l(d.scrollTarget).offset().top)):n=0,a.click(function(o){o.preventDefault(),l("html, body").animate({scrollTop:n},d.scrollSpeed,d.easingType)})},l.fn.scrollUp.defaults={scrollName:"scrollUp",scrollDistance:300,scrollFrom:"top",scrollSpeed:300,easingType:"linear",animation:"fade",animationSpeed:200,scrollTrigger:!1,scrollTarget:!1,scrollText:"Scroll to top",scrollTitle:!1,scrollImg:!1,activeOverlay:!1,zIndex:2147483647},l.fn.scrollUp.destroy=function(r){l.removeData(e.body,"scrollUp"),l("#"+l.fn.scrollUp.Settings.scrollName).remove(),l("#"+l.fn.scrollUp.Settings.scrollName+"-active").remove(),l.fn.jquery.split(".")[1]>=7?l(o).off("scroll",r):l(o).unbind("scroll",r)},l.scrollUp=l.fn.scrollUp}(jQuery,window,document); + + +/*! + Zoom 1.7.21 + license: MIT + http://www.jacklmoore.com/zoom +*/ +!function(o){var t={url:!1,callback:!1,target:!1,duration:120,on:"mouseover",touch:!0,onZoomIn:!1,onZoomOut:!1,magnify:1};o.zoom=function(t,n,e,i){var u,c,a,r,m,l,s,f=o(t),h=f.css("position"),d=o(n);return t.style.position=/(absolute|fixed)/.test(h)?h:"relative",t.style.overflow="hidden",e.style.width=e.style.height="",o(e).addClass("zoomImg").css({position:"absolute",top:0,left:0,opacity:0,width:e.width*i,height:e.height*i,border:"none",maxWidth:"none",maxHeight:"none"}).appendTo(t),{init:function(){c=f.outerWidth(),u=f.outerHeight(),n===t?(r=c,a=u):(r=d.outerWidth(),a=d.outerHeight()),m=(e.width-c)/r,l=(e.height-u)/a,s=d.offset()},move:function(o){var t=o.pageX-s.left,n=o.pageY-s.top;n=Math.max(Math.min(n,a),0),t=Math.max(Math.min(t,r),0),e.style.left=t*-m+"px",e.style.top=n*-l+"px"}}},o.fn.zoom=function(n){return this.each(function(){var e=o.extend({},t,n||{}),i=e.target&&o(e.target)[0]||this,u=this,c=o(u),a=document.createElement("img"),r=o(a),m="mousemove.zoom",l=!1,s=!1;if(!e.url){var f=u.querySelector("img");if(f&&(e.url=f.getAttribute("data-src")||f.currentSrc||f.src),!e.url)return}c.one("zoom.destroy",function(o,t){c.off(".zoom"),i.style.position=o,i.style.overflow=t,a.onload=null,r.remove()}.bind(this,i.style.position,i.style.overflow)),a.onload=function(){function t(t){f.init(),f.move(t),r.stop().fadeTo(o.support.opacity?e.duration:0,1,!!o.isFunction(e.onZoomIn)&&e.onZoomIn.call(a))}function n(){r.stop().fadeTo(e.duration,0,!!o.isFunction(e.onZoomOut)&&e.onZoomOut.call(a))}var f=o.zoom(i,u,a,e.magnify);"grab"===e.on?c.on("mousedown.zoom",function(e){1===e.which&&(o(document).one("mouseup.zoom",function(){n(),o(document).off(m,f.move)}),t(e),o(document).on(m,f.move),e.preventDefault())}):"click"===e.on?c.on("click.zoom",function(e){return l?void 0:(l=!0,t(e),o(document).on(m,f.move),o(document).one("click.zoom",function(){n(),l=!1,o(document).off(m,f.move)}),!1)}):"toggle"===e.on?c.on("click.zoom",function(o){l?n():t(o),l=!l}):"mouseover"===e.on&&(f.init(),c.on("mouseenter.zoom",t).on("mouseleave.zoom",n).on(m,f.move)),e.touch&&c.on("touchstart.zoom",function(o){o.preventDefault(),s?(s=!1,n()):(s=!0,t(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0]))}).on("touchmove.zoom",function(o){o.preventDefault(),f.move(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0])}).on("touchend.zoom",function(o){o.preventDefault(),s&&(s=!1,n())}),o.isFunction(e.callback)&&e.callback.call(a)},a.setAttribute("role","presentation"),a.alt="",a.src=e.url})},o.fn.zoom.defaults=t}(window.jQuery); + + + +/* jQuery Nice Select - v1.0 + https://github.com/hernansartorio/jquery-nice-select + Made by Hernán Sartorio */ + + +!function(e){e.fn.niceSelect=function(t){function s(t){t.after(e("
    ").addClass("nice-select").addClass(t.attr("class")||"").addClass(t.attr("disabled")?"disabled":"").attr("tabindex",t.attr("disabled")?null:"0").html('
      '));var s=t.next(),n=t.find("option"),i=t.find("option:selected");s.find(".current").html(i.data("display")||i.text()),n.each(function(t){var n=e(this),i=n.data("display");s.find("ul").append(e("
    • ").attr("data-value",n.val()).attr("data-display",i||null).addClass("option"+(n.is(":selected")?" selected":"")+(n.is(":disabled")?" disabled":"")).html(n.text()))})}if("string"==typeof t)return"update"==t?this.each(function(){var t=e(this),n=e(this).next(".nice-select"),i=n.hasClass("open");n.length&&(n.remove(),s(t),i&&t.next().trigger("click"))}):"destroy"==t?(this.each(function(){var t=e(this),s=e(this).next(".nice-select");s.length&&(s.remove(),t.css("display",""))}),0==e(".nice-select").length&&e(document).off(".nice_select")):console.log('Method "'+t+'" does not exist.'),this;this.hide(),this.each(function(){var t=e(this);t.next().hasClass("nice-select")||s(t)}),e(document).off(".nice_select"),e(document).on("click.nice_select",".nice-select",function(t){var s=e(this);e(".nice-select").not(s).removeClass("open"),s.toggleClass("open"),s.hasClass("open")?(s.find(".option"),s.find(".focus").removeClass("focus"),s.find(".selected").addClass("focus")):s.focus()}),e(document).on("click.nice_select",function(t){0===e(t.target).closest(".nice-select").length&&e(".nice-select").removeClass("open").find(".option")}),e(document).on("click.nice_select",".nice-select .option:not(.disabled)",function(t){var s=e(this),n=s.closest(".nice-select");n.find(".selected").removeClass("selected"),s.addClass("selected");var i=s.data("display")||s.text();n.find(".current").text(i),n.prev("select").val(s.data("value")).trigger("change")}),e(document).on("keydown.nice_select",".nice-select",function(t){var s=e(this),n=e(s.find(".focus")||s.find(".list .option.selected"));if(32==t.keyCode||13==t.keyCode)return s.hasClass("open")?n.trigger("click"):s.trigger("click"),!1;if(40==t.keyCode){if(s.hasClass("open")){var i=n.nextAll(".option:not(.disabled)").first();i.length>0&&(s.find(".focus").removeClass("focus"),i.addClass("focus"))}else s.trigger("click");return!1}if(38==t.keyCode){if(s.hasClass("open")){var l=n.prevAll(".option:not(.disabled)").first();l.length>0&&(s.find(".focus").removeClass("focus"),l.addClass("focus"))}else s.trigger("click");return!1}if(27==t.keyCode)s.hasClass("open")&&s.trigger("click");else if(9==t.keyCode&&s.hasClass("open"))return!1});var n=document.createElement("a").style;return n.cssText="pointer-events:auto","auto"!==n.pointerEvents&&e("html").addClass("no-csspointerevents"),this}}(jQuery); + + + + +$(document).ready(function() { + $("#slider-range").slider({ + range: true, + min: 0, + max: 100, + values: [0, 100], + slide: function(event, ui) { + $("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]); + } + }); + $("#amount").val("$" + $("#slider-range").slider("values", 0) + + " - $" + $("#slider-range").slider("values", 1)); + +}); + + +/*! + * The Final Countdown for jQuery v2.1.0 (http://hilios.github.io/jQuery.countdown/) + * Copyright (c) 2015 Edson Hilios + */ +!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(t){"use strict";function e(t){var e=t.toString().replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return new RegExp(e)}function s(t){return function(s){var i=s.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);if(i)for(var a=0,o=i.length;o>a;++a){var r=i[a].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/),l=e(r[0]),c=r[1]||"",u=r[3]||"",f=null;r=r[2],h.hasOwnProperty(r)&&(f=h[r],f=Number(t[f])),null!==f&&("!"===c&&(f=n(u,f)),""===c&&10>f&&(f="0"+f.toString()),s=s.replace(l,f.toString()))}return s.replace(/%%/,"%")}}function n(t,e){var s="s",n="";return t&&(1===(t=t.replace(/(:|;|\s)/gi,"").split(/\,/)).length?s=t[0]:(n=t[0],s=t[1])),1===Math.abs(e)?n:s}var i=[],a=[],o={precision:100,elapse:!1};a.push(/^[0-9]*$/.source),a.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),a.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),a=new RegExp(a.join("|"));var h={Y:"years",m:"months",n:"daysToMonth",w:"weeks",d:"daysToWeek",D:"totalDays",H:"hours",M:"minutes",S:"seconds"},r=function(e,s,n){this.el=e,this.$el=t(e),this.interval=null,this.offset={},this.options=t.extend({},o),this.instanceNumber=i.length,i.push(this),this.$el.data("countdown-instance",this.instanceNumber),n&&("function"==typeof n?(this.$el.on("update.countdown",n),this.$el.on("stoped.countdown",n),this.$el.on("finish.countdown",n)):this.options=t.extend({},o,n)),this.setFinalDate(s),this.start()};t.extend(r.prototype,{start:function(){null!==this.interval&&clearInterval(this.interval);var t=this;this.update(),this.interval=setInterval(function(){t.update.call(t)},this.options.precision)},stop:function(){clearInterval(this.interval),this.interval=null,this.dispatchEvent("stoped")},toggle:function(){this.interval?this.stop():this.start()},pause:function(){this.stop()},resume:function(){this.start()},remove:function(){this.stop.call(this),i[this.instanceNumber]=null,delete this.$el.data().countdownInstance},setFinalDate:function(t){this.finalDate=function(t){if(t instanceof Date)return t;if(String(t).match(a))return String(t).match(/^[0-9]*$/)&&(t=Number(t)),String(t).match(/\-/)&&(t=String(t).replace(/\-/g,"/")),new Date(t);throw new Error("Couldn't cast `"+t+"` to a date object.")}(t)},update:function(){if(0!==this.$el.closest("html").length){var e,s=void 0!==t._data(this.el,"events"),n=new Date;e=this.finalDate.getTime()-n.getTime(),e=Math.ceil(e/1e3),e=!this.options.elapse&&0>e?0:Math.abs(e),this.totalSecsLeft!==e&&s&&(this.totalSecsLeft=e,this.elapsed=n>=this.finalDate,this.offset={seconds:this.totalSecsLeft%60,minutes:Math.floor(this.totalSecsLeft/60)%60,hours:Math.floor(this.totalSecsLeft/60/60)%24,days:Math.floor(this.totalSecsLeft/60/60/24)%7,daysToWeek:Math.floor(this.totalSecsLeft/60/60/24)%7,daysToMonth:Math.floor(this.totalSecsLeft/60/60/24%30.4368),totalDays:Math.floor(this.totalSecsLeft/60/60/24),weeks:Math.floor(this.totalSecsLeft/60/60/24/7),months:Math.floor(this.totalSecsLeft/60/60/24/30.4368),years:Math.abs(this.finalDate.getFullYear()-n.getFullYear())},this.options.elapse||0!==this.totalSecsLeft?this.dispatchEvent("update"):(this.stop(),this.dispatchEvent("finish")))}else this.remove()},dispatchEvent:function(e){var n=t.Event(e+".countdown");n.finalDate=this.finalDate,n.elapsed=this.elapsed,n.offset=t.extend({},this.offset),n.strftime=s(this.offset),this.$el.trigger(n)}}),t.fn.countdown=function(){var e=Array.prototype.slice.call(arguments,0);return this.each(function(){var s=t(this).data("countdown-instance");if(void 0!==s){var n=i[s],a=e[0];r.prototype.hasOwnProperty(a)?n[a].apply(n,e.slice(1)):null===String(a).match(/^[$A-Z_][0-9A-Z_$]*$/i)?(n.setFinalDate.call(n,a),n.start()):t.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi,a))}else new r(this,e[0],e[1])})}}); + + +/* + * VenoBox - jQuery Plugin + * version: 1.9.1 + * @requires jQuery >= 1.7.0 + * + * Examples at http://veno.es/venobox/ + * License: MIT License + * License URI: https://github.com/nicoldfranchini/VenoBox/blob/master/LICENSE + * Copyright 2013-2021 Nicold Franchini - @nicoldfranchini + * + */ + +!function(e){"use strict";var s,i,a,t,o,c,r,l,d,n,v,u,b,h,k,p,g,m,f,x,w,y,_,C,z,B,P,M,E,O,D,N,U,V,I,j,R,X,Y,W,q,$,T,A,H,Q,S,Z='',F='',G='',J='',K='';e.fn.extend({venobox:function(L){var ee=this,se=e.extend({arrowsColor:"#B6B6B6",autoplay:!1,bgcolor:"#fff",border:"0",closeBackground:"transparent",closeColor:"#d2d2d2",framewidth:"",frameheight:"",gallItems:!1,infinigall:!1,htmlClose:"×",htmlNext:"Next",htmlPrev:"Prev",numeratio:!1,numerationBackground:"#161617",numerationColor:"#d2d2d2",numerationPosition:"top",overlayClose:!0,overlayColor:"rgba(23,23,23,0.85)",spinner:"double-bounce",spinColor:"#d2d2d2",titleattr:"title",titleBackground:"#161617",titleColor:"#d2d2d2",titlePosition:"top",share:[],cb_pre_open:function(){return!0},cb_post_open:function(){},cb_pre_close:function(){return!0},cb_post_close:function(){},cb_post_resize:function(){},cb_after_nav:function(){},cb_content_loaded:function(){},cb_init:function(){}},L);return se.cb_init(ee),this.each(function(){if((N=e(this)).data("venobox"))return!0;function L(){C=N.data("gall"),x=N.data("numeratio"),k=N.data("gallItems"),p=N.data("infinigall"),H=N.data("share"),o.html(""),"iframe"!==N.data("vbtype")&&"inline"!==N.data("vbtype")&&"ajax"!==N.data("vbtype")&&(Q={pinterest:'
      '+Z+"",facebook:''+F+"",twitter:''+G+"",linkedin:''+J+"",download:''+K+""},e.each(H,function(e,s){o.append(Q[s])})),(g=k||e('.vbox-item[data-gall="'+C+'"]')).length<2&&(p=!1,x=!1),z=g.eq(g.index(N)+1),B=g.eq(g.index(N)-1),z.length||!0!==p||(z=g.eq(0)),g.length>=1?(U=g.index(N)+1,t.html(U+" / "+g.length)):U=1,!0===x?t.show():t.hide(),""!==_?c.show():c.hide(),z.length||!0===p?(e(".vbox-next").css("display","block"),P=!0):(e(".vbox-next").css("display","none"),P=!1),g.index(N)>0||!0===p?(e(".vbox-prev").css("display","block"),M=!0):(e(".vbox-prev").css("display","none"),M=!1),!0!==M&&!0!==P||(n.on(de.DOWN,ce),n.on(de.MOVE,re),n.on(de.UP,le))}function ie(e){return!(e.length<1)&&!m&&(m=!0,w=e.data("overlay")||e.data("overlaycolor"),b=e.data("framewidth"),h=e.data("frameheight"),r=e.data("border"),i=e.data("bgcolor"),v=e.data("href")||e.attr("href"),s=e.data("autoplay"),_=e.data("titleattr")&&e.attr(e.data("titleattr"))||"",e===B&&n.addClass("vbox-animated").addClass("swipe-right"),e===z&&n.addClass("vbox-animated").addClass("swipe-left"),O.show(),void n.animate({opacity:0},500,function(){y.css("background",w),n.removeClass("vbox-animated").removeClass("swipe-left").removeClass("swipe-right").css({"margin-left":0,"margin-right":0}),"iframe"==e.data("vbtype")?he():"inline"==e.data("vbtype")?pe():"ajax"==e.data("vbtype")?be():"video"==e.data("vbtype")?ke(s):(n.html(''),ge()),N=e,L(),m=!1,se.cb_after_nav(N,U,z,B)}))}function ae(e){27===e.keyCode&&te(),37==e.keyCode&&!0===M&&ie(B),39==e.keyCode&&!0===P&&ie(z)}function te(){if(!1===se.cb_pre_close(N,U,z,B))return!1;e("body").off("keydown",ae).removeClass("vbox-open"),N.focus(),y.animate({opacity:0},500,function(){y.remove(),m=!1,se.cb_post_close()})}ee.VBclose=function(){te()},N.addClass("vbox-item"),N.data("framewidth",se.framewidth),N.data("frameheight",se.frameheight),N.data("border",se.border),N.data("bgcolor",se.bgcolor),N.data("numeratio",se.numeratio),N.data("gallItems",se.gallItems),N.data("infinigall",se.infinigall),N.data("overlaycolor",se.overlayColor),N.data("titleattr",se.titleattr),N.data("share",se.share),N.data("venobox",!0),N.on("click",function(k){if(k.preventDefault(),N=e(this),!1===se.cb_pre_open(N))return!1;switch(ee.VBnext=function(){ie(z)},ee.VBprev=function(){ie(B)},w=N.data("overlay")||N.data("overlaycolor"),b=N.data("framewidth"),h=N.data("frameheight"),s=N.data("autoplay")||se.autoplay,r=N.data("border"),i=N.data("bgcolor"),P=!1,M=!1,m=!1,v=N.data("href")||N.attr("href"),u=N.data("css")||"",_=N.attr(N.data("titleattr"))||"",H=N.data("share"),E='
      ',se.spinner){case"rotating-plane":E+='
      ';break;case"double-bounce":E+='
      ';break;case"wave":E+='
      ';break;case"wandering-cubes":E+='
      ';break;case"spinner-pulse":E+='
      ';break;case"chasing-dots":E+='
      ';break;case"three-bounce":E+='
      ';break;case"circle":E+='
      ';break;case"cube-grid":E+='
      ';break;case"fading-circle":E+='
      ';break;case"folding-cube":E+='
      '}return E+="
      ",D=''+se.htmlNext+''+se.htmlPrev+"",I='
      0/0
      '+se.htmlClose+"
      ",l='
      '+E+'
      '+I+D+'
      ',e("body").append(l).addClass("vbox-open"),e(".vbox-preloader div:not(.sk-circle) .sk-child, .vbox-preloader .sk-rotating-plane, .vbox-preloader .sk-rect, .vbox-preloader div:not(.sk-folding-cube) .sk-cube, .vbox-preloader .sk-spinner-pulse").css("background-color",se.spinColor),y=e(".vbox-overlay"),d=e(".vbox-container"),n=e(".vbox-content"),a=e(".vbox-left"),t=e(".vbox-num"),o=e(".vbox-share"),c=e(".vbox-title"),(O=e(".vbox-preloader")).show(),S="top"==se.titlePosition?"bottom":"top",o.css(S,"-1px"),o.css({color:se.titleColor,fill:se.titleColor,"background-color":se.titleBackground}),c.css(se.titlePosition,"-1px"),c.css({color:se.titleColor,"background-color":se.titleBackground}),e(".vbox-close").css({color:se.closeColor,"background-color":se.closeBackground}),a.css(se.numerationPosition,"-1px"),a.css({color:se.numerationColor,"background-color":se.numerationBackground}),e(".vbox-next span, .vbox-prev span").css({"border-top-color":se.arrowsColor,"border-right-color":se.arrowsColor}),n.html(""),n.css("opacity","0"),y.css("opacity","0"),L(),y.animate({opacity:1},250,function(){"iframe"==N.data("vbtype")?he():"inline"==N.data("vbtype")?pe():"ajax"==N.data("vbtype")?be():"video"==N.data("vbtype")?ke(s):(n.html(''),ge()),se.cb_post_open(N,U,z,B)}),e("body").keydown(ae),e(".vbox-prev").on("click",function(){ie(B)}),e(".vbox-next").on("click",function(){ie(z)}),!1});var oe=".vbox-overlay";function ce(e){n.addClass("vbox-animated"),R=Y=e.pageY,X=W=e.pageX,V=!0}function re(e){if(!0===V){W=e.pageX,Y=e.pageY,$=W-X,T=Y-R;var s=Math.abs($);s>Math.abs(T)&&s<=100&&(e.preventDefault(),n.css("margin-left",$))}}function le(e){if(!0===V){V=!1;var s=N,i=!1;(q=W-X)<0&&!0===P&&(s=z,i=!0),q>0&&!0===M&&(s=B,i=!0),Math.abs(q)>=A&&!0===i?ie(s):n.css({"margin-left":0,"margin-right":0})}}se.overlayClose||(oe=".vbox-close"),e("body").on("click touchstart",oe,function(s){(e(s.target).is(".vbox-overlay")||e(s.target).is(".vbox-content")||e(s.target).is(".vbox-close")||e(s.target).is(".vbox-preloader")||e(s.target).is(".vbox-container"))&&te()}),X=0,W=0,q=0,A=50,V=!1;var de={DOWN:"touchmousedown",UP:"touchmouseup",MOVE:"touchmousemove"},ne=function(s){var i;switch(s.type){case"mousedown":i=de.DOWN;break;case"mouseup":case"mouseout":i=de.UP;break;case"mousemove":i=de.MOVE;break;default:return}var a=ue(i,s,s.pageX,s.pageY);e(s.target).trigger(a)},ve=function(s){var i;switch(s.type){case"touchstart":i=de.DOWN;break;case"touchend":i=de.UP;break;case"touchmove":i=de.MOVE;break;default:return}var a,t=s.originalEvent.touches[0];a=i==de.UP?ue(i,s,null,null):ue(i,s,t.pageX,t.pageY),e(s.target).trigger(a)},ue=function(s,i,a,t){return e.Event(s,{pageX:a,pageY:t,originalEvent:i})};function be(){e.ajax({url:v,cache:!1}).done(function(e){n.html('
      '+e+"
      "),ge()}).fail(function(){n.html('

      Error retrieving contents, please retry

      '),me()})}function he(){n.html(''),me()}function ke(e){var s,i=function(e){var s;return v.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/),RegExp.$3.indexOf("youtu")>-1?s="youtube":RegExp.$3.indexOf("vimeo")>-1&&(s="vimeo"),{type:s,id:RegExp.$6}}(),a=(e?"?rel=0&autoplay=1":"?rel=0")+function(e){var s="",i=decodeURIComponent(v).split("?");if(void 0!==i[1]){var a,t,o=i[1].split("&");for(t=0;t'),me()}function pe(){n.html('
      '+e(v).html()+"
      "),me()}function ge(){(j=n.find("img")).length?j.each(function(){e(this).one("load",function(){me()})}):me()}function me(){c.html(_),n.find(">:first-child").addClass("vbox-figlio").css({width:b,height:h,padding:r,background:i}),e("img.vbox-figlio").on("dragstart",function(e){e.preventDefault()}),d.scrollTop(0),fe(),n.animate({opacity:"1"},"slow",function(){O.hide()}),se.cb_content_loaded(N,U,z,B)}function fe(){var s=n.outerHeight(),i=e(window).height();f=s+60+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){p()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(j=O.call(w.childNodes),w.childNodes),j[w.childNodes.length].nodeType}catch(t){H={apply:j.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(e,t,r,i){var o,s,l,c,f,h,y,m=t&&t.ownerDocument,w=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==w&&9!==w&&11!==w)return r;if(!i&&(p(t),t=t||d,g)){if(11!==w&&(f=Z.exec(e)))if(o=f[1]){if(9===w){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return H.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return H.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!A[e+" "]&&(!v||!v.test(e))&&(1!==w||"object"!==t.nodeName.toLowerCase())){if(y=e,m=t,1===w&&(U.test(e)||z.test(e))){for((m=ee.test(e)&&ye(t.parentNode)||t)===t&&n.scope||((c=t.getAttribute("id"))?c=c.replace(re,ie):t.setAttribute("id",c=b)),s=(h=a(e)).length;s--;)h[s]=(c?"#"+c:":scope")+" "+xe(h[s]);y=h.join(",")}try{return H.apply(r,m.querySelectorAll(y)),r}catch(t){A(e,!0)}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace($,"$1"),t,r,i)}function ue(){var e=[];return function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}}function le(e){return e[b]=!0,e}function ce(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split("|"),i=n.length;i--;)r.attrHandle[n[i]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function de(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function he(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ge(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ae(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function ve(e){return le(function(t){return t=+t,le(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ye(e){return e&&void 0!==e.getElementsByTagName&&e}for(t in n=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},p=se.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!=d&&9===a.nodeType&&a.documentElement&&(h=(d=a).documentElement,g=!o(d),w!=d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",oe,!1):i.attachEvent&&i.attachEvent("onunload",oe)),n.scope=ce(function(e){return h.appendChild(e).appendChild(d.createElement("div")),void 0!==e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),n.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ce(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=K.test(d.getElementsByClassName),n.getById=ce(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(te,ne);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&g)return t.getElementsByClassName(e)},y=[],v=[],(n.qsa=K.test(d.querySelectorAll))&&(ce(function(e){var t;h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+b+"-]").length||v.push("~="),(t=d.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(n.matchesSelector=K.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ce(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),y.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),y=y.length&&new RegExp(y.join("|")),t=K.test(h.compareDocumentPosition),x=t||K.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},N=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e==d||e.ownerDocument==w&&x(w,e)?-1:t==d||t.ownerDocument==w&&x(w,t)?1:c?P(c,e)-P(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==d?-1:t==d?1:i?-1:o?1:c?P(c,e)-P(c,t):0;if(i===o)return pe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?pe(a[r],s[r]):a[r]==w?-1:s[r]==w?1:0}),d},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(p(e),n.matchesSelector&&g&&!A[t+" "]&&(!y||!y.test(t))&&(!v||!v.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=se.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,t,n){return h(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:v,!0)),N.test(r[1])&&w.isPlainObject(t))for(r in t)h(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=v.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):h(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,j=w(v);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=v.createDocumentFragment().appendChild(v.createElement("div")),(fe=v.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),d.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",d.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",d.option=!!ce.lastChild;var ge={thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};function ve(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?w.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&w(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(e.scriptAttrs||{}).prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&i("error"===e.type?404:200,e.type)}),v.head.appendChild(t[0])},abort:function(){n&&n()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||w.expando+"_"+Ct.guid++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Vt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=h(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Vt,"$1"+i):!1!==t.jsonp&&(t.url+=(Et.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Xt.push(i)),a&&h(o)&&o(a[0]),a=o=void 0}),"script"}),d.createHTMLDocument=((Ut=v.implementation.createHTMLDocument("").body).innerHTML="
      ",2===Ut.childNodes.length),w.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(d.createHTMLDocument?((r=(t=v.implementation.createHTMLDocument("")).createElement("base")).href=v.location.href,t.head.appendChild(r)):t=v),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&w(o).remove(),w.merge([],i.childNodes)));var r,i,o},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=w.css(e,"position"),c=w(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=w.css(e,"top"),u=w.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),h(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];return r?r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&"static"===w.css(e,"position");)e=e.offsetParent;return e||re})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return $(this,function(e,r,i){var o;if(g(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=$e(d.pixelPosition,function(e,n){if(n)return n=Be(e,t),Me.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return $(this,function(t,n,i){var o;return g(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return 0{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t},e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i="#"+i.split("#")[1]),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},s=t=>{const i=e(t);return i?document.querySelector(i):null},n=t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const s=Number.parseFloat(e),n=Number.parseFloat(i);return s||n?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0},o=t=>{t.dispatchEvent(new Event("transitionend"))},r=t=>(t[0]||t).nodeType,a=(t,e)=>{let i=!1;const s=e+5;t.addEventListener("transitionend",(function e(){i=!0,t.removeEventListener("transitionend",e)})),setTimeout(()=>{i||o(t)},s)},l=(t,e,i)=>{Object.keys(i).forEach(s=>{const n=i[s],o=e[s],a=o&&r(o)?"element":null==(l=o)?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(n).test(a))throw new TypeError(t.toUpperCase()+": "+`Option "${s}" provided type "${a}" `+`but expected type "${n}".`)})},c=t=>{if(!t)return!1;if(t.style&&t.parentNode&&t.parentNode.style){const e=getComputedStyle(t),i=getComputedStyle(t.parentNode);return"none"!==e.display&&"none"!==i.display&&"hidden"!==e.visibility}return!1},d=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},f=()=>function(){},u=t=>t.offsetHeight,p=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},g=()=>"rtl"===document.documentElement.dir,m=(t,e)=>{var i;i=()=>{const i=p();if(i){const s=i.fn[t];i.fn[t]=e.jQueryInterface,i.fn[t].Constructor=e,i.fn[t].noConflict=()=>(i.fn[t]=s,e.jQueryInterface)}},"loading"===document.readyState?document.addEventListener("DOMContentLoaded",i):i()},_=new Map;var b={set(t,e,i){_.has(t)||_.set(t,new Map);const s=_.get(t);s.has(e)||0===s.size?s.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(t,e)=>_.has(t)&&_.get(t).get(e)||null,remove(t,e){if(!_.has(t))return;const i=_.get(t);i.delete(e),0===i.size&&_.delete(t)}};const v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,E={};let T=1;const A={mouseenter:"mouseover",mouseleave:"mouseout"},L=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function k(t){const e=O(t);return t.uidEvent=e,E[e]=E[e]||{},E[e]}function D(t,e,i=null){const s=Object.keys(t);for(let n=0,o=s.length;n{!function(t,e,i,s){const n=e[i]||{};Object.keys(n).forEach(o=>{if(o.includes(s)){const s=n[o];S(t,e,i,s.originalHandler,s.delegationSelector)}})}(t,l,i,e.slice(1))});const d=l[r]||{};Object.keys(d).forEach(i=>{const s=i.replace(w,"");if(!a||e.includes(s)){const e=d[i];S(t,l,r,e.originalHandler,e.delegationSelector)}})},trigger(t,e,i){if("string"!=typeof e||!t)return null;const s=p(),n=e.replace(y,""),o=e!==n,r=L.has(n);let a,l=!0,c=!0,d=!1,h=null;return o&&s&&(a=s.Event(e,i),s(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),d=a.isDefaultPrevented()),r?(h=document.createEvent("HTMLEvents"),h.initEvent(n,l,!0)):h=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==i&&Object.keys(i).forEach(t=>{Object.defineProperty(h,t,{get:()=>i[t]})}),d&&h.preventDefault(),c&&t.dispatchEvent(h),h.defaultPrevented&&void 0!==a&&a.preventDefault(),h}};class j{constructor(t){(t="string"==typeof t?document.querySelector(t):t)&&(this._element=t,b.set(this._element,this.constructor.DATA_KEY,this))}dispose(){b.remove(this._element,this.constructor.DATA_KEY),this._element=null}static getInstance(t){return b.get(t,this.DATA_KEY)}static get VERSION(){return"5.0.0-beta3"}}class P extends j{static get DATA_KEY(){return"bs.alert"}close(t){const e=t?this._getRootElement(t):this._element,i=this._triggerCloseEvent(e);null===i||i.defaultPrevented||this._removeElement(e)}_getRootElement(t){return s(t)||t.closest(".alert")}_triggerCloseEvent(t){return N.trigger(t,"close.bs.alert")}_removeElement(t){if(t.classList.remove("show"),!t.classList.contains("fade"))return void this._destroyElement(t);const e=n(t);N.one(t,"transitionend",()=>this._destroyElement(t)),a(t,e)}_destroyElement(t){t.parentNode&&t.parentNode.removeChild(t),N.trigger(t,"closed.bs.alert")}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.alert");e||(e=new P(this)),"close"===t&&e[t](this)}))}static handleDismiss(t){return function(e){e&&e.preventDefault(),t.close(this)}}}N.on(document,"click.bs.alert.data-api",'[data-bs-dismiss="alert"]',P.handleDismiss(new P)),m("alert",P);class I extends j{static get DATA_KEY(){return"bs.button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.button");e||(e=new I(this)),"toggle"===t&&e[t]()}))}}function M(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function R(t){return t.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}N.on(document,"click.bs.button.data-api",'[data-bs-toggle="button"]',t=>{t.preventDefault();const e=t.target.closest('[data-bs-toggle="button"]');let i=b.get(e,"bs.button");i||(i=new I(e)),i.toggle()}),m("button",I);const B={setDataAttribute(t,e,i){t.setAttribute("data-bs-"+R(e),i)},removeDataAttribute(t,e){t.removeAttribute("data-bs-"+R(e))},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter(t=>t.startsWith("bs")).forEach(i=>{let s=i.replace(/^bs/,"");s=s.charAt(0).toLowerCase()+s.slice(1,s.length),e[s]=M(t.dataset[i])}),e},getDataAttribute:(t,e)=>M(t.getAttribute("data-bs-"+R(e))),offset(t){const e=t.getBoundingClientRect();return{top:e.top+document.body.scrollTop,left:e.left+document.body.scrollLeft}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},H={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter(t=>t.matches(e)),parents(t,e){const i=[];let s=t.parentNode;for(;s&&s.nodeType===Node.ELEMENT_NODE&&3!==s.nodeType;)s.matches(e)&&i.push(s),s=s.parentNode;return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]}},W={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},U={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},$="next",F="prev",z="left",K="right";class Y extends j{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=H.findOne(".carousel-indicators",this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return W}static get DATA_KEY(){return"bs.carousel"}next(){this._isSliding||this._slide($)}nextWhenVisible(){!document.hidden&&c(this._element)&&this.next()}prev(){this._isSliding||this._slide(F)}pause(t){t||(this._isPaused=!0),H.findOne(".carousel-item-next, .carousel-item-prev",this._element)&&(o(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=H.findOne(".active.carousel-item",this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,"slid.bs.carousel",()=>this.to(t));if(e===t)return this.pause(),void this.cycle();const i=t>e?$:F;this._slide(i,this._items[t])}dispose(){N.off(this._element,".bs.carousel"),this._items=null,this._config=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null,super.dispose()}_getConfig(t){return t={...W,...t},l("carousel",t,U),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=40)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?K:z)}_addEventListeners(){this._config.keyboard&&N.on(this._element,"keydown.bs.carousel",t=>this._keydown(t)),"hover"===this._config.pause&&(N.on(this._element,"mouseenter.bs.carousel",t=>this.pause(t)),N.on(this._element,"mouseleave.bs.carousel",t=>this.cycle(t))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>{!this._pointerEvent||"pen"!==t.pointerType&&"touch"!==t.pointerType?this._pointerEvent||(this.touchStartX=t.touches[0].clientX):this.touchStartX=t.clientX},e=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},i=t=>{!this._pointerEvent||"pen"!==t.pointerType&&"touch"!==t.pointerType||(this.touchDeltaX=t.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(t=>this.cycle(t),500+this._config.interval))};H.find(".carousel-item img",this._element).forEach(t=>{N.on(t,"dragstart.bs.carousel",t=>t.preventDefault())}),this._pointerEvent?(N.on(this._element,"pointerdown.bs.carousel",e=>t(e)),N.on(this._element,"pointerup.bs.carousel",t=>i(t)),this._element.classList.add("pointer-event")):(N.on(this._element,"touchstart.bs.carousel",e=>t(e)),N.on(this._element,"touchmove.bs.carousel",t=>e(t)),N.on(this._element,"touchend.bs.carousel",t=>i(t)))}_keydown(t){/input|textarea/i.test(t.target.tagName)||("ArrowLeft"===t.key?(t.preventDefault(),this._slide(z)):"ArrowRight"===t.key&&(t.preventDefault(),this._slide(K)))}_getItemIndex(t){return this._items=t&&t.parentNode?H.find(".carousel-item",t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const i=t===$,s=t===F,n=this._getItemIndex(e),o=this._items.length-1;if((s&&0===n||i&&n===o)&&!this._config.wrap)return e;const r=(n+(s?-1:1))%this._items.length;return-1===r?this._items[this._items.length-1]:this._items[r]}_triggerSlideEvent(t,e){const i=this._getItemIndex(t),s=this._getItemIndex(H.findOne(".active.carousel-item",this._element));return N.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:s,to:i})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=H.findOne(".active",this._indicatorsElement);e.classList.remove("active"),e.removeAttribute("aria-current");const i=H.find("[data-bs-target]",this._indicatorsElement);for(let e=0;e{r.classList.remove(h,f),r.classList.add("active"),s.classList.remove("active",f,h),this._isSliding=!1,setTimeout(()=>{N.trigger(this._element,"slid.bs.carousel",{relatedTarget:r,direction:p,from:o,to:l})},0)}),a(s,t)}else s.classList.remove("active"),r.classList.add("active"),this._isSliding=!1,N.trigger(this._element,"slid.bs.carousel",{relatedTarget:r,direction:p,from:o,to:l});c&&this.cycle()}}_directionToOrder(t){return[K,z].includes(t)?g()?t===K?F:$:t===K?$:F:t}_orderToDirection(t){return[$,F].includes(t)?g()?t===$?z:K:t===$?K:z:t}static carouselInterface(t,e){let i=b.get(t,"bs.carousel"),s={...W,...B.getDataAttributes(t)};"object"==typeof e&&(s={...s,...e});const n="string"==typeof e?e:s.slide;if(i||(i=new Y(t,s)),"number"==typeof e)i.to(e);else if("string"==typeof n){if(void 0===i[n])throw new TypeError(`No method named "${n}"`);i[n]()}else s.interval&&s.ride&&(i.pause(),i.cycle())}static jQueryInterface(t){return this.each((function(){Y.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=s(this);if(!e||!e.classList.contains("carousel"))return;const i={...B.getDataAttributes(e),...B.getDataAttributes(this)},n=this.getAttribute("data-bs-slide-to");n&&(i.interval=!1),Y.carouselInterface(e,i),n&&b.get(e,"bs.carousel").to(n),t.preventDefault()}}N.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",Y.dataApiClickHandler),N.on(window,"load.bs.carousel.data-api",()=>{const t=H.find('[data-bs-ride="carousel"]');for(let e=0,i=t.length;et===this._element);null!==n&&o.length&&(this._selector=n,this._triggerArray.push(e))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}static get Default(){return q}static get DATA_KEY(){return"bs.collapse"}toggle(){this._element.classList.contains("show")?this.hide():this.show()}show(){if(this._isTransitioning||this._element.classList.contains("show"))return;let t,e;this._parent&&(t=H.find(".show, .collapsing",this._parent).filter(t=>"string"==typeof this._config.parent?t.getAttribute("data-bs-parent")===this._config.parent:t.classList.contains("collapse")),0===t.length&&(t=null));const i=H.findOne(this._selector);if(t){const s=t.find(t=>i!==t);if(e=s?b.get(s,"bs.collapse"):null,e&&e._isTransitioning)return}if(N.trigger(this._element,"show.bs.collapse").defaultPrevented)return;t&&t.forEach(t=>{i!==t&&X.collapseInterface(t,"hide"),e||b.set(t,"bs.collapse",null)});const s=this._getDimension();this._element.classList.remove("collapse"),this._element.classList.add("collapsing"),this._element.style[s]=0,this._triggerArray.length&&this._triggerArray.forEach(t=>{t.classList.remove("collapsed"),t.setAttribute("aria-expanded",!0)}),this.setTransitioning(!0);const o="scroll"+(s[0].toUpperCase()+s.slice(1)),r=n(this._element);N.one(this._element,"transitionend",()=>{this._element.classList.remove("collapsing"),this._element.classList.add("collapse","show"),this._element.style[s]="",this.setTransitioning(!1),N.trigger(this._element,"shown.bs.collapse")}),a(this._element,r),this._element.style[s]=this._element[o]+"px"}hide(){if(this._isTransitioning||!this._element.classList.contains("show"))return;if(N.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=this._element.getBoundingClientRect()[t]+"px",u(this._element),this._element.classList.add("collapsing"),this._element.classList.remove("collapse","show");const e=this._triggerArray.length;if(e>0)for(let t=0;t{this.setTransitioning(!1),this._element.classList.remove("collapsing"),this._element.classList.add("collapse"),N.trigger(this._element,"hidden.bs.collapse")}),a(this._element,i)}setTransitioning(t){this._isTransitioning=t}dispose(){super.dispose(),this._config=null,this._parent=null,this._triggerArray=null,this._isTransitioning=null}_getConfig(t){return(t={...q,...t}).toggle=Boolean(t.toggle),l("collapse",t,V),t}_getDimension(){return this._element.classList.contains("width")?"width":"height"}_getParent(){let{parent:t}=this._config;r(t)?void 0===t.jquery&&void 0===t[0]||(t=t[0]):t=H.findOne(t);const e=`[data-bs-toggle="collapse"][data-bs-parent="${t}"]`;return H.find(e,t).forEach(t=>{const e=s(t);this._addAriaAndCollapsedClass(e,[t])}),t}_addAriaAndCollapsedClass(t,e){if(!t||!e.length)return;const i=t.classList.contains("show");e.forEach(t=>{i?t.classList.remove("collapsed"):t.classList.add("collapsed"),t.setAttribute("aria-expanded",i)})}static collapseInterface(t,e){let i=b.get(t,"bs.collapse");const s={...q,...B.getDataAttributes(t),..."object"==typeof e&&e?e:{}};if(!i&&s.toggle&&"string"==typeof e&&/show|hide/.test(e)&&(s.toggle=!1),i||(i=new X(t,s)),"string"==typeof e){if(void 0===i[e])throw new TypeError(`No method named "${e}"`);i[e]()}}static jQueryInterface(t){return this.each((function(){X.collapseInterface(this,t)}))}}N.on(document,"click.bs.collapse.data-api",'[data-bs-toggle="collapse"]',(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=B.getDataAttributes(this),s=i(this);H.find(s).forEach(t=>{const i=b.get(t,"bs.collapse");let s;i?(null===i._parent&&"string"==typeof e.parent&&(i._config.parent=e.parent,i._parent=i._getParent()),s="toggle"):s=e,X.collapseInterface(t,s)})})),m("collapse",X);var Q="top",G="bottom",Z="right",J="left",tt=[Q,G,Z,J],et=tt.reduce((function(t,e){return t.concat([e+"-start",e+"-end"])}),[]),it=[].concat(tt,["auto"]).reduce((function(t,e){return t.concat([e,e+"-start",e+"-end"])}),[]),st=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function nt(t){return t?(t.nodeName||"").toLowerCase():null}function ot(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function rt(t){return t instanceof ot(t).Element||t instanceof Element}function at(t){return t instanceof ot(t).HTMLElement||t instanceof HTMLElement}function lt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof ot(t).ShadowRoot||t instanceof ShadowRoot)}var ct={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},s=e.attributes[t]||{},n=e.elements[t];at(n)&&nt(n)&&(Object.assign(n.style,i),Object.keys(s).forEach((function(t){var e=s[t];!1===e?n.removeAttribute(t):n.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var s=e.elements[t],n=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});at(s)&&nt(s)&&(Object.assign(s.style,o),Object.keys(n).forEach((function(t){s.removeAttribute(t)})))}))}},requires:["computeStyles"]};function dt(t){return t.split("-")[0]}function ht(t){var e=t.getBoundingClientRect();return{width:e.width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left,x:e.left,y:e.top}}function ft(t){var e=ht(t),i=t.offsetWidth,s=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-s)<=1&&(s=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:s}}function ut(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&<(i)){var s=e;do{if(s&&t.isSameNode(s))return!0;s=s.parentNode||s.host}while(s)}return!1}function pt(t){return ot(t).getComputedStyle(t)}function gt(t){return["table","td","th"].indexOf(nt(t))>=0}function mt(t){return((rt(t)?t.ownerDocument:t.document)||window.document).documentElement}function _t(t){return"html"===nt(t)?t:t.assignedSlot||t.parentNode||(lt(t)?t.host:null)||mt(t)}function bt(t){return at(t)&&"fixed"!==pt(t).position?t.offsetParent:null}function vt(t){for(var e=ot(t),i=bt(t);i&>(i)&&"static"===pt(i).position;)i=bt(i);return i&&("html"===nt(i)||"body"===nt(i)&&"static"===pt(i).position)?e:i||function(t){for(var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox"),i=_t(t);at(i)&&["html","body"].indexOf(nt(i))<0;){var s=pt(i);if("none"!==s.transform||"none"!==s.perspective||"paint"===s.contain||-1!==["transform","perspective"].indexOf(s.willChange)||e&&"filter"===s.willChange||e&&s.filter&&"none"!==s.filter)return i;i=i.parentNode}return null}(t)||e}function yt(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}var wt=Math.max,Et=Math.min,Tt=Math.round;function At(t,e,i){return wt(t,Et(e,i))}function Lt(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Ot(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}var kt={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,s=t.name,n=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=dt(i.placement),l=yt(a),c=[J,Z].indexOf(a)>=0?"height":"width";if(o&&r){var d=function(t,e){return Lt("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Ot(t,tt))}(n.padding,i),h=ft(o),f="y"===l?Q:J,u="y"===l?G:Z,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],g=r[l]-i.rects.reference[l],m=vt(o),_=m?"y"===l?m.clientHeight||0:m.clientWidth||0:0,b=p/2-g/2,v=d[f],y=_-h[c]-d[u],w=_/2-h[c]/2+b,E=At(v,w,y),T=l;i.modifiersData[s]=((e={})[T]=E,e.centerOffset=E-w,e)}},effect:function(t){var e=t.state,i=t.options.element,s=void 0===i?"[data-popper-arrow]":i;null!=s&&("string"!=typeof s||(s=e.elements.popper.querySelector(s)))&&ut(e.elements.popper,s)&&(e.elements.arrow=s)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},Dt={top:"auto",right:"auto",bottom:"auto",left:"auto"};function xt(t){var e,i=t.popper,s=t.popperRect,n=t.placement,o=t.offsets,r=t.position,a=t.gpuAcceleration,l=t.adaptive,c=t.roundOffsets,d=!0===c?function(t){var e=t.x,i=t.y,s=window.devicePixelRatio||1;return{x:Tt(Tt(e*s)/s)||0,y:Tt(Tt(i*s)/s)||0}}(o):"function"==typeof c?c(o):o,h=d.x,f=void 0===h?0:h,u=d.y,p=void 0===u?0:u,g=o.hasOwnProperty("x"),m=o.hasOwnProperty("y"),_=J,b=Q,v=window;if(l){var y=vt(i),w="clientHeight",E="clientWidth";y===ot(i)&&"static"!==pt(y=mt(i)).position&&(w="scrollHeight",E="scrollWidth"),y=y,n===Q&&(b=G,p-=y[w]-s.height,p*=a?1:-1),n===J&&(_=Z,f-=y[E]-s.width,f*=a?1:-1)}var T,A=Object.assign({position:r},l&&Dt);return a?Object.assign({},A,((T={})[b]=m?"0":"",T[_]=g?"0":"",T.transform=(v.devicePixelRatio||1)<2?"translate("+f+"px, "+p+"px)":"translate3d("+f+"px, "+p+"px, 0)",T)):Object.assign({},A,((e={})[b]=m?p+"px":"",e[_]=g?f+"px":"",e.transform="",e))}var Ct={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,s=i.gpuAcceleration,n=void 0===s||s,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:dt(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:n};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,xt(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,xt(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}},St={passive:!0},Nt={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,s=t.options,n=s.scroll,o=void 0===n||n,r=s.resize,a=void 0===r||r,l=ot(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,St)})),a&&l.addEventListener("resize",i.update,St),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,St)})),a&&l.removeEventListener("resize",i.update,St)}},data:{}},jt={left:"right",right:"left",bottom:"top",top:"bottom"};function Pt(t){return t.replace(/left|right|bottom|top/g,(function(t){return jt[t]}))}var It={start:"end",end:"start"};function Mt(t){return t.replace(/start|end/g,(function(t){return It[t]}))}function Rt(t){var e=ot(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Bt(t){return ht(mt(t)).left+Rt(t).scrollLeft}function Ht(t){var e=pt(t),i=e.overflow,s=e.overflowX,n=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+n+s)}function Wt(t,e){var i;void 0===e&&(e=[]);var s=function t(e){return["html","body","#document"].indexOf(nt(e))>=0?e.ownerDocument.body:at(e)&&Ht(e)?e:t(_t(e))}(t),n=s===(null==(i=t.ownerDocument)?void 0:i.body),o=ot(s),r=n?[o].concat(o.visualViewport||[],Ht(s)?s:[]):s,a=e.concat(r);return n?a:a.concat(Wt(_t(r)))}function Ut(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function $t(t,e){return"viewport"===e?Ut(function(t){var e=ot(t),i=mt(t),s=e.visualViewport,n=i.clientWidth,o=i.clientHeight,r=0,a=0;return s&&(n=s.width,o=s.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=s.offsetLeft,a=s.offsetTop)),{width:n,height:o,x:r+Bt(t),y:a}}(t)):at(e)?function(t){var e=ht(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Ut(function(t){var e,i=mt(t),s=Rt(t),n=null==(e=t.ownerDocument)?void 0:e.body,o=wt(i.scrollWidth,i.clientWidth,n?n.scrollWidth:0,n?n.clientWidth:0),r=wt(i.scrollHeight,i.clientHeight,n?n.scrollHeight:0,n?n.clientHeight:0),a=-s.scrollLeft+Bt(t),l=-s.scrollTop;return"rtl"===pt(n||i).direction&&(a+=wt(i.clientWidth,n?n.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(mt(t)))}function Ft(t){return t.split("-")[1]}function zt(t){var e,i=t.reference,s=t.element,n=t.placement,o=n?dt(n):null,r=n?Ft(n):null,a=i.x+i.width/2-s.width/2,l=i.y+i.height/2-s.height/2;switch(o){case Q:e={x:a,y:i.y-s.height};break;case G:e={x:a,y:i.y+i.height};break;case Z:e={x:i.x+i.width,y:l};break;case J:e={x:i.x-s.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?yt(o):null;if(null!=c){var d="y"===c?"height":"width";switch(r){case"start":e[c]=e[c]-(i[d]/2-s[d]/2);break;case"end":e[c]=e[c]+(i[d]/2-s[d]/2)}}return e}function Kt(t,e){void 0===e&&(e={});var i=e,s=i.placement,n=void 0===s?t.placement:s,o=i.boundary,r=void 0===o?"clippingParents":o,a=i.rootBoundary,l=void 0===a?"viewport":a,c=i.elementContext,d=void 0===c?"popper":c,h=i.altBoundary,f=void 0!==h&&h,u=i.padding,p=void 0===u?0:u,g=Lt("number"!=typeof p?p:Ot(p,tt)),m="popper"===d?"reference":"popper",_=t.elements.reference,b=t.rects.popper,v=t.elements[f?m:d],y=function(t,e,i){var s="clippingParents"===e?function(t){var e=Wt(_t(t)),i=["absolute","fixed"].indexOf(pt(t).position)>=0&&at(t)?vt(t):t;return rt(i)?e.filter((function(t){return rt(t)&&ut(t,i)&&"body"!==nt(t)})):[]}(t):[].concat(e),n=[].concat(s,[i]),o=n[0],r=n.reduce((function(e,i){var s=$t(t,i);return e.top=wt(s.top,e.top),e.right=Et(s.right,e.right),e.bottom=Et(s.bottom,e.bottom),e.left=wt(s.left,e.left),e}),$t(t,o));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}(rt(v)?v:v.contextElement||mt(t.elements.popper),r,l),w=ht(_),E=zt({reference:w,element:b,strategy:"absolute",placement:n}),T=Ut(Object.assign({},b,E)),A="popper"===d?T:w,L={top:y.top-A.top+g.top,bottom:A.bottom-y.bottom+g.bottom,left:y.left-A.left+g.left,right:A.right-y.right+g.right},O=t.modifiersData.offset;if("popper"===d&&O){var k=O[n];Object.keys(L).forEach((function(t){var e=[Z,G].indexOf(t)>=0?1:-1,i=[Q,G].indexOf(t)>=0?"y":"x";L[t]+=k[i]*e}))}return L}function Yt(t,e){void 0===e&&(e={});var i=e,s=i.placement,n=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?it:l,d=Ft(s),h=d?a?et:et.filter((function(t){return Ft(t)===d})):tt,f=h.filter((function(t){return c.indexOf(t)>=0}));0===f.length&&(f=h);var u=f.reduce((function(e,i){return e[i]=Kt(t,{placement:i,boundary:n,rootBoundary:o,padding:r})[dt(i)],e}),{});return Object.keys(u).sort((function(t,e){return u[t]-u[e]}))}var qt={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,s=t.name;if(!e.modifiersData[s]._skip){for(var n=i.mainAxis,o=void 0===n||n,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,d=i.boundary,h=i.rootBoundary,f=i.altBoundary,u=i.flipVariations,p=void 0===u||u,g=i.allowedAutoPlacements,m=e.options.placement,_=dt(m),b=l||(_!==m&&p?function(t){if("auto"===dt(t))return[];var e=Pt(t);return[Mt(t),e,Mt(e)]}(m):[Pt(m)]),v=[m].concat(b).reduce((function(t,i){return t.concat("auto"===dt(i)?Yt(e,{placement:i,boundary:d,rootBoundary:h,padding:c,flipVariations:p,allowedAutoPlacements:g}):i)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,T=!0,A=v[0],L=0;L=0,C=x?"width":"height",S=Kt(e,{placement:O,boundary:d,rootBoundary:h,altBoundary:f,padding:c}),N=x?D?Z:J:D?G:Q;y[C]>w[C]&&(N=Pt(N));var j=Pt(N),P=[];if(o&&P.push(S[k]<=0),a&&P.push(S[N]<=0,S[j]<=0),P.every((function(t){return t}))){A=O,T=!1;break}E.set(O,P)}if(T)for(var I=function(t){var e=v.find((function(e){var i=E.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return A=e,"break"},M=p?3:1;M>0&&"break"!==I(M);M--);e.placement!==A&&(e.modifiersData[s]._skip=!0,e.placement=A,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Vt(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Xt(t){return[Q,Z,G,J].some((function(e){return t[e]>=0}))}var Qt={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,s=e.rects.reference,n=e.rects.popper,o=e.modifiersData.preventOverflow,r=Kt(e,{elementContext:"reference"}),a=Kt(e,{altBoundary:!0}),l=Vt(r,s),c=Vt(a,n,o),d=Xt(l),h=Xt(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:d,hasPopperEscaped:h},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":d,"data-popper-escaped":h})}},Gt={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,s=t.name,n=i.offset,o=void 0===n?[0,0]:n,r=it.reduce((function(t,i){return t[i]=function(t,e,i){var s=dt(t),n=[J,Q].indexOf(s)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*n,[J,Z].indexOf(s)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[s]=r}},Zt={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=zt({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},Jt={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,s=t.name,n=i.mainAxis,o=void 0===n||n,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,d=i.altBoundary,h=i.padding,f=i.tether,u=void 0===f||f,p=i.tetherOffset,g=void 0===p?0:p,m=Kt(e,{boundary:l,rootBoundary:c,padding:h,altBoundary:d}),_=dt(e.placement),b=Ft(e.placement),v=!b,y=yt(_),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,T=e.rects.reference,A=e.rects.popper,L="function"==typeof g?g(Object.assign({},e.rects,{placement:e.placement})):g,O={x:0,y:0};if(E){if(o||a){var k="y"===y?Q:J,D="y"===y?G:Z,x="y"===y?"height":"width",C=E[y],S=E[y]+m[k],N=E[y]-m[D],j=u?-A[x]/2:0,P="start"===b?T[x]:A[x],I="start"===b?-A[x]:-T[x],M=e.elements.arrow,R=u&&M?ft(M):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},H=B[k],W=B[D],U=At(0,T[x],R[x]),$=v?T[x]/2-j-U-H-L:P-U-H-L,F=v?-T[x]/2+j+U+W+L:I+U+W+L,z=e.elements.arrow&&vt(e.elements.arrow),K=z?"y"===y?z.clientTop||0:z.clientLeft||0:0,Y=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,q=E[y]+$-Y-K,V=E[y]+F-Y;if(o){var X=At(u?Et(S,q):S,C,u?wt(N,V):N);E[y]=X,O[y]=X-C}if(a){var tt="x"===y?Q:J,et="x"===y?G:Z,it=E[w],st=it+m[tt],nt=it-m[et],ot=At(u?Et(st,q):st,it,u?wt(nt,V):nt);E[w]=ot,O[w]=ot-it}}e.modifiersData[s]=O}},requiresIfExists:["offset"]};function te(t,e,i){void 0===i&&(i=!1);var s,n,o=mt(e),r=ht(t),a=at(e),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(a||!a&&!i)&&(("body"!==nt(e)||Ht(o))&&(l=(s=e)!==ot(s)&&at(s)?{scrollLeft:(n=s).scrollLeft,scrollTop:n.scrollTop}:Rt(s)),at(e)?((c=ht(e)).x+=e.clientLeft,c.y+=e.clientTop):o&&(c.x=Bt(o))),{x:r.left+l.scrollLeft-c.x,y:r.top+l.scrollTop-c.y,width:r.width,height:r.height}}var ee={placement:"bottom",modifiers:[],strategy:"absolute"};function ie(){for(var t=arguments.length,e=new Array(t),i=0;i"applyStyles"===t.name&&!1===t.enabled);this._popper=re(e,this._menu,i),s&&B.setDataAttribute(this._menu,"popper","static")}"ontouchstart"in document.documentElement&&!t.closest(".navbar-nav")&&[].concat(...document.body.children).forEach(t=>N.on(t,"mouseover",null,(function(){}))),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.toggle("show"),this._element.classList.toggle("show"),N.trigger(this._element,"shown.bs.dropdown",e)}}hide(){if(this._element.disabled||this._element.classList.contains("disabled")||!this._menu.classList.contains("show"))return;const t={relatedTarget:this._element};N.trigger(this._element,"hide.bs.dropdown",t).defaultPrevented||(this._popper&&this._popper.destroy(),this._menu.classList.toggle("show"),this._element.classList.toggle("show"),B.removeDataAttribute(this._menu,"popper"),N.trigger(this._element,"hidden.bs.dropdown",t))}dispose(){N.off(this._element,".bs.dropdown"),this._menu=null,this._popper&&(this._popper.destroy(),this._popper=null),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_addEventListeners(){N.on(this._element,"click.bs.dropdown",t=>{t.preventDefault(),this.toggle()})}_getConfig(t){if(t={...this.constructor.Default,...B.getDataAttributes(this._element),...t},l("dropdown",t,this.constructor.DefaultType),"object"==typeof t.reference&&!r(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError("dropdown".toUpperCase()+': Option "reference" provided type "object" without a required "getBoundingClientRect" method.');return t}_getMenuElement(){return H.next(this._element,".dropdown-menu")[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains("dropend"))return ue;if(t.classList.contains("dropstart"))return pe;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?de:ce:e?fe:he}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}static dropdownInterface(t,e){let i=b.get(t,"bs.dropdown");if(i||(i=new _e(t,"object"==typeof e?e:null)),"string"==typeof e){if(void 0===i[e])throw new TypeError(`No method named "${e}"`);i[e]()}}static jQueryInterface(t){return this.each((function(){_e.dropdownInterface(this,t)}))}static clearMenus(t){if(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;if(/input|select|textarea|form/i.test(t.target.tagName))return}const e=H.find('[data-bs-toggle="dropdown"]');for(let i=0,s=e.length;it.composedPath().includes(e)))continue;if("keyup"===t.type&&"Tab"===t.key&&o.contains(t.target))continue}N.trigger(e[i],"hide.bs.dropdown",n).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>N.off(t,"mouseover",null,(function(){}))),e[i].setAttribute("aria-expanded","false"),s._popper&&s._popper.destroy(),o.classList.remove("show"),e[i].classList.remove("show"),B.removeDataAttribute(o,"popper"),N.trigger(e[i],"hidden.bs.dropdown",n))}}}static getParentFromElement(t){return s(t)||t.parentNode}static dataApiKeydownHandler(t){if(/input|textarea/i.test(t.target.tagName)?"Space"===t.key||"Escape"!==t.key&&("ArrowDown"!==t.key&&"ArrowUp"!==t.key||t.target.closest(".dropdown-menu")):!le.test(t.key))return;if(t.preventDefault(),t.stopPropagation(),this.disabled||this.classList.contains("disabled"))return;const e=_e.getParentFromElement(this),i=this.classList.contains("show");if("Escape"===t.key)return(this.matches('[data-bs-toggle="dropdown"]')?this:H.prev(this,'[data-bs-toggle="dropdown"]')[0]).focus(),void _e.clearMenus();if(!i&&("ArrowUp"===t.key||"ArrowDown"===t.key))return void(this.matches('[data-bs-toggle="dropdown"]')?this:H.prev(this,'[data-bs-toggle="dropdown"]')[0]).click();if(!i||"Space"===t.key)return void _e.clearMenus();const s=H.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",e).filter(c);if(!s.length)return;let n=s.indexOf(t.target);"ArrowUp"===t.key&&n>0&&n--,"ArrowDown"===t.key&&nthis.hide(t)),N.on(this._dialog,"mousedown.dismiss.bs.modal",()=>{N.one(this._element,"mouseup.dismiss.bs.modal",t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)})}),this._showBackdrop(()=>this._showElement(t)))}hide(t){if(t&&t.preventDefault(),!this._isShown||this._isTransitioning)return;if(N.trigger(this._element,"hide.bs.modal").defaultPrevented)return;this._isShown=!1;const e=this._isAnimated();if(e&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),N.off(document,"focusin.bs.modal"),this._element.classList.remove("show"),N.off(this._element,"click.dismiss.bs.modal"),N.off(this._dialog,"mousedown.dismiss.bs.modal"),e){const t=n(this._element);N.one(this._element,"transitionend",t=>this._hideModal(t)),a(this._element,t)}else this._hideModal()}dispose(){[window,this._element,this._dialog].forEach(t=>N.off(t,".bs.modal")),super.dispose(),N.off(document,"focusin.bs.modal"),this._config=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null}handleUpdate(){this._adjustDialog()}_getConfig(t){return t={...be,...t},l("modal",t,ve),t}_showElement(t){const e=this._isAnimated(),i=H.findOne(".modal-body",this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,i&&(i.scrollTop=0),e&&u(this._element),this._element.classList.add("show"),this._config.focus&&this._enforceFocus();const s=()=>{this._config.focus&&this._element.focus(),this._isTransitioning=!1,N.trigger(this._element,"shown.bs.modal",{relatedTarget:t})};if(e){const t=n(this._dialog);N.one(this._dialog,"transitionend",s),a(this._dialog,t)}else s()}_enforceFocus(){N.off(document,"focusin.bs.modal"),N.on(document,"focusin.bs.modal",t=>{document===t.target||this._element===t.target||this._element.contains(t.target)||this._element.focus()})}_setEscapeEvent(){this._isShown?N.on(this._element,"keydown.dismiss.bs.modal",t=>{this._config.keyboard&&"Escape"===t.key?(t.preventDefault(),this.hide()):this._config.keyboard||"Escape"!==t.key||this._triggerBackdropTransition()}):N.off(this._element,"keydown.dismiss.bs.modal")}_setResizeEvent(){this._isShown?N.on(window,"resize.bs.modal",()=>this._adjustDialog()):N.off(window,"resize.bs.modal")}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop(()=>{document.body.classList.remove("modal-open"),this._resetAdjustments(),this._resetScrollbar(),N.trigger(this._element,"hidden.bs.modal")})}_removeBackdrop(){this._backdrop.parentNode.removeChild(this._backdrop),this._backdrop=null}_showBackdrop(t){const e=this._isAnimated();if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",e&&this._backdrop.classList.add("fade"),document.body.appendChild(this._backdrop),N.on(this._element,"click.dismiss.bs.modal",t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===this._config.backdrop?this._triggerBackdropTransition():this.hide())}),e&&u(this._backdrop),this._backdrop.classList.add("show"),!e)return void t();const i=n(this._backdrop);N.one(this._backdrop,"transitionend",t),a(this._backdrop,i)}else if(!this._isShown&&this._backdrop){this._backdrop.classList.remove("show");const i=()=>{this._removeBackdrop(),t()};if(e){const t=n(this._backdrop);N.one(this._backdrop,"transitionend",i),a(this._backdrop,t)}else i()}else t()}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight;t||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");const e=n(this._dialog);N.off(this._element,"transitionend"),N.one(this._element,"transitionend",()=>{this._element.classList.remove("modal-static"),t||(N.one(this._element,"transitionend",()=>{this._element.style.overflowY=""}),a(this._element,e))}),a(this._element,e),this._element.focus()}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight;(!this._isBodyOverflowing&&t&&!g()||this._isBodyOverflowing&&!t&&g())&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),(this._isBodyOverflowing&&!t&&!g()||!this._isBodyOverflowing&&t&&g())&&(this._element.style.paddingRight=this._scrollbarWidth+"px")}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}_checkScrollbar(){const t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)t+this._scrollbarWidth),this._setElementAttributes(".sticky-top","marginRight",t=>t-this._scrollbarWidth),this._setElementAttributes("body","paddingRight",t=>t+this._scrollbarWidth)),document.body.classList.add("modal-open")}_setElementAttributes(t,e,i){H.find(t).forEach(t=>{if(t!==document.body&&window.innerWidth>t.clientWidth+this._scrollbarWidth)return;const s=t.style[e],n=window.getComputedStyle(t)[e];B.setDataAttribute(t,e,s),t.style[e]=i(Number.parseFloat(n))+"px"})}_resetScrollbar(){this._resetElementAttributes(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top","paddingRight"),this._resetElementAttributes(".sticky-top","marginRight"),this._resetElementAttributes("body","paddingRight")}_resetElementAttributes(t,e){H.find(t).forEach(t=>{const i=B.getDataAttribute(t,e);void 0===i&&t===document.body?t.style[e]="":(B.removeDataAttribute(t,e),t.style[e]=i)})}_getScrollbarWidth(){const t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);const e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e}static jQueryInterface(t,e){return this.each((function(){let i=b.get(this,"bs.modal");const s={...be,...B.getDataAttributes(this),..."object"==typeof t&&t?t:{}};if(i||(i=new ye(this,s)),"string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=s(this);"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault(),N.one(e,"show.bs.modal",t=>{t.defaultPrevented||N.one(e,"hidden.bs.modal",()=>{c(this)&&this.focus()})});let i=b.get(e,"bs.modal");if(!i){const t={...B.getDataAttributes(e),...B.getDataAttributes(this)};i=new ye(e,t)}i.toggle(this)})),m("modal",ye);const we=()=>{const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)},Ee=(t,e,i)=>{const s=we();H.find(t).forEach(t=>{if(t!==document.body&&window.innerWidth>t.clientWidth+s)return;const n=t.style[e],o=window.getComputedStyle(t)[e];B.setDataAttribute(t,e,n),t.style[e]=i(Number.parseFloat(o))+"px"})},Te=(t,e)=>{H.find(t).forEach(t=>{const i=B.getDataAttribute(t,e);void 0===i&&t===document.body?t.style.removeProperty(e):(B.removeDataAttribute(t,e),t.style[e]=i)})},Ae={backdrop:!0,keyboard:!0,scroll:!1},Le={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"};class Oe extends j{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._addEventListeners()}static get Default(){return Ae}static get DATA_KEY(){return"bs.offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._element.style.visibility="visible",this._config.backdrop&&document.body.classList.add("offcanvas-backdrop"),this._config.scroll||((t=we())=>{document.body.style.overflow="hidden",Ee(".fixed-top, .fixed-bottom, .is-fixed","paddingRight",e=>e+t),Ee(".sticky-top","marginRight",e=>e-t),Ee("body","paddingRight",e=>e+t)})(),this._element.classList.add("offcanvas-toggling"),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add("show"),setTimeout(()=>{this._element.classList.remove("offcanvas-toggling"),N.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t}),this._enforceFocusOnElement(this._element)},n(this._element)))}hide(){this._isShown&&(N.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._element.classList.add("offcanvas-toggling"),N.off(document,"focusin.bs.offcanvas"),this._element.blur(),this._isShown=!1,this._element.classList.remove("show"),setTimeout(()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.backdrop&&document.body.classList.remove("offcanvas-backdrop"),this._config.scroll||(document.body.style.overflow="auto",Te(".fixed-top, .fixed-bottom, .is-fixed","paddingRight"),Te(".sticky-top","marginRight"),Te("body","paddingRight")),N.trigger(this._element,"hidden.bs.offcanvas"),this._element.classList.remove("offcanvas-toggling")},n(this._element))))}_getConfig(t){return t={...Ae,...B.getDataAttributes(this._element),..."object"==typeof t?t:{}},l("offcanvas",t,Le),t}_enforceFocusOnElement(t){N.off(document,"focusin.bs.offcanvas"),N.on(document,"focusin.bs.offcanvas",e=>{document===e.target||t===e.target||t.contains(e.target)||t.focus()}),t.focus()}_addEventListeners(){N.on(this._element,"click.dismiss.bs.offcanvas",'[data-bs-dismiss="offcanvas"]',()=>this.hide()),N.on(document,"keydown",t=>{this._config.keyboard&&"Escape"===t.key&&this.hide()}),N.on(document,"click.bs.offcanvas.data-api",t=>{const e=H.findOne(i(t.target));this._element.contains(t.target)||e===this._element||this.hide()})}static jQueryInterface(t){return this.each((function(){const e=b.get(this,"bs.offcanvas")||new Oe(this,"object"==typeof t?t:{});if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=s(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),d(this))return;N.one(e,"hidden.bs.offcanvas",()=>{c(this)&&this.focus()});const i=H.findOne(".offcanvas.show, .offcanvas-toggling");i&&i!==e||(b.get(e,"bs.offcanvas")||new Oe(e)).toggle(this)})),N.on(window,"load.bs.offcanvas.data-api",()=>{H.find(".offcanvas.show").forEach(t=>(b.get(t,"bs.offcanvas")||new Oe(t)).show())}),m("offcanvas",Oe);const ke=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),De=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i,xe=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Ce=(t,e)=>{const i=t.nodeName.toLowerCase();if(e.includes(i))return!ke.has(i)||Boolean(De.test(t.nodeValue)||xe.test(t.nodeValue));const s=e.filter(t=>t instanceof RegExp);for(let t=0,e=s.length;t{Ce(t,a)||i.removeAttribute(t.nodeName)})}return s.body.innerHTML}const Ne=new RegExp("(^|\\s)bs-tooltip\\S+","g"),je=new Set(["sanitize","allowList","sanitizeFn"]),Pe={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},Ie={AUTO:"auto",TOP:"top",RIGHT:g()?"left":"right",BOTTOM:"bottom",LEFT:g()?"right":"left"},Me={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Re={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"};class Be extends j{constructor(t,e){if(void 0===ae)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return Me}static get NAME(){return"tooltip"}static get DATA_KEY(){return"bs.tooltip"}static get Event(){return Re}static get EVENT_KEY(){return".bs.tooltip"}static get DefaultType(){return Pe}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains("show"))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),N.off(this._element,this.constructor.EVENT_KEY),N.off(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.tip&&this.tip.parentNode&&this.tip.parentNode.removeChild(this.tip),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.config=null,this.tip=null,super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const e=N.trigger(this._element,this.constructor.Event.SHOW),i=h(this._element),s=null===i?this._element.ownerDocument.documentElement.contains(this._element):i.contains(this._element);if(e.defaultPrevented||!s)return;const o=this.getTipElement(),r=t(this.constructor.NAME);o.setAttribute("id",r),this._element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&o.classList.add("fade");const l="function"==typeof this.config.placement?this.config.placement.call(this,o,this._element):this.config.placement,c=this._getAttachment(l);this._addAttachmentClass(c);const d=this._getContainer();b.set(o,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(d.appendChild(o),N.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=re(this._element,o,this._getPopperConfig(c)),o.classList.add("show");const f="function"==typeof this.config.customClass?this.config.customClass():this.config.customClass;f&&o.classList.add(...f.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>{N.on(t,"mouseover",(function(){}))});const u=()=>{const t=this._hoverState;this._hoverState=null,N.trigger(this._element,this.constructor.Event.SHOWN),"out"===t&&this._leave(null,this)};if(this.tip.classList.contains("fade")){const t=n(this.tip);N.one(this.tip,"transitionend",u),a(this.tip,t)}else u()}hide(){if(!this._popper)return;const t=this.getTipElement(),e=()=>{this._isWithActiveTrigger()||("show"!==this._hoverState&&t.parentNode&&t.parentNode.removeChild(t),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.Event.HIDDEN),this._popper&&(this._popper.destroy(),this._popper=null))};if(!N.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented){if(t.classList.remove("show"),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>N.off(t,"mouseover",f)),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this.tip.classList.contains("fade")){const i=n(t);N.one(t,"transitionend",e),a(t,i)}else e();this._hoverState=""}}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");return t.innerHTML=this.config.template,this.tip=t.children[0],this.tip}setContent(){const t=this.getTipElement();this.setElementContent(H.findOne(".tooltip-inner",t),this.getTitle()),t.classList.remove("fade","show")}setElementContent(t,e){if(null!==t)return"object"==typeof e&&r(e)?(e.jquery&&(e=e[0]),void(this.config.html?e.parentNode!==t&&(t.innerHTML="",t.appendChild(e)):t.textContent=e.textContent)):void(this.config.html?(this.config.sanitize&&(e=Se(e,this.config.allowList,this.config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){let t=this._element.getAttribute("data-bs-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this._element):this.config.title),t}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){const i=this.constructor.DATA_KEY;return(e=e||b.get(t.delegateTarget,i))||(e=new this.constructor(t.delegateTarget,this._getDelegateConfig()),b.set(t.delegateTarget,i,e)),e}_getOffset(){const{offset:t}=this.config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{altBoundary:!0,fallbackPlacements:this.config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this.config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this.config.popperConfig?this.config.popperConfig(e):this.config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add("bs-tooltip-"+this.updateAttachment(t))}_getContainer(){return!1===this.config.container?document.body:r(this.config.container)?this.config.container:H.findOne(this.config.container)}_getAttachment(t){return Ie[t.toUpperCase()]}_setListeners(){this.config.trigger.split(" ").forEach(t=>{if("click"===t)N.on(this._element,this.constructor.Event.CLICK,this.config.selector,t=>this.toggle(t));else if("manual"!==t){const e="hover"===t?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,i="hover"===t?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;N.on(this._element,e,this.config.selector,t=>this._enter(t)),N.on(this._element,i,this.config.selector,t=>this._leave(t))}}),this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.config.selector?this.config={...this.config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e.getTipElement().classList.contains("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout(()=>{"show"===e._hoverState&&e.show()},e.config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(()=>{"out"===e._hoverState&&e.hide()},e.config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=B.getDataAttributes(this._element);return Object.keys(e).forEach(t=>{je.has(t)&&delete e[t]}),t&&"object"==typeof t.container&&t.container.jquery&&(t.container=t.container[0]),"number"==typeof(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),l("tooltip",t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};if(this.config)for(const e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=t.getAttribute("class").match(Ne);null!==e&&e.length>0&&e.map(t=>t.trim()).forEach(e=>t.classList.remove(e))}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.tooltip");const i="object"==typeof t&&t;if((e||!/dispose|hide/.test(t))&&(e||(e=new Be(this,i)),"string"==typeof t)){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m("tooltip",Be);const He=new RegExp("(^|\\s)bs-popover\\S+","g"),We={...Be.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},Ue={...Be.DefaultType,content:"(string|element|function)"},$e={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"};class Fe extends Be{static get Default(){return We}static get NAME(){return"popover"}static get DATA_KEY(){return"bs.popover"}static get Event(){return $e}static get EVENT_KEY(){return".bs.popover"}static get DefaultType(){return Ue}isWithContent(){return this.getTitle()||this._getContent()}setContent(){const t=this.getTipElement();this.setElementContent(H.findOne(".popover-header",t),this.getTitle());let e=this._getContent();"function"==typeof e&&(e=e.call(this._element)),this.setElementContent(H.findOne(".popover-body",t),e),t.classList.remove("fade","show")}_addAttachmentClass(t){this.getTipElement().classList.add("bs-popover-"+this.updateAttachment(t))}_getContent(){return this._element.getAttribute("data-bs-content")||this.config.content}_cleanTipClass(){const t=this.getTipElement(),e=t.getAttribute("class").match(He);null!==e&&e.length>0&&e.map(t=>t.trim()).forEach(e=>t.classList.remove(e))}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.popover");const i="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new Fe(this,i),b.set(this,"bs.popover",e)),"string"==typeof t)){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m("popover",Fe);const ze={offset:10,method:"auto",target:""},Ke={offset:"number",method:"string",target:"(string|element)"};class Ye extends j{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._selector=`${this._config.target} .nav-link, ${this._config.target} .list-group-item, ${this._config.target} .dropdown-item`,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,N.on(this._scrollElement,"scroll.bs.scrollspy",()=>this._process()),this.refresh(),this._process()}static get Default(){return ze}static get DATA_KEY(){return"bs.scrollspy"}refresh(){const t=this._scrollElement===this._scrollElement.window?"offset":"position",e="auto"===this._config.method?t:this._config.method,s="position"===e?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),H.find(this._selector).map(t=>{const n=i(t),o=n?H.findOne(n):null;if(o){const t=o.getBoundingClientRect();if(t.width||t.height)return[B[e](o).top+s,n]}return null}).filter(t=>t).sort((t,e)=>t[0]-e[0]).forEach(t=>{this._offsets.push(t[0]),this._targets.push(t[1])})}dispose(){super.dispose(),N.off(this._scrollElement,".bs.scrollspy"),this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null}_getConfig(e){if("string"!=typeof(e={...ze,..."object"==typeof e&&e?e:{}}).target&&r(e.target)){let{id:i}=e.target;i||(i=t("scrollspy"),e.target.id=i),e.target="#"+i}return l("scrollspy",e,Ke),e}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),i=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=i){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`),i=H.findOne(e.join(","));i.classList.contains("dropdown-item")?(H.findOne(".dropdown-toggle",i.closest(".dropdown")).classList.add("active"),i.classList.add("active")):(i.classList.add("active"),H.parents(i,".nav, .list-group").forEach(t=>{H.prev(t,".nav-link, .list-group-item").forEach(t=>t.classList.add("active")),H.prev(t,".nav-item").forEach(t=>{H.children(t,".nav-link").forEach(t=>t.classList.add("active"))})})),N.trigger(this._scrollElement,"activate.bs.scrollspy",{relatedTarget:t})}_clear(){H.find(this._selector).filter(t=>t.classList.contains("active")).forEach(t=>t.classList.remove("active"))}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.scrollspy");if(e||(e=new Ye(this,"object"==typeof t&&t)),"string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,"load.bs.scrollspy.data-api",()=>{H.find('[data-bs-spy="scroll"]').forEach(t=>new Ye(t,B.getDataAttributes(t)))}),m("scrollspy",Ye);class qe extends j{static get DATA_KEY(){return"bs.tab"}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains("active")||d(this._element))return;let t;const e=s(this._element),i=this._element.closest(".nav, .list-group");if(i){const e="UL"===i.nodeName||"OL"===i.nodeName?":scope > li > .active":".active";t=H.find(e,i),t=t[t.length-1]}const n=t?N.trigger(t,"hide.bs.tab",{relatedTarget:this._element}):null;if(N.trigger(this._element,"show.bs.tab",{relatedTarget:t}).defaultPrevented||null!==n&&n.defaultPrevented)return;this._activate(this._element,i);const o=()=>{N.trigger(t,"hidden.bs.tab",{relatedTarget:this._element}),N.trigger(this._element,"shown.bs.tab",{relatedTarget:t})};e?this._activate(e,e.parentNode,o):o()}_activate(t,e,i){const s=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?H.children(e,".active"):H.find(":scope > li > .active",e))[0],o=i&&s&&s.classList.contains("fade"),r=()=>this._transitionComplete(t,s,i);if(s&&o){const t=n(s);s.classList.remove("show"),N.one(s,"transitionend",r),a(s,t)}else r()}_transitionComplete(t,e,i){if(e){e.classList.remove("active");const t=H.findOne(":scope > .dropdown-menu .active",e.parentNode);t&&t.classList.remove("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),u(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&t.parentNode.classList.contains("dropdown-menu")&&(t.closest(".dropdown")&&H.find(".dropdown-toggle").forEach(t=>t.classList.add("active")),t.setAttribute("aria-expanded",!0)),i&&i()}static jQueryInterface(t){return this.each((function(){const e=b.get(this,"bs.tab")||new qe(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){t.preventDefault(),(b.get(this,"bs.tab")||new qe(this)).show()})),m("tab",qe);const Ve={animation:"boolean",autohide:"boolean",delay:"number"},Xe={animation:!0,autohide:!0,delay:5e3};class Qe extends j{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._setListeners()}static get DefaultType(){return Ve}static get Default(){return Xe}static get DATA_KEY(){return"bs.toast"}show(){if(N.trigger(this._element,"show.bs.toast").defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");const t=()=>{this._element.classList.remove("showing"),this._element.classList.add("show"),N.trigger(this._element,"shown.bs.toast"),this._config.autohide&&(this._timeout=setTimeout(()=>{this.hide()},this._config.delay))};if(this._element.classList.remove("hide"),u(this._element),this._element.classList.add("showing"),this._config.animation){const e=n(this._element);N.one(this._element,"transitionend",t),a(this._element,e)}else t()}hide(){if(!this._element.classList.contains("show"))return;if(N.trigger(this._element,"hide.bs.toast").defaultPrevented)return;const t=()=>{this._element.classList.add("hide"),N.trigger(this._element,"hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){const e=n(this._element);N.one(this._element,"transitionend",t),a(this._element,e)}else t()}dispose(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),N.off(this._element,"click.dismiss.bs.toast"),super.dispose(),this._config=null}_getConfig(t){return t={...Xe,...B.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},l("toast",t,this.constructor.DefaultType),t}_setListeners(){N.on(this._element,"click.dismiss.bs.toast",'[data-bs-dismiss="toast"]',()=>this.hide())}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){let e=b.get(this,"bs.toast");if(e||(e=new Qe(this,"object"==typeof t&&t)),"string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return m("toast",Qe),{Alert:P,Button:I,Carousel:Y,Collapse:X,Dropdown:_e,Modal:ye,Offcanvas:Oe,Popover:Fe,ScrollSpy:Ye,Tab:qe,Toast:Qe,Tooltip:Be}})); + + +/* Jquery migrate 3.3.0*/ + +void 0===jQuery.migrateMute&&(jQuery.migrateMute=!0),function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],function(t){return e(t,window)}):"object"==typeof module&&module.exports?module.exports=e(require("jquery"),window):e(jQuery,window)}(function(e,t){"use strict";function r(t){return 0<=function(e,t){var r,n=/^(\d+)\.(\d+)\.(\d+)/,o=n.exec(e)||[],i=n.exec(t)||[];for(r=1;r<=3;r++){if(+o[r]>+i[r])return 1;if(+o[r]<+i[r])return-1}return 0}(e.fn.jquery,t)}e.migrateVersion="3.3.0",t.console&&t.console.log&&(e&&r("3.0.0")||t.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED"),e.migrateWarnings&&t.console.log("JQMIGRATE: Migrate plugin loaded multiple times"),t.console.log("JQMIGRATE: Migrate is installed"+(e.migrateMute?"":" with logging active")+", version "+e.migrateVersion));var n={};function o(r){var o=t.console;e.migrateDeduplicateWarnings&&n[r]||(n[r]=!0,e.migrateWarnings.push(r),o&&o.warn&&!e.migrateMute&&(o.warn("JQMIGRATE: "+r),e.migrateTrace&&o.trace&&o.trace()))}function i(e,t,r,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return o(n),r},set:function(e){o(n),r=e}})}function a(e,t,r,n){e[t]=function(){return o(n),r.apply(this,arguments)}}e.migrateDeduplicateWarnings=!0,e.migrateWarnings=[],void 0===e.migrateTrace&&(e.migrateTrace=!0),e.migrateReset=function(){n={},e.migrateWarnings.length=0},"BackCompat"===t.document.compatMode&&o("jQuery is not compatible with Quirks Mode");var s,u={},c=e.fn.init,d=e.find,l=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,p=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g,f=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;for(s in e.fn.init=function(e){var t=Array.prototype.slice.call(arguments);return"string"==typeof e&&"#"===e&&(o("jQuery( '#' ) is not a valid selector"),t[0]=[]),c.apply(this,t)},e.fn.init.prototype=e.fn,e.find=function(e){var r=Array.prototype.slice.call(arguments);if("string"==typeof e&&l.test(e))try{t.document.querySelector(e)}catch(n){e=e.replace(p,function(e,t,r,n){return"["+t+r+'"'+n+'"]'});try{t.document.querySelector(e),o("Attribute selector with '#' must be quoted: "+r[0]),r[0]=e}catch(e){o("Attribute selector with '#' was not fixed: "+r[0])}}return d.apply(this,r)},d)Object.prototype.hasOwnProperty.call(d,s)&&(e.find[s]=d[s]);if(a(e.fn,"size",function(){return this.length},"jQuery.fn.size() is deprecated and removed; use the .length property"),a(e,"parseJSON",function(){return JSON.parse.apply(null,arguments)},"jQuery.parseJSON is deprecated; use JSON.parse"),a(e,"holdReady",e.holdReady,"jQuery.holdReady is deprecated"),a(e,"unique",e.uniqueSort,"jQuery.unique is deprecated; use jQuery.uniqueSort"),i(e.expr,"filters",e.expr.pseudos,"jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"),i(e.expr,":",e.expr.pseudos,"jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos"),r("3.1.1")&&a(e,"trim",function(e){return null==e?"":(e+"").replace(f,"")},"jQuery.trim is deprecated; use String.prototype.trim"),r("3.2.0")&&a(e,"nodeName",function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},"jQuery.nodeName is deprecated"),r("3.3.0")&&(a(e,"isNumeric",function(e){var t=typeof e;return("number"==t||"string"==t)&&!isNaN(e-parseFloat(e))},"jQuery.isNumeric() is deprecated"),e.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){u["[object "+t+"]"]=t.toLowerCase()}),a(e,"type",function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?u[Object.prototype.toString.call(e)]||"object":typeof e},"jQuery.type is deprecated"),a(e,"isFunction",function(e){return"function"==typeof e},"jQuery.isFunction() is deprecated"),a(e,"isWindow",function(e){return null!=e&&e===e.window},"jQuery.isWindow() is deprecated"),a(e,"isArray",Array.isArray,"jQuery.isArray is deprecated; use Array.isArray")),e.ajax){var y=e.ajax;e.ajax=function(){var e=y.apply(this,arguments);return e.promise&&(a(e,"success",e.done,"jQXHR.success is deprecated and removed"),a(e,"error",e.fail,"jQXHR.error is deprecated and removed"),a(e,"complete",e.always,"jQXHR.complete is deprecated and removed")),e}}var m=e.fn.removeAttr,g=e.fn.toggleClass,h=/\S+/g;function v(e){return e.replace(/-([a-z])/g,function(e,t){return t.toUpperCase()})}e.fn.removeAttr=function(t){var r=this;return e.each(t.match(h),function(t,n){e.expr.match.bool.test(n)&&(o("jQuery.fn.removeAttr no longer sets boolean properties: "+n),r.prop(n,!1))}),m.apply(this,arguments)};var j,Q=!(e.fn.toggleClass=function(t){return void 0!==t&&"boolean"!=typeof t?g.apply(this,arguments):(o("jQuery.fn.toggleClass( boolean ) is deprecated"),this.each(function(){var r=this.getAttribute&&this.getAttribute("class")||"";r&&e.data(this,"__className__",r),this.setAttribute&&this.setAttribute("class",r||!1===t?"":e.data(this,"__className__")||"")}))}),b=/^[a-z]/,w=/^(?:Border(?:Top|Right|Bottom|Left)?(?:Width|)|(?:Margin|Padding)?(?:Top|Right|Bottom|Left)?|(?:Min|Max)?(?:Width|Height))$/;e.swap&&e.each(["height","width","reliableMarginRight"],function(t,r){var n=e.cssHooks[r]&&e.cssHooks[r].get;n&&(e.cssHooks[r].get=function(){var e;return Q=!0,e=n.apply(this,arguments),Q=!1,e})}),e.swap=function(e,t,r,n){var i,a,s={};for(a in Q||o("jQuery.swap() is undocumented and deprecated"),t)s[a]=e.style[a],e.style[a]=t[a];for(a in i=r.apply(e,n||[]),t)e.style[a]=s[a];return i},r("3.4.0")&&"undefined"!=typeof Proxy&&(e.cssProps=new Proxy(e.cssProps||{},{set:function(){return o("JQMIGRATE: jQuery.cssProps is deprecated"),Reflect.set.apply(this,arguments)}})),e.cssNumber||(e.cssNumber={}),j=e.fn.css,e.fn.css=function(t,r){var n=this;return"string"!=typeof t&&e.each(t,function(t,r){e.fn.css.call(n,t,r)}),"number"!=typeof r||function(e){return b.test(e)&&w.test(e[0].toUpperCase()+e.slice(1))}(v(t))||o("Use of number-typed values is deprecated in jQuery.fn.css"),j.apply(this,arguments)};var x=e.data;if(e.data=function(t,r,n){var i,a,s;if(r&&"object"==typeof r&&2===arguments.length){for(s in i=e.hasData(t)&&x.call(this,t),a={},r)s!==v(s)?(o("jQuery.data() always sets/gets camelCased names: "+s),i[s]=r[s]):a[s]=r[s];return x.call(this,t,a),r}return r&&"string"==typeof r&&r!==v(r)&&(i=e.hasData(t)&&x.call(this,t))&&r in i?(o("jQuery.data() always sets/gets camelCased names: "+r),2");t!==e&&C(e)!==C(t)&&o("HTML tags must be properly nested and closed: "+e)}e.event.props=[],e.event.fixHooks={},i(e.event.props,"concat",e.event.props.concat,"jQuery.event.props.concat() is deprecated and removed"),e.event.fix=function(t){var r,n=t.type,i=this.fixHooks[n],a=e.event.props;if(a.length)for(o("jQuery.event.props are deprecated and removed: "+a.join());a.length;)e.event.addProp(a.pop());if(i&&!i._migrated_&&(i._migrated_=!0,o("jQuery.event.fixHooks are deprecated and removed: "+n),(a=i.props)&&a.length))for(;a.length;)e.event.addProp(a.pop());return r=N.call(this,t),i&&i.filter?i.filter(r,t):r},e.event.add=function(e,r){return e===t&&"load"===r&&"complete"===t.document.readyState&&o("jQuery(window).on('load'...) called after load event occurred"),R.apply(this,arguments)},e.each(["load","unload","error"],function(t,r){e.fn[r]=function(){var e=Array.prototype.slice.call(arguments,0);return"load"===r&&"string"==typeof e[0]?H.apply(this,e):(o("jQuery.fn."+r+"() is deprecated"),e.splice(0,0,r),arguments.length?this.on.apply(this,e):(this.triggerHandler.apply(this,e),this))}}),e.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(t,r){e.fn[r]=function(e,t){return o("jQuery.fn."+r+"() event shorthand is deprecated"),0\x20\t\r\n\f]*)[^>]*)\/>/gi,q=e.htmlPrefilter;e.UNSAFE_restoreLegacyHtmlPrefilter=function(){e.htmlPrefilter=function(e){return T(e),e.replace(P,"<$1>")}},e.htmlPrefilter=function(e){return T(e),q(e)};var D=e.fn.offset;if(e.fn.offset=function(){var r,n=this[0];if(n&&n.nodeType)return r=(n.ownerDocument||t.document).documentElement,e.contains(r,n)?D.apply(this,arguments):(o("jQuery.fn.offset() requires an element connected to a document"),{top:0,left:0});o("jQuery.fn.offset() requires a valid DOM element")},e.ajax){var E=e.param;e.param=function(t,r){var n=e.ajaxSettings&&e.ajaxSettings.traditional;return void 0===r&&n&&(o("jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),r=n),E.call(this,t,r)}}var _=e.fn.andSelf||e.fn.addBack;if(e.fn.andSelf=function(){return o("jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),_.apply(this,arguments)},e.Deferred){var F=e.Deferred,O=[["resolve","done",e.Callbacks("once memory"),e.Callbacks("once memory"),"resolved"],["reject","fail",e.Callbacks("once memory"),e.Callbacks("once memory"),"rejected"],["notify","progress",e.Callbacks("memory"),e.Callbacks("memory")]];e.Deferred=function(t){var r=F(),n=r.promise();return r.pipe=n.pipe=function(){var t=arguments;return o("deferred.pipe() is deprecated"),e.Deferred(function(o){e.each(O,function(e,i){var a="function"==typeof t[e]&&t[e];r[i[1]](function(){var e=a&&a.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().done(o.resolve).fail(o.reject).progress(o.notify):o[i[0]+"With"](this===n?o.promise():this,a?[e]:arguments)})}),t=null}).promise()},t&&t.call(r,r),r},e.Deferred.exceptionHook=F.exceptionHook}return e}); + +/*! modernizr 3.11.2 (Custom Build) | MIT */ + +!function(e,t,n,r){function o(e,t){return typeof e===t}function i(e){var t=b.className,n=w._config.classPrefix||"";if(S&&(t=t.baseVal),w._config.enableJSClass){var r=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(r,"$1"+n+"js$2")}w._config.enableClasses&&(e.length>0&&(t+=" "+n+e.join(" "+n)),S?b.className.baseVal=t:b.className=t)}function s(e,t){if("object"==typeof e)for(var n in e)T(e,n)&&s(n,e[n]);else{var r=(e=e.toLowerCase()).split("."),o=w[r[0]];if(2===r.length&&(o=o[r[1]]),void 0!==o)return w;t="function"==typeof t?t():t,1===r.length?w[r[0]]=t:(!w[r[0]]||w[r[0]]instanceof Boolean||(w[r[0]]=new Boolean(w[r[0]])),w[r[0]][r[1]]=t),i([(t&&!1!==t?"":"no-")+r.join("-")]),w._trigger(e,t)}return w}function a(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):S?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}function l(e,t,r,o){var i,s,l,u,f="modernizr",c=a("div"),d=function(){var e=n.body;return e||((e=a(S?"svg":"body")).fake=!0),e}();if(parseInt(r,10))for(;r--;)(l=a("div")).id=o?o[r]:f+(r+1),c.appendChild(l);return(i=a("style")).type="text/css",i.id="s"+f,(d.fake?d:c).appendChild(i),d.appendChild(c),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(n.createTextNode(e)),c.id=f,d.fake&&(d.style.background="",d.style.overflow="hidden",u=b.style.overflow,b.style.overflow="hidden",b.appendChild(d)),s=t(c,e),d.fake?(d.parentNode.removeChild(d),b.style.overflow=u,b.offsetHeight):c.parentNode.removeChild(c),!!s}function u(e,n,r){var o;if("getComputedStyle"in t){o=getComputedStyle.call(t,e,n);var i=t.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){i[i.error?"error":"log"].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!n&&e.currentStyle&&e.currentStyle[r];return o}function f(e,t){return!!~(""+e).indexOf(t)}function c(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function d(e,n){var o=e.length;if("CSS"in t&&"supports"in t.CSS){for(;o--;)if(t.CSS.supports(c(e[o]),n))return!0;return!1}if("CSSSupportsRule"in t){for(var i=[];o--;)i.push("("+c(e[o])+":"+n+")");return l("@supports ("+(i=i.join(" or "))+") { #modernizr { position: absolute; } }",function(e){return"absolute"===u(e,null,"position")})}return r}function p(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function A(e,t,n,i){function s(){u&&(delete z.style,delete z.modElem)}if(i=!o(i,"undefined")&&i,!o(n,"undefined")){var l=d(e,n);if(!o(l,"undefined"))return l}for(var u,c,A,m,h,v=["modernizr","tspan","samp"];!z.style&&v.length;)u=!0,z.modElem=a(v.shift()),z.style=z.modElem.style;for(A=e.length,c=0;c +// +---------------------------------------------------------------------- + +// [ 应用入口文件 ] +namespace think; +if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) { + $origin = rtrim($_SERVER['HTTP_REFERER'],'/'); + header("Access-Control-Allow-Origin:".$origin); + header("Access-Control-Allow-Credentials: true"); + header("Access-Control-Allow-Headers:Authorization,Content-Type,If-Match,If-Modified-Since,If-None-Match,If-Unmodified-Since,X-Requested-With,x_requested_with,x-token,whitelist"); + header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH'); + exit; +} +require __DIR__ . '/../vendor/autoload.php'; + +// 执行HTTP应用并响应 +$http = (new App())->http; + +$response = $http->run(); + +$response->send(); + +$http->end($response); diff --git a/public/php/Uploader.class.php b/public/php/Uploader.class.php new file mode 100644 index 0000000..b7d6bf8 --- /dev/null +++ b/public/php/Uploader.class.php @@ -0,0 +1,372 @@ + "临时文件错误", + "ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件", + "ERROR_SIZE_EXCEED" => "文件大小超出网站限制", + "ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许", + "ERROR_CREATE_DIR" => "目录创建失败", + "ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限", + "ERROR_FILE_MOVE" => "文件保存时出错", + "ERROR_FILE_NOT_FOUND" => "找不到上传文件", + "ERROR_WRITE_CONTENT" => "写入文件内容错误", + "ERROR_UNKNOWN" => "未知错误", + "ERROR_DEAD_LINK" => "链接不可用", + "ERROR_HTTP_LINK" => "链接不是http链接", + "ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确", + "INVALID_URL" => "非法 URL", + "INVALID_IP" => "非法 IP" + ); + + /** + * 构造函数 + * @param string $fileField 表单名称 + * @param array $config 配置项 + * @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名 + */ + public function __construct($fileField, $config, $type = "upload") + { + $this->fileField = $fileField; + $this->config = $config; + $this->type = $type; + if ($type == "remote") { + $this->saveRemote(); + } else if($type == "base64") { + $this->upBase64(); + } else { + $this->upFile(); + } + + $this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']); + } + + /** + * 上传文件的主处理方法 + * @return mixed + */ + private function upFile() + { + $file = $this->file = $_FILES[$this->fileField]; + if (!$file) { + $this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND"); + return; + } + if ($this->file['error']) { + $this->stateInfo = $this->getStateInfo($file['error']); + return; + } else if (!file_exists($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND"); + return; + } else if (!is_uploaded_file($file['tmp_name'])) { + $this->stateInfo = $this->getStateInfo("ERROR_TMPFILE"); + return; + } + + $this->oriName = $file['name']; + $this->fileSize = $file['size']; + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //检查是否不允许的文件格式 + if (!$this->checkType()) { + $this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + } + + /** + * 处理base64编码的图片上传 + * @return mixed + */ + private function upBase64() + { + $base64Data = $_POST[$this->fileField]; + $img = base64_decode($base64Data); + + $this->oriName = $this->config['oriName']; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 拉取远程图片 + * @return mixed + */ + private function saveRemote() + { + $imgUrl = htmlspecialchars($this->fileField); + $imgUrl = str_replace("&", "&", $imgUrl); + + //http开头验证 + if (strpos($imgUrl, "http") !== 0) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK"); + return; + } + + preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches); + $host_with_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 判断是否是合法 url + if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) { + $this->stateInfo = $this->getStateInfo("INVALID_URL"); + return; + } + + preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches); + $host_without_protocol = count($matches) > 1 ? $matches[1] : ''; + + // 此时提取出来的可能是 ip 也有可能是域名,先获取 ip + $ip = gethostbyname($host_without_protocol); + // 判断是否是私有 ip + if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { + $this->stateInfo = $this->getStateInfo("INVALID_IP"); + return; + } + + //获取请求头并检测死链 + $heads = get_headers($imgUrl, 1); + if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) { + $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK"); + return; + } + //格式验证(扩展名验证和Content-Type验证) + $fileType = strtolower(strrchr($imgUrl, '.')); + if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) { + $this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE"); + return; + } + + //打开输出缓冲区并获取远程图片 + ob_start(); + $context = stream_context_create( + array('http' => array( + 'follow_location' => false // don't follow redirects + )) + ); + readfile($imgUrl, false, $context); + $img = ob_get_contents(); + ob_end_clean(); + preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m); + + $this->oriName = $m ? $m[1]:""; + $this->fileSize = strlen($img); + $this->fileType = $this->getFileExt(); + $this->fullName = $this->getFullName(); + $this->filePath = $this->getFilePath(); + $this->fileName = $this->getFileName(); + $dirname = dirname($this->filePath); + + //检查文件大小是否超出限制 + if (!$this->checkSize()) { + $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED"); + return; + } + + //创建目录失败 + if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) { + $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR"); + return; + } else if (!is_writeable($dirname)) { + $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE"); + return; + } + + //移动文件 + if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败 + $this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT"); + } else { //移动成功 + $this->stateInfo = $this->stateMap[0]; + } + + } + + /** + * 上传错误检查 + * @param $errCode + * @return string + */ + private function getStateInfo($errCode) + { + return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode]; + } + + /** + * 获取文件扩展名 + * @return string + */ + private function getFileExt() + { + return strtolower(strrchr($this->oriName, '.')); + } + + /** + * 重命名文件 + * @return string + */ + private function getFullName() + { + //替换日期事件 + $t = time(); + $d = explode('-', date("Y-y-m-d-H-i-s")); + $format = $this->config["pathFormat"]; + $format = str_replace("{yyyy}", $d[0], $format); + $format = str_replace("{yy}", $d[1], $format); + $format = str_replace("{mm}", $d[2], $format); + $format = str_replace("{dd}", $d[3], $format); + $format = str_replace("{hh}", $d[4], $format); + $format = str_replace("{ii}", $d[5], $format); + $format = str_replace("{ss}", $d[6], $format); + $format = str_replace("{time}", $t, $format); + + //过滤文件名的非法自负,并替换文件名 + $oriName = substr($this->oriName, 0, strrpos($this->oriName, '.')); + $oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName); + $format = str_replace("{filename}", $oriName, $format); + + //替换随机字符串 + $randNum = rand(1, 10000000000) . rand(1, 10000000000); + if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) { + $format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format); + } + + $ext = $this->getFileExt(); + return $format . $ext; + } + + /** + * 获取文件名 + * @return string + */ + private function getFileName () { + return substr($this->filePath, strrpos($this->filePath, '/') + 1); + } + + /** + * 获取文件完整路径 + * @return string + */ + private function getFilePath() + { + $fullname = $this->fullName; + $rootPath = $_SERVER['DOCUMENT_ROOT']; + + if (substr($fullname, 0, 1) != '/') { + $fullname = '/' . $fullname; + } + + return $rootPath . $fullname; + } + + /** + * 文件类型检测 + * @return bool + */ + private function checkType() + { + return in_array($this->getFileExt(), $this->config["allowFiles"]); + } + + /** + * 文件大小检测 + * @return bool + */ + private function checkSize() + { + return $this->fileSize <= ($this->config["maxSize"]); + } + + /** + * 获取当前上传成功文件的各项信息 + * @return array + */ + public function getFileInfo() + { + return array( + "state" => $this->stateInfo, + "url" => $this->fullName, + "title" => $this->fileName, + "original" => $this->oriName, + "type" => $this->fileType, + "size" => $this->fileSize + ); + } + +} \ No newline at end of file diff --git a/public/php/action_crawler.php b/public/php/action_crawler.php new file mode 100644 index 0000000..b9e18df --- /dev/null +++ b/public/php/action_crawler.php @@ -0,0 +1,44 @@ + $CONFIG['catcherPathFormat'], + "maxSize" => $CONFIG['catcherMaxSize'], + "allowFiles" => $CONFIG['catcherAllowFiles'], + "oriName" => "remote.png" +); +$fieldName = $CONFIG['catcherFieldName']; + +/* 抓取远程图片 */ +$list = array(); +if (isset($_POST[$fieldName])) { + $source = $_POST[$fieldName]; +} else { + $source = $_GET[$fieldName]; +} +foreach ($source as $imgUrl) { + $item = new Uploader($imgUrl, $config, "remote"); + $info = $item->getFileInfo(); + array_push($list, array( + "state" => $info["state"], + "url" => $info["url"], + "size" => $info["size"], + "title" => htmlspecialchars($info["title"]), + "original" => htmlspecialchars($info["original"]), + "source" => htmlspecialchars($imgUrl) + )); +} + +/* 返回抓取数据 */ +return json_encode(array( + 'state'=> count($list) ? 'SUCCESS':'ERROR', + 'list'=> $list +)); \ No newline at end of file diff --git a/public/php/action_list.php b/public/php/action_list.php new file mode 100644 index 0000000..bf9cd62 --- /dev/null +++ b/public/php/action_list.php @@ -0,0 +1,92 @@ + "no match file", + "list" => array(), + "start" => $start, + "total" => count($files) + )); +} + +/* 获取指定范围的列表 */ +$len = count($files); +for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){ + $list[] = $files[$i]; +} +//倒序 +//for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){ +// $list[] = $files[$i]; +//} + +/* 返回数据 */ +$result = json_encode(array( + "state" => "SUCCESS", + "list" => $list, + "start" => $start, + "total" => count($files) +)); + +return $result; + + +/** + * 遍历获取目录下的指定类型的文件 + * @param $path + * @param array $files + * @return array + */ +function getfiles($path, $allowFiles, &$files = array()) +{ + if (!is_dir($path)) return null; + if(substr($path, strlen($path) - 1) != '/') $path .= '/'; + $handle = opendir($path); + while (false !== ($file = readdir($handle))) { + if ($file != '.' && $file != '..') { + $path2 = $path . $file; + if (is_dir($path2)) { + getfiles($path2, $allowFiles, $files); + } else { + if (preg_match("/\.(".$allowFiles.")$/i", $file)) { + $files[] = array( + 'url'=> substr($path2, strlen($_SERVER['DOCUMENT_ROOT'])), + 'mtime'=> filemtime($path2) + ); + } + } + } + } + return $files; +} \ No newline at end of file diff --git a/public/php/action_upload.php b/public/php/action_upload.php new file mode 100644 index 0000000..d55b659 --- /dev/null +++ b/public/php/action_upload.php @@ -0,0 +1,66 @@ + $CONFIG['imagePathFormat'], + "maxSize" => $CONFIG['imageMaxSize'], + "allowFiles" => $CONFIG['imageAllowFiles'] + ); + $fieldName = $CONFIG['imageFieldName']; + break; + case 'uploadscrawl': + $config = array( + "pathFormat" => $CONFIG['scrawlPathFormat'], + "maxSize" => $CONFIG['scrawlMaxSize'], + "allowFiles" => $CONFIG['scrawlAllowFiles'], + "oriName" => "scrawl.png" + ); + $fieldName = $CONFIG['scrawlFieldName']; + $base64 = "base64"; + break; + case 'uploadvideo': + $config = array( + "pathFormat" => $CONFIG['videoPathFormat'], + "maxSize" => $CONFIG['videoMaxSize'], + "allowFiles" => $CONFIG['videoAllowFiles'] + ); + $fieldName = $CONFIG['videoFieldName']; + break; + case 'uploadfile': + default: + $config = array( + "pathFormat" => $CONFIG['filePathFormat'], + "maxSize" => $CONFIG['fileMaxSize'], + "allowFiles" => $CONFIG['fileAllowFiles'] + ); + $fieldName = $CONFIG['fileFieldName']; + break; +} + +/* 生成上传实例对象并完成上传 */ +$up = new Uploader($fieldName, $config, $base64); + +/** + * 得到上传文件所对应的各个参数,数组结构 + * array( + * "state" => "", //上传状态,上传成功时必须返回"SUCCESS" + * "url" => "", //返回的地址 + * "title" => "", //新文件名 + * "original" => "", //原始文件名 + * "type" => "" //文件类型 + * "size" => "", //文件大小 + * ) + */ + +/* 返回数据 */ +return json_encode($up->getFileInfo()); diff --git a/public/php/config.json b/public/php/config.json new file mode 100644 index 0000000..20ba137 --- /dev/null +++ b/public/php/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "http://cms.oricogroup.com/", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "http://cms.oricogroup.com/", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "http://cms.oricogroup.com/", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "http://cms.oricogroup.com/", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "http://cms.oricogroup.com/", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "http://cms.oricogroup.com/", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "http://cms.oricogroup.com/", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "http://cms.oricogroup.com/", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/public/php/controller.php b/public/php/controller.php new file mode 100644 index 0000000..a60adc1 --- /dev/null +++ b/public/php/controller.php @@ -0,0 +1,60 @@ + '请求地址出错' + )); + break; +} + +/* 输出结果 */ +if (isset($_GET["callback"])) { + if (preg_match("/^[\w_]+$/", $_GET["callback"])) { + echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')'; + } else { + echo json_encode(array( + 'state'=> 'callback参数不合法' + )); + } +} else { + echo $result; +} \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/public/router.php b/public/router.php new file mode 100644 index 0000000..9b39a62 --- /dev/null +++ b/public/router.php @@ -0,0 +1,19 @@ + +// +---------------------------------------------------------------------- +// $Id$ + +if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) { + return false; +} else { + $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php'; + + require __DIR__ . "/index.php"; +} diff --git a/public/static/.gitignore b/public/static/.gitignore new file mode 100755 index 0000000..c96a04f --- /dev/null +++ b/public/static/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/public/upload b/public/upload new file mode 100644 index 0000000..5b445ab --- /dev/null +++ b/public/upload @@ -0,0 +1,175 @@ + + + + + + + Title + + + + + +
      +
      +
      +
      选择文件
      + +
      +
      + + + + + diff --git a/route/app.php b/route/app.php new file mode 100644 index 0000000..52c6f3c --- /dev/null +++ b/route/app.php @@ -0,0 +1,18 @@ + +// +---------------------------------------------------------------------- +use think\facade\Route; + +return [ + //全局错误路由 + Route::miss(function(){ + return json(["status"=>504,'message'=>'不支持直接请求,请使用正确的接口地址和参数','route'=>request()->url(),'create_time'=>time(),'date_time'=>date("Y-m-d H:i:s",time())]); + }) +]; diff --git a/think b/think new file mode 100644 index 0000000..2429d22 --- /dev/null +++ b/think @@ -0,0 +1,10 @@ +#!/usr/bin/env php +console->run(); \ No newline at end of file